N/A
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## 3.2.0
|
||||
|
||||
- Floating menu is anchored near the current cursor item instead of a fixed screen position.
|
||||
- Added configurable archive, file, folder, shell and file-information menu actions.
|
||||
- Added Pack as ZIP and Pack as tar.gz.
|
||||
- Added Extract archive here for common archive formats.
|
||||
- Added Rename, New folder, New file, Open shell here, SHA-256 and File information.
|
||||
- Added generic `archive` menu condition.
|
||||
- All menu entries remain configurable in `.tui`.
|
||||
|
||||
|
||||
## 3.1.0
|
||||
|
||||
- Added floating action menu rendered over the browser without clearing the underlying file list.
|
||||
|
||||
132
tui/example.tui
132
tui/example.tui
@@ -1,5 +1,4 @@
|
||||
# TUI configuration. The Python program only provides the generic UI engine;
|
||||
# actions, labels, shortcuts and context-specific menu entries live here.
|
||||
# TUI configuration. UI behavior, labels, shortcuts and actions belong here.
|
||||
|
||||
keys:
|
||||
up: up
|
||||
@@ -13,7 +12,6 @@ keys:
|
||||
folder: enter
|
||||
file:
|
||||
- "*.zip": list-zip
|
||||
- "*.md": view
|
||||
|
||||
enter:
|
||||
folder: enter
|
||||
@@ -39,14 +37,6 @@ keys:
|
||||
folder:
|
||||
- "*": delete
|
||||
|
||||
# M opens this menu. The menu is entirely data-driven.
|
||||
#
|
||||
# selection: auto -> marked objects if there are marks, otherwise current object
|
||||
# selection: current -> always current object
|
||||
# selection: marked -> only when there is a marked selection
|
||||
# selection: none -> action runs in the current directory, without a target
|
||||
#
|
||||
# when: git means this directory is inside a Git worktree.
|
||||
menu:
|
||||
- label: "View"
|
||||
key: v
|
||||
@@ -58,6 +48,13 @@ menu:
|
||||
action: edit
|
||||
when: file
|
||||
|
||||
- label: "List archive"
|
||||
key: l
|
||||
action: list-zip
|
||||
when:
|
||||
- file
|
||||
- glob:*.zip
|
||||
|
||||
- separator: true
|
||||
|
||||
- label: "Copy"
|
||||
@@ -75,6 +72,56 @@ menu:
|
||||
action: delete
|
||||
selection: auto
|
||||
|
||||
- label: "Rename"
|
||||
key: r
|
||||
action: rename
|
||||
selection: current
|
||||
|
||||
- separator: true
|
||||
|
||||
- label: "Pack as ZIP"
|
||||
key: z
|
||||
action: pack-zip
|
||||
selection: auto
|
||||
|
||||
- label: "Pack as tar.gz"
|
||||
key: t
|
||||
action: pack-targz
|
||||
selection: auto
|
||||
|
||||
- label: "Extract archive here"
|
||||
key: x
|
||||
action: extract
|
||||
when: archive
|
||||
selection: current
|
||||
|
||||
- separator: true
|
||||
|
||||
- label: "New folder"
|
||||
key: n
|
||||
action: new-folder
|
||||
selection: none
|
||||
|
||||
- label: "New file"
|
||||
key: f
|
||||
action: new-file
|
||||
selection: none
|
||||
|
||||
- label: "Open shell here"
|
||||
key: s
|
||||
action: shell
|
||||
selection: none
|
||||
|
||||
- label: "SHA-256"
|
||||
key: h
|
||||
action: sha256
|
||||
selection: auto
|
||||
|
||||
- label: "File information"
|
||||
key: i
|
||||
action: info
|
||||
selection: auto
|
||||
|
||||
- separator: true
|
||||
|
||||
- label: "Git: Status"
|
||||
@@ -88,6 +135,11 @@ menu:
|
||||
selection: none
|
||||
when: git
|
||||
|
||||
- label: "Git: Add -A"
|
||||
action: git-add
|
||||
selection: none
|
||||
when: git
|
||||
|
||||
- label: "Git: Diff"
|
||||
action: git-diff
|
||||
selection: none
|
||||
@@ -98,11 +150,6 @@ menu:
|
||||
selection: none
|
||||
when: git
|
||||
|
||||
- label: "Git: Add -A"
|
||||
action: git-add
|
||||
selection: none
|
||||
when: git
|
||||
|
||||
- label: "Git: Commit"
|
||||
action: git-commit
|
||||
selection: none
|
||||
@@ -120,21 +167,54 @@ actions:
|
||||
- read -rp "Press Enter to continue..."
|
||||
|
||||
copy:
|
||||
command: cp -v <path> <dir>copy_<name>
|
||||
command: cp -v -- <path> <dir>copy_<name>
|
||||
|
||||
move:
|
||||
command: mv -v <path> <dir>
|
||||
command: mv -v -- <path> <dir>
|
||||
|
||||
delete:
|
||||
command: rm -v <path>
|
||||
command: rm -v -- <path>
|
||||
|
||||
edit:
|
||||
command: joe <path>
|
||||
rename:
|
||||
command: 'read -rp "New name for <name>: " new_name && mv -v -- <path> "<dir>$new_name"'
|
||||
|
||||
view:
|
||||
command: less <path>
|
||||
|
||||
# target: none means that the action runs once in the current TUI folder.
|
||||
edit:
|
||||
command: joe <path>
|
||||
|
||||
pack-zip:
|
||||
command: 'zip -r "<dir><name>.zip" <path>'
|
||||
|
||||
pack-targz:
|
||||
command: 'tar -czvf "<dir><name>.tar.gz" <name>'
|
||||
|
||||
extract:
|
||||
command:
|
||||
- 'case "<path>" in *.zip) unzip -o -- <path> -d <dir> ;; *.tar.gz|*.tgz) tar -xzvf <path> -C <dir> ;; *.tar.bz2|*.tbz2) tar -xjvf <path> -C <dir> ;; *.tar.xz|*.txz) tar -xJvf <path> -C <dir> ;; *.tar) tar -xvf <path> -C <dir> ;; *.7z) 7z x <path> -o<dir> ;; *.rar) unrar x <path> <dir> ;; *) echo "Unsupported archive: <path>"; false ;; esac'
|
||||
- read -rp "Press Enter to continue..."
|
||||
|
||||
new-folder:
|
||||
target: none
|
||||
command: 'read -rp "Folder name: " name && mkdir -pv -- "$name"'
|
||||
|
||||
new-file:
|
||||
target: none
|
||||
command: 'read -rp "File name: " name && touch -- "$name"'
|
||||
|
||||
shell:
|
||||
target: none
|
||||
command: 'bash'
|
||||
|
||||
sha256:
|
||||
command: sha256sum <path>
|
||||
|
||||
info:
|
||||
command:
|
||||
- 'stat -- <path>'
|
||||
- read -rp "Press Enter to continue..."
|
||||
|
||||
git-status:
|
||||
target: none
|
||||
command: git status
|
||||
@@ -143,6 +223,10 @@ actions:
|
||||
target: none
|
||||
command: git pull
|
||||
|
||||
git-add:
|
||||
target: none
|
||||
command: git add -A
|
||||
|
||||
git-diff:
|
||||
target: none
|
||||
command: git diff
|
||||
@@ -151,10 +235,6 @@ actions:
|
||||
target: none
|
||||
command: git log --oneline --decorate -20
|
||||
|
||||
git-add:
|
||||
target: none
|
||||
command: git add -A
|
||||
|
||||
git-commit:
|
||||
target: none
|
||||
command: git commit
|
||||
|
||||
23
tui/tui.py
23
tui/tui.py
@@ -6,7 +6,7 @@ import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
TUI_VERSION = "3.1.0"
|
||||
TUI_VERSION = "3.2.0"
|
||||
SHELL_HANDOFF = 42
|
||||
TUI_EXIT = 43
|
||||
|
||||
@@ -146,6 +146,14 @@ class TuiConfig:
|
||||
if condition == "folder":
|
||||
target = browser.selected()
|
||||
return bool(target and target.is_dir())
|
||||
if condition == "archive":
|
||||
target = browser.selected()
|
||||
if not target or not target.is_file():
|
||||
return False
|
||||
return target.suffix.lower() in {
|
||||
".zip", ".tar", ".gz", ".tgz", ".bz2", ".tbz2",
|
||||
".xz", ".txz", ".7z", ".rar",
|
||||
} or target.name.lower().endswith((".tar.gz", ".tar.bz2", ".tar.xz"))
|
||||
if condition == "marked":
|
||||
return bool(browser.marked)
|
||||
if condition == "multiple":
|
||||
@@ -579,7 +587,18 @@ def show_menu(stdscr, browser):
|
||||
menu_top = max(1, cursor_screen_row - menu_rows - 1)
|
||||
if menu_top + menu_rows > height - 1:
|
||||
menu_top = max(1, height - 1 - menu_rows)
|
||||
menu_left = max(1, min((width - menu_width) // 2, width - menu_width - 1))
|
||||
# Anchor the floating menu near the current item rather than at a
|
||||
# fixed screen position. The current row remains visible because the
|
||||
# menu starts after the item's text when there is enough room.
|
||||
if browser.cursor == 0:
|
||||
cursor_text = "../" if browser.path != browser.root else "./"
|
||||
elif 1 <= browser.cursor <= len(browser.entries):
|
||||
current = browser.entries[browser.cursor - 1]
|
||||
cursor_text = current.name + ("/" if current.is_dir() else "")
|
||||
else:
|
||||
cursor_text = ""
|
||||
preferred_left = min(max(2, len(cursor_text) + 3), max(2, width - menu_width - 2))
|
||||
menu_left = max(1, min(preferred_left, width - menu_width - 1))
|
||||
|
||||
win = curses.newwin(menu_rows, menu_width, menu_top, menu_left)
|
||||
win.keypad(True)
|
||||
|
||||
Reference in New Issue
Block a user