Closed jarun closed 4 years ago
My absolutely biggest usability problem at the moment is that I search, don't find what I want and press "up" to access the search history.
In nnn this means that you don't access the search history but move up in the file-list, the status bar is displayed again and your previous search-term is gone for good.
So a big gain for me would be for nnn to at least remember the last search item, so you could search, see what you find, move around, and then maybe slightly tweak your search without having to retype everything. It would be even better if maybe the last 5 items or so could be kept - maybe even saved to disk so that they would be accessible again after a restart.
I don't know if the string-search as it currently works is intended to work across directories, because I could live very well with typing "/" to start a search, then if the next char is again a "/" it will be a regex search (which should be case-sensitive as you can build case-insensitivy into the regex if you want it) and if not it's a string.
So "/hubba" would search case-insensitive for "hubba", while "//h[0-9]{2}" would regex-search for a lower-case h followed by 2 digits. If I also wanted to include upper-case "H", I would simply do "//[hH][0-9]{2}"
I would not really need all the powers of pcres, that would be silly in a file manager, but to be able to search for patters of digits and letters in a simple way would be very handy - so I would like to have things like "\d" or "\w" etc.
One idea would be to allow occurances of \d in a typed-in regex and then translate this regex into a POSIX-compatible version.
That would mean a user could type in "//\d{2}-\d{2} and nnn would in a first step replace all occurances of "\d" with "[[:digit:]]" before it's handed over to the regex-library. In that way there would be no real need for a pcre-engine, while still having the benefit of being able to express pattern is a succinct way suitable for typing in (I do want to search for digits, but I do not want to type "[[:digit:]]" every time).
Oh - to your idea about triggering case-sensitivtiy via capital-letters - I think that's not bad.
"/hubba" => case insensitive /"Hubba" => case sensitive
So how would I search for an all-lower case word in a case-sensitive way?
If regexes would be case-sensitive (as I proposed above) and started with "//" you simply do
"//hubba"
All cases covered I believe.
@ghistes I have added the line items. These are up for grabs now. If possible, please get your hands dirty with the code, understand how it is today and raise PRs.
The last filter is remembered at commit 0e203288b4662c7781a2c5fc519da219f9eb7403.
@ghistes I sent you 2 invites - for nnn
collab and dev-discussions. Can you please join? I want to share the notes I was talking about.
@ghistes
maybe slightly tweak your search without having to retype everything
is not possible without redesigning search. Filters are search as you type - you type the next char and the scan happens. This also helps in having a very efficient algorithm wrt. performance. So if you wanna come back, you have to delete chars and come back. Another advantage is the left and right key work as they should in normal mode.
I don't know if the string-search as it currently works is intended to work across directories,
No, it's not. We can have what you are proposing with some modification I guess.
One idea would be to allow occurrences of \d in a typed-in regex and then translate this regex into a POSIX-compatible version.
This is hacky. Tomorrow there might be another case. I wouldn't want to parse and modify input provided by users. That warrants documentation and may take users by surprise. Compiling in the PCRE lib option is really not that scary. Probably give it a shot yourself.
Oh - to your idea about triggering case-sensitivtiy via capital-letters - I think that's not bad.
It wouldn't work. Say the string is "abcDeF". If you erase F
and come back the logic would need to scan the whole string to determine case-sensitivity. I think the best is to have a toggle.
Similarly I think it would be best to have a toggle like \
to enable regex filter.
regex and string toggle is implemented at 8588b3f0bd39496dbcf481c31aa7a61d7e6df20a.
Toggle filter case-sensitivity is implemented at 70dcbf43d786da63598ad1080c518e4c44baa7bd.
Wow, quick progess again. This is really getting very useful very fast.
There seems to be a little bug (or at least an inconsistent behaviour) with the history:
Press "/" to search. Then enter "n". Files are filtered. Press backspace. Filter is now empty, all files are visible. Press backspace again. Filter-prompt is replaced with status-bar. Press "/" to search again. Now "up" to access history (should either result in an empty filter or "n", depending on whether an empty search should go to history) but what happens is that the filter-prompt is closed and instead a file is selected.
So sometimes "/" + "up" accesses history and sometimes not.
I would want predictable behaviour. When you are in the prompt for a filter "up" should never leave this prompt. When the history is empty then simply nothing should be done.
The current key-bindings have a certain logic, but please keep in mind that "\" and "|" are both a bit awkward to enter on non-us keyboards.
What I ultimately would like to have is remembering maybe 5 history-entries, so you could easily re-run previous searches.
But to do that the history would need to remember not just the filter-expression but also how to interpret them (ie if they should be seen as string or regex, and with what sort of sensitivity).
At the moment (as far as I understand it) the modes seem to be a state not of the individual filter, but of nnn.
So if I do a regex-search and then a string-search (assuming I had more than one history) and then wanted to repeat the regex-search I would have to change the mode first - recalling the history would not be enough.
Ideally I would like to have something like booksmarks for filter, where I could specify a specific filter including all the modes, eg. "=|hubba" to mean a case-insensitive string search for hubba or "/-abc[0-9]*" to mean a case-sensitive regex-search and associate such filter-expressions with a key (like the regular bookmarks) so that these filters could be accessed very fast.
Finally I started to look at the code a little bit and noticed that the dependency on dbg.h is missing from the Makefile and that in the DPRINTF_D-macro there seems to be a spurious LINE at the end that is absent from the other debug-macros.
Do you want a PR for that?
@ghistes please join the nnn-dev discussion.
There seems to be a little bug Press backspace again
The filter is gone.
should either result in an empty filter So sometimes "/" + "up" accesses history and sometimes not.
The filter is empty, meaning there is no filter in history, so the Up arrow's original behaviour picks up. It's the correct behaviour.
I would want predictable behaviour.
Yes, you should predict and expect that when you erased the filter with backspace, the filter is gone. ;) Let's word it this way - the Up arrow shows the last filter if one exists.
The current key-bindings have a certain logic, but please keep in mind that "" and "|" are both a bit awkward to enter on non-us keyboards.
Suggest alternatives. I changed |
to :
.
What I ultimately would like to have is remembering maybe 5 history-entries, so you could easily re-run previous searches. Ideally I would like to have something like booksmarks for filter, where I could specify a specific filter including all the modes, eg. "=|hubba" to mean a case-insensitive string search for hubba or "/-abc[0-9]*" to mean a case-sensitive regex-search and associate such filter-expressions with a key (like the regular bookmarks) so that these filters could be accessed very fast.
Yes. Maybe a better option is to add custom filters with a keybind and use the same keybind to add a filter when the prompt is empty.
But to do that the history would need to remember not just the filter-expression but also how to interpret them (ie if they should be seen as string or regex, and with what sort of sensitivity).
We are talking about a structure with a char pointer and 2 bools here.
Do you want a PR for that?
I had something to push. To removed the spurious arg. Leave the Makefile dep. Not super-important.
Ideally I would like to have something like booksmarks for filter
Should they be pre-defined in your rc file or you would dynamically add and forget during a run? Maybe we can have 5 fixed and 5 dynamic?
Should they be pre-defined in your rc file or you would dynamically add and forget during a run? Maybe we can have 5 fixed and 5 dynamic?
Forget I asked. Maybe we are over-complicating this thing with filtering.
@0xACE @KlzXS @annagrram what do you think?
Ideally (for christmas maybe?) I would like to have nnn remember the last 5 seaches/filters. They should be persisted to a file so they survive a restart.
Also I would like to define searches/filters in the same way as bookmarks work today - every one assigned to a letter via an enviroment variable.
When the search-prompt is open you should be able to navigate through the history with up and down keys.
And there should be a way to fast-acess them by having some hot-key
\
Also I would like to have a way to edit the filter-prompt so you can iteratively build expressions. At the moment all I seem to be able to do is to delete a character from the end and append to the end. So e.g. modifying a regex in the middle is hard work. Maybe some toggle to change the left-right keys from selecting files/dirs to move within the search-expression?
What I am striving for would be a workflow where you open nnn. Go to a bookmark. Run a pre-defined filter (eg list all log-files) with two keystrokes. Then you realise you've got the wrong dir. No problem. You navigate to the proper dir and just re-run your search with two keystrokes. etc etc etc
But clearly this won't happen overnight any maybe you have a different vision...
And if I delete all chars from a filter I still have a filter (it's the emtpy filter showing all files). So if I delete all the chars from a filter the last history-entry is this - the empty filter. And when I then search the history it's not that there is no history.
What I am trying to say is that when you're in the search-prompt and press "up" you should NEVER select a file as (conceptually) the history is never empty.
I really dislike the behaviour that my search-history determines what happens when I press "Up". I don't want to remember what I did before in oder to predict how the app will behave.
But it's a big step forward as it is.
Regarding getting list of files as input. Is it final that we create a subtree with symlinks in /tmp
?
I wanted to discuss what we get for input. Does the user give absolute or relative paths, if absolute, do I assume that they point to something in the subtree of the current working dir i.e. relative paths but with cwd as prefix? Also can I assume that the paths don't contain /./
, /../
and multiple slashes?
I think the tmp dir is the simplest solution. Note that the symlinks may point across volumes. We need to handle that.
Regarding absolute and relative, there can be a mix. We already handle that in main().
We already handle that in main().
What do you mean we already handle it? My main concern is how should the tree in tmp look like. Say I get the following:
/a/b/c/d
/a/b/c/e
/a/b/c/f
Should I make a dir and put symlinks to d, e and f, should I make a dir c and in it make links to the files, should I go even higher? I would need to assume that they are pointing to something in the subtree of the cwd in which case just skip cwd prefix and pretend they are relative paths.
Okk, put symlinks to d, e, f in the same dir.
Ok. I'll make minimal assumptions and we'll see how it behaves.
I'll make minimal assumptions and we'll see how it behaves.
It should work. Because in this particular mode, for each file we will stat with follow_symlink and get the details of the target file.
It will. How does this sound:
realpath()
implementation (call it xrealpath()
) that doesn't resolve symlinksI don't like the second point, but I don't like resolving symlinks even more, because that would make the result look confusing.
Find the longest common prefix of all paths
How does this help?
Say I have
/a/b/c/d/e
/a/b/c/f
/a/b/g
I would display the following
c/d/e
c/f
g
I could display everything, but I think this way is more compact and straight to the point.
Sounds good to me!
Some notes on the algos to avoid re-work (you can suggest better ones, of course):
I think to get the common path you'll use an algo like:
get first file and take it's dirname, get second one, see how far they match (I am not sure if there's an API to do that already) and now this is you minimum common. Match third file's dirname with minimum common and so on...
In case there's no API to find matching parts of strings, check xstrlcpy()
code. We can use sizeof(long)
byte comparisons at a time to find the first non matching 4 or 8 bytes and then XOR and get the offset to the first non-zero byte. It must follow a /
.
Where should we draw the limit to the size of input? I need to allocate some memory for the input, but how much the first time, and when do I stop and say that's too much?
I think we can start with 256 paths which translates to 1MiB, and go up to 216, which is 256MiB. If you need more than that you probably know how to use xargs.
What do you think?
Chunks of 4Kb would be fine with 0 gap. See dentfill on how we do this for file names today.
Ahh OK. The input. I think we should go in steps of 512 KB.
Ok. Do we put an upper limit or do we let it allocate until it crashes the system. I think 216 paths is enough.
2^16 is more than enough!
I noticed there are like 3 occurrences of malloc()
which are not checked for NULL
. Will you take care of this or should I? They are in archive_selection()
, get_kv_val()
and setup_config()
.
Will you take care of this or should I?
Please take care. :)
Please raise this PR separately. We can have it for next release.
Idea: ability to exit nnn
with non-zero exit code.
I have a real-world use-case that I'd like to try out in nnn
(where I currently use vifm
for this), and it requires both take list of files as input and show
(so I would be interested to test a PR when it's ready) as well as ability to exit file manager with non-zero exit code.
Without going too much into details for now, an ability to exit file manager with non-zero exit code allows me to flag if I successfully completed or aborted the task I was doing.
vifm
is a lot like vim
in terms of key bindings, so :q
means "exit vifm with exit code of 0" and :cq
means "exit vifm with exit code of 1". I don't particularly have an opinion whether this should be a separate hotkey or something else (we already have 3 different flavors of "quit" functionality...), open for ideas and proposals.
@KlzXS is already working on the list of files input. Please discuss with him.
Yeah I know, that's why I wrote I would he interested to test the PR 🙂 What do you think about the idea of non zero exit codes though?
non 0 - raise a PR please!
@maximbaz I am considering replacing the config NNN_USE_EDITOR
with a program option -e
. Generally people use nnn
with aliases and reading an env var is costlier than checking an option. What do you think?
I am looking for areas to reduce startup time.
Similarly -t
can replace NNN_IDLE_TIMEOUT
.
you are right about people using aliases, I do that too, and yes to be honest I do find it a bit unusual that some nnn options are configured via env variables and others via cli args.
I would support replacing some env variables with cli flags.
Let me ask this: why not replace ALL env variables with cli arguments?
There is a specific cases where we do not want data loss - NNN_TRASH
.
The longer ones (strings) I want to keep as env vars. Users may find it intimidating they have to type a long option to do something. The alias is not always obvious to newbies.
For now, can you raise a PR for -e
and -t
? I have to go to sleep.
Notes:
I can think of the opposite example, when you create a nnn.desktop as described on wiki, for many people this instance of nnn will not respect environment variables (users must know that they should these env variables not in .bashrc but in e.g. /etc/environment to have effect on nnn started as GUI app), and in this case data loss is very possible. When there only are cli arguments, users know they must pass them, no accidents like that can occur.
I unfortunately forgot my laptop at the office, I'm writing from phone, unable to contribute tonight... But yeah let's pick this up tomorrow!
That's a good point. But let's document that. It's a one time setting for a system. There are instances where people may run nnn
as nnn
without an alias.
I have been away for about a month, and geez a lot of things happened while I was gone.
I try to keep up with master all the time (referring to you asking us to use the master branch), but I run my personal changes ontop of it.
I just spent the last 30minutes rebasing ontop of the latest version. and seems like a lot of keys has been changed. I was in particular not happy with the removal of:
SEL_RUNEDIT
- used to edit rather than executing filesSEL_RUNPAGE
- used to quickly view text filesSEL_EXEC
- execute files which may be defaulted to another action (commonly done on sh
scripts in my case)I tried to skim through the discussion happening. I think KlzXS mentioned the changing of keys being a annoyance, and i agree.
But I would also like to add the changing of command line arguments nnn
takes being annoying. Because that also requires me to update all my machines that use nnn
: because they have their own wrapper script writing over nnn
defaults.
Only my main machine runs on master, my other machines are based on the build from december last year, as i cba to update the commandline parameters on each machine (as my other machines dont have mvg/cpg i have to maintain a seperate config). and I'm dropping nnn.vim
on my machine because it also needs another update because of this (though mostly over the past 6 months I have never used any thing to open files in vim other than :e
, gf
and various tag-jumping method...)
I'm still working on rebasing my personal
branch ontop of master and will have to give a long term review at a later point. as I still haven't got my nnn
environment restored...
Don't worry! These are convered. Only with more regular workflows.
Runedit and runpage can be easily achieved through run cmd as plugin. I have updated the plugin docs with your use-case in mind - https://github.com/jarun/nnn/tree/master/plugins#some-useful-key-command-examples
I am using EDITOR that way myself with ;e
.
SEL_EXEC
- did you try "./$nnn" at the prompt?
But I would also like to add the changing of command line arguments nnn takes being annoying
This has also been addressed and frozen in #422.
I'm dropping nnn.vim on my machine because it also needs another update because of this
Do you mean the plugin needs a change? Then @mcchrish should be informed right away.
Don't worry! These are convered. Only with more regular workflows.
Runedit and runpage can be easily achieved through run cmd as plugin. I have updated the plugin docs with your use-case in mind - https://github.com/jarun/nnn/tree/master/plugins#some-useful-key-command-examples
I am using EDITOR that way myself with
;e
.
Ah, my dumbass just got into the seat cold and started tinkering on things, ofc a plugin can do that... Alas as I have made another patch for it. i'm maintining it as seperate until i grow tired.
SEL_EXEC
- did you try "./$nnn" at the prompt?
That's too many characters to hit for something i use commonly, i guess a plugin keystroke would do it better. but again I'll maintain this locally until i grow tired.
But I would also like to add the changing of command line arguments nnn takes being annoying
This has also been addressed and frozen in #422.
Yeah, i tried to read that thread but as my time was limited with all the catching up i had to do i couldn't read it through and through...
I'm dropping nnn.vim on my machine because it also needs another update because of this
Do you mean the plugin needs a change? Then @mcchrish should be informed right away.
Well I have this in my ~/.vimrc
let $NNN_BMS=$NNN_BMS
let $NNN_USE_EDITOR=$NNN_USE_EDITOR
let $NNN_NO_AUTOSELECT=$NNN_NO_AUTOSELECT
let $NNN_NOTE=$NNN_NOTE
let $NNN_OPS_PROG=$NNN_OPS_PROG
let $NNN_CP_MV_PROG=$NNN_CP_MV_PROG
let $NNN_SSHFS_OPTS=$NNN_SSHFS_OPTS
let $NNN_TRASH=$NNN_TRASH
let $NNN_COPIER=$NNN_COPIER
let $NNN_RESTRICT_NAV_OPEN=$NNN_RESTRICT_NAV_OPEN
let $NNN_OPENER=$NNN_OPENER
let $NNN_CONTEXT_COLORS=$NNN_CONTEXT_COLORS
let $NNN_IDLE_TIMEOUT=$NNN_IDLE_TIMEOUT
let $NNNLVL=$NNNLVL
I guess the probelm wasn't updating the commandline arguments, i guess it was the environment variable name changes. as you can see, some of those variable names has been deprecated... alas i tried it out for months and it never entered my workflow, i haven't used any of the other navigation plugins for vim either, im rather plugin free tbh (though vim-surround
should be included in the default build if you ask me)
Shall we change $nnn
to $n
? What issues do you guys see? Any possibility of conflict with n used as var in a script?
Rolled from #386.
For next release
-e
replacesNNN_USE_EDITOR
-t
replacesNNN_IDLE_TIMEOUT
umount
on macOS to unmountglow
as Markdown viewer innuke
Proposed features and tasks (up for grabs)
nnn.vim
plugin to show a persistent bar (https://github.com/mcchrish/nnn.vim/issues/46)nnn
pluginsAnything else which would add value (please discuss in this thread).
List of completed features and tasks.