Compare commits

..

152 Commits

Author SHA1 Message Date
272ee62ad8 Make a release
All checks were successful
Alpine 3.20 Success
Arch Linux AUR Success
OpenBSD 7.5 Success
2024-12-21 09:10:54 +01:00
a85426541a sdn-install: improve macOS installation
All checks were successful
Alpine 3.20 Success
Arch Linux AUR Success
OpenBSD 7.5 Success
Login shells have a dash at the beginning of their first argument.
2024-12-21 08:16:23 +01:00
c9b003735d Fix OpenBSD build
All checks were successful
Arch Linux AUR Success
Alpine 3.20 Success
OpenBSD 7.5 Success
2024-12-21 07:59:44 +01:00
52a28f01c8 Add support for BSD derivatives, fix macOS
All checks were successful
Alpine 3.20 Success
Arch Linux AUR Success
2024-12-21 07:37:06 +01:00
3607757554 Improve filename passing
All checks were successful
Alpine 3.19 Success
Arch Linux AUR Success
c9662f1 forgot about internal helpers.

Moreover, it is annoying to see the -- in shell history
for every single external helper call.
2024-04-17 02:00:10 +02:00
6eb216a40a Remove linker preference from CMakeLists.txt
All checks were successful
Arch Linux AUR Success
Alpine 3.19 Success
ld.gold doesn't understand all options that ld.bfd does.

In particular, this broke AUR builds with the current makepkg.conf.
2024-04-08 01:49:55 +02:00
9ce6f47716 Use more precise filesizes
Some checks failed
Arch Linux AUR Scripts failed
The behaviour differs from GNU `ls -lh` in that we use binary units,
meaning we get 1023 before 1.0K rather than 999 before 1.0K,
which is nonetheless still four characters wide.
2024-04-07 16:00:21 +02:00
c9662f1a7b Fix passing filenames starting with -
We don't want to pass them as program options.
2024-01-20 08:33:17 +01:00
9ddeb03652 CMakeLists.txt: declare compatibility with 3.27
Sadly, the 3.5 deprecation warning doesn't go away after this.
2023-08-01 03:11:11 +02:00
acb187c6b1 README.adoc: update package information 2023-07-01 21:58:29 +02:00
9427df62e7 Fix code formatting, bump copyright years 2023-06-12 14:00:58 +02:00
4d6999c415 Do not beep on window resizes 2023-06-11 21:11:20 +02:00
30ed61fdd2 Implement ^W in the editor 2023-06-11 21:05:55 +02:00
2df916c9b3 Support wildcards in interactive search
The previous search for the longest match is functionally
duplicated by typing individual characters on the input line,
and wildcards can be escaped, so there shouldn't be regressions
in terms of capability.
2022-09-03 12:17:02 +02:00
24401825b4 Add a missing case break 2022-01-08 11:23:36 +01:00
2bfb490798 Add and bind an action to center the cursor
"z" stands for VIM's "zz".
2022-01-08 11:17:24 +01:00
338d00d605 Do not crash on opendir() failures
Show an error message, and a way out.
2021-11-09 07:52:48 +01:00
015652e379 Fix build with recent ncurses
Easily gained, easily lost.  No more ^S binding.
2021-11-09 07:45:20 +01:00
c298b6fc97 bash integration: add helpers to command history 2021-11-05 22:11:30 +01:00
7c2ab8ab59 zsh integration: add helpers to command history 2021-11-05 21:54:56 +01:00
e423a3a1b1 Add clang-format configuration, clean up 2021-11-05 21:34:05 +01:00
916f354c9b Move the cursor to just created directories 2021-10-30 12:32:40 +02:00
050f875c47 Clean up 2021-10-30 12:13:45 +02:00
aeffe40efc Bind ^S to search, as in Emacs, with a trick
We heavily depend on ncurses anyway, so no worries about portability.
2021-10-18 11:23:17 +02:00
536aa57761 Slightly optimize very large directories
Cumulatively 10% of user time, give or take.

These are mainly pointless multibyte to wide string conversions.

The hit to source code readibility is minimal.
2021-10-05 21:01:32 +02:00
0d10ae06e6 Measured stat performance, io_uring not worth it
Large directories are slow for different reasons.
2021-10-05 19:18:15 +02:00
e1b0831854 Don't reload on sort changes
It is unexpected behaviour, and likes to take too long.
2021-09-26 09:38:16 +02:00
4e93dfbb8d Add a comment about libacl
So that I don't repeat my actions in the future.
2021-09-26 09:19:54 +02:00
8a6bb54eb5 Ignore empty XDG_CONFIG_DIRS
As the specification says we should.  GLib does this as well.

It is still possible to achieve an empty set by using ":",
which are two non-absolute paths that should be ignored.
GLib doesn't implement this.  Thus, we're now better than GLib.
2021-09-26 08:59:57 +02:00
4ef7c9edf7 Makefile: make the static build a non-phony target 2021-07-19 09:28:50 +02:00
3eea106c3c Explicitly disable GCC's -Wmisleading-indentation 2021-07-19 09:23:28 +02:00
7de8c84e8f Fix a signedness compiler warning 2021-07-19 09:12:17 +02:00
e17c5e2083 Bind F6 to a rename prompt
Mostly just so that the F7 binding isn't completely alone.

Since Shift-F6 isn't something we can just bind to, use a prefill.
2021-07-17 14:47:50 +02:00
9bd3739122 Bind F7 to an mkdir prompt
This might have needed more thought, but we'll see.
2021-07-17 14:41:57 +02:00
ec1f1031cc Implement search iteration
The interactive search now has its own keymap, overriding "input".

Closes #5
2021-07-17 14:19:37 +02:00
bc99b3dd48 Add a right-side prompt to the search 2021-07-17 13:04:42 +02:00
e948741864 Enable pushing the search in a certain direction
We want to make it possible to iterate all current matches.
2021-07-17 08:49:54 +02:00
0adbac2066 Make search() return the number of matches 2021-07-17 07:54:03 +02:00
2238db5a4e Make removing characters invoke g.editor_on_change 2021-07-17 07:24:16 +02:00
98612f5492 Improve C-char parsing
I was hoping that a superoptimiser would help me find a miraculous
branchless equation to cover it, but in the end the branching
doesn't hurt at all in our case.

It's more readable than `(((char >> 2) - 0x38) & 0x60) ^ char`
or `(char ^ 0x40) & (((char >> 1) ^ 0x20) | 0x5f)`.
2021-07-09 05:16:37 +02:00
1034321f81 sdn-install: explain why -dot is experimental
Add an explanatory link, so that I don't need to look it up again.
2021-07-07 22:13:46 +02:00
e7da32160c Makefile: fix version extraction
Regression introduced by cc59fcf.
2021-07-07 21:21:52 +02:00
fdb338fe12 Allow binding to custom key sequences
And document this feature in the manual page.
2021-07-07 21:21:32 +02:00
9056ef4194 README.adoc: make use of the "plus" attribute 2020-11-07 03:22:51 +01:00
b8a4742fb9 sdn.1: refer to a better manual page 2020-11-05 01:24:05 +01:00
c999e5a8e4 sdn.1: take care about sentence spacing
For more info, see e.g.
https://github.com/asciidoc/asciidoc-py3/issues/137

I'll probably commit to mandoc here but scdoc is appealing.

Somewhat sadly, it explicitly suppresses sentence spacing
but I'm wondering whether it couldn't be reimplemented better,
in a more AsciiDoc-like fashion.
2020-10-29 19:22:20 +01:00
07ef834a1e Include a header required for kill()
Yet, this program remains fairly unportable.
2020-10-29 03:24:37 +01:00
997f5c25a2 sdn.1: improve wording about envvars 2020-10-27 14:58:23 +01:00
39e68a977c sdn.1: fix default key binding references 2020-10-27 14:46:04 +01:00
c20d3780b2 Make the manpages mostly acceptable
Closes #1
2020-10-27 04:17:52 +01:00
22725ba3b7 Update README.adoc
I've put the project in AUR, it seems to deserve it.
2020-10-27 01:16:07 +01:00
df046bb071 Add some mediocre manpages
I'm not particularly happy to write in mdoc but here goes.
2020-10-26 20:46:09 +01:00
0c1a8d9902 Implement the --version option
Since we have a version number at all, even if it's meaningless.
2020-10-26 19:07:47 +01:00
cc59fcfb41 CMakeLists.txt: cleanup 2020-10-26 18:56:14 +01:00
c88566e7bb Bind F1 to show the help 2020-10-25 08:19:49 +01:00
39c840cd74 Mark a minor issue for later resolution 2020-10-24 19:28:11 +02:00
f231828e8d sdn-install: bash: fix UTF-8 collisions 2020-10-24 19:27:07 +02:00
1318c4983f Makefile: make portable, support static linking
We can happily stick to POSIX and the usual variable names,
with the following exceptions:
 - pkg-config(1) is used to find libraries and compile flags
 - the new "static" target uses non-standard compiler
   and linker flags, though it's not the default target

sdn is predestined for wild distribution,
even the dynamically linked libc is rather suboptimal.
2020-10-23 08:22:59 +02:00
c503954f44 Cleanup
The wchar_t variant of compute_width() is no longer needed.

So all in all the better help has saved code.
2020-10-23 07:53:37 +02:00
77973fc026 Group help message by action
Considerably more useful and concise.
2020-10-23 03:51:26 +02:00
61be9528e4 Bind M-Up to the "parent" action
Taken from Windows Explorer, which previously used Backspace.

We might want to use h/l for parent/choose by default.
2020-10-23 03:38:47 +02:00
2313485970 Bind C-d in the editor
We do get these as a key, after all.

Closes #4
2020-10-23 01:37:14 +02:00
20c883fb8a Implement C-v in the editor
Not completely happy with the explicit `halfdelay (1)`.

Updates #4
2020-10-23 01:37:07 +02:00
bbf97f6d3d Implement C-u C-k in the editor
Updates #4
2020-10-23 01:21:25 +02:00
706795c85c Cleanup 2020-10-22 00:51:57 +02:00
e8eaa2366a Implement Delete in the editor
Not caring about C-d right now, we might have to convince the tty
to send it to us--I'm not sure if it does, or returns EOF.

Updates #4
2020-10-22 00:06:41 +02:00
12d8f6a931 Implement C-a C-e C-b C-f in the editor
Updates #4
2020-10-21 23:57:16 +02:00
5d0c105b10 Make backspace erase combining characters
They might not be even printed correctly, though.

Updates #4
2020-10-21 23:56:51 +02:00
33a8e26efc Track cursor position in the editor
Updates #4
2020-10-21 23:55:01 +02:00
bbd23187bc Minor fix-ups and adjustments 2020-10-21 08:34:32 +02:00
a0eacf4607 Add an installation script
Copying snippets from the README was uncomfortable and laborious,
and wasted a lot of space in the document, especially after
the recent additions.

Closes #3
2020-10-21 08:26:42 +02:00
37ad5f43df README.adoc: avoid unnecessary quotes for bash
Word expansion is not performed there.
2020-10-20 03:58:11 +02:00
a95fa2f96d README.adoc: fish after bash
Bash is a bad citizen but this order makes more sense.
2020-10-20 03:47:12 +02:00
6f40b8db3a Fix ext-helpers with older bash versions
See Midnight Commander commit 436296f, blindly trusting it.

wc(1) could be used unconditionally but let's make it clear.
2020-10-20 03:44:15 +02:00
63e7895905 Let the caller decide how to launch helpers
In the end, we don't need to impose any policy on it,
and it removes a level of quoting, as well as an `eval`.
2020-10-08 19:50:04 +02:00
6aa4bd2ff5 When resuming a child, resume the whole group
SIGTSTP is sent to the entire foreground process group,
so do the some with our SIGCONT.

Debian's default sh (dash) doesn't replace itself with
the command, even if it's the last one in the -c option.

Of course, we do not need to use /bin/sh for the helpers
at all, though it doesn't cost us much.  We could also
issue an explicit `exec`.
2020-10-08 19:49:07 +02:00
000315165d Fix the help in absence of a bindings file 2020-10-08 14:28:49 +02:00
d2e4b91262 Fix showing DEL in the help
And in general fix all CTRL processing to handle the DEL character.
2020-10-08 14:28:24 +02:00
c18630295c README.adoc: add configuration for elvish
And remove it from the "similar software" section.

Our relationship has progressed.

Other unusual shells I've checked before I gave up:
 - nushell lacks the ability to bind keys to user functions
 - yash can but is otherwise way too basic
2020-10-07 20:57:37 +02:00
b53a3a0981 Revisit zsh integration
zsh's antisocial behaviour was fairly promptly fixed (thanks to
Stephane Chazelas and his patience).

zle-line-init and zle-line-reset seem to be user-defined widgets
and the order inverted.  Put zle-line-init before reset-prompt
because some people do weird things in there.
2020-10-04 14:27:51 +02:00
cf80a15501 Survive a removed CWD, as well as an empty root
All the omitted error checking sometimes sucks a lot,
and I need to include it later anyway.
2020-10-02 16:35:12 +02:00
2d6d0582a1 README.adoc: fix zsh integration snippet 2020-10-02 15:36:51 +02:00
5451eba2a3 Make the outer prompt look more normal
There's a slight issue with the inverted cell representing
the cursor standing out a bit too much amongst the rest of
the characters.

The resulting experience is a lot more consistent, though.
2020-10-01 13:40:52 +02:00
b8c767354e Show external command line if appropriate
Since I'm already dealing with the fish shell.

All of our supported shells seem to handle cursor position
in Unicode (wide character) codepoints.

It was easiest and most straight-forward to pass the data
through yet-unused program arguments.

The cursor position is marked by a Unicode glyph equivalent
to ACS_DIAMOND, although ncurses doesn't get a chance
to make any ACS translation.
2020-10-01 11:58:32 +02:00
c07f557c16 README.adoc: clarify bash problems
I've also tried tcsh but while it /can/ be used for directory
navigation, it has several issues that are much more serious.
2020-10-01 08:41:58 +02:00
5fff336e77 README.adoc: fix up hswg compatibility 2020-10-01 04:20:10 +02:00
6e8d816ada README.adoc: split into subsections 2020-10-01 04:07:56 +02:00
063938ff60 README.adoc: add configuration for fish 2020-10-01 04:04:19 +02:00
93172797e1 Set cursor to child when going to parent dir
That is, if it's missing from our history.

This makes for a more consistent experience when traversing
the filesystem.  Arguably, it's only good for when 'h' is
bound to the 'parent' action.

Also make sure that the offset and cursor are reset when
the path is changed.
2020-09-29 03:39:13 +02:00
1507f2dff9 Cleanup 2020-09-29 02:31:49 +02:00
9a12fd8021 Add ability to run helpers externally
So far experimental and essentially undocumented.
2020-09-29 01:33:19 +02:00
f596bb8f5e reload() doesn't really need to know the old path
Just whether it's safe for it to keep an anchor on the current item.

I've left in the safety check for an empty entries array,
for the theoretical case of an empty or entirely filtered-out root
directory.  It will likely crash in that case, anyway,
the cursor may be either -1 or 0.
2020-09-28 22:52:33 +02:00
67da8d965b Make anchor processing a bit more obvious 2020-09-28 22:18:17 +02:00
e60ffeeb20 Improve PAGER defaults
We basically need less(1), nothing else will work correctly.

I'm not sure where I took pager(1) from, might be a Debian thing.
2020-09-28 21:34:09 +02:00
9a2f6ab5cf README.adoc: talk about view and edit helpers 2020-09-28 21:26:33 +02:00
0a66ae4d26 Expand a comment about overstriked underlining 2020-09-28 20:11:38 +02:00
121d7850fe Show error output from failed helpers
Usually, when the pager or the editor fail and return a non-zero
exit status, they display a message on the standard error output.

We might also try to redirect this output to show_mesage() but
it might not fit as a whole, so, given the relative rareness
of this situation, this slight inconsistency shouldn't be much
of an issue.

It'd also be possible to redirect the output to run_pager() but
in doing so, we might make the problem recursive.
2020-09-28 20:05:29 +02:00
98c8dc5b7d Fix tilde expansion algorithm
In principle correct, in practice completely broken.

I wrongly assumed basic_string::find() would behave like strcspn(),
and also used a nonsensical string index to check for the tilde.
2020-09-28 02:00:29 +02:00
b99f96cf6a Fix comment: the word "no-op" needs to be split 2020-09-28 01:46:38 +02:00
5759df156b Support tilde expansion in the "chdir" action
The tilde may be escaped, and this first escape may be escaped
as well, so all paths should be expressable.

All will just work(TM) for those who need it, and those who start
filenames with backslashes are begging to have their foot shot.

It appears that even Shift JIS, Big5, GB 18030, and GBK are
compatible with Unix paths, meaning they don't redefine the slash
(0x2F), so I'm okay with my direct multibyte string handling in
unknown locales.

Legacy stuff smells.
2020-09-28 01:45:56 +02:00
91df92f49a Make F3 change directories
Best complemented with a less(1) configuration that also quits on F3,
just like mcview.  Or invoke sdn with PAGER=mcview, even though you
lose the ability to view the help that way (but gain filters).
2020-09-27 23:33:10 +02:00
bff886841b Always accept ^? as well as ^H as backspace 2020-09-21 21:15:15 +02:00
ebb444dda1 README: add an example of configuring bindings 2020-09-15 19:36:19 +02:00
da0252ff98 README: make it also work with asciidoctor 2020-09-15 19:31:54 +02:00
98da5f6d35 Add an action to go to the parent directory 2020-09-15 19:15:30 +02:00
f4eebf59af README: make listings hswg-compatible 2020-08-28 18:33:08 +02:00
63982b3754 README: make listings libasciidoc-compatible 2020-08-28 18:30:49 +02:00
d6eaf44aee README: fix upstream URL 2020-08-28 18:25:32 +02:00
b8344f215c Name change 2020-08-28 18:23:46 +02:00
623c4914d1 Work around an infinite loop issue 2020-04-19 22:40:57 +02:00
c0f0328762 README: fix integration snippets
Runs of whitespace used to be smashed together.
2020-02-13 20:33:16 +01:00
571ec74706 Guard against ^Z in helper programs
Resume them immediately, we are not a shell.
2019-12-09 19:01:16 +01:00
7cce0cc2fd Fix change notifications
Another embarrassing 71fbaca regression.
2019-09-27 23:06:12 +02:00
bf38e4e9ea Position indicator like in vi 2019-09-27 22:38:48 +02:00
2c847fb4a3 Add actions imitating L/M/H in vi 2019-09-27 21:08:12 +02:00
296c0cc66f Fixes for previous commits
".." used to be hidden together with hidden files,
and the symlink patch introduced a compiler warning.
2018-12-09 05:29:59 +01:00
71fbaca9e5 Embrace paths with symbolic links 2018-12-08 01:41:41 +01:00
4ce6454ebb Add Norton Commander-like actions for F3 and F4 2018-12-03 22:05:00 +01:00
315b662581 Don't show .. in the root directory 2018-12-03 22:04:35 +01:00
4a2a49312b Fix formatting 2018-12-03 00:11:00 +01:00
7174b507d3 Fix crash on unknown groups 2018-12-01 15:57:35 +01:00
aae9c392fa Also sort symlinks to directories first 2018-11-10 01:32:59 +01:00
fad0d264a5 Support old libstdc++ 4.9
Now sdn can be built under Debian jessie with clang++ and libstdc++.
2018-11-04 19:46:06 +01:00
473aa8788c Update README 2018-11-03 17:04:50 +01:00
85ada4dd2b Fix build on not-my-system 2018-11-03 15:23:31 +01:00
e6ed7da395 Update README 2018-11-03 15:01:39 +01:00
c065238e75 Reliability improvement 2018-11-03 15:01:19 +01:00
579e4c9a34 Make confirming a search choose the item 2018-11-02 22:12:34 +01:00
3c056dde91 Add screenshot to README 2018-11-02 21:19:41 +01:00
081b4db5c3 Fix level popping 2018-11-02 20:22:50 +01:00
36454fb90c Fix history loading 2018-11-02 18:30:36 +01:00
6b1ff048b8 Flash column when sorting is changed 2018-11-02 18:30:35 +01:00
3790f8dfa0 Allow changing the sort column
Directories always come first and the .. entry even before that.
2018-11-02 18:07:06 +01:00
5c086016b5 Allow hiding so-called hidden files 2018-11-02 17:45:18 +01:00
232ecffa2d Allow reversing the sort 2018-11-02 17:25:10 +01:00
f3fffe4b25 Add an action to quit without chdir
Also fixed ACTION_CHOOSE_FULL to quote properly.
2018-11-02 15:50:58 +01:00
77313663a3 Update README 2018-11-02 15:40:56 +01:00
5f2eaa88e0 Create the config directory if needed 2018-11-02 15:37:56 +01:00
d6846e6327 Add an action for chdir 2018-11-02 15:09:27 +01:00
314ba114a1 Implement messages to the user 2018-11-02 15:05:04 +01:00
4de89faf7e Store runtime and configuration to a file
Added a toggle for gravity, now turned off by default.
2018-11-02 14:48:16 +01:00
beee2e2683 Unnecessary c_str() 2018-11-02 12:35:03 +01:00
4ab0db3c04 Make sure to quote empty strings 2018-11-02 12:08:43 +01:00
3624636c2f New config parser
Basically a subset of Bourne shell.
2018-11-01 22:42:49 +01:00
e80c56e249 Cleanup 2018-11-01 22:19:31 +01:00
2c595100ae Fix setcchar invocation 2018-11-01 20:05:06 +01:00
e4af5b4147 Remember cursor position in ancestor directories 2018-11-01 19:40:05 +01:00
c9bffc6046 Fix uninitialized iterator 2018-11-01 19:29:43 +01:00
292829852e Implement simple in-application help
It could be made more complicated but I guess it's fine for now.

We've learnt to run pagers.
2018-11-01 16:03:17 +01:00
db051698e6 Use words for prompts, not cryptic characters 2018-11-01 12:33:47 +01:00
51ed172d5d Only quote output when necessary 2018-10-27 21:26:11 +02:00
ffa5754b59 Cleanup 2018-10-26 07:51:44 +02:00
11 changed files with 1657 additions and 320 deletions

14
.clang-format Normal file
View File

@@ -0,0 +1,14 @@
BasedOnStyle: LLVM
ColumnLimit: 80
IndentWidth: 4
TabWidth: 4
UseTab: ForContinuationAndIndentation
SpaceAfterCStyleCast: true
SpaceBeforeParens: Always
AlignAfterOpenBracket: DontAlign
AlignEscapedNewlines: DontAlign
AlignOperands: DontAlign
AlignConsecutiveMacros: Consecutive
BreakBeforeTernaryOperators: true
SpacesBeforeTrailingComments: 2
WhitespaceSensitiveMacros: ['XX', 'ACTIONS', 'LS']

View File

@@ -1,46 +1,45 @@
# target_compile_features has been introduced in that version
cmake_minimum_required (VERSION 3.1.0)
project (sdn CXX)
set (version 0.1)
cmake_minimum_required (VERSION 3.1...3.27)
project (sdn VERSION 1.0 LANGUAGES CXX)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
endif ()
# Since we use a language with slow compilers, let's at least use a fast linker
execute_process (COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE ld_version)
if ("${ld_version}" MATCHES "GNU gold")
set (CMAKE_EXE_LINKER_FLAGS "-fuse-ld=gold ${CMAKE_EXE_LINKER_FLAGS}")
set (CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-misleading-indentation -pedantic")
endif ()
find_package (PkgConfig REQUIRED)
pkg_check_modules (NCURSESW QUIET ncursesw)
pkg_check_modules (ACL libacl)
pkg_check_modules (NCURSESW ncursesw)
if (NOT NCURSESW_FOUND)
find_library (NCURSESW_LIBRARIES NAMES ncursesw)
find_path (NCURSESW_INCLUDE_DIRS ncurses.h PATH_SUFFIXES ncurses)
endif ()
add_executable (${PROJECT_NAME} ${PROJECT_NAME}.cpp)
target_include_directories (${PROJECT_NAME} PUBLIC ${NCURSESW_INCLUDE_DIRS})
target_link_libraries (${PROJECT_NAME} PUBLIC ${NCURSESW_LIBRARIES} acl)
target_link_libraries (${PROJECT_NAME}
PUBLIC ${NCURSESW_LIBRARIES} ${ACL_LIBRARIES})
target_compile_features (${PROJECT_NAME} PUBLIC cxx_std_14)
target_compile_definitions (${PROJECT_NAME} PUBLIC
-DPROJECT_NAME=\"${PROJECT_NAME}\" -DPROJECT_VERSION=\"${version}\")
-DPROJECT_NAME=\"${PROJECT_NAME}\" -DPROJECT_VERSION=\"${PROJECT_VERSION}\")
include (GNUInstallDirs)
install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
install (PROGRAMS ${PROJECT_NAME}-install DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES sdn.1 sdn-install.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Directory navigator")
set (CPACK_PACKAGE_VENDOR "Premysl Janouch")
set (CPACK_PACKAGE_CONTACT "Přemysl Janouch <p@janouch.name>")
set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
set (CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>")
set (CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set (CPACK_PACKAGE_VERSION ${version})
set (CPACK_GENERATOR "TGZ;ZIP")
set (CPACK_PACKAGE_FILE_NAME
"${PROJECT_NAME}-${version}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set (CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}-${version}")
"${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set (CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}-${PROJECT_VERSION}")
set (CPACK_SOURCE_GENERATOR "TGZ;ZIP")
set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user")
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${version}")
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set (CPACK_SET_DESTDIR TRUE)
include (CPack)

View File

@@ -1,4 +1,4 @@
Copyright (c) 2017 - 2018, Přemysl Janouch <p@janouch.name>
Copyright (c) 2017 - 2024, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

View File

@@ -1,12 +1,19 @@
.POSIX:
SHELL = /bin/sh
CXXFLAGS = -g -std=c++14 -Wall -Wextra -pedantic -static-libstdc++
CXXFLAGS = -g -std=c++14 -Wall -Wextra -Wno-misleading-indentation -pedantic
CPPFLAGS = `sed -ne '/^project (\([^ )]*\) VERSION \([^ )]*\).*/ \
s//-DPROJECT_NAME="\1" -DPROJECT_VERSION="\2"/p' CMakeLists.txt`
all: sdn
%: %.cpp CMakeLists.txt
$(CXX) $(CXXFLAGS) $< -o $@ `pkg-config --libs --cflags ncursesw` -lacl \
`sed -ne 's/^project (\([^ )]*\).*/-DPROJECT_NAME="\1"/p' \
-e 's/^set (version \([^ )]*\).*/-DPROJECT_VERSION="\1"/p' CMakeLists.txt`
sdn: sdn.cpp CMakeLists.txt
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $< -o $@ \
-lacl `pkg-config --libs --cflags ncursesw`
sdn-static: sdn.cpp CMakeLists.txt
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $< -o $@ \
-static-libstdc++ \
-Wl,--start-group,-Bstatic \
-lacl `pkg-config --static --libs --cflags ncursesw` \
-Wl,--end-group,-Bdynamic
clean:
rm -f sdn
rm -f sdn sdn-static
.PHONY: all clean
.PHONY: clean

4
NEWS Normal file
View File

@@ -0,0 +1,4 @@
1.0.0 (2024-12-21)
* Initial release

View File

@@ -11,15 +11,28 @@ commands. It enables you to:
can be simply forwarded if it is to be edited. What's more, it will always
be obvious whether the navigator is running.
Development has just started and the only supported platform is Linux.
I wanted to try a different, simpler approach here.
'sdn' runs on Linux and all BSD derivatives. I wanted to try a different,
simpler approach here, and the end result is very friendly to tinkering.
image::sdn.png[align="center"]
Packages
--------
Regular releases are sporadic. git master should be stable enough.
You can get a package with the latest development version using Arch Linux's
https://aur.archlinux.org/packages/sdn-git[AUR],
or as a https://git.janouch.name/p/nixexprs[Nix derivation].
Building
--------
Build dependencies: CMake and/or make, a C++14 compiler, pkg-config +
Runtime dependencies: ncursesw
Runtime dependencies: ncursesw, libacl (on Linux)
$ git clone https://github.com/pjanouch/sdn.git
// Working around libasciidoc's missing support for escaping it like \++
Unfortunately most LLVM libc{plus}{plus} versions have a bug that crashes 'sdn'
on start. Use GNU libstdc{plus}{plus} if you're affected.
$ git clone https://git.janouch.name/p/sdn.git
$ mkdir sdn/build
$ cd sdn/build
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug
@@ -37,64 +50,63 @@ Or you can try telling CMake to make a package for you. For Debian it is:
There is also a Makefile you can use to quickly build a binary to be copied
into the PATH of any machine you want to have 'sdn' on.
zsh
---
To start using this navigator, put the following in your .zshrc:
....
sdn-navigate () {
# ... possibly zle-line-init
eval `sdn`
[ -z "$cd" ] || cd "$cd"
[ -z "$insert" ] || LBUFFER="$LBUFFER$insert "
zle reset-prompt
# ... possibly zle-line-finish
}
zle -N sdn-navigate
bindkey '\eo' sdn-navigate
....
Configuration
-------------
For a slightly more technical explanation please refer to manual pages.
bash
----
Here we can't reset the prompt from within a `bind -x` handler but there is
an acceptable workaround:
....
sdn-navigate () {
SDN_L=$READLINE_LINE SDN_P=$READLINE_POINT
READLINE_LINE=
Integration
~~~~~~~~~~~
The package contains an installation script called 'sdn-install' which will bind
'sdn' to Alt-o in your shell's initialisation file. The supported shells are:
eval `sdn`
[[ -z "$cd" ]] || cd "$cd"
[[ -z "$insert" ]] || {
SDN_L="${SDN_L:0:$SDN_P}$insert ${SDN_L:$SDN_P}"
((SDN_P=SDN_P+${#insert}+1))
}
}
sdn-restore () {
READLINE_LINE=$SDN_L READLINE_POINT=$SDN_P
unset SDN_L SDN_P
}
- *zsh*: works well
- *bash*: minor issue: exiting the navigator confirms an empty prompt
- *fish*: works well
- *elvish*: version 0.14.1 and above, an unstable API is used, works well
+
elvish is absolutely perverse. And so is integrating 'sdn' into it because it
already includes a custom file manager, bound to Ctrl-N (though I find the
ranger-like interface confusing and resource-demanding).
bind -x '"\200": sdn-navigate'
bind -x '"\201": sdn-restore'
bind '"\eo":"\200\C-m\201"'
....
Colors
------
Colours
~~~~~~~
Here is an example of a '~/.config/sdn/look' file; the format is similar to
that of git, only named colors aren't supported:
that of git, only named colours aren't supported:
....
cursor 231 202
bar 16 255 ul
cwd bold
input
cmdline 145
....
Similar software
----------------
* https://elvish.io/ is an entire shell with an integrated ranger-like file
manager on Ctrl-N (I find this confusing and resource-demanding, preferring
to keep closer to "orthodox file managers")
Filename colours are taken from the `LS_COLORS` environment variable.
Run `dircolors` to get some defaults.
Bindings
~~~~~~~~
To obtain more vifm-like controls, you may write the following to your
'~/.config/sdn/bindings' file:
....
normal h parent
normal l choose
....
Helper programs
~~~~~~~~~~~~~~~
The F3 and F4 keys are normally bound to actions 'view' and 'edit', similarly to
Norton Commander and other orthodox file managers. The helper programs used
here may be changed by setting the PAGER and VISUAL (or EDITOR) environment
variables.
While it is mostly possible to get 'mcview' working using an invocation like
`PAGER='mcview -u' sdn`, beware that this helper cannot read files from its
standard input, nor does it enable overstrike processing by default (F9, could
be hacked around in 'mc.ext' by turning on the `nroff` switch for a custom file
extension, just without actually invoking 'nroff'), and thus it can't show the
program help. 'sdn' is currently optimised for 'less' as the pager.
Contributing and Support
------------------------

182
sdn-install Executable file
View File

@@ -0,0 +1,182 @@
#!/bin/sh -e
# sdn-install: integrate sdn with the shell, binding to M-o
# vim: set sw=2 ts=2 sts=2 et tw=80:
zsh() {
cat <<'EOF'
sdn-navigate () {
# optionally: zle zle-line-finish
while eval "`SDN=1 sdn "$BUFFER" "$CURSOR"`"
do
[ -z "$cd" ] || cd "$cd"
[ -z "$insert" ] || LBUFFER="$LBUFFER$insert "
[ -z "$helper" ] && break
# Workaround for "zsh: suspended (tty output)" when invoking
# helpers after the terminal has been resized while running sdn
command true
# Add to history, see https://www.zsh.org/mla/workers/2020/msg00633.html
fc -R =(print -- "$helper")
/bin/sh -c "$helper" </dev/tty || break
done
# optionally: zle zle-line-init
zle reset-prompt
}
zle -N sdn-navigate
bindkey '\eo' sdn-navigate
EOF
}
bash() {
cat <<'EOF'
# We can't make the shell update the prompt on directory changes
# since there's no way to invoke `prompt_again()` from a `bind -x`
# handler but we can work around it by submitting a blank line.
sdn-cursor () {
if [[ $BASH_VERSINFO -lt 5 ]]
then echo -n "$SDN_L" | wc -m
else echo "$SDN_P"
fi
}
sdn-navigate () {
SDN_L=$READLINE_LINE SDN_P=$READLINE_POINT
READLINE_LINE=
while eval "`SDN=1 sdn "$SDN_L" "$(sdn-cursor)"`"
do
[[ -z $cd ]] || cd "$cd"
[[ -z $insert ]] || {
SDN_L="${SDN_L:0:$SDN_P}$insert ${SDN_L:$SDN_P}"
((SDN_P=SDN_P+${#insert}+1))
}
[[ -z $helper ]] && break
history -s -- "$helper"
/bin/sh -c "$helper" || break
done
}
sdn-restore () {
READLINE_LINE=$SDN_L READLINE_POINT=$SDN_P
unset SDN_L SDN_P
}
# These never occur in UTF-8: \300-\301 \365-\367 \370-\377
bind -x '"\300": sdn-navigate'
bind -x '"\301": sdn-restore'
bind '"\eo": "\300\C-m\301"'
EOF
}
fish() {
cat <<'EOF'
function sdn-navigate
set --local IFS
set --local buffer (commandline)
set --local cursor (commandline --cursor)
while eval (SDN=1 sdn $buffer $cursor | \
string replace -ar '^(.*?)=' 'set --$1 ')
test -z "$cd" || cd "$cd"
test -z "$insert" || commandline --insert "$insert "
test -z "$helper" && break
/bin/sh -c "$helper" || break
end
commandline --function repaint
end
bind \eo sdn-navigate
EOF
}
elvish() {
cat <<'EOF'
edit:insert:binding[Alt-o] = {
use str
local:reesc = [posix]{ str:replace "'\\''" "''" $posix }
local:posix = [cmd]{ /bin/sh -c $cmd </dev/tty >/dev/tty 2>&1 }
# XXX: the -dot is not a stable API, and may hence break soon
# https://elv.sh/ref/builtin.html#do-not-use-functions-and-variables
local:buffer = $edit:current-command
local:cursor = (str:to-codepoints $buffer[0..$edit:-dot] | count)
local:ns = (ns [&])
while ?(eval ($reesc (E:SDN=1 sdn $buffer $cursor |
sed 's/^local //' | slurp)) &ns=$ns) {
if (not-eq $ns[cd] "") { cd $ns[cd] }
if (not-eq $ns[insert] "") { edit:insert-at-dot $ns[insert]" " }
if (or (eq $ns[helper] "") (not ?($posix $ns[helper]))) { break }
}
edit:redraw &full=$true
}
EOF
}
shell= path=
while getopts s:f:h opt
do
case $opt in
s) shell=$OPTARG;;
f) path=$OPTARG;;
*) echo "Usage: $0 [-s SHELL] [-f RCPATH | -]"; exit 2
esac
done
# Figure out the shell to integrate with
login=$(basename "$SHELL")
actual=$(ps -p $$ -o ppid= | xargs ps -o comm= -p | sed 's/^-//')
if [ -z "$shell" ]
then
if [ "$login" != "$actual" ]
then
echo "Conflict between login ($login) and invoking ($actual) shell."
echo "Specify the shell with the -s option."
exit 1
fi
shell=$actual
fi
# Figure out the default initialisation file
case "$shell" in
zsh|bash)
rc=~/.${shell}rc;;
fish)
rc=${XDG_CONFIG_HOME:-$HOME/.config}/fish/conf.d/sdn.fish;;
elvish)
rc=~/.elvish/rc.elv;;
*)
echo "$shell is not supported."
exit 1
esac
# Just print out the snippet if requested
if [ "$path" = "-" ]
then
$shell
exit 0
fi
# Finally append to or update the appropriate file
b="# sdn-install begin"
e="# sdn-install end"
[ -z "$path" ] && path=$rc
mkdir -p "$(dirname "$path")"
touch "$path"
if ! grep -q "^$b" "$path" 2>/dev/null || ! grep -q "^$e" "$path" 2>/dev/null
then
printf "\n$b\n%s\n$e\n" "$($shell)" >> "$path"
echo "The snippet has been added to $path"
exit 0
fi
# POSIX-compliant in-place sed, trying to retain permissions here
temp=$path.sdn.new
cp -p -- "$path" "$temp"
sed < "$path" > "$temp" "/^$b/,/^$e/c\\
$b\\
$($shell | sed 's/\\/&&/g; s/$/\\/')
$e"
mv -- "$temp" "$path"
echo "The snippet in $path has been updated."

35
sdn-install.1 Normal file
View File

@@ -0,0 +1,35 @@
.Dd October 27, 2020
.Dt SDN-INSTALL 1
.Os Linux
.Sh NAME
.Nm sdn-install
.Nd integrate sdn with the shell
.Sh SYNOPSIS
.Nm sdn-install
.Op Fl s Ar shell
.Op Fl p Ar - | rcpath
.Sh DESCRIPTION
.Nm
integrates
.Xr sdn 1
with your shell, binding it to M-o. If the navigator has already been
integrated, it updates the snippet in-place.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl p Ar -
Merely print the integration snippet for the appropriate shell to the standard
output, not changing anything.
.It Fl p Ar rcpath
Install the integration snippet into a different shell initialization file than
the default one for your user.
.It Fl s Ar shell
If you want to integrate
.Xr sdn 1
with a different shell than the one you're running, use this option to specify
it.
.El
.Sh REPORTING BUGS
Use
.Lk https://git.janouch.name/p/sdn
to report bugs, request features, or submit pull requests.

131
sdn.1 Normal file
View File

@@ -0,0 +1,131 @@
\" https://mandoc.bsd.lv/man/roff.7.html#Sentence_Spacing
.Dd October 27, 2020
.Dt SDN 1
.Os Linux
.Sh NAME
.Nm sdn
.Nd directory navigator
.Sh SYNOPSIS
.Nm sdn
.Op Ar line Ar point
.Nm sdn
.Cm --version
.Sh DESCRIPTION
.Nm
is a simple directory navigator that you can launch while editing shell
commands.
Use the
.Xr sdn-install 1
script to integrate it with your shell, then invoke it at any time with M-o.
.Pp
Press F1 to get a list of active key bindings and their assigned actions,
grouped by their contexts.
.Pp
Program arguments are only used by integration snippets to forward the parent
shell's command line.
The
.Ar point
is given in terms of characters.
.Sh OPTIONS
While some behaviour can be toggled from within the program, some can only be
changed by modifying configuration files manually.
.Pp
The files follow a simple syntax derived from the Bourne shell: each option is
on its own line, with words separated by linear whitespace.
Comments start with a hash (#) and continue until the end of the line.
All special characters may be quoted using either a backslash or single-quoted
strings.
.Pp
The options and the default key bindings controlling them are as follows:
.Bl -tag
.It full-view Em bool No (t)
If non-zero, the equivalent format to
.Ql ls -l
is used to display directory contents rather than simply listing the filenames.
.It gravity Em bool
If non-zero, all entries stick to the bottom of the screen, i.e., all empty
space is at the top.
.It reverse-sort Em bool No (R)
If non-zero, the order of entries is reversed.
.It show-hidden Em bool No (M-.)
If non-zero, filenames beginning with a full stop are shown.
.It ext-helpers Em bool
If non-zero, viewers and editors are launched from the parent shell.
This way you can suspend them and use job control features of the shell.
However it also enforces any pending change to the shell's working directory.
.It sort-column Em number No (< >)
The zero-based index of the
.Ql full-view
column that entries are ordered by.
.El
.Sh ENVIRONMENT
.Bl -tag -width 15n
.It Ev LS_COLORS
Used to retrieve filename colours.
The format is described in
.Xr dir_colors 5
and you can use the
.Xr dircolors 1
utility to initialize this variable.
.It Ev PAGER
The viewer program to be launched by the F3 key binding as well as to show
the internal help message.
If none is set, it defaults to
.Xr less 1 .
.It Ev VISUAL , Ev EDITOR
The editor program to be launched by the F4 key binding.
If neither variable is set, it defaults to
.Xr vi 1 .
.El
.Sh FILES
.Bl -tag -width 25n -compact
.It Pa ~/.config/sdn/config
Program configuration and navigation state, initialized or overwritten on exit.
.It Pa ~/.config/sdn/bindings
Custom key binding overrides.
.It Pa ~/.config/sdn/look
Redefine terminal attributes for UI elements.
.El
.Sh EXAMPLES
.Ss Pa bindings
Key names or combinations follow the Emacs syntax for Control and Meta prefixes
and
.Xr terminfo 5
names are used for special keys.
To obtain more vifm-like controls and Windows-like quit abilities:
.Bd -literal -offset indent
normal h parent
normal l choose
normal M-f4 quit
.Ed
.Pp
Midnight Commander binds the same traversal actions to sequences normally
unknown to ncurses, due to them being missing from terminfo.
You'll need to define them manually to match your terminal.
For rxvt, that would be:
.Bd -literal -offset indent
define C-ppage ^[[5^
define C-npage ^[[6^
normal C-ppage parent
normal C-npage choose
.Ed
.Pp
Escape characters must be inserted verbatim, e.g., by pressing C-v ESC in vi,
or C-q ESC in Emacs.
.Ss Pa look
Terminal attributes are accepted in a format similar to that of
.Xr git-config 1 ,
only named colours aren't supported.
For a black-on-white terminal supporting 256 colours, a theme such as the
following may work:
.Bd -literal -offset indent
cursor 231 202
bar 16 255 ul
cwd bold
input
cmdline 145
.Ed
.Sh REPORTING BUGS
Use
.Lk https://git.janouch.name/p/sdn
to report bugs, request features, or submit pull requests.

1405
sdn.cpp

File diff suppressed because it is too large Load Diff

BIN
sdn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB