colors, ../ och -a
This commit is contained in:
@@ -28,3 +28,7 @@
|
||||
- Cursor can now move to the empty line immediately below the last object.
|
||||
- `Ctrl+K K` now behaves like joe: the block end is the row immediately above the cursor.
|
||||
- On the bottom empty line, `Ctrl+K K` therefore selects through the last object.
|
||||
|
||||
## v2 update
|
||||
- The bottom empty row now visibly shows the cursor.
|
||||
- When TUI exits normally, the shell integration changes the parent Bash shell to the directory where TUI was closed.
|
||||
|
||||
@@ -44,19 +44,31 @@ tui() {
|
||||
fi
|
||||
rc=$?
|
||||
|
||||
if (( rc != 42 )); then
|
||||
rm -f "$command_file" "$cwd_file"
|
||||
return "$rc"
|
||||
fi
|
||||
|
||||
tui_cwd="$(<"$cwd_file")"
|
||||
|
||||
if [[ -z "$tui_cwd" || ! -d "$tui_cwd" ]]; then
|
||||
if (( rc != 42 )); then
|
||||
rm -f "$command_file" "$cwd_file"
|
||||
return "$rc"
|
||||
fi
|
||||
echo "tui: invalid TUI working directory" >&2
|
||||
rm -f "$command_file" "$cwd_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# A normal TUI exit means the user wants to leave TUI. Change the
|
||||
# parent Bash shell to the directory where TUI was actually closed.
|
||||
if (( rc != 42 )); then
|
||||
if (( rc == 0 )); then
|
||||
cd "$tui_cwd" || {
|
||||
rm -f "$command_file" "$cwd_file"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
rm -f "$command_file" "$cwd_file"
|
||||
return "$rc"
|
||||
fi
|
||||
|
||||
# Execute all commands belonging to one TUI action before starting
|
||||
# TUI again. Each command remains a normal Bash command and gets its
|
||||
# own history entry. If a command fails, stop the action and pause so
|
||||
|
||||
115
tui/tui.py
115
tui/tui.py
@@ -443,10 +443,12 @@ def draw(stdscr, browser, status=""):
|
||||
text = entry.name + ("/" if entry.is_dir() else "")
|
||||
else:
|
||||
# One empty line after the final object, matching the cursor range.
|
||||
# A literal space is needed here: curses does not draw attributes
|
||||
# for an empty string, so the cursor would otherwise be invisible.
|
||||
entry = None
|
||||
is_marked = False
|
||||
attrs = curses.A_NORMAL
|
||||
text = ""
|
||||
text = " "
|
||||
|
||||
if index == browser.cursor:
|
||||
attrs |= curses.A_UNDERLINE
|
||||
@@ -502,6 +504,18 @@ def run(stdscr, start_dir=".", show_all=False):
|
||||
|
||||
status = ""
|
||||
|
||||
def save_cwd():
|
||||
cwd_file = os.environ.get("TUI_CWD_FILE")
|
||||
if cwd_file:
|
||||
try:
|
||||
Path(cwd_file).write_text(str(browser.path), encoding="utf-8")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# Always leave the shell wrapper with the directory in which TUI was
|
||||
# actually closed, not merely the directory of the last action.
|
||||
save_cwd()
|
||||
|
||||
def configured_action(key):
|
||||
if key == curses.KEY_UP:
|
||||
return browser.resolve_key_action(["up"], browser.selected())
|
||||
@@ -522,62 +536,65 @@ def run(stdscr, start_dir=".", show_all=False):
|
||||
|
||||
return None
|
||||
|
||||
while True:
|
||||
draw(stdscr, browser, status)
|
||||
status = ""
|
||||
try:
|
||||
while True:
|
||||
draw(stdscr, browser, status)
|
||||
status = ""
|
||||
|
||||
key = stdscr.getch()
|
||||
key = stdscr.getch()
|
||||
|
||||
if key == 11: # Ctrl-K
|
||||
action, message = read_ctrl_k(stdscr, browser)
|
||||
if key == 11: # Ctrl-K
|
||||
action, message = read_ctrl_k(stdscr, browser)
|
||||
|
||||
if action == "mark-begin":
|
||||
browser.mark_begin()
|
||||
elif action == "mark-end":
|
||||
browser.mark_end()
|
||||
if action == "mark-begin":
|
||||
browser.mark_begin()
|
||||
elif action == "mark-end":
|
||||
browser.mark_end()
|
||||
elif action:
|
||||
result = browser.execute_action(
|
||||
action,
|
||||
stdscr,
|
||||
marked_only=True,
|
||||
)
|
||||
if result == SHELL_HANDOFF:
|
||||
return SHELL_HANDOFF
|
||||
if result is False:
|
||||
return
|
||||
else:
|
||||
status = message
|
||||
continue
|
||||
|
||||
# Left is navigation, not an action: first move the cursor to the
|
||||
# parent entry; pressing left again enters that parent. This also
|
||||
# makes the parent entry visible at the top of every directory.
|
||||
if key == curses.KEY_LEFT:
|
||||
if browser.cursor == 0:
|
||||
if browser.parent() is False:
|
||||
return
|
||||
else:
|
||||
browser.cursor = 0
|
||||
continue
|
||||
|
||||
action = configured_action(key)
|
||||
|
||||
if action == "up":
|
||||
browser.move(-1)
|
||||
elif action == "down":
|
||||
browser.move(1)
|
||||
elif action == "enter":
|
||||
if browser.enter() is False:
|
||||
return
|
||||
elif action == "parent":
|
||||
if browser.parent() is False:
|
||||
return
|
||||
elif action:
|
||||
result = browser.execute_action(
|
||||
action,
|
||||
stdscr,
|
||||
marked_only=True,
|
||||
)
|
||||
result = browser.execute_action(action, stdscr)
|
||||
if result == SHELL_HANDOFF:
|
||||
return SHELL_HANDOFF
|
||||
if result is False:
|
||||
return
|
||||
else:
|
||||
status = message
|
||||
continue
|
||||
|
||||
# Left is navigation, not an action: first move the cursor to the
|
||||
# parent entry; pressing left again enters that parent. This also
|
||||
# makes the parent entry visible at the top of every directory.
|
||||
if key == curses.KEY_LEFT:
|
||||
if browser.cursor == 0:
|
||||
if browser.parent() is False:
|
||||
return
|
||||
else:
|
||||
browser.cursor = 0
|
||||
continue
|
||||
|
||||
action = configured_action(key)
|
||||
|
||||
if action == "up":
|
||||
browser.move(-1)
|
||||
elif action == "down":
|
||||
browser.move(1)
|
||||
elif action == "enter":
|
||||
if browser.enter() is False:
|
||||
return
|
||||
elif action == "parent":
|
||||
if browser.parent() is False:
|
||||
return
|
||||
elif action:
|
||||
result = browser.execute_action(action, stdscr)
|
||||
if result == SHELL_HANDOFF:
|
||||
return SHELL_HANDOFF
|
||||
if result is False:
|
||||
return
|
||||
finally:
|
||||
save_cwd()
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
Reference in New Issue
Block a user