Last active
February 21, 2023 10:44
-
-
Save shikishima/3d6fe941f274fe5e466b2c64bb45922f to your computer and use it in GitHub Desktop.
regionなど最低限必要な機能に絞り込んだkeyhacの設定
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import datetime | |
| import glob | |
| import os | |
| import logging | |
| import unicodedata | |
| import configparser | |
| from keyhac import * | |
| logging.basicConfig(filename="debug.log", level=logging.DEBUG) | |
| def configure(keymap): | |
| keymap.setFont("Migu 1M", 14) | |
| keymap.clipboard_history.maxnum = 10000 | |
| global_exclude_target = [ | |
| "bash.exe", | |
| "emacs.exe", | |
| "gvim.exe", | |
| "xyzzy.exe", | |
| "VirtualBox.exe", | |
| "putty.exe", | |
| "poderosa.exe", | |
| "fenrir.exe", | |
| ] | |
| minimum_bindings_target = [ | |
| "explorer.exe", | |
| "KeePass.exe", | |
| "firefox.exe", | |
| "msedge.exe", | |
| ] | |
| clipboard_key = "242" # ひらがなキー | |
| applications_key = "240" # Caps | |
| # Launcher | |
| def command_PopApplicationList(): | |
| # If the list window is already opened, just close it | |
| if keymap.isListWindowOpened(): | |
| keymap.cancelListWindow() | |
| return | |
| def popApplicationList(): | |
| # items | |
| priority_directories = [] | |
| for priority_directory in ["opt", "share", "Data", "work", "lib", "tmp"]: | |
| priority_directories += glob.glob("{0}{1}{2}".format(os.environ["home"], os.sep, priority_directory)) | |
| priority_directories += glob.glob("{0}{1}{2}*{1}*".format(os.environ["home"], os.sep, priority_directory)) | |
| # application | |
| local_apps1 = glob.glob( | |
| "{0}{1}opt{1}local{1}*{1}**{1}*.exe".format(os.environ["home"], os.sep), | |
| ) | |
| local_apps1.sort(key=len) | |
| local_apps2 = glob.glob( | |
| "{0}{1}opt{1}windows_apps{1}*{1}**{1}*.exe".format(os.environ["home"], os.sep), | |
| recursive=True | |
| ) | |
| local_apps2.sort(key=len) | |
| emu = glob.glob("{0}{1}opt{1}emu{1}*{1}**.exe".format(os.environ["home"], os.sep)) | |
| emu.sort(key=len) | |
| scripts = glob.glob("{0}{1}opt{1}scripts{1}*".format(os.environ["home"], os.sep)) | |
| # 64Bit版PythonはPROGRAMFILESとPROGRAMFILES(X64)で同じ値を返すのでPROGRAMW6432を使う | |
| windows_apps = glob.glob("{0}**{1}*.exe".format(os.environ["ProgramFiles(X86)"], os.path), | |
| recursive=True, | |
| ) + glob.glob( | |
| "{0}**{1}*.exe".format(os.environ["PROGRAMW6432"], os.path), | |
| recursive=True, | |
| ) | |
| windows_apps.sort(key=len) | |
| launchList = [] | |
| # アプリ本体をディレクトリ(opt_recursive_directories)より優先する | |
| for items in ( | |
| priority_directories | |
| + scripts | |
| + local_apps1 | |
| + local_apps2 | |
| + emu | |
| + windows_apps | |
| ): | |
| launchList.append( | |
| ( | |
| items, | |
| keymap.ShellExecuteCommand( | |
| None, items, "", os.path.dirname(items) | |
| ), | |
| ) # たまに動作しないアプリがあるので作業フォルダを指定 | |
| ) | |
| listers = [ | |
| ("Launcher", cblister_FixedPhrase(launchList)), | |
| ] | |
| item, mod = keymap.popListWindow(listers) | |
| if item: | |
| item[1]() | |
| # Because the blocking procedure cannot be executed in the key-hook, | |
| # delayed-execute the procedure by delayedCall(). | |
| keymap.delayedCall(popApplicationList, 0) | |
| keymap.delayedCall(keymap.InputKeyCommand("F"), 1) | |
| # 定型文 | |
| # 関数を受け取り、現在のクリップボード内容をその引数に与えて実行する関数を返す | |
| # https://zenn.dev/awtnb/books/adf6c5162a9f08/viewer/de6e84 | |
| def format_cb(func): | |
| def _format(): | |
| cb = getClipboardText() | |
| if cb: | |
| return func(cb) | |
| return _format | |
| fixed_items = [ | |
| ("おはようございます。", "おはようございます。\n今日はいい天気です。"), | |
| ( | |
| "休憩に入ります。", | |
| lambda: "休憩に入ります。\n" | |
| + (datetime.datetime.now() + datetime.timedelta(hours=1)).strftime("%H:%M") | |
| + "に再開します。", | |
| ), | |
| ("全角英数→半角英数,半角カナ→全角カナ", format_cb(lambda s: unicodedata.normalize('NFKC', s))), | |
| ("大文字→小文字&スペース→-", format_cb(lambda s: s.lower().replace(' ', '-'))), | |
| ("Reload config.py", keymap.command_ReloadConfig), | |
| ] | |
| # 設定ファイル(keyhac.exeと同階層のuser.ini)読み込み | |
| config = configparser.ConfigParser(allow_no_value=True) | |
| config.read(os.path.join(getAppExePath(), 'user.ini'), 'UTF-8') | |
| # sample | |
| # [templates] | |
| # Gmail1=foo@gmail.com | |
| # Gmail2=bar@gmail.com | |
| for key, name in config.items('templates'): | |
| temp_tuple = key, name | |
| fixed_items.append(temp_tuple) | |
| keymap.cblisters += [ | |
| ("定型文", cblister_FixedPhrase(fixed_items)), | |
| ] | |
| # for Vivaldi | |
| def is_chrome(window): | |
| if window.getClassName() in ("Chrome_WidgetWin_1"): | |
| return True | |
| return False | |
| class Region: | |
| enabled = False | |
| def on(self): | |
| keymap.popBalloon("region.enabled", "Region On.", 200) | |
| self.enabled = True | |
| def off(self): | |
| keymap.InputKeyCommand("Left")() | |
| keymap.InputKeyCommand("Right")() | |
| keymap.closeBalloon("region.enabled") | |
| self.enabled = False | |
| def esc(self): | |
| if self.enabled: | |
| self.off() | |
| else: | |
| keymap.InputKeyCommand("Esc")() | |
| def toggle(self): | |
| if self.enabled: | |
| self.off() | |
| else: | |
| self.on() | |
| def send_key_through_ime(self, before_input, after_input): | |
| # Google日本語入力が有効なら何もしない | |
| wnd = keymap.getWindow() | |
| # 候補窓が表示されている時 | |
| # google_ime_candidate = wnd.find("GoogleJapaneseInputCandidateWindow", None) | |
| # google_ime_candidate.isVisible() | |
| # Google日本語入力クラス上でIMEが有効 | |
| google_ime_composition = wnd.find("MSCTFIME Composition", None) | |
| if google_ime_composition and google_ime_composition.getImeStatus(): | |
| return keymap.InputKeyCommand(before_input)() | |
| else: | |
| return self.send_key(after_input) | |
| def send_key(self, key, use_region_key=False): | |
| send_key = key | |
| if self.enabled: | |
| if use_region_key: | |
| send_key = use_region_key | |
| else: | |
| send_key = "S-" + key | |
| return keymap.InputKeyCommand(send_key)() | |
| def forward_char(self): | |
| self.send_key("Right") | |
| def forward_word(self): | |
| self.send_key("C-Right", "C-S-Right") | |
| def backward_word(self): | |
| self.send_key("C-Left", "C-S-Left") | |
| def delete_word(self): | |
| self.on() | |
| self.forward_word() | |
| keymap.InputKeyCommand("S-Delete")() | |
| self.off() | |
| def backward_char(self): | |
| self.send_key("Left") | |
| def beginning_of_line(self): | |
| self.send_key("Home") | |
| def end_of_line(self): | |
| self.send_key("End") | |
| def kill_line(self): | |
| self.on() | |
| self.end_of_line() | |
| keymap.InputKeyCommand("S-Delete")() | |
| self.off() | |
| def scroll_up_command(self): | |
| self.send_key("Pagedown") | |
| def scroll_down_command(self): | |
| self.send_key("Pageup") | |
| def next_line(self): | |
| self.send_key_through_ime("C-N", "Down") | |
| def previous_line(self): | |
| self.send_key_through_ime("C-P", "Up") | |
| def beginning_of_buffer(self): | |
| self.send_key("C-Home", "C-S-Home") | |
| def end_of_buffer(self): | |
| self.send_key("C-End", "C-S-End") | |
| def mark_whole_buffer(self): | |
| self.send_key("C-End") | |
| self.on() | |
| self.send_key("C-Home") | |
| def kill_region(self): | |
| keymap.InputKeyCommand("S-Delete")() | |
| self.enabled = False | |
| def kill_ring_save(self): | |
| keymap.InputKeyCommand("C-Insert")() | |
| self.enabled = False | |
| region = Region() | |
| keymap_global = keymap.defineWindowKeymap( | |
| check_func=lambda window: not window.getProcessName() in global_exclude_target | |
| ) | |
| keymap_maximum = keymap.defineWindowKeymap( | |
| check_func=lambda window: not is_chrome(window) | |
| and not window.getProcessName() in global_exclude_target | |
| and not window.getProcessName() in minimum_bindings_target | |
| ) | |
| keymap_minimum = keymap.defineWindowKeymap( | |
| check_func=lambda window: is_chrome(window) | |
| or window.getProcessName() in minimum_bindings_target | |
| ) | |
| # for global | |
| keymap_global[clipboard_key] = keymap.command_ClipboardList # ひらがな | |
| keymap.replaceKey(applications_key, "235") # Capslockを仮想キーに | |
| keymap_global["235"] = command_PopApplicationList # Capslockをランチャーに | |
| # Quattro TKLの機能をどこでも使う | |
| keymap_global["29"] = keymap.MouseButtonClickCommand("left") # 無変換 | |
| keymap_global["A-C-N"] = "A-Down" | |
| keymap_global["A-S-Comma"] = region.beginning_of_buffer | |
| keymap_global["A-S-Period"] = region.end_of_buffer | |
| keymap_global["A-B"] = region.backward_word | |
| keymap_global["A-D"] = region.delete_word | |
| keymap_global["A-F"] = region.forward_word | |
| keymap_global["A-W"] = region.kill_ring_save | |
| keymap_global["A-H"] = region.mark_whole_buffer | |
| keymap_global["A-V"] = region.scroll_down_command | |
| keymap_global["C-A"] = region.beginning_of_line | |
| keymap_global["C-E"] = region.end_of_line | |
| keymap_global["C-K"] = region.kill_line | |
| keymap_global["C-V"] = region.scroll_up_command | |
| keymap_global["C-B"] = region.backward_char | |
| keymap_global["C-C"] = region.kill_ring_save | |
| keymap_global["C-D"] = "Delete" | |
| keymap_global["C-E"] = region.end_of_line | |
| keymap_global["C-F"] = region.forward_char | |
| keymap_global["C-G"] = region.esc | |
| keymap_global["C-H"] = "Back" | |
| keymap_global["C-M"] = "Enter" | |
| keymap_global["C-N"] = region.next_line | |
| keymap_global["C-P"] = region.previous_line | |
| keymap_global["C-S"] = "C-F" | |
| keymap_global["C-Slash"] = "C-z" | |
| keymap_global["C-Space"] = region.toggle | |
| keymap_global["C-Y"] = "S-Insert" | |
| keymap_global["C-BackSlash"] = "243" # 半角/全角 | |
| # 標準アプリ | |
| keymap_maximum["A-Y"] = keymap.command_ClipboardList | |
| keymap_maximum["C-BackSlash"] = "243" # 半角/全角 | |
| keymap_maximum["C-OpenBracket"] = "Esc" | |
| keymap_maximum["C-X"] = keymap.defineMultiStrokeKeymap("C-X") | |
| keymap_maximum["C-X"]["C-F"] = "C-F" | |
| # 全てのキーをクオート | |
| keymap_global["C-Q"] = keymap.defineMultiStrokeKeymap("C-Q") | |
| for alphabet in [chr(ord("A") + i) for i in range(26)]: | |
| for modifier in ["A-", "C-", "A-C-", "C-S-"]: | |
| keymap_global["C-Q"][modifier + alphabet] = modifier + alphabet | |
| # ブラウザなど元々のキーを活かすアプリ用 | |
| keymap_minimum["C-X"] = region.kill_region | |
| # https://github.com/kumamotone/keyhac/blob/master/config.py | |
| # ExplorerでCtrl+Mでフォルダを開こうとするとCtrlキーが押されてるからって | |
| # 新しいウィンドウで開こうとして最悪なのでそれを半ば無理やり回避するコード | |
| # http://anago.2ch.net/test/read.cgi/software/1239109333#569 | |
| keymap_explorer = keymap.defineWindowKeymap(exe_name="explorer.exe") | |
| def input_enter(): | |
| del keymap_explorer["U-LCtrl"] | |
| keymap.wnd = 0 | |
| keymap.InputKeyCommand("U-LCtrl", "Enter")() | |
| def set_trap(): | |
| keymap_explorer["U-LCtrl"] = input_enter | |
| keymap.wnd = 0 | |
| keymap_explorer["C-M"] = set_trap | |
| def configure_ListWindow(window): | |
| def key_repeat(key): | |
| print(key) | |
| keymap.InputKeyCommand(key)() | |
| keymap.InputKeyCommand(key)() | |
| def cut(item): | |
| keymap.ShellExecuteCommand(None, items, "", os.path.dirname(items)) | |
| del window.keymap["Enter"] | |
| del window.keymap["C-M"] | |
| window.keymap["Enter"] = key_repeat("Enter") | |
| window.keymap["C-G"] = key_repeat("Esc") | |
| window.keymap["C-M"] = key_repeat("Enter") |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ローカルアプリのディレクトリは名前が短い順にソート。
同じディレクトリに大量の実行ファイルがある場合に余計なものが上に表示されるため。