From 53567c1f205cf1032ccf87330973c6c6d2991acd Mon Sep 17 00:00:00 2001 From: Emmett1 Date: Sun, 16 Aug 2026 14:25:34 +0800 Subject: [PATCH] bookmark updated --- README | 4 ++-- sfm.1 | 6 +++--- sfm.cpp | 40 +++++++++++++++++++++++++++++++--------- sfm.sh | 21 +++++++++++++++++---- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/README b/README index 212ade5..e511eae 100644 --- a/README +++ b/README @@ -152,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 diff --git a/sfm.1 b/sfm.1 index e671fd7..50a8c24 100644 --- a/sfm.1 +++ b/sfm.1 @@ -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 diff --git a/sfm.cpp b/sfm.cpp index 6218484..1d4fceb 100644 --- a/sfm.cpp +++ b/sfm.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -333,8 +334,9 @@ private: // ── overlays ─────────────────────────────────────────────────────────── bool confirm_overlay(const std::string &prompt); std::string overlay_picker(const std::string &title, - const std::vector &items, - bool allow_cancel = true); + std::vector items, + bool allow_cancel = true, + const std::function &on_delete = nullptr); // ── input ────────────────────────────────────────────────────────────── bool handle_key(int key); // returns false to quit @@ -1102,8 +1104,9 @@ bool FileManager::confirm_overlay(const std::string &prompt) { } std::string FileManager::overlay_picker(const std::string &title, - const std::vector &items, - bool allow_cancel) { + std::vector items, + bool allow_cancel, + const std::function &on_delete) { if (items.empty()) return ""; int nitems = static_cast(items.size()); @@ -1205,6 +1208,14 @@ std::string FileManager::overlay_picker(const std::string &title, case 'q': case 'Q': case 'h': if (allow_cancel) { need_full_redraw_ = true; return ""; } break; + case KEY_DC: + if (on_delete && !items.empty()) { + on_delete(items[psel]); + items.erase(items.begin() + psel); + nitems = static_cast(items.size()); + if (nitems == 0) { need_full_redraw_ = true; return ""; } + } + break; case 27: need_full_redraw_ = true; return ""; default: break; } @@ -1621,8 +1632,8 @@ void FileManager::do_help() { {" + chmod +x (make executable)", false, false}, {" - chmod -x (remove executable)", false, false}, {"", true, false}, - {" b bookmark current dir", false, false}, - {" B open bookmark picker", false, false}, + {" b open bookmark picker", false, false}, + {" B bookmark current dir", false, false}, {" c copy path to clipboard", false, false}, {" ~ go to home directory", false, false}, {" ` jump to previous directory", false, false}, @@ -2023,7 +2034,18 @@ void FileManager::do_bookmark_jump() { return; } - std::string chosen = overlay_picker(" BOOKMARKS", bookmarks); + auto remove_bookmark = [&](const std::string &path) { + std::vector kept; + std::ifstream fin(bookmark_file_); + std::string l; + while (std::getline(fin, l)) + if (l != path) kept.push_back(l); + fin.close(); + std::ofstream fout(bookmark_file_, std::ios::trunc); + for (const auto &k : kept) fout << k << '\n'; + flash_msg("bookmark removed: " + path); + }; + std::string chosen = overlay_picker(" BOOKMARKS", bookmarks, true, remove_bookmark); if (chosen.empty()) { need_full_redraw_ = true; return; } if (fs::is_directory(chosen)) { @@ -2443,8 +2465,8 @@ bool FileManager::handle_key(int key) { do_open(); break; case 'h': case KEY_LEFT: do_go_back(); break; - case 'b': do_bookmark_add(); break; - case 'B': do_bookmark_jump(); break; + case 'b': do_bookmark_jump(); break; + case 'B': do_bookmark_add(); break; case '?': do_help(); break; case 'R': load_entries(); flash_msg("refreshed"); break; case '/': do_search(); break; diff --git a/sfm.sh b/sfm.sh index 032b6e5..9d26be6 100755 --- a/sfm.sh +++ b/sfm.sh @@ -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 ;;