0
# User Interface and Interaction
1
2
Interactive command selection, keyboard input handling, and user confirmation interfaces for selecting and executing corrections. The UI system provides cross-platform terminal interaction with intuitive navigation and selection capabilities.
3
4
## Capabilities
5
6
### Interactive Command Selection
7
8
Core class for managing command selection with keyboard navigation.
9
10
```python { .api }
11
class CommandSelector:
12
"""
13
Interactive command selection with navigation.
14
15
Provides navigation through multiple command corrections with
16
keyboard controls and change event handling.
17
"""
18
19
def __init__(self, commands):
20
"""
21
Initialize command selector.
22
23
Parameters:
24
- commands (SortedCorrectedCommandsSequence): Available corrections
25
"""
26
27
def next(self):
28
"""
29
Move to next command in the list.
30
31
Wraps around to first command when reaching the end.
32
Triggers change callback with new selection.
33
"""
34
35
def previous(self):
36
"""
37
Move to previous command in the list.
38
39
Wraps around to last command when at the beginning.
40
Triggers change callback with new selection.
41
"""
42
43
@property
44
def value(self):
45
"""
46
Get currently selected command.
47
48
Returns:
49
CorrectedCommand: Currently selected correction
50
"""
51
52
def on_change(self, fn):
53
"""
54
Register callback for selection changes.
55
56
Parameters:
57
- fn (callable): Function to call when selection changes
58
59
The callback receives the new selected command as parameter.
60
"""
61
```
62
63
### Input and Action Processing
64
65
Functions for handling keyboard input and converting to user actions.
66
67
```python { .api }
68
def getch():
69
"""
70
Cross-platform single character input without echo.
71
72
Returns:
73
str: Single character from keyboard input
74
75
Raises:
76
KeyboardInterrupt: When Ctrl+C is pressed
77
78
Platform-specific implementation:
79
- Windows: Uses msvcrt.getch()
80
- Unix/Linux/macOS: Uses termios for raw input
81
"""
82
83
def read_actions():
84
"""
85
Generator yielding actions for pressed keys.
86
87
Yields:
88
int: Action constants (SELECT, ABORT, PREVIOUS, NEXT)
89
90
Key mappings:
91
- Enter/Return: SELECT
92
- Ctrl+C: ABORT
93
- Up Arrow: PREVIOUS
94
- Down Arrow: NEXT
95
"""
96
```
97
98
### Main Selection Interface Function
99
100
High-level function for complete command selection workflow.
101
102
```python { .api }
103
def select_command(corrected_commands, settings):
104
"""
105
Interactive command selection interface.
106
107
Parameters:
108
- corrected_commands (SortedCorrectedCommandsSequence): Available corrections
109
- settings (Settings): Application settings
110
111
Returns:
112
CorrectedCommand or None: Selected command or None if aborted
113
114
Behavior:
115
- Returns first command immediately if require_confirmation=False
116
- Returns None if no corrections available
117
- Provides interactive selection if require_confirmation=True
118
- Handles user abort (Ctrl+C) gracefully
119
120
Interactive controls:
121
- Enter: Select current command
122
- Up/Down arrows: Navigate between options
123
- Ctrl+C: Abort selection
124
"""
125
```
126
127
### Action Constants
128
129
User action constants for keyboard input interpretation.
130
131
```python { .api }
132
SELECT = 0
133
"""Action constant for selecting current command (Enter key)."""
134
135
ABORT = 1
136
"""Action constant for aborting selection (Ctrl+C)."""
137
138
PREVIOUS = 2
139
"""Action constant for moving to previous command (Up arrow)."""
140
141
NEXT = 3
142
"""Action constant for moving to next command (Down arrow)."""
143
```
144
145
## Usage Examples
146
147
### Basic Command Selection
148
149
```python
150
from thefuck.ui import select_command
151
from thefuck.corrector import get_corrected_commands
152
from thefuck.types import Command
153
154
# Setup (assuming settings and user_dir are available)
155
command = Command("git pussh origin main", "", "git: 'pussh' is not a git command")
156
corrections = get_corrected_commands(command, user_dir, settings)
157
158
# Interactive selection
159
selected = select_command(corrections, settings)
160
161
if selected:
162
print(f"User selected: {selected.script}")
163
else:
164
print("User aborted selection")
165
```
166
167
### Manual Command Selector Usage
168
169
```python
170
from thefuck.ui import CommandSelector
171
from thefuck.types import CorrectedCommand
172
173
# Create some example corrections
174
corrections = [
175
CorrectedCommand("git push origin main", None, 1000),
176
CorrectedCommand("git push origin master", None, 1100),
177
CorrectedCommand("git push --set-upstream origin main", None, 1200)
178
]
179
180
# Create selector
181
selector = CommandSelector(corrections)
182
183
# Set up change handler
184
def on_selection_change(command):
185
print(f"Now selected: {command.script}")
186
187
selector.on_change(on_selection_change)
188
189
# Navigate programmatically
190
print(f"Initial: {selector.value.script}")
191
selector.next()
192
print(f"After next: {selector.value.script}")
193
selector.previous()
194
print(f"After previous: {selector.value.script}")
195
```
196
197
### Custom Input Processing
198
199
```python
200
from thefuck.ui import read_actions, SELECT, ABORT, PREVIOUS, NEXT
201
202
# Process user input manually
203
print("Use arrow keys to navigate, Enter to select, Ctrl+C to abort:")
204
205
for action in read_actions():
206
if action == SELECT:
207
print("User selected current option")
208
break
209
elif action == ABORT:
210
print("User aborted")
211
break
212
elif action == PREVIOUS:
213
print("User wants previous option")
214
elif action == NEXT:
215
print("User wants next option")
216
```
217
218
### Settings-Aware Selection
219
220
```python
221
from thefuck.ui import select_command
222
from thefuck.types import Settings
223
224
# Create settings that skip confirmation
225
settings = Settings({
226
'require_confirmation': False,
227
'no_colors': False
228
})
229
230
# This will return first correction immediately without user interaction
231
selected = select_command(corrections, settings)
232
print(f"Auto-selected: {selected.script}")
233
234
# Enable confirmation for interactive selection
235
interactive_settings = settings.update(require_confirmation=True)
236
selected = select_command(corrections, interactive_settings)
237
```
238
239
## Platform Compatibility
240
241
The UI system handles cross-platform differences transparently:
242
243
### Windows Support
244
- Uses `msvcrt.getch()` for character input
245
- Handles Windows-specific key codes
246
- Supports standard Windows terminal behavior
247
248
### Unix/Linux/macOS Support
249
- Uses `termios` and `tty` modules for raw input
250
- Handles ANSI escape sequences for arrow keys
251
- Maintains terminal state properly
252
- Supports various terminal emulators
253
254
### Common Features
255
- Ctrl+C handling for graceful interruption
256
- Arrow key navigation (↑/↓)
257
- Enter key selection
258
- No echo during input
259
- Proper cleanup of terminal state
260
261
## Display Integration
262
263
The UI system integrates with the logging system for display:
264
265
### Visual Feedback
266
- Shows current selection highlighting
267
- Displays navigation instructions
268
- Provides confirmation prompts
269
- Shows error messages for no corrections
270
271
### Color Support
272
- Respects `no_colors` setting
273
- Uses colored output when available
274
- Falls back gracefully on non-color terminals
275
276
## Error Handling
277
278
The UI system handles various error conditions:
279
280
- **No corrections available**: Shows appropriate message and returns None
281
- **Keyboard interrupt**: Catches Ctrl+C and returns None gracefully
282
- **Terminal errors**: Handles terminal state restoration on errors
283
- **Invalid input**: Ignores unrecognized keystrokes
284
- **Empty command lists**: Handles gracefully without crashing
285
286
## Accessibility
287
288
The interface provides good accessibility:
289
290
- **Keyboard-only navigation**: No mouse required
291
- **Clear feedback**: Visual and textual confirmation of actions
292
- **Standard key mappings**: Uses common terminal navigation patterns
293
- **Escape options**: Always provides way to abort
294
- **Simple interface**: Minimal learning curve for users