Last active
August 31, 2025 07:44
-
-
Save xewelus/044dd7284c07f7f9b25517a2f6ace367 to your computer and use it in GitHub Desktop.
AutoHotKey script for control Telegram Desktop on Windows 11 by vim-like keys
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
| /* | |
| ============================================================================== | |
| tg.ahk - Vim-style Modal Navigation for Telegram Desktop | |
| ============================================================================== | |
| A Vim-inspired modal navigation system for Telegram Desktop that provides | |
| keyboard-only navigation through topic groups, topics, and messages. | |
| OVERVIEW: | |
| This script implements a dual-mode system (Insert/Normal) similar to Vim, | |
| allowing efficient keyboard navigation within Telegram Desktop without | |
| interfering with regular typing. | |
| MODES: | |
| - INSERT MODE: Default state, all keys work normally for typing | |
| - NORMAL MODE: Navigation mode with three sub-modes: | |
| 1. Topic Groups - Navigate between different chat groups | |
| 2. Topics - Navigate between individual chats/channels | |
| 3. Messages - Navigate through message history | |
| KEY BINDINGS: | |
| Mode Switching: | |
| - Ctrl+[ : Enter Normal mode (starts in Messages sub-mode) | |
| - Escape : Exit to Insert mode (or pass through if already in Insert) | |
| - i : Enter Insert mode from Normal mode | |
| - kj : Quick sequence to exit Normal mode (Vim-style) | |
| Navigation (Normal mode only): | |
| - h : Previous sub-mode (Topic Groups ← Topics ← Messages) | |
| - l : Next sub-mode (Topic Groups → Topics → Messages) | |
| - k : Navigate up/previous in current sub-mode | |
| - j : Navigate down/next in current sub-mode | |
| Sub-mode Actions: | |
| Topic Groups (1): k/j = Ctrl+Shift+Up/Down (navigate chat groups) | |
| Topics (2): k/j = Ctrl+Shift+Tab/Ctrl+Tab (switch between chats) | |
| Messages (3): k/j = Ctrl+Up/Down (navigate message history) | |
| AUTO-FEATURES: | |
| - Automatic first topic activation when switching to Topics mode | |
| - Visual notifications showing current mode and sub-mode | |
| REQUIREMENTS: | |
| - AutoHotkey v1 | |
| - Telegram Desktop (ahk_exe Telegram.exe) | |
| - Windows (tested on Windows 11) | |
| USAGE: | |
| 1. Run the script while Telegram Desktop is open | |
| 2. Use Ctrl+[ to enter Normal mode for navigation | |
| 3. Use h/l to switch between navigation contexts | |
| 4. Use k/j to navigate within the current context | |
| 5. Press i or kj to return to Insert mode for typing | |
| The script only activates when Telegram Desktop window is focused, | |
| ensuring it doesn't interfere with other applications. | |
| ============================================================================== | |
| */ | |
| #SingleInstance force | |
| SetWorkingDir %A_ScriptDir% | |
| ; Global variables for mode management | |
| VimMode := "insert" ; insert, normal | |
| NormalSubMode := 1 ; 1=topic_groups, 2=topics, 3=messages | |
| SubModeNames := ["Topic Groups", "Topics", "Messages"] | |
| ; Helper function to show mode notification | |
| ShowModeNotification(mode, submode := "") { | |
| if (mode = "insert") { | |
| ToolTip, [INSERT MODE], 0, 0 | |
| } else if (mode = "normal") { | |
| submodeText := SubModeNames[submode] | |
| ToolTip, [NORMAL - %submodeText%], 0, 0 | |
| } | |
| ; Auto-remove tooltip after 1.5 seconds | |
| SetTimer, RemoveToolTip, 1500 | |
| } | |
| ; Timer function to remove tooltip | |
| RemoveToolTip: | |
| ToolTip | |
| SetTimer, RemoveToolTip, Off | |
| return | |
| ; Function to activate first topic with visual feedback | |
| ActivateFirstTopic() { | |
| ; Show visual feedback where we're clicking | |
| ToolTip, [AUTO-CLICK], 120, 100 | |
| SetTimer, RemoveClickTooltip, 800 | |
| ; Perform the click | |
| Click, 140, 140 | |
| } | |
| ; Initialize in insert mode (no notification on startup) | |
| ; User will see notification only when switching modes | |
| ; Telegram Desktop window detection | |
| #IfWinActive, ahk_exe Telegram.exe | |
| ; Mode switching hotkeys - work in any mode | |
| ; Enter normal mode | |
| ^[:: ; Ctrl + [ | |
| VimMode := "normal" | |
| NormalSubMode := 3 ; Start with messages navigation | |
| ShowModeNotification("normal", NormalSubMode) | |
| return | |
| Escape:: | |
| if (VimMode = "normal") { | |
| VimMode := "insert" | |
| ShowModeNotification("insert") | |
| } else { | |
| Send, {Escape} ; Pass through if in insert mode | |
| } | |
| return | |
| ; k key handler - navigation and kj sequence detection | |
| k:: | |
| if (VimMode = "insert") { | |
| Send, {k} | |
| return | |
| } | |
| ; In normal mode: set ktime for kj sequence and handle navigation | |
| ktime := A_TickCount | |
| ; Navigation in normal mode | |
| if (NormalSubMode = 1) { | |
| ; Topic Groups: k = Ctrl + Shift + Up | |
| Send, ^+{Up} | |
| } else if (NormalSubMode = 2) { | |
| ; Topics: k = Ctrl + Shift + Tab | |
| Send, ^+{Tab} | |
| } else if (NormalSubMode = 3) { | |
| ; Messages: k = Ctrl + Up | |
| Send, ^{Up} | |
| } | |
| return | |
| j:: | |
| currentTime := A_TickCount | |
| if (VimMode = "insert") { | |
| Send, j | |
| return | |
| } | |
| ; Check for kj sequence in normal mode | |
| timeDiff := currentTime - kTime | |
| if (timeDiff <= 100) { | |
| VimMode := "insert" | |
| ShowModeNotification("insert") | |
| kTime := 0 | |
| return | |
| } | |
| ; Regular j navigation in normal mode | |
| if (VimMode = "normal") { | |
| if (NormalSubMode = 1) { | |
| ; Topic Groups: j = Ctrl + Shift + Down | |
| Send, ^+{Down} | |
| } else if (NormalSubMode = 2) { | |
| ; Topics: j = Ctrl + Tab | |
| Send, ^{Tab} | |
| } else if (NormalSubMode = 3) { | |
| ; Messages: j = Ctrl + Down | |
| Send, ^{Down} | |
| } | |
| } | |
| return | |
| ; Enter insert mode | |
| i:: | |
| if (VimMode = "normal") { | |
| VimMode := "insert" | |
| ShowModeNotification("insert") | |
| } else { | |
| Send, {i} ; Pass through if already in insert mode | |
| } | |
| return | |
| ; Sub-mode switching in normal mode | |
| h:: | |
| if (VimMode = "normal") { | |
| ; Previous sub-mode (cycle backwards) | |
| NormalSubMode := NormalSubMode - 1 | |
| if (NormalSubMode < 1) { | |
| NormalSubMode := 3 ; Wrap to last mode | |
| } | |
| ShowModeNotification("normal", NormalSubMode) | |
| ; Auto-click when switching to Topics mode (submode 2) | |
| if (NormalSubMode = 2) { | |
| ActivateFirstTopic() | |
| } | |
| } else { | |
| Send, {h} ; Pass through if in insert mode | |
| } | |
| return | |
| l:: | |
| if (VimMode = "normal") { | |
| ; Next sub-mode (cycle forwards) | |
| NormalSubMode := NormalSubMode + 1 | |
| if (NormalSubMode > 3) { | |
| NormalSubMode := 1 ; Wrap to first mode | |
| } | |
| ShowModeNotification("normal", NormalSubMode) | |
| ; Auto-click when switching to Topics mode (submode 2) | |
| if (NormalSubMode = 2) { | |
| ActivateFirstTopic() | |
| } | |
| } else { | |
| Send, {l} ; Pass through if in insert mode | |
| } | |
| return | |
| #If ; End of Telegram-specific hotkeys | |
| RemoveClickTooltip: | |
| ToolTip | |
| SetTimer, RemoveClickTooltip, Off | |
| return |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment