termjump 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- termjump-0.1.0/PKG-INFO +164 -0
- termjump-0.1.0/README.md +151 -0
- termjump-0.1.0/pyproject.toml +30 -0
- termjump-0.1.0/setup.cfg +4 -0
- termjump-0.1.0/termjump/__init__.py +4 -0
- termjump-0.1.0/termjump/cli.py +45 -0
- termjump-0.1.0/termjump/editor.py +137 -0
- termjump-0.1.0/termjump/shell.py +35 -0
- termjump-0.1.0/termjump.egg-info/PKG-INFO +164 -0
- termjump-0.1.0/termjump.egg-info/SOURCES.txt +13 -0
- termjump-0.1.0/termjump.egg-info/dependency_links.txt +1 -0
- termjump-0.1.0/termjump.egg-info/entry_points.txt +3 -0
- termjump-0.1.0/termjump.egg-info/requires.txt +1 -0
- termjump-0.1.0/termjump.egg-info/top_level.txt +1 -0
- termjump-0.1.0/tests/test_termjump.py +20 -0
termjump-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: termjump
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Click-to-position terminal command editor for zsh
|
|
5
|
+
Author-email: Your Name <you@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/srisowmya2000/termjump
|
|
8
|
+
Project-URL: Repository, https://github.com/srisowmya2000/termjump
|
|
9
|
+
Keywords: terminal,cli,zsh,editor,readline,cursor
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: prompt_toolkit>=3.0.0
|
|
13
|
+
|
|
14
|
+
<div align="center">
|
|
15
|
+
|
|
16
|
+
# โก termjump
|
|
17
|
+
|
|
18
|
+
### Stop pressing `โ` 47 times. Just click.
|
|
19
|
+
|
|
20
|
+
**A tiny TUI editor that lets you click any character in your terminal command to jump your cursor there instantly.**
|
|
21
|
+
|
|
22
|
+
[](https://pypi.org/project/termjump/)
|
|
23
|
+
[](https://www.python.org/)
|
|
24
|
+
[](https://www.zsh.org/)
|
|
25
|
+
[](LICENSE)
|
|
26
|
+
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ๐ค The Problem
|
|
32
|
+
|
|
33
|
+
Every terminal user knows this pain:
|
|
34
|
+
```
|
|
35
|
+
$ docker run -it --rm -v /home/user/projects:/workspace -p 8080:8080 myimage:latest
|
|
36
|
+
^^^^^^^^
|
|
37
|
+
typo is here ๐ญ
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Your options?
|
|
41
|
+
|
|
42
|
+
| Option | Reality |
|
|
43
|
+
|--------|---------|
|
|
44
|
+
| Press `โ` repeatedly | 37 keypresses for one typo |
|
|
45
|
+
| `Alt+B` / `Alt+F` | How many words back? Who knows |
|
|
46
|
+
| `Ctrl+X Ctrl+E` | Opens full vim. For one character. |
|
|
47
|
+
| Retype the whole thing | ๐ค |
|
|
48
|
+
|
|
49
|
+
**There is no way to just click where you want to edit. Until now.**
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## โ
The Solution
|
|
54
|
+
|
|
55
|
+
**termjump** opens a lightweight inline editor right in your terminal.
|
|
56
|
+
Press `Ctrl+E` โ the editor pops up โ **click any character** โ cursor jumps there โ fix it โ `Enter`.
|
|
57
|
+
```
|
|
58
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
59
|
+
โ โ termjump โ smart command editor โ
|
|
60
|
+
โ โ
|
|
61
|
+
โ docker run -it --rm -v /home/user/projects:/workspace -p 8080:8080 โ
|
|
62
|
+
โ ^ โ
|
|
63
|
+
โ click here โ
|
|
64
|
+
โ โ
|
|
65
|
+
โ termjump col 36/72 ENTER confirm ยท ESC cancel ยท click to jump โ
|
|
66
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## ๐ Quick Start
|
|
72
|
+
|
|
73
|
+
**1. Install**
|
|
74
|
+
```bash
|
|
75
|
+
pip install termjump
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**2. Add to your `~/.zshrc`**
|
|
79
|
+
```zsh
|
|
80
|
+
eval "$(termjump init)"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**3. Reload your shell**
|
|
84
|
+
```bash
|
|
85
|
+
source ~/.zshrc
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**4. Use it**
|
|
89
|
+
> Type any command โ press `Ctrl+E` โ click any character โ edit โ `Enter`
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## ๐ฎ How It Works
|
|
94
|
+
```
|
|
95
|
+
You type a command Press Ctrl+E Click a character
|
|
96
|
+
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
|
|
97
|
+
|
|
98
|
+
$ git commit -m โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
|
|
99
|
+
"fix autentication" โโโบ โ termjump โ โโโโโโโบ โ cursor jumps โ
|
|
100
|
+
โ editor โ click! โ exactly there โ
|
|
101
|
+
โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
|
|
102
|
+
โ
|
|
103
|
+
โผ
|
|
104
|
+
Fix typo โ Enter
|
|
105
|
+
Command runs โ
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## โจ๏ธ Keyboard Shortcuts
|
|
111
|
+
|
|
112
|
+
| Key | Action |
|
|
113
|
+
|-----|--------|
|
|
114
|
+
| ๐ฑ๏ธ **Click** | Jump cursor instantly to any character |
|
|
115
|
+
| `โ` / `โ` | Move one character at a time |
|
|
116
|
+
| `Alt+โ` / `Alt+โ` | Jump one word |
|
|
117
|
+
| `Ctrl+A` | Jump to beginning of command |
|
|
118
|
+
| `Ctrl+E` | Jump to end of command |
|
|
119
|
+
| `Enter` | Confirm and run the command |
|
|
120
|
+
| `Esc` / `Ctrl+C` | Cancel โ original command stays untouched |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## โ๏ธ Configuration
|
|
125
|
+
|
|
126
|
+
**Change the trigger key** (default is `Ctrl+E`):
|
|
127
|
+
```zsh
|
|
128
|
+
# In your ~/.zshrc, after the eval line:
|
|
129
|
+
eval "$(termjump init)"
|
|
130
|
+
bindkey '^F' _termjump_widget # Ctrl+F instead
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## ๐ Requirements
|
|
136
|
+
|
|
137
|
+
- **Python** 3.10+
|
|
138
|
+
- **Shell** โ zsh (default on macOS since Catalina)
|
|
139
|
+
- **Terminal** with mouse support:
|
|
140
|
+
- โ
iTerm2
|
|
141
|
+
- โ
Kitty
|
|
142
|
+
- โ
WezTerm
|
|
143
|
+
- โ
macOS Terminal.app
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## ๐ค Contributing
|
|
148
|
+
|
|
149
|
+
PRs and issues are very welcome!
|
|
150
|
+
```bash
|
|
151
|
+
git clone https://github.com/srisowmya2000/termjump
|
|
152
|
+
cd termjump
|
|
153
|
+
pip install -e ".[dev]"
|
|
154
|
+
python tests/test_termjump.py
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
<div align="center">
|
|
160
|
+
<br>
|
|
161
|
+
<b>termjump</b> โ because arrow keys are not a navigation strategy.
|
|
162
|
+
<br><br>
|
|
163
|
+
Made with ๐ฑ๏ธ for everyone who has ever rage-retyped a long command.
|
|
164
|
+
</div>
|
termjump-0.1.0/README.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# โก termjump
|
|
4
|
+
|
|
5
|
+
### Stop pressing `โ` 47 times. Just click.
|
|
6
|
+
|
|
7
|
+
**A tiny TUI editor that lets you click any character in your terminal command to jump your cursor there instantly.**
|
|
8
|
+
|
|
9
|
+
[](https://pypi.org/project/termjump/)
|
|
10
|
+
[](https://www.python.org/)
|
|
11
|
+
[](https://www.zsh.org/)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## ๐ค The Problem
|
|
19
|
+
|
|
20
|
+
Every terminal user knows this pain:
|
|
21
|
+
```
|
|
22
|
+
$ docker run -it --rm -v /home/user/projects:/workspace -p 8080:8080 myimage:latest
|
|
23
|
+
^^^^^^^^
|
|
24
|
+
typo is here ๐ญ
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Your options?
|
|
28
|
+
|
|
29
|
+
| Option | Reality |
|
|
30
|
+
|--------|---------|
|
|
31
|
+
| Press `โ` repeatedly | 37 keypresses for one typo |
|
|
32
|
+
| `Alt+B` / `Alt+F` | How many words back? Who knows |
|
|
33
|
+
| `Ctrl+X Ctrl+E` | Opens full vim. For one character. |
|
|
34
|
+
| Retype the whole thing | ๐ค |
|
|
35
|
+
|
|
36
|
+
**There is no way to just click where you want to edit. Until now.**
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## โ
The Solution
|
|
41
|
+
|
|
42
|
+
**termjump** opens a lightweight inline editor right in your terminal.
|
|
43
|
+
Press `Ctrl+E` โ the editor pops up โ **click any character** โ cursor jumps there โ fix it โ `Enter`.
|
|
44
|
+
```
|
|
45
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
46
|
+
โ โ termjump โ smart command editor โ
|
|
47
|
+
โ โ
|
|
48
|
+
โ docker run -it --rm -v /home/user/projects:/workspace -p 8080:8080 โ
|
|
49
|
+
โ ^ โ
|
|
50
|
+
โ click here โ
|
|
51
|
+
โ โ
|
|
52
|
+
โ termjump col 36/72 ENTER confirm ยท ESC cancel ยท click to jump โ
|
|
53
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## ๐ Quick Start
|
|
59
|
+
|
|
60
|
+
**1. Install**
|
|
61
|
+
```bash
|
|
62
|
+
pip install termjump
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**2. Add to your `~/.zshrc`**
|
|
66
|
+
```zsh
|
|
67
|
+
eval "$(termjump init)"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**3. Reload your shell**
|
|
71
|
+
```bash
|
|
72
|
+
source ~/.zshrc
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**4. Use it**
|
|
76
|
+
> Type any command โ press `Ctrl+E` โ click any character โ edit โ `Enter`
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## ๐ฎ How It Works
|
|
81
|
+
```
|
|
82
|
+
You type a command Press Ctrl+E Click a character
|
|
83
|
+
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
|
|
84
|
+
|
|
85
|
+
$ git commit -m โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
|
|
86
|
+
"fix autentication" โโโบ โ termjump โ โโโโโโโบ โ cursor jumps โ
|
|
87
|
+
โ editor โ click! โ exactly there โ
|
|
88
|
+
โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
|
|
89
|
+
โ
|
|
90
|
+
โผ
|
|
91
|
+
Fix typo โ Enter
|
|
92
|
+
Command runs โ
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## โจ๏ธ Keyboard Shortcuts
|
|
98
|
+
|
|
99
|
+
| Key | Action |
|
|
100
|
+
|-----|--------|
|
|
101
|
+
| ๐ฑ๏ธ **Click** | Jump cursor instantly to any character |
|
|
102
|
+
| `โ` / `โ` | Move one character at a time |
|
|
103
|
+
| `Alt+โ` / `Alt+โ` | Jump one word |
|
|
104
|
+
| `Ctrl+A` | Jump to beginning of command |
|
|
105
|
+
| `Ctrl+E` | Jump to end of command |
|
|
106
|
+
| `Enter` | Confirm and run the command |
|
|
107
|
+
| `Esc` / `Ctrl+C` | Cancel โ original command stays untouched |
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## โ๏ธ Configuration
|
|
112
|
+
|
|
113
|
+
**Change the trigger key** (default is `Ctrl+E`):
|
|
114
|
+
```zsh
|
|
115
|
+
# In your ~/.zshrc, after the eval line:
|
|
116
|
+
eval "$(termjump init)"
|
|
117
|
+
bindkey '^F' _termjump_widget # Ctrl+F instead
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## ๐ Requirements
|
|
123
|
+
|
|
124
|
+
- **Python** 3.10+
|
|
125
|
+
- **Shell** โ zsh (default on macOS since Catalina)
|
|
126
|
+
- **Terminal** with mouse support:
|
|
127
|
+
- โ
iTerm2
|
|
128
|
+
- โ
Kitty
|
|
129
|
+
- โ
WezTerm
|
|
130
|
+
- โ
macOS Terminal.app
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## ๐ค Contributing
|
|
135
|
+
|
|
136
|
+
PRs and issues are very welcome!
|
|
137
|
+
```bash
|
|
138
|
+
git clone https://github.com/srisowmya2000/termjump
|
|
139
|
+
cd termjump
|
|
140
|
+
pip install -e ".[dev]"
|
|
141
|
+
python tests/test_termjump.py
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
<div align="center">
|
|
147
|
+
<br>
|
|
148
|
+
<b>termjump</b> โ because arrow keys are not a navigation strategy.
|
|
149
|
+
<br><br>
|
|
150
|
+
Made with ๐ฑ๏ธ for everyone who has ever rage-retyped a long command.
|
|
151
|
+
</div>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=42", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "termjump"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Click-to-position terminal command editor for zsh"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Your Name", email = "you@example.com" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["terminal", "cli", "zsh", "editor", "readline", "cursor"]
|
|
16
|
+
dependencies = [
|
|
17
|
+
"prompt_toolkit>=3.0.0",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
termjump = "termjump.cli:termjump_main"
|
|
22
|
+
termjump-edit = "termjump.cli:termjump_edit_main"
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/srisowmya2000/termjump"
|
|
26
|
+
Repository = "https://github.com/srisowmya2000/termjump"
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.packages.find]
|
|
29
|
+
where = ["."]
|
|
30
|
+
include = ["termjump*"]
|
termjump-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""
|
|
2
|
+
termjump CLI
|
|
3
|
+
|
|
4
|
+
termjump init โ print zsh shell integration snippet
|
|
5
|
+
termjump-edit <cmd> โ open TUI editor, print result to stdout
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def termjump_main():
|
|
12
|
+
"""Entry point for the `termjump` command."""
|
|
13
|
+
args = sys.argv[1:]
|
|
14
|
+
|
|
15
|
+
if not args or args[0] in ("-h", "--help"):
|
|
16
|
+
print("Usage:")
|
|
17
|
+
print(" termjump init Print shell integration snippet")
|
|
18
|
+
print(" termjump-edit <command> Open command editor")
|
|
19
|
+
print()
|
|
20
|
+
print("Quick setup (add to ~/.zshrc):")
|
|
21
|
+
print(' eval "$(termjump init)"')
|
|
22
|
+
sys.exit(0)
|
|
23
|
+
|
|
24
|
+
if args[0] == "init":
|
|
25
|
+
from termjump.shell import print_init_script
|
|
26
|
+
print_init_script("zsh")
|
|
27
|
+
sys.exit(0)
|
|
28
|
+
|
|
29
|
+
if args[0] == "version":
|
|
30
|
+
from termjump import __version__
|
|
31
|
+
print(f"termjump {__version__}")
|
|
32
|
+
sys.exit(0)
|
|
33
|
+
|
|
34
|
+
print(f"Unknown command: {args[0]}", file=sys.stderr)
|
|
35
|
+
sys.exit(1)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def termjump_edit_main():
|
|
39
|
+
"""Entry point for `termjump-edit` โ opens the TUI editor."""
|
|
40
|
+
from termjump.editor import main
|
|
41
|
+
main()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
if __name__ == "__main__":
|
|
45
|
+
termjump_main()
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""
|
|
2
|
+
termjump editor โ click any character to jump cursor there.
|
|
3
|
+
Built on prompt_toolkit for full terminal/mouse support.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from prompt_toolkit import Application
|
|
7
|
+
from prompt_toolkit.buffer import Buffer
|
|
8
|
+
from prompt_toolkit.layout.containers import HSplit, Window
|
|
9
|
+
from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
|
|
10
|
+
from prompt_toolkit.layout.layout import Layout
|
|
11
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
12
|
+
from prompt_toolkit.formatted_text import HTML
|
|
13
|
+
from prompt_toolkit.styles import Style
|
|
14
|
+
from prompt_toolkit.mouse_events import MouseEventType
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
STYLE = Style.from_dict({
|
|
19
|
+
"status": "bg:#1a1a2e fg:#7c83fd bold",
|
|
20
|
+
"status.key": "bg:#1a1a2e fg:#e2e8f0",
|
|
21
|
+
"token.cmd": "fg:#ffa657 bold",
|
|
22
|
+
"token.flag": "fg:#3fb950",
|
|
23
|
+
"token.string": "fg:#d2a8ff",
|
|
24
|
+
"token.path": "fg:#79c0ff",
|
|
25
|
+
"token.default": "fg:#e6edf3",
|
|
26
|
+
"header": "bg:#0d1117 fg:#484f58",
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def tokenize_command(text):
|
|
31
|
+
import re
|
|
32
|
+
tokens = []
|
|
33
|
+
pattern = re.compile(
|
|
34
|
+
r'("(?:[^"\\]|\\.)*")'
|
|
35
|
+
r"|('(?:[^'\\]|\\.)*')"
|
|
36
|
+
r"|(--?[a-zA-Z][a-zA-Z0-9_-]*)"
|
|
37
|
+
r"|([^\s]+)"
|
|
38
|
+
)
|
|
39
|
+
first = True
|
|
40
|
+
for m in pattern.finditer(text):
|
|
41
|
+
s, e = m.start(), m.end()
|
|
42
|
+
tok = m.group(0)
|
|
43
|
+
if m.group(1) or m.group(2):
|
|
44
|
+
cls = "token.string"
|
|
45
|
+
elif m.group(3):
|
|
46
|
+
cls = "token.flag"
|
|
47
|
+
elif "/" in tok or tok.endswith((".conf", ".json", ".yaml", ".toml", ".sh", ".py")):
|
|
48
|
+
cls = "token.path"
|
|
49
|
+
elif first:
|
|
50
|
+
cls = "token.cmd"
|
|
51
|
+
else:
|
|
52
|
+
cls = "token.default"
|
|
53
|
+
tokens.append((s, e, cls))
|
|
54
|
+
first = False
|
|
55
|
+
return tokens
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def run_editor(initial_command: str) -> str | None:
|
|
59
|
+
result_holder = {"command": None, "cancelled": False}
|
|
60
|
+
|
|
61
|
+
from prompt_toolkit.document import Document
|
|
62
|
+
buf = Buffer(
|
|
63
|
+
name="main",
|
|
64
|
+
initial_document=Document(initial_command, cursor_position=len(initial_command)),
|
|
65
|
+
multiline=False,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
kb = KeyBindings()
|
|
69
|
+
|
|
70
|
+
@kb.add("enter")
|
|
71
|
+
def accept(event):
|
|
72
|
+
result_holder["command"] = buf.text
|
|
73
|
+
event.app.exit()
|
|
74
|
+
|
|
75
|
+
@kb.add("escape")
|
|
76
|
+
@kb.add("c-c")
|
|
77
|
+
def cancel(event):
|
|
78
|
+
result_holder["cancelled"] = True
|
|
79
|
+
event.app.exit()
|
|
80
|
+
|
|
81
|
+
@kb.add("c-a")
|
|
82
|
+
def go_home(event):
|
|
83
|
+
buf.cursor_position = 0
|
|
84
|
+
|
|
85
|
+
@kb.add("c-e")
|
|
86
|
+
def go_end(event):
|
|
87
|
+
buf.cursor_position = len(buf.text)
|
|
88
|
+
|
|
89
|
+
def get_status():
|
|
90
|
+
pos = buf.cursor_position
|
|
91
|
+
total = len(buf.text)
|
|
92
|
+
return HTML(
|
|
93
|
+
f'<status> termjump </status>'
|
|
94
|
+
f'<status.key> col <b>{pos}</b>/{total} </status.key>'
|
|
95
|
+
f'<status.key> ENTER confirm ยท ESC cancel ยท click to jump </status.key>'
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def mouse_handler(mouse_event):
|
|
99
|
+
if mouse_event.event_type == MouseEventType.MOUSE_UP:
|
|
100
|
+
col = mouse_event.position.x
|
|
101
|
+
buf.cursor_position = min(col, len(buf.text))
|
|
102
|
+
|
|
103
|
+
layout = Layout(
|
|
104
|
+
HSplit([
|
|
105
|
+
Window(FormattedTextControl(HTML('<header> โ termjump โ smart command editor</header>')), height=1),
|
|
106
|
+
Window(BufferControl(buffer=buf, focusable=True, mouse_handler=mouse_handler), height=1, style="bg:#0d1117 fg:#e6edf3"),
|
|
107
|
+
Window(FormattedTextControl(get_status), height=1),
|
|
108
|
+
])
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
from prompt_toolkit.output.color_depth import ColorDepth
|
|
112
|
+
app = Application(
|
|
113
|
+
layout=layout,
|
|
114
|
+
key_bindings=kb,
|
|
115
|
+
style=STYLE,
|
|
116
|
+
mouse_support=True,
|
|
117
|
+
full_screen=False,
|
|
118
|
+
color_depth=ColorDepth.TRUE_COLOR,
|
|
119
|
+
)
|
|
120
|
+
app.run()
|
|
121
|
+
|
|
122
|
+
if result_holder["cancelled"]:
|
|
123
|
+
return None
|
|
124
|
+
return result_holder["command"]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def main():
|
|
128
|
+
initial = " ".join(sys.argv[1:]) if len(sys.argv) >= 2 else ""
|
|
129
|
+
edited = run_editor(initial)
|
|
130
|
+
if edited is None:
|
|
131
|
+
sys.exit(1)
|
|
132
|
+
print(edited, end="")
|
|
133
|
+
sys.exit(0)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if __name__ == "__main__":
|
|
137
|
+
main()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generates shell integration scripts for termjump.
|
|
3
|
+
Usage: termjump init โ prints zsh snippet to eval
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
ZSH_WIDGET = r"""
|
|
7
|
+
# โโ termjump zsh integration โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
8
|
+
_termjump_widget() {
|
|
9
|
+
local current_cmd="$BUFFER"
|
|
10
|
+
|
|
11
|
+
# Run the editor; capture output
|
|
12
|
+
local edited
|
|
13
|
+
edited=$(termjump-edit "$current_cmd" </dev/tty 2>/dev/tty)
|
|
14
|
+
local exit_code=$?
|
|
15
|
+
|
|
16
|
+
if [[ $exit_code -eq 0 && -n "$edited" ]]; then
|
|
17
|
+
BUFFER="$edited"
|
|
18
|
+
CURSOR=${#BUFFER}
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
zle redisplay
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
zle -N _termjump_widget
|
|
25
|
+
# Bind to Ctrl+E (change to taste)
|
|
26
|
+
bindkey '^E' _termjump_widget
|
|
27
|
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def print_init_script(shell: str = "zsh") -> None:
|
|
32
|
+
if shell == "zsh":
|
|
33
|
+
print(ZSH_WIDGET)
|
|
34
|
+
else:
|
|
35
|
+
raise ValueError(f"Unsupported shell: {shell}. Currently only zsh is supported.")
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: termjump
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Click-to-position terminal command editor for zsh
|
|
5
|
+
Author-email: Your Name <you@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/srisowmya2000/termjump
|
|
8
|
+
Project-URL: Repository, https://github.com/srisowmya2000/termjump
|
|
9
|
+
Keywords: terminal,cli,zsh,editor,readline,cursor
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: prompt_toolkit>=3.0.0
|
|
13
|
+
|
|
14
|
+
<div align="center">
|
|
15
|
+
|
|
16
|
+
# โก termjump
|
|
17
|
+
|
|
18
|
+
### Stop pressing `โ` 47 times. Just click.
|
|
19
|
+
|
|
20
|
+
**A tiny TUI editor that lets you click any character in your terminal command to jump your cursor there instantly.**
|
|
21
|
+
|
|
22
|
+
[](https://pypi.org/project/termjump/)
|
|
23
|
+
[](https://www.python.org/)
|
|
24
|
+
[](https://www.zsh.org/)
|
|
25
|
+
[](LICENSE)
|
|
26
|
+
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ๐ค The Problem
|
|
32
|
+
|
|
33
|
+
Every terminal user knows this pain:
|
|
34
|
+
```
|
|
35
|
+
$ docker run -it --rm -v /home/user/projects:/workspace -p 8080:8080 myimage:latest
|
|
36
|
+
^^^^^^^^
|
|
37
|
+
typo is here ๐ญ
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Your options?
|
|
41
|
+
|
|
42
|
+
| Option | Reality |
|
|
43
|
+
|--------|---------|
|
|
44
|
+
| Press `โ` repeatedly | 37 keypresses for one typo |
|
|
45
|
+
| `Alt+B` / `Alt+F` | How many words back? Who knows |
|
|
46
|
+
| `Ctrl+X Ctrl+E` | Opens full vim. For one character. |
|
|
47
|
+
| Retype the whole thing | ๐ค |
|
|
48
|
+
|
|
49
|
+
**There is no way to just click where you want to edit. Until now.**
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## โ
The Solution
|
|
54
|
+
|
|
55
|
+
**termjump** opens a lightweight inline editor right in your terminal.
|
|
56
|
+
Press `Ctrl+E` โ the editor pops up โ **click any character** โ cursor jumps there โ fix it โ `Enter`.
|
|
57
|
+
```
|
|
58
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
59
|
+
โ โ termjump โ smart command editor โ
|
|
60
|
+
โ โ
|
|
61
|
+
โ docker run -it --rm -v /home/user/projects:/workspace -p 8080:8080 โ
|
|
62
|
+
โ ^ โ
|
|
63
|
+
โ click here โ
|
|
64
|
+
โ โ
|
|
65
|
+
โ termjump col 36/72 ENTER confirm ยท ESC cancel ยท click to jump โ
|
|
66
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## ๐ Quick Start
|
|
72
|
+
|
|
73
|
+
**1. Install**
|
|
74
|
+
```bash
|
|
75
|
+
pip install termjump
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**2. Add to your `~/.zshrc`**
|
|
79
|
+
```zsh
|
|
80
|
+
eval "$(termjump init)"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**3. Reload your shell**
|
|
84
|
+
```bash
|
|
85
|
+
source ~/.zshrc
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**4. Use it**
|
|
89
|
+
> Type any command โ press `Ctrl+E` โ click any character โ edit โ `Enter`
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## ๐ฎ How It Works
|
|
94
|
+
```
|
|
95
|
+
You type a command Press Ctrl+E Click a character
|
|
96
|
+
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
|
|
97
|
+
|
|
98
|
+
$ git commit -m โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
|
|
99
|
+
"fix autentication" โโโบ โ termjump โ โโโโโโโบ โ cursor jumps โ
|
|
100
|
+
โ editor โ click! โ exactly there โ
|
|
101
|
+
โโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
|
|
102
|
+
โ
|
|
103
|
+
โผ
|
|
104
|
+
Fix typo โ Enter
|
|
105
|
+
Command runs โ
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## โจ๏ธ Keyboard Shortcuts
|
|
111
|
+
|
|
112
|
+
| Key | Action |
|
|
113
|
+
|-----|--------|
|
|
114
|
+
| ๐ฑ๏ธ **Click** | Jump cursor instantly to any character |
|
|
115
|
+
| `โ` / `โ` | Move one character at a time |
|
|
116
|
+
| `Alt+โ` / `Alt+โ` | Jump one word |
|
|
117
|
+
| `Ctrl+A` | Jump to beginning of command |
|
|
118
|
+
| `Ctrl+E` | Jump to end of command |
|
|
119
|
+
| `Enter` | Confirm and run the command |
|
|
120
|
+
| `Esc` / `Ctrl+C` | Cancel โ original command stays untouched |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## โ๏ธ Configuration
|
|
125
|
+
|
|
126
|
+
**Change the trigger key** (default is `Ctrl+E`):
|
|
127
|
+
```zsh
|
|
128
|
+
# In your ~/.zshrc, after the eval line:
|
|
129
|
+
eval "$(termjump init)"
|
|
130
|
+
bindkey '^F' _termjump_widget # Ctrl+F instead
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## ๐ Requirements
|
|
136
|
+
|
|
137
|
+
- **Python** 3.10+
|
|
138
|
+
- **Shell** โ zsh (default on macOS since Catalina)
|
|
139
|
+
- **Terminal** with mouse support:
|
|
140
|
+
- โ
iTerm2
|
|
141
|
+
- โ
Kitty
|
|
142
|
+
- โ
WezTerm
|
|
143
|
+
- โ
macOS Terminal.app
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## ๐ค Contributing
|
|
148
|
+
|
|
149
|
+
PRs and issues are very welcome!
|
|
150
|
+
```bash
|
|
151
|
+
git clone https://github.com/srisowmya2000/termjump
|
|
152
|
+
cd termjump
|
|
153
|
+
pip install -e ".[dev]"
|
|
154
|
+
python tests/test_termjump.py
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
<div align="center">
|
|
160
|
+
<br>
|
|
161
|
+
<b>termjump</b> โ because arrow keys are not a navigation strategy.
|
|
162
|
+
<br><br>
|
|
163
|
+
Made with ๐ฑ๏ธ for everyone who has ever rage-retyped a long command.
|
|
164
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
termjump/__init__.py
|
|
4
|
+
termjump/cli.py
|
|
5
|
+
termjump/editor.py
|
|
6
|
+
termjump/shell.py
|
|
7
|
+
termjump.egg-info/PKG-INFO
|
|
8
|
+
termjump.egg-info/SOURCES.txt
|
|
9
|
+
termjump.egg-info/dependency_links.txt
|
|
10
|
+
termjump.egg-info/entry_points.txt
|
|
11
|
+
termjump.egg-info/requires.txt
|
|
12
|
+
termjump.egg-info/top_level.txt
|
|
13
|
+
tests/test_termjump.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
prompt_toolkit>=3.0.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
termjump
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import sys, os
|
|
2
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
3
|
+
from termjump.editor import tokenize_command
|
|
4
|
+
from termjump import __version__
|
|
5
|
+
|
|
6
|
+
def test_version():
|
|
7
|
+
assert __version__ == "0.1.0"
|
|
8
|
+
|
|
9
|
+
def test_tokenize_flags():
|
|
10
|
+
tokens = tokenize_command("ls --color -la")
|
|
11
|
+
assert any(c == "token.flag" for _, _, c in tokens)
|
|
12
|
+
|
|
13
|
+
def test_tokenize_empty():
|
|
14
|
+
assert tokenize_command("") == []
|
|
15
|
+
|
|
16
|
+
if __name__ == "__main__":
|
|
17
|
+
test_version()
|
|
18
|
+
test_tokenize_flags()
|
|
19
|
+
test_tokenize_empty()
|
|
20
|
+
print("All tests passed โ")
|