Skip to content

Commit 272d3a8

Browse files
authored
Merge pull request #7 from TunaCuma/feature/emacs-insert-mode-support
feat: add emacs mode and vi insert mode support
2 parents 1fa104b + 8c2ecce commit 272d3a8

File tree

5 files changed

+195
-19
lines changed

5 files changed

+195
-19
lines changed

.github/workflows/test.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ jobs:
128128
zsh test_config.zsh
129129
shell: bash
130130

131+
- name: Test multi-mode support (emacs and insert modes)
132+
run: |
133+
zsh test_modes.zsh
134+
shell: zsh {0}
135+
131136
- name: Test integration with zsh-vi-mode (simulation)
132137
run: |
133138
cat > test_zvm_integration.zsh << 'EOF'

Makefile

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: test test-load test-keybinding test-config test-all check clean help
1+
.PHONY: test test-load test-keybinding test-config test-modes test-all check clean help
22

33
# Default target
44
.DEFAULT_GOAL := help
@@ -46,7 +46,11 @@ test-config: ## Test custom configuration
4646
exit 1; \
4747
fi'
4848

49-
test-all: test test-load test-keybinding test-config ## Run all tests
49+
test-modes: ## Test emacs and insert mode support
50+
@echo "Testing multi-mode support..."
51+
@zsh test_modes.zsh
52+
53+
test-all: test test-load test-keybinding test-config test-modes ## Run all tests
5054
@echo ""
5155
@echo "All tests completed successfully"
5256

@@ -56,7 +60,7 @@ check: test-all ## Run all tests (alias for test-all)
5660

5761
clean: ## Clean up temporary files
5862
@echo "Cleaning up..."
59-
@rm -f test_*.zsh 2>/dev/null || true
63+
@rm -f test_load.zsh test_keybinding.zsh test_config.zsh test_zvm_integration.zsh 2>/dev/null || true
6064
@echo "Cleanup complete"
6165

6266
install-local: ## Install to local zsh config
@@ -73,15 +77,23 @@ demo: ## Show a quick demo of the plugin
7377
@echo " zsh-vi-man Demo"
7478
@echo "==================================="
7579
@echo ""
76-
@echo "1. Type a command: ls -la"
77-
@echo "2. Press Escape: (enter vi normal mode)"
78-
@echo "3. Move cursor: to 'ls' or '-la'"
79-
@echo "4. Press K: opens man page"
80+
@echo "Vi Normal Mode (default):"
81+
@echo " 1. Type a command: ls -la"
82+
@echo " 2. Press Escape: (enter vi normal mode)"
83+
@echo " 3. Move cursor: to 'ls' or '-la'"
84+
@echo " 4. Press K: opens man page"
85+
@echo ""
86+
@echo "Emacs Mode:"
87+
@echo " 1. Type a command: grep --color pattern"
88+
@echo " 2. Move cursor: to 'grep' or '--color'"
89+
@echo " 3. Press Ctrl-X k: opens man page"
8090
@echo ""
81-
@echo "Try it yourself!"
91+
@echo "Vi Insert Mode:"
92+
@echo " 1. Type a command: git commit -m"
93+
@echo " 2. Press Ctrl-K: opens man page (no Escape needed!)"
8294
@echo ""
8395
@echo "To test the plugin interactively:"
8496
@echo " zsh"
8597
@echo " source ./zsh-vi-man.plugin.zsh"
86-
@echo " # Now type commands and press Esc, then K"
98+
@echo " # Try the keybindings above!"
8799

README.md

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
# 📖 zsh-vi-man
44

5-
**Smart man page lookup for zsh vi mode**
5+
**Smart man page lookup for zsh vi mode (now with emacs mode support!)**
66

7-
Press `Shift-K` on any command or option to instantly open its man page
7+
Press `K` (vi normal mode), `Ctrl-X k` (emacs mode), or `Ctrl-K` (vi insert mode) on any command or option to instantly open its man page
88

99
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
1010
[![Zsh](https://img.shields.io/badge/Shell-Zsh-green.svg)](https://www.zsh.org/)
@@ -156,11 +156,19 @@ echo 'source ~/.zsh-vi-man/zsh-vi-man.plugin.zsh' >> ~/.zshrc
156156

157157
## 🚀 Usage
158158

159+
### Vi Normal Mode (Default)
160+
159161
1. Type a command (e.g., `ls -la` or `git commit --amend`)
160162
2. Press `Escape` to enter vi normal mode
161163
3. Move cursor to any word
162164
4. Press **`K`** to open the man page
163165

166+
### Emacs Mode / Vi Insert Mode
167+
168+
Without leaving insert mode or if using emacs mode:
169+
- **Emacs mode**: Press **`Ctrl-X`** then **`k`**
170+
- **Vi insert mode**: Press **`Ctrl-K`**
171+
164172
<br>
165173

166174
### Examples
@@ -181,13 +189,61 @@ echo 'source ~/.zsh-vi-man/zsh-vi-man.plugin.zsh' >> ~/.zshrc
181189
Set these variables **before** sourcing the plugin:
182190

183191
```zsh
184-
# Change the trigger key (default: K)
192+
# Vi normal mode key (default: K)
185193
ZVM_MAN_KEY='?'
186194

195+
# Emacs mode key sequence (default: ^Xk, i.e., Ctrl-X k)
196+
ZVM_MAN_KEY_EMACS='^X^K' # Example: Ctrl-X Ctrl-K
197+
198+
# Vi insert mode key (default: ^K, i.e., Ctrl-K)
199+
ZVM_MAN_KEY_INSERT='^H' # Example: Ctrl-H
200+
201+
# Enable/disable emacs mode binding (default: true)
202+
ZVM_MAN_ENABLE_EMACS=false
203+
204+
# Enable/disable vi insert mode binding (default: true)
205+
ZVM_MAN_ENABLE_INSERT=false
206+
187207
# Use a different pager (default: less)
188208
ZVM_MAN_PAGER='bat'
189209
```
190210

211+
### Troubleshooting
212+
213+
**Keybindings not working?**
214+
215+
If keybindings don't work after sourcing the plugin, try running:
216+
217+
```zsh
218+
zvm_man_rebind
219+
```
220+
221+
This can happen if:
222+
- Your plugin manager loads plugins before setting up keymaps
223+
- You call `bindkey -e` or `bindkey -v` after the plugin loads
224+
- Another plugin resets your keybindings
225+
226+
**For persistent issues**, add this to your `.zshrc` **after** sourcing the plugin:
227+
228+
```zsh
229+
# Ensure zsh-vi-man bindings are set
230+
zvm_man_rebind
231+
```
232+
233+
<details>
234+
<summary><b>Key Binding Examples</b></summary>
235+
236+
| Key Notation | Description |
237+
|:-------------|:------------|
238+
| `^K` | Ctrl-K |
239+
| `^Xk` | Ctrl-X then k |
240+
| `^X^K` | Ctrl-X then Ctrl-K |
241+
| `\ek` | Alt-k (or Escape then k) |
242+
243+
For special keys, use zsh notation: `^[` for Escape, `^?` for Backspace, etc.
244+
245+
</details>
246+
191247
<br>
192248

193249
## 🔌 Integration with zsh-vi-mode

test_modes.zsh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env zsh
2+
# Test script for emacs mode and vi insert mode support
3+
4+
echo "Testing zsh-vi-man mode support..."
5+
echo
6+
7+
# Source the plugin
8+
source "${0:h}/zsh-vi-man.zsh"
9+
10+
# Test 1: Check if the widget is registered
11+
echo "✓ Test 1: Widget registration"
12+
if zle -l | grep -q "zvm-man"; then
13+
echo " PASS: zvm-man widget is registered"
14+
else
15+
echo " FAIL: zvm-man widget not found"
16+
fi
17+
echo
18+
19+
# Test 2: Check vicmd binding
20+
echo "✓ Test 2: Vi normal mode binding"
21+
if bindkey -M vicmd | grep -q "zvm-man"; then
22+
echo " PASS: Key bound in vicmd mode"
23+
bindkey -M vicmd | grep "zvm-man"
24+
else
25+
echo " FAIL: No binding in vicmd mode"
26+
fi
27+
echo
28+
29+
# Test 3: Check emacs binding
30+
echo "✓ Test 3: Emacs mode binding"
31+
if bindkey -M emacs | grep -q "zvm-man"; then
32+
echo " PASS: Key bound in emacs mode"
33+
bindkey -M emacs | grep "zvm-man"
34+
else
35+
echo " FAIL: No binding in emacs mode"
36+
fi
37+
echo
38+
39+
# Test 4: Check viins binding
40+
echo "✓ Test 4: Vi insert mode binding"
41+
if bindkey -M viins | grep -q "zvm-man"; then
42+
echo " PASS: Key bound in viins mode"
43+
bindkey -M viins | grep "zvm-man"
44+
else
45+
echo " FAIL: No binding in viins mode"
46+
fi
47+
echo
48+
49+
# Test 5: Test with emacs mode disabled
50+
echo "✓ Test 5: Disabling emacs mode"
51+
ZVM_MAN_ENABLE_EMACS=false
52+
_zvm_man_bind_key
53+
if bindkey -M emacs | grep -q "zvm-man"; then
54+
echo " FAIL: Key still bound in emacs mode (should be disabled)"
55+
else
56+
echo " PASS: Emacs mode binding correctly disabled"
57+
fi
58+
echo
59+
60+
# Test 6: Test with insert mode disabled
61+
echo "✓ Test 6: Disabling vi insert mode"
62+
ZVM_MAN_ENABLE_INSERT=false
63+
_zvm_man_bind_key
64+
if bindkey -M viins | grep -q "zvm-man"; then
65+
echo " FAIL: Key still bound in viins mode (should be disabled)"
66+
else
67+
echo " PASS: Vi insert mode binding correctly disabled"
68+
fi
69+
echo
70+
71+
echo "All tests completed!"
72+

zsh-vi-man.zsh

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
1-
# zsh-vi-man.zsh -- Smart man page viewer for zsh vi mode
1+
# zsh-vi-man.zsh -- Smart man page viewer for zsh
22
# https://github.com/TunaCuma/zsh-vi-man
33
#
4-
# Press K in vi normal mode to open the man page for the current command.
5-
# If your cursor is on an option (like -r or --recursive), it will jump
6-
# directly to that option in the man page.
4+
# Press K in vi normal mode, Ctrl-X k in emacs mode, or Ctrl-K in vi insert mode
5+
# to open the man page for the current command. If your cursor is on an option
6+
# (like -r or --recursive), it will jump directly to that option in the man page.
77
#
88
# MIT License - Copyright (c) 2025 Tuna Cuma
99

1010
# Configuration variables (can be set before sourcing)
11-
# ZVM_MAN_KEY: the key to trigger man page lookup (default: K)
11+
# ZVM_MAN_KEY: the key to trigger man page lookup in vi normal mode (default: K)
12+
# ZVM_MAN_KEY_EMACS: the key sequence for emacs mode (default: ^Xk, i.e., Ctrl-X k)
13+
# ZVM_MAN_KEY_INSERT: the key for vi insert mode (default: ^K, i.e., Ctrl-K)
1214
# ZVM_MAN_PAGER: the pager to use (default: less)
15+
# ZVM_MAN_ENABLE_EMACS: enable emacs mode binding (default: true)
16+
# ZVM_MAN_ENABLE_INSERT: enable vi insert mode binding (default: true)
1317

1418
: ${ZVM_MAN_KEY:=K}
19+
: ${ZVM_MAN_KEY_EMACS:='^Xk'}
20+
: ${ZVM_MAN_KEY_INSERT:='^K'}
1521
: ${ZVM_MAN_PAGER:=less}
22+
: ${ZVM_MAN_ENABLE_EMACS:=true}
23+
: ${ZVM_MAN_ENABLE_INSERT:=true}
1624

1725
function zvm-man() {
1826
# Get the word at cursor position
@@ -87,7 +95,30 @@ function zvm-man() {
8795
zle -N zvm-man
8896

8997
function _zvm_man_bind_key() {
90-
bindkey -M vicmd "${ZVM_MAN_KEY}" zvm-man
98+
# Bind in vi normal mode (always enabled)
99+
bindkey -M vicmd "${ZVM_MAN_KEY}" zvm-man 2>/dev/null
100+
101+
# Handle emacs mode binding
102+
if [[ "${ZVM_MAN_ENABLE_EMACS}" == true ]]; then
103+
bindkey -M emacs "${ZVM_MAN_KEY_EMACS}" zvm-man 2>/dev/null
104+
else
105+
# Remove existing binding if disabled
106+
bindkey -M emacs -r "${ZVM_MAN_KEY_EMACS}" 2>/dev/null
107+
fi
108+
109+
# Handle vi insert mode binding
110+
if [[ "${ZVM_MAN_ENABLE_INSERT}" == true ]]; then
111+
bindkey -M viins "${ZVM_MAN_KEY_INSERT}" zvm-man 2>/dev/null
112+
else
113+
# Remove existing binding if disabled
114+
bindkey -M viins -r "${ZVM_MAN_KEY_INSERT}" 2>/dev/null
115+
fi
116+
}
117+
118+
# Expose function so users can manually rebind if needed
119+
# Usage: zvm_man_rebind (if keybindings don't work after sourcing)
120+
function zvm_man_rebind() {
121+
_zvm_man_bind_key
91122
}
92123

93124
# Support both immediate binding and lazy loading with zsh-vi-mode
@@ -102,7 +133,7 @@ elif (( ${+functions[zvm_after_init]} )); then
102133
# zsh-vi-mode without lazy keybindings
103134
zvm_after_init_commands+=(_zvm_man_bind_key)
104135
else
105-
# Standalone or other vi-mode setups
136+
# Standalone or other vi-mode setups - bind immediately
106137
_zvm_man_bind_key
107138
fi
108139

0 commit comments

Comments
 (0)