5 Commits
Author SHA1 Message Date
emmett1 53567c1f20 bookmark updated 2026-08-16 14:25:34 +08:00
emmett1 c6f4023768 updated 2026-08-16 11:52:05 +08:00
emmett1 cc0dbb0cad fix 2026-07-23 12:08:05 +08:00
emmett1 cd2a4dffb8 added permission error messsage, fix pane line, add root message if running as root 2026-06-20 16:07:40 +08:00
emmett1 40e5d2815c added cpp version, sh version as backup 2026-06-16 07:43:51 +08:00
6 changed files with 2627 additions and 30 deletions
+2
View File
@@ -0,0 +1,2 @@
CLAUDE.md
sfm
+18 -6
View File
@@ -5,33 +5,45 @@ BINDIR ?= $(PREFIX)/bin
MANDIR ?= $(PREFIX)/share/man/man1 MANDIR ?= $(PREFIX)/share/man/man1
DOCDIR ?= $(PREFIX)/share/doc/sfm DOCDIR ?= $(PREFIX)/share/doc/sfm
CXX ?= g++
CXXFLAGS ?= -std=c++17 -O2 -Wall -Wextra
# Pick a curses library: prefer ncursesw, fall back to ncurses, then plain
# curses (netbsd-curses and BSD base systems provide only libcurses).
CURSES_LIBS ?= $(shell pkg-config --libs ncursesw 2>/dev/null || pkg-config --libs ncurses 2>/dev/null || echo -lcurses)
LDLIBS ?= $(CURSES_LIBS)
INSTALL ?= install INSTALL ?= install
RM ?= rm -f RM ?= rm -f
.PHONY: all install uninstall clean .PHONY: all install uninstall clean
all: all: sfm
@echo "sfm is a shell script — nothing to build."
@echo "Run 'make install' to install."
install: sfm: sfm.cpp
$(CXX) $(CXXFLAGS) -o $@ $< $(LDLIBS)
install: all
@echo "Installing sfm to $(DESTDIR)$(BINDIR)/sfm ..." @echo "Installing sfm to $(DESTDIR)$(BINDIR)/sfm ..."
$(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -m 755 sfm $(DESTDIR)$(BINDIR)/sfm $(INSTALL) -m 755 sfm $(DESTDIR)$(BINDIR)/sfm
@echo "Installing sfm.sh to $(DESTDIR)$(BINDIR)/sfm.sh ..."
$(INSTALL) -m 755 sfm.sh $(DESTDIR)$(BINDIR)/sfm.sh
@echo "Installing man page to $(DESTDIR)$(MANDIR)/sfm.1 ..." @echo "Installing man page to $(DESTDIR)$(MANDIR)/sfm.1 ..."
$(INSTALL) -d $(DESTDIR)$(MANDIR) $(INSTALL) -d $(DESTDIR)$(MANDIR)
$(INSTALL) -m 644 sfm.1 $(DESTDIR)$(MANDIR)/sfm.1 $(INSTALL) -m 644 sfm.1 $(DESTDIR)$(MANDIR)/sfm.1
@echo "Installing README to $(DESTDIR)$(DOCDIR)/README ..." @echo "Installing README to $(DESTDIR)$(DOCDIR)/README ..."
$(INSTALL) -d $(DESTDIR)$(DOCDIR) $(INSTALL) -d $(DESTDIR)$(DOCDIR)
$(INSTALL) -m 644 README $(DESTDIR)$(DOCDIR)/README $(INSTALL) -m 644 README $(DESTDIR)$(DOCDIR)/README
@echo "Done. Run 'sfm' to start, or 'man sfm' for help." @echo "Done."
uninstall: uninstall:
@echo "Removing sfm ..." @echo "Removing sfm ..."
$(RM) $(DESTDIR)$(BINDIR)/sfm $(RM) $(DESTDIR)$(BINDIR)/sfm
$(RM) $(DESTDIR)$(BINDIR)/sfm.sh
$(RM) $(DESTDIR)$(MANDIR)/sfm.1 $(RM) $(DESTDIR)$(MANDIR)/sfm.1
$(RM) -r $(DESTDIR)$(DOCDIR) $(RM) -r $(DESTDIR)$(DOCDIR)
@echo "Done." @echo "Done."
clean: clean:
@echo "Nothing to clean." $(RM) sfm
@echo "Cleaned."
+27 -17
View File
@@ -4,16 +4,24 @@ sfm - Simple File Manager
DESCRIPTION DESCRIPTION
----------- -----------
sfm is a lightweight, terminal-based file manager written entirely in sfm is a lightweight, terminal-based file manager with a vim-inspired
POSIX sh. It runs in your terminal with no external dependencies beyond key layout. The primary version is a fast C++ binary that works with
standard Unix tools (ls, awk, tput, stty, mv, cp, rm). Designed to be both ncurses and netbsd-curses. A portable POSIX sh version (sfm.sh) is
fast, flicker-free, and keyboard-driven with a vim-inspired key layout. also included, requiring only standard Unix tools (ls, awk, tput, stty,
mv, cp, rm).
REQUIREMENTS REQUIREMENTS
------------ ------------
C++ version (sfm):
- A curses library: ncursesw, ncurses, or netbsd-curses (libcurses)
- A C++17 compiler (g++ or compatible)
Shell version (sfm.sh):
- A POSIX-compatible shell (sh, dash, bash, etc.) - A POSIX-compatible shell (sh, dash, bash, etc.)
- Standard Unix tools: ls, awk, tput, stty, cp, mv, rm, mkdir, touch - Standard Unix tools: ls, awk, tput, stty, cp, mv, rm, mkdir, touch
Both versions:
- Optional: wl-copy / xclip / xsel / pbcopy (for clipboard support) - Optional: wl-copy / xclip / xsel / pbcopy (for clipboard support)
- Optional: mpv, vlc, feh, zathura, etc. (for smart file opening) - Optional: mpv, vlc, feh, zathura, etc. (for smart file opening)
- Optional: readlink (for symlink display) - Optional: readlink (for symlink display)
@@ -23,21 +31,23 @@ REQUIREMENTS
INSTALLATION INSTALLATION
------------ ------------
Using make (recommended): Using make (recommended):
make install make install
This installs sfm to /usr/local/bin by default. To change the prefix: This builds the C++ binary and installs both sfm (C++ binary)
and sfm.sh (shell script) to /usr/local/bin by default.
To change the prefix:
make install PREFIX=/usr make install PREFIX=/usr
To uninstall: To uninstall:
make uninstall make uninstall
Manual installation: Manual installation (shell version only):
cp sfm /usr/local/bin/sfm cp sfm.sh /usr/local/bin/sfm.sh
chmod +x /usr/local/bin/sfm chmod +x /usr/local/bin/sfm.sh
USAGE USAGE
@@ -142,8 +152,8 @@ MULTI-SELECT
BOOKMARKS BOOKMARKS
--------- ---------
b Bookmark current directory (press again to remove) b Open bookmark picker (j/k navigate, enter jump, del remove)
B Open bookmark picker (j/k navigate, enter jump) B Bookmark current directory (press again to remove)
Bookmarks are saved to: ~/.config/sfm/bookmarks Bookmarks are saved to: ~/.config/sfm/bookmarks
+3 -3
View File
@@ -151,11 +151,11 @@ Multi-select works with
.SS Bookmarks .SS Bookmarks
.TP .TP
.B b .B b
Bookmark the current directory. Press again to remove it. Open the bookmark picker.
Use j/k to navigate, enter to jump, del to remove, esc to close.
.TP .TP
.B B .B B
Open the bookmark picker. Bookmark the current directory. Press again to remove it.
Use j/k to navigate, enter to jump, esc to close.
.SS Other .SS Other
.TP .TP
+2560
View File
File diff suppressed because it is too large Load Diff
+17 -4
View File
@@ -912,8 +912,8 @@ do_help() {
help_row 30 " + chmod +x (make executable)" help_row 30 " + chmod +x (make executable)"
help_row 31 " - chmod -x (remove executable)" help_row 31 " - chmod -x (remove executable)"
help_sep 32 help_sep 32
help_row 33 " b bookmark current dir" help_row 33 " b open bookmark picker"
help_row 34 " B open bookmark picker" help_row 34 " B bookmark current dir"
help_row 35 " c copy path to clipboard" help_row 35 " c copy path to clipboard"
help_row 36 " ~ go to home directory" help_row 36 " ~ go to home directory"
help_row 37 " \` jump to previous directory" help_row 37 " \` jump to previous directory"
@@ -1674,6 +1674,19 @@ do_bookmark_jump() {
fi fi
return ;; return ;;
'[D') NEED_FULL_REDRAW=1; return ;; # left — close '[D') NEED_FULL_REDRAW=1; return ;; # left — close
'[3') # delete — remove selected bookmark
IFS= read -r -n1 -t 0.05 _rest 2>/dev/null # swallow trailing ~
_chosen=$(awk -v n="$_bsel" 'NR==n&&NF{print;exit}' "$BOOKMARK_FILE")
if [ -n "$_chosen" ]; then
_tmp=$(grep -vxF "$_chosen" "$BOOKMARK_FILE")
printf '%s\n' "$_tmp" > "$BOOKMARK_FILE"
INFO_MSG="bookmark removed: ${_chosen}"
_bc=$((_bc-1))
if [ "$_bc" -eq 0 ]; then NEED_FULL_REDRAW=1; return; fi
[ "$_bsel" -gt "$_bc" ] && _bsel=$_bc
[ "$_bsel" -lt "$_boff" ] && _boff=$_bsel
[ "$_bsel" -ge $((_boff + _bvis)) ] && _boff=$((_bsel - _bvis + 1))
fi ;;
*) NEED_FULL_REDRAW=1; return ;; # bare esc — close *) NEED_FULL_REDRAW=1; return ;; # bare esc — close
esac ;; esac ;;
"$(printf '\n')"|\ "$(printf '\n')"|\
@@ -1829,8 +1842,8 @@ while true; do
l) do_open ;; l) do_open ;;
"$(printf '\033[D')"|\ "$(printf '\033[D')"|\
h) do_go_back ;; h) do_go_back ;;
b) do_bookmark_add ;; b) do_bookmark_jump ;;
B) do_bookmark_jump ;; B) do_bookmark_add ;;
'?') do_help ;; '?') do_help ;;
R) load_entries; INFO_MSG="refreshed" ;; R) load_entries; INFO_MSG="refreshed" ;;
/) do_search ;; /) do_search ;;