kamiyaa / joshuto

ranger-like terminal file manager written in Rust
https://crates.io/crates/joshuto
GNU Lesser General Public License v3.0
3.43k stars 151 forks source link

Add more parameter-variables to more commands (like `%s` for `shell`) #456

Open DLFW opened 11 months ago

DLFW commented 11 months ago

Hi, to get on with https://github.com/kamiyaa/joshuto/issues/241#issuecomment-1546851335, I would maybe try to add more variables to more commands soon.

Currently, only spawn and shell support the variable %s, which is substituted by a list of names of the selected files.

The idea is...

  1. ...to provide more variables (like d for the current directory, or t for a list of directories of all tabs )
  2. ...to equip more commands with the ability to evaluate these variables
  3. ...and to provide variables for the exit code and stdout of the last shell sub-process

Point 1. would allow to hand over more information to external scripts, like the list of tabs, the highlighted file, or the current directory.

With 2. and 3. and the command-chains, introduced in 31beaab, it would be possible to process the output of scripts in joshuto, like opening a new tab in a directory that was calculated by a script, or to select certain files (would require a new command to select multiple files by index or name).

As we would have to format dynamic strings with a potentially growing number of named variables, this would require some kind of dynamic string formatting library or a template engine that is able to substitute sub-strings by name, not only by position. Because we don't want some complex HTML-template engine for this, I see only two options at hand in Rust-land:

If somebody knows a better alternative, please let me know.

However, all these solutions would require a breaking change in Joshuto: %s would change to something else, for example {{s}}. @kamiyaa: Would that be acceptable?

I would probably implement the variable substitution in src/key_command/impl_from_str.rs, either for some dedicated commands or for the complete command-line string as it comes in. Have to think about it.

Input welcome. Maybe I would take this up in the next weeks.

kamiyaa commented 10 months ago

However, all these solutions would require a breaking change in Joshuto: %s would change to something else, for example {{s}}. @kamiyaa: Would that be acceptable?

I'm cool with breaking changes if it means better UX and maintainability moving forward

DLFW commented 7 months ago

Hi, I'm not much further on this, I just was too busy with other stuff.

However, I did some experimental implementations around Christmas and I came to the conclusion that a generic variable solution I had in mind won't work well with the current way Joshuto parses the command line input. To get such a solution straight, it would require a complete refactoring of Joshuto's command handling. The problem is mostly with escaping and quoting (I don't even remember all the details). I thought of introducing some CLI parser library (like clap) to parse the commands, but that would be too much effort for me at the moment. In any case, it would have some negative impact on performance. (don't know how much; maybe negligible).

I then re-thought to just introduce new variables the same way we already have %s, but this also has significant downsides (my [personal notes here](), in case somebody is really interested). Essentially, each command needs to implement each supported variable on its own and I think this could turn into quite some mess (code-wise) and a non-intuitive UI.

My latest idea now is to leave all commands just as they are but to introduce one new command, which I currently call stdout in my head. This command's job is to do something with the stdout of the last shell command.

This stdout command would take an action as first (and usually only) parameter. An action could for example be

So, instead of using variables with the stdout content for the existing command, I would add one new command that takes some “last-stdout” specific action as parameter. It's less generic, but more explicit and does not negatively impact the code, the usability, or the performance.

Just dumping my thoughts here. If somebody has ideas or opinions, feel free.... 😉 I hope I will finally find some time to work on this.