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
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
RM ?= rm -f
.PHONY: all install uninstall clean
all:
@echo "sfm is a shell script — nothing to build."
@echo "Run 'make install' to install."
all: sfm
install:
sfm: sfm.cpp
$(CXX) $(CXXFLAGS) -o $@ $< $(LDLIBS)
install: all
@echo "Installing sfm to $(DESTDIR)$(BINDIR)/sfm ..."
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(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 ..."
$(INSTALL) -d $(DESTDIR)$(MANDIR)
$(INSTALL) -m 644 sfm.1 $(DESTDIR)$(MANDIR)/sfm.1
@echo "Installing README to $(DESTDIR)$(DOCDIR)/README ..."
$(INSTALL) -d $(DESTDIR)$(DOCDIR)
$(INSTALL) -m 644 README $(DESTDIR)$(DOCDIR)/README
@echo "Done. Run 'sfm' to start, or 'man sfm' for help."
@echo "Done."
uninstall:
@echo "Removing sfm ..."
$(RM) $(DESTDIR)$(BINDIR)/sfm
$(RM) $(DESTDIR)$(BINDIR)/sfm.sh
$(RM) $(DESTDIR)$(MANDIR)/sfm.1
$(RM) -r $(DESTDIR)$(DOCDIR)
@echo "Done."
clean:
@echo "Nothing to clean."
$(RM) sfm
@echo "Cleaned."
+20 -10
View File
@@ -4,16 +4,24 @@ sfm - Simple File Manager
DESCRIPTION
-----------
sfm is a lightweight, terminal-based file manager written entirely in
POSIX sh. It runs in your terminal with no external dependencies beyond
standard Unix tools (ls, awk, tput, stty, mv, cp, rm). Designed to be
fast, flicker-free, and keyboard-driven with a vim-inspired key layout.
sfm is a lightweight, terminal-based file manager with a vim-inspired
key layout. The primary version is a fast C++ binary that works with
both ncurses and netbsd-curses. A portable POSIX sh version (sfm.sh) is
also included, requiring only standard Unix tools (ls, awk, tput, stty,
mv, cp, rm).
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.)
- Standard Unix tools: ls, awk, tput, stty, cp, mv, rm, mkdir, touch
Both versions:
- Optional: wl-copy / xclip / xsel / pbcopy (for clipboard support)
- Optional: mpv, vlc, feh, zathura, etc. (for smart file opening)
- Optional: readlink (for symlink display)
@@ -26,7 +34,9 @@ Using make (recommended):
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
@@ -34,10 +44,10 @@ To uninstall:
make uninstall
Manual installation:
Manual installation (shell version only):
cp sfm /usr/local/bin/sfm
chmod +x /usr/local/bin/sfm
cp sfm.sh /usr/local/bin/sfm.sh
chmod +x /usr/local/bin/sfm.sh
USAGE
@@ -142,8 +152,8 @@ MULTI-SELECT
BOOKMARKS
---------
b Bookmark current directory (press again to remove)
B Open bookmark picker (j/k navigate, enter jump)
b Open bookmark picker (j/k navigate, enter jump, del remove)
B Bookmark current directory (press again to remove)
Bookmarks are saved to: ~/.config/sfm/bookmarks
+3 -3
View File
@@ -151,11 +151,11 @@ Multi-select works with
.SS Bookmarks
.TP
.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
.B B
Open the bookmark picker.
Use j/k to navigate, enter to jump, esc to close.
Bookmark the current directory. Press again to remove it.
.SS Other
.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 31 " - chmod -x (remove executable)"
help_sep 32
help_row 33 " b bookmark current dir"
help_row 34 " B open bookmark picker"
help_row 33 " b open bookmark picker"
help_row 34 " B bookmark current dir"
help_row 35 " c copy path to clipboard"
help_row 36 " ~ go to home directory"
help_row 37 " \` jump to previous directory"
@@ -1674,6 +1674,19 @@ do_bookmark_jump() {
fi
return ;;
'[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
esac ;;
"$(printf '\n')"|\
@@ -1829,8 +1842,8 @@ while true; do
l) do_open ;;
"$(printf '\033[D')"|\
h) do_go_back ;;
b) do_bookmark_add ;;
B) do_bookmark_jump ;;
b) do_bookmark_jump ;;
B) do_bookmark_add ;;
'?') do_help ;;
R) load_entries; INFO_MSG="refreshed" ;;
/) do_search ;;