shfm/README

184 lines
4.7 KiB
Plaintext
Raw Normal View History

2020-08-04 00:24:58 +02:00
shfm
2020-08-03 15:30:38 +02:00
________________________________________________________________________________
2020-08-04 00:24:58 +02:00
file manager written in posix shell
2020-08-03 15:30:38 +02:00
2020-08-04 10:17:36 +02:00
screenshot: https://user-images.githubusercontent.com/6799467/89270554-2b40ab00-d644-11ea-9f2b-bdabcba61a09.png
2020-08-03 15:35:13 +02:00
features
________________________________________________________________________________
2020-08-04 00:23:27 +02:00
* no dependencies other than a POSIX shell + POSIX printf, dd and stty
* tiny
* single file
* no compilation needed
2020-08-03 15:36:58 +02:00
2020-08-03 15:35:13 +02:00
2020-08-03 15:38:13 +02:00
keybinds
________________________________________________________________________________
j - down
k - up
l - open file or directory
h - go up level
2020-08-03 22:00:36 +02:00
g - go to top
G - go to bottom
2020-08-03 15:38:13 +02:00
q - quit
2020-08-03 23:17:56 +02:00
: - cd to <input>
2020-08-03 23:27:28 +02:00
/ - search current directory *<input>*
2020-08-04 00:02:11 +02:00
- - go to last directory
~ - go home
! - spawn shell
2020-08-04 00:09:15 +02:00
. - toggle hidden files
2020-08-03 22:33:13 +02:00
2020-08-04 01:00:49 +02:00
todo
________________________________________________________________________________
- [ ] sanitize filenames for display.
- [ ] fix buggy focus after exit from inline editor.
2020-08-04 10:17:36 +02:00
- [ ] maybe file operations.
- [ ] add / to directories.
- [ ] use clearer variable names.
2020-08-04 01:00:49 +02:00
2020-08-03 22:33:13 +02:00
opener
________________________________________________________________________________
2020-08-03 22:37:58 +02:00
Opening files in different applications (based on mime-type or file extension)
2020-08-03 22:33:13 +02:00
can be achieved via an environment variable (SHFM_OPENER) set to the location of
2020-08-03 22:37:58 +02:00
a small external script. If unset, the default for all files is '$EDITOR' (and
if that is unset, 'vi').
2020-08-03 22:33:13 +02:00
The script receives a single argument, the full path to the selected file.
2020-08-03 22:36:48 +02:00
The opener script is also useful on the command-line. The environment variable
is set as follows.
export SHFM_OPENER=/path/to/script
2020-08-03 22:33:13 +02:00
Example scripts:
#!/bin/sh -e
#
# open file in application based on file extension
case $1 in
*.mp3|*.flac|*.wav)
mpv --no-video "$1"
;;
*.mp4|*.mkv|*.webm)
mpv "$1"
;;
*.png|*.gif||*.jpg|*.jpe|*.jpeg)
gimp "$1"
;;
*.html|*.pdf)
firefox "$1"
;;
# all other files
*)
"${EDITOR:=vi}" "$1"
;;
esac
#!/bin/sh -e
#
# open file in application based on mime-type
mime_type=$(file -bi)
case $mime_type in
audio/*)
mpv --no-video "$1"
;;
video/*)
mpv "$1"
;;
image/*)
gimp "$1"
;;
text/html*|application/pdf*)
firefox "$1"
;;
text/*|)
"${EDITOR:=vi}" "$1"
;;
*)
printf 'unknown mime-type %s\n' "$mime_type"
;;
esac
2020-08-04 01:00:49 +02:00
2020-08-04 09:34:33 +02:00
implementation details
________________________________________________________________________________
* Draws are partial!
The file manager will only redraw what is necessary. Every line scrolled
corresponds to three lines being redrawn. The current line (clear highlight),
the destination line (set highlight) and the status line (update location).
* POSIX shell has no arrays.
It does however have an argument list (used for passing command-line arguments
to the script and when calling functions).
Restrictions:
- Can only have one list at a time (in the same scope).
- Can restrict a list's scope but cannot extend it.
- Cannot grab element by index.
Things I'm thankful for:
- Elements can be "popped" off the front of the list (using shift).
- List size is given to us (via $#).
- No need to use a string delimited by some character.
- Can loop over elements.
* Cursor position is tracked manually.
Grabbing the current cursor position cannot be done reliably from POSIX shell.
Instead, the cursor starts at 0,0 and each movement modifies the value of a
variable (relative Y position in screen). This variable is how the file
manager knows which line of the screen the cursor is on.
* Multi-byte input is handled by using a 2D case statement.
(I don't really know what to call this, suggestions appreciated)
Rather than using read timeouts (we can't sleep < 1s in POSIX shell anyway)
to handle multi-byte input, shfm tracks location within sequences and handles
this in a really nice way.
The case statement matches "$char$esc" with "$esc" being an integer holding
position in sequences. To give an example, down arrow emits '\033[B'.
- When '\033?' is found, the value of 'esc' is set to '1'.
- When '[1' is found, the value of 'esc' is set to '2'.
- When 'B2' is found, we know it's '\033[B' and handle down arrow.
- If input doesn't follow this sequence, 'esc' is reset to '0'.
* There is no usage of '[' or 'test'.
Despite these being commonly provided as "shell builtins" (part of the shell),
a lot of shells still use the external utilities from the coreutils. All usage
of these has been replaced with 'case' as it is always a "shell keyword".