Skip to content

Instantly share code, notes, and snippets.

@mizuneko
Created April 7, 2019 08:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mizuneko/9667936a0395670cd26c20801a8e6a6c to your computer and use it in GitHub Desktop.
Save mizuneko/9667936a0395670cd26c20801a8e6a6c to your computer and use it in GitHub Desktop.
[keyhac] SandSとかhjklでのカーソル移動とか
import sys
import os
import datetime
import pyauto
from keyhac import *
# 追加モジュール
import time
import re
import functools
import urllib.parse
from PIL import ImageGrab
def configure(keymap):
# 単純なキー入れ替え
keymap.replaceKey( "(29)", 235 ) # 無変換キーに仮想コード235を割り当て
keymap.replaceKey( "(28)", 236 ) # 変換キーに仮想コード236を割り当て
# ユーザモディファイアの設定
keymap.defineModifier( 235, "User0" )
keymap.defineModifier( 236, "User1" )
# クリップボード監視を無効化
keymap.clipboard_history.enableHook(True)
# 履歴の最大件数
keymap.clipboard_history.maxnum = 200
# 履歴の最大サイズ
keymap.clipboard_history.quota = 10*1024*1024
# Ctrl と組み合わせたときの引用記号
keymap.quote_mark = "> "
# どのウインドウにフォーカスがあっても効くキーマップ
keymap_global = keymap.defineWindowKeymap()
# クリップボード履歴表示
keymap_global["LC-LS-X"] = keymap.command_ClipboardList
# IME制御
keymap_global[ "U0-J" ] = lambda: keymap.getWindow().setImeStatus(1)
keymap_global[ "U0-F" ] = lambda: keymap.getWindow().setImeStatus(0)
########################################
# SandS
########################################
keymap.replaceKey( "Space", "RShift" )
keymap.replaceKey( "RShift", "LShift" )
keymap_global["O-RShift"] = "Space"
########################################
# VIM風キーバインディング
########################################
for any in ("", "S-", "C-", "A-", "C-S-", "C-A-", "S-A-", "C-A-S-"):
# カーソル移動
keymap_global[any + "U1-H"] = any + "Left"
keymap_global[any + "U1-J"] = any + "Down"
keymap_global[any + "U1-K"] = any + "Up"
keymap_global[any + "U1-L"] = any + "Right"
# Home/End
keymap_global[any + "U1-A"] = any + "Home"
keymap_global[any + "U1-E"] = any + "End"
# Enter
keymap_global[any + "U1-M"] = any + "Enter"
# 「カタカナひらがなローマ」キーを徹底的に無視
keymap_global["D-" + any + "(240)"] = lambda: None
keymap_global["U-" + any + "(240)"] = lambda: None
keymap_global["D-" + any + "(241)"] = lambda: None
keymap_global["U-" + any + "(241)"] = lambda: None
keymap_global["D-" + any + "(242)"] = lambda: None
keymap_global["U-" + any + "(242)"] = lambda: None
# Escape
keymap_global["U1-OpenBracket"] = "ESC"
# 1行Cut、前のワードCut、後のワードCut
keymap_global["U0-D"] = keymap.defineMultiStrokeKeymap("U0-D")
keymap_global["U0-D"]["U0-D"] = "Home", "S-End", "C-X", "Back"
keymap_global["U0-D"]["U0-W"] = "C-S-Right", "C-X"
keymap_global["U0-D"]["U0-B"] = "C-S-Left", "C-X"
keymap_global[ "U0-Slash" ] = "C-F"
keymap_global[ "U0-N" ] = "F3"
keymap_global[ "U0-S-N" ] = "S-F3"
########################################
# その他キーバインディング
########################################
keymap_global[ "U0-Q" ] = "ESC"
keymap_global[ "U0-I" ] = "OpenBracket"
keymap_global[ "U0-O" ] = "CloseBracket"
keymap_global[ "U0-S-I" ] = "S-OpenBracket"
keymap_global[ "U0-S-O" ] = "S-CloseBracket"
########################################
# functions for custom hotkey
########################################
# 関数を返す関数にするデコレータ http://d.hatena.ne.jp/Koonies/20110731/keyhac_decorator
# ・「『関数を返す関数』を生成する関数」なので3重ネスト。
# ・キーリマップではキーストロークに特定の「処理」を結びつけているので、
# 割り当て式の右辺にそのまま関数を書くと関数で処理された「戻り値」がキー入力と結びついてエラーとなる。
# lambda式でも回避可能だがデコレータを使用することでより簡潔に記述可能。
def ret_func(func):
@functools.wraps(func)
def _wrapper(*args, **kw):
@functools.wraps(func)
def _execute_func():
return func(*args, **kw)
return _execute_func
return _wrapper
# 遅延関数
def delay(sec=0.05):
time.sleep(sec)
# IME制御による文字/キー入力用関数
# ・keysはリスト形式で指定。キー入力と文字入力をまとめて記述可能
# ・キー入力にアプリケーションの応答が間に合わない場合はsleep_secを調整
@ret_func
def send_input(ime_mode, keys, sleep_sec=0.01):
if ime_mode is not None:
keymap.getWindow().setImeStatus(ime_mode)
for key in keys:
delay(sleep_sec)
try:
keymap.InputKeyCommand(key)()
except:
keymap.InputTextCommand(key)()
# 文字列を直接入力する関数
@ret_func
def direct_input(s, after_IME_state=None):
wnd = keymap.getWindow()
before_IME_state = wnd.getImeStatus()
send_input(0, s, 0)()
delay()
if after_IME_state is not None:
wnd.setImeStatus(after_IME_state)
return None
wnd.setImeStatus(before_IME_state)
# 文字列を貼り付ける関数
def paste_string(s):
setClipboardText(s)
send_input(None, ["C-V"])()
# クリップボード内容を文字列として取得する関数
# 文字列以外がコピーされている状態にも None ではなく空文字を返す
def get_clippedText():
cb = getClipboardText()
return str(cb or "")
# 文字列コピー用関数
def copy_string(sec=0.05):
setClipboardText("")
keymap.InputKeyCommand("C-C")()
delay(sec)
return get_clippedText()
# 複数行の文字列に対して各行の先頭/末尾に指定文字列を挿入する関数
def insert2eachline(tgt_lines, insert_str, insert_to_BOL=True):
lines = tgt_lines.splitlines()
ret = []
for line in lines:
if line:
if insert_to_BOL:
line = insert_str + line
else:
line = line + insert_str
else:
line = ""
ret.append(line)
ret = os.linesep.join(ret)
if tgt_lines.endswith(os.linesep):
ret = ret + os.linesep
return ret
# 複数行の文字列から空白行をの取り除き各行をリストに格納する関数
def lines2list(multiline_str):
ret_list = [line for line in multiline_str.splitlines() if line and not line.isspace()]
return ret_list
# アドレスバーから現在のパスを取得する関数
def get_current_dir():
send_input(None, ["A-D"])()
cb = copy_string(0.1)
if re.search("[  ]", cb):
cb = '"{}"'.format(cb)
return cb
# 各種関数を用いて選択している文字列を処理するラッパー関数
# 引数に渡す関数 func は第1引数に選択中の文字列を受け取ること(第2引数以降は *args にタプル形式で格納される)
@ret_func
def modify_selected_string(func, *args):
backup = get_clippedText()
selected_str = copy_string()
if selected_str:
pasted = func(selected_str, *args)
paste_string(pasted)
delay()
setClipboardText(backup)
################################
# custom hotkey
################################
# Copy
keymap_global["U1-Y"] = lambda: copy_string()
# テキストとして貼り付け
keymap_global["U1-P"] = lambda: paste_string(get_clippedText())
# ダイレクトに引用貼り付け
keymap_global["U1-Q"] = lambda: paste_string(insert2eachline(get_clippedText(), "> ", True))
################################
# modify selected string
################################
# 選択文字列の各行にクリップボード項目を貼り付け
@ret_func
def paste_eachLine(insert_to_BOL = True):
cb = get_clippedText()
modify_selected_string(insert2eachline, cb, insert_to_BOL)()
keymap_global["U0-P"] = keymap.defineMultiStrokeKeymap('paste to: "B"eginning or "E"nd of each line')
keymap_global["U0-P"]["B"] = paste_eachLine(True)
keymap_global["U0-P"]["E"] = paste_eachLine(False)
# 全角の半角変換
def zen_to_han(s):
zenkaku = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!”#$%&’()*+,−./:;<=>?@[¥]^_‘{|}~0123456789 -"
hankaku = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~0123456789 -"
return s.translate(str.maketrans(zenkaku, hankaku))
# 数字の変換処理
zen_digit = "0123456789"
han_digit = "0123456789"
kanji = "〇一二三四五六七八九"
def digit_to_kanji(s):
# 算用数字を漢数字に変換
s = s.translate(str.maketrans(zen_digit, han_digit))
return s.translate(str.maketrans(han_digit, kanji))
def kanji_to_digit(s):
# 漢数字を算用数字に変換
return s.translate(str.maketrans(kanji, han_digit))
# "{{num}}" に連番を挿入
def increment_num(s, start=1, digit=2):
while not s.find("{{num}}") == -1:
zero_index = str(start).zfill(digit)
s = s.replace("{{num}}", zero_index, 1)
start += 1
return s
keymap_global["U0-M"] = keymap.defineMultiStrokeKeymap('modify: 1=>zenkaku to hankaku, 2=>digit to kanji, 3=>kanji to digit, 4 =>increment {{num}}')
keymap_global["U0-M"]["1"] = modify_selected_string(zen_to_han)
keymap_global["U0-M"]["2"] = modify_selected_string(digit_to_kanji)
keymap_global["U0-M"]["3"] = modify_selected_string(kanji_to_digit)
keymap_global["U0-M"]["4"] = modify_selected_string(increment_num, 1, 2)
# 空白行を削除して貼り付け
def delete_blanc_lines():
cb = get_clippedText()
return os.linesep.join(lines2list(cb))
# 重複行を削除して貼り付け
def delete_duplicate_lines():
lines = lines2list(get_clippedText())
uniq = []
for line in lines:
if line not in uniq:
uniq.append(line)
uniq = os.linesep.join(uniq)
return uniq
################################
# popup clipboard menu
################################
# この設定ファイル(config.py)の内容を貼り付ける
def paste_this():
script_path = os.path.dirname(sys.argv[0]) + r"\config.py"
f = open(script_path, mode='r', encoding='utf-8')
content = f.read()
f.close
return content
# 配列読みに変換して貼り付け
from_char = "ぁぃぅぇぉヴがぎぐげござじずぜぞだぢづっでどばびぶべぼぱぴぷぺぽゃゅょァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲン"
to_char = "あいうえおうかきくけこさしすせそたちつつてとはひふへほはひふへほやゆよああいいううええおおかかききくくけけここささししすすせせそそたたちちつつつててととなにぬねのはははひひひふふふへへへほほほまみむめもややゆゆよよらりるれろゎわゐゑをん"
del_char = "ー・!”#$%&’()*+,−./:;<=>?@[¥]^_‘{|}~!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~  「」"
def sakuyomi():
cb = get_clippedText()
r = cb.translate(str.maketrans(from_char, to_char, del_char))
return r
# 空白行を削除して貼り付け
def delete_blanc_lines():
cb = get_clippedText()
return os.linesep.join(lines2list(cb))
# 重複行を削除して貼り付け
def delete_duplicate_lines():
lines = lines2list(get_clippedText())
uniq = []
for line in lines:
if line not in uniq:
uniq.append(line)
uniq = os.linesep.join(uniq)
return uniq
# メニュー
menu_general = [
("Reload config.py" , keymap.command_ReloadConfig),
("Edit config.py" , keymap.command_EditConfig),
("Paste config.py" , paste_this),
("----------- Exit -----------", None),
]
menu_format_clipboard_item = [
("',' to '、'" , lambda: re.sub(",", "、", get_clippedText())),
("Delete blanc lines" , delete_blanc_lines),
("Delete duplicate lines" , delete_duplicate_lines),
("Decode URL" , lambda: urllib.parse.unquote(get_clippedText())),
("Quote mark: Double to Single", lambda: re.sub('\"', "\'", get_clippedText())),
("Quote mark: Single to Double", lambda: re.sub("\'", '\"', get_clippedText())),
("----------- Exit -----------", None),
]
keymap.cblisters += [
("Menu" , cblister_FixedPhrase(menu_general)),
("Format clipboard item" , cblister_FixedPhrase(menu_format_clipboard_item)),
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment