Skip to content

Instantly share code, notes, and snippets.

@xewelus
Last active August 31, 2025 07:44
Show Gist options
  • Select an option

  • Save xewelus/044dd7284c07f7f9b25517a2f6ace367 to your computer and use it in GitHub Desktop.

Select an option

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
/*
==============================================================================
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