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.
|
- 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.
|
- `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.
|
- 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
|
fi
|
||||||
rc=$?
|
rc=$?
|
||||||
|
|
||||||
if (( rc != 42 )); then
|
|
||||||
rm -f "$command_file" "$cwd_file"
|
|
||||||
return "$rc"
|
|
||||||
fi
|
|
||||||
|
|
||||||
tui_cwd="$(<"$cwd_file")"
|
tui_cwd="$(<"$cwd_file")"
|
||||||
|
|
||||||
if [[ -z "$tui_cwd" || ! -d "$tui_cwd" ]]; then
|
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
|
echo "tui: invalid TUI working directory" >&2
|
||||||
rm -f "$command_file" "$cwd_file"
|
rm -f "$command_file" "$cwd_file"
|
||||||
return 1
|
return 1
|
||||||
fi
|
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
|
# Execute all commands belonging to one TUI action before starting
|
||||||
# TUI again. Each command remains a normal Bash command and gets its
|
# 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
|
# 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 "")
|
text = entry.name + ("/" if entry.is_dir() else "")
|
||||||
else:
|
else:
|
||||||
# One empty line after the final object, matching the cursor range.
|
# 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
|
entry = None
|
||||||
is_marked = False
|
is_marked = False
|
||||||
attrs = curses.A_NORMAL
|
attrs = curses.A_NORMAL
|
||||||
text = ""
|
text = " "
|
||||||
|
|
||||||
if index == browser.cursor:
|
if index == browser.cursor:
|
||||||
attrs |= curses.A_UNDERLINE
|
attrs |= curses.A_UNDERLINE
|
||||||
@@ -502,6 +504,18 @@ def run(stdscr, start_dir=".", show_all=False):
|
|||||||
|
|
||||||
status = ""
|
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):
|
def configured_action(key):
|
||||||
if key == curses.KEY_UP:
|
if key == curses.KEY_UP:
|
||||||
return browser.resolve_key_action(["up"], browser.selected())
|
return browser.resolve_key_action(["up"], browser.selected())
|
||||||
@@ -522,62 +536,65 @@ def run(stdscr, start_dir=".", show_all=False):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
while True:
|
try:
|
||||||
draw(stdscr, browser, status)
|
while True:
|
||||||
status = ""
|
draw(stdscr, browser, status)
|
||||||
|
status = ""
|
||||||
|
|
||||||
key = stdscr.getch()
|
key = stdscr.getch()
|
||||||
|
|
||||||
if key == 11: # Ctrl-K
|
if key == 11: # Ctrl-K
|
||||||
action, message = read_ctrl_k(stdscr, browser)
|
action, message = read_ctrl_k(stdscr, browser)
|
||||||
|
|
||||||
if action == "mark-begin":
|
if action == "mark-begin":
|
||||||
browser.mark_begin()
|
browser.mark_begin()
|
||||||
elif action == "mark-end":
|
elif action == "mark-end":
|
||||||
browser.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:
|
elif action:
|
||||||
result = browser.execute_action(
|
result = browser.execute_action(action, stdscr)
|
||||||
action,
|
|
||||||
stdscr,
|
|
||||||
marked_only=True,
|
|
||||||
)
|
|
||||||
if result == SHELL_HANDOFF:
|
if result == SHELL_HANDOFF:
|
||||||
return SHELL_HANDOFF
|
return SHELL_HANDOFF
|
||||||
if result is False:
|
if result is False:
|
||||||
return
|
return
|
||||||
else:
|
finally:
|
||||||
status = message
|
save_cwd()
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
Reference in New Issue
Block a user