Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simple :sh command substitutions #3134

Open
aikomastboom opened this issue Jul 21, 2022 · 27 comments · May be fixed by #11164
Open

Simple :sh command substitutions #3134

aikomastboom opened this issue Jul 21, 2022 · 27 comments · May be fixed by #11164
Labels
A-helix-term Area: Helix term improvements C-enhancement Category: Improvements

Comments

@aikomastboom
Copy link
Contributor

It would be nice to be able to reference editor information on the :sh line.

Things like for example:

subs description
$fn filename (= $bn.$ex)
$bn basename
$ex extension
$fp full path
$rp relative path (to .git root?)
$ln line number

to be able to execute things like:

:sh gh browse $fn:$ln

Of course above example is just a starting point to get the idea across.

@aikomastboom aikomastboom added the C-enhancement Category: Improvements label Jul 21, 2022
@kirawi kirawi added the A-helix-term Area: Helix term improvements label Jul 22, 2022
@the-mikedavis
Copy link
Member

It's a bit of a nit but I'd prefer more explicit names like $file, $line rather than two-character shortcuts. They're not very discoverable and are only marginally easier to type

@aikomastboom
Copy link
Contributor Author

Indeed, whole words as tokens is indeed nicer, especially when combined with completion to speed up the typing.

Also it occurred to me the $ prefix may not be such a great idea, as it commonly used by sh itself. What about # as a tokenizer?

  • #line
  • #filename
    Etc. (TBD)

@the-mikedavis
Copy link
Member

I imagine this would be implemented by setting environment variables for the shell command and then the shell command would interpret them - so $var for unix-like and %var% or whatever it is for windows - rather than a search-and-replace or templating language rendered ahead of time.

@aikomastboom
Copy link
Contributor Author

Ah, yes, of course we have full control over the env space at execution time.

Still would like to have some help typing the longer vars though ;)

@AceofSpades5757
Copy link
Contributor

I think longer variable names also follows Helix' way of doing things. I imagine that aliases would be implemented in the future with more configuration options.

Instead of environment variables, configuration variables could be used as well, for the project/.helix directory.

@aikomastboom
Copy link
Contributor Author

aikomastboom commented Jul 28, 2022

Revised table:

env description
$HX_FILENAME filename
$HX_BASENAME basename
$HX_FILE_EXT file extension
$HX_PATH full absolute path
$HX_RELATIVE_PATH relative path (to .git root? or $CWD)
$HX_LINE line number
$HX_COLUMN cursor pos (on line)

@the-mikedavis
Copy link
Member

I think we should start small: we probably only need file, line and column. The others can be derived in the shell with basename/extname/dirname/pwd/etc (I'm sure windows has equivalents, right? 🙃)

@aikomastboom
Copy link
Contributor Author

I would suggest keeping $HX_PATH as this is a known fact of the editor, not having it would add unneeded clutter to constructing an arbitrary command line.

@aikomastboom
Copy link
Contributor Author

... (I'm sure windows has equivalents, right? 🙃)

🕵️‍♂️ No clue either, haven't used it in a long time.. but I certainly hope command.com got improved upon. 🤔 Is Cygwin still around?

@AceofSpades5757
Copy link
Contributor

Windows has the capacity to derive the same values and Cygwin, or similar programs, are available. I'd recommend WSL if you need Linux capabilities, though, compared to Cygwin or other alternatives.

@devyn
Copy link
Contributor

devyn commented Aug 4, 2022

I kind of like the way Kakoune does it. They have interpolations like %val{bufname} (access a value) or %opt{filetype} (access an option), but some common things are also in registers, which Helix already supports, but they just have more of them. The % register contains the buffer name, so you can always <C-r> % to get the buffer name.

On that note I'd love to be able to access the regex captures that way too - registers 0-9 in Kakoune are used for the capture groups. So you can s pattern <ret> c <C-r> 1 <esc> to replace with capture group 1 for example.

@AceofSpades5757
Copy link
Contributor

@devyn Ah, that's an interesting take on it. Looks pretty nice. I wonder if there's a common Rust library that essentially does the same thing.

Kakoune Commands (Prompt)
Kakoune Prompt Expansion

The only expansions I can think of with Vim is % and #, but I'm really not a fan of how unintuitive it feels. I'm sure there are other things that I'm simply not aware of, given the docs and implementation.

@mindreader
Copy link

The percent register comes from vim. I have a habit of constantly in vim using adhoc shell commands like eg. !git diff %. (diff of the current file), !ls %:s/src/ (list of a subdirectory of the current file's location). And I'm kind of missing it.

Bonus points for keeping it simple to type.

@georgesboris
Copy link

it would be great to define custom variables like these as part of my config as well - I'm currently using kitty remote to trigger tests, file browser, etc. however, every command I build has to begin with 40 characters of setup before I get to my 6 character's command and sh apparently doesn't get access to my shell's aliases so I can't make these shorter outside helix as well...

e.g.

[keys.normal]
C-f = ":sh kitty @ launch --no-response --copy-env --hold --cwd=current --type=overlay lf"
C-t = ":sh kitty @ launch --no-response --copy-env --hold --cwd=current --type=tab mix test"
C-T = ":sh kitty @ launch --no-response --copy-env --hold --cwd=current --type=tab pnpm test"

vs

[keys.normal]
C-f = ":sh $HX_OVERLAY lf"
C-t = ":sh $HX_TAB mix test"
C-T = ":sh $HX_TAB pnpm test"

[shell]
OVERLAY = "kitty @ launch --no-response --copy-env --hold --cwd=current --type=overlay"
TAB = "kitty @ launch --no-response --copy-env --hold --cwd=current --type=tab"

@sebashwa
Copy link

sebashwa commented Dec 9, 2022

It could potentially be useful to also provide context information like the class / function path names relative to the current cursor position e.g. to trigger single tests for some test runners. See also #5014 (comment).

@sporto
Copy link

sporto commented Feb 1, 2023

I would love something like this to be able to make a copy of the current file I am working on in the same directory. e.g.

Given I have a/b/one.txt opened, I will like to create a/b/two.txt with something like

:w $pwd/two.txt

@rcorre
Copy link
Contributor

rcorre commented Feb 10, 2023

to be able to execute things like:

:sh gh browse $fn:$ln

This is the exact use case I came here looking for. It would be nice to support a multiline selection (like GBrowse from vim-fugitive). Would it be reasonable to add $HX_LINE_END and $HX_COLUMN_END?

I'm assuming that the LINE/COLUMN vars refer only to the primary selection, and other cursors are ignored, right? Or do we run the command separately on each selection?

@edrex
Copy link

edrex commented Apr 12, 2023

Not being able to have commands parameterized by either context variables like the current file or the output of a shell command is blocking so many workflow integration tasks for me (stuff like keys.normal."\\".j = ":o ~/journal/%sh{my-date-alias}.md" using the syntax of #3393), but I don't have Rust chops (yet) and haven't wanted to be a "me too" clogging that PR's thread.

I think simple and well-designed shell-integration features like this, the existing shell_* family of commands, and a good implementation of job-control-based tag-teaming with other apps like ranger, as laid out in kakoune/wiki: Integrating Other CLI Apps (I'll probably do this and document it soon, if someone else doesn't) can take care of a large portion of the use cases a lot of folks are thinking of when they go looking for a "Plugin system", leaving the real eventual plugins API (#3806) the remaining usecases that require substantial, nontrivial, and deep integration with Helix. Thanks for listening to my TED talk.

@pascalkuthe pascalkuthe linked a pull request May 13, 2023 that will close this issue
@edrex edrex mentioned this issue May 17, 2023
@mostafaqanbaryan
Copy link

This is a really important feature for using helix.
Apparently #6979 got stuck.
I hope it'd be merged soon.

@CAESIUS-TIM
Copy link

Is there a way to copy %(document path) to *(system path) for a temporary solution? Thanks!

@finalclass
Copy link

This one is the only issue that is keeping me from switching to helix. The thing is that helix has great built in features however there are few things which are non standard that I heavily rely on. Unfortunately helix is not giving us any way to integrate custom stuff. Adding a way to pass information about current selection (or current cursor positions) to a shell script would solve 90% of the issues.

@cpdean
Copy link

cpdean commented May 6, 2024

The PR that has been open for a while to implement this appears to be stuck on some tricky parsing issues. I wonder if we can sidestep the need to figure out the ideal variable expansion implementation by having :sh set a bunch of environment variables instead? That way we can at least write scripts that use the environment variables instead of using positional arguments. Even if the script is just

#!/bin/bash

command_that_needs_positional_args $HELIX_FILENAME $HELIX_LINE_NUMBER $HELIX_COLUMN_NUMBER

Compared to the command parsing issues of #6979, it would be both simpler as well as not introducing any changes that would be broken when that PR eventually merges.

@quantonganh
Copy link
Contributor

Adding a way to pass information about current selection to a shell script would solve 90% of the issues.

@finalclass: Have you tried yank_main_selection_to_clipboard then pipe it to a shell script by using :sh, :insert-output, ...:

[keys.select.";"]
q = ["yank_main_selection_to_clipboard", "delete_selection", ":insert-output echo `pbpaste` | quicktype -l go"]

or current cursor positions

WezTerm has a feature to get the content of a pane. In the mean time, would you like to give it a try?

status_line=$(wezterm cli get-text | rg -e "(?:NORMAL|INSERT|SELECT)\s+[\x{2800}-\x{28FF}]*\s+(\S*)\s[^│]* (\d+):*.*" -o --replace '$1 $2')
filename=$(echo $status_line | awk '{ print $1}')
line_number=$(echo $status_line | awk '{ print $2}')

https://quantonganh.com/2023/08/19/turn-helix-into-ide.md#running-code

@rcorre
Copy link
Contributor

rcorre commented May 6, 2024

Have you tried yank_main_selection_to_clipboard then pipe it to a shell script by using :sh, :insert-output, ...:

@quantonganh I'm not sure how this is different from :pipe. The issue is that you have no positional information, which is necessary for things like gh.

@quantonganh
Copy link
Contributor

Sorry for breaking up the @finalclass's question into two smaller questions.

@rcorre I meant that:

  1. To pipe the current selection to a shell script, we can use: yank_main_selection_to_clipboard, then :pipe, :insert-output, ...

  2. To get the current cursor positions, I'm using wezterm cli get-text to parse the status line to get the filename and the line number. Then we can open it in the browser by using something like:

  "open")
    remote_url=$(git config remote.origin.url)
    if [[ $remote_url == *"github.com"* ]]; then
      gh browse $filename:$line_number
    else
      current_branch=$(git rev-parse --abbrev-ref HEAD)
      open $(echo $remote_url | sed -e 's|:|/|' -e 's|\.git||' -e 's|git@|https://|')/-/blob/${current_branch}/${filename}#L${line_number}
    fi
    ;;

@rcorre
Copy link
Contributor

rcorre commented May 6, 2024

My bad @quantonganh, I didn't read closely enough. It would still be great to have a non-terminal specific solution, but that's a neat workaround!

@rcorre rcorre linked a pull request Aug 7, 2024 that will close this issue
@the-mikedavis the-mikedavis linked a pull request Aug 7, 2024 that will close this issue
@7flash
Copy link

7flash commented Sep 15, 2024

it would be great to define custom variables like these as part of my config as well - I'm currently using kitty remote to trigger tests, file browser, etc. however, every command I build has to begin with 40 characters of setup before I get to my 6 character's command and sh apparently doesn't get access to my shell's aliases so I can't make these shorter outside helix as well...

e.g.

[keys.normal]
C-f = ":sh kitty @ launch --no-response --copy-env --hold --cwd=current --type=overlay lf"
C-t = ":sh kitty @ launch --no-response --copy-env --hold --cwd=current --type=tab mix test"
C-T = ":sh kitty @ launch --no-response --copy-env --hold --cwd=current --type=tab pnpm test"

vs

[keys.normal]
C-f = ":sh $HX_OVERLAY lf"
C-t = ":sh $HX_TAB mix test"
C-T = ":sh $HX_TAB pnpm test"

[shell]
OVERLAY = "kitty @ launch --no-response --copy-env --hold --cwd=current --type=overlay"
TAB = "kitty @ launch --no-response --copy-env --hold --cwd=current --type=tab"

In your example, how can you reference the file currently opened in helix active buffer? Let's say you don't want to do "pnpm test" over all the files but just current one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-helix-term Area: Helix term improvements C-enhancement Category: Improvements
Projects
None yet
Development

Successfully merging a pull request may close this issue.