5

Is it possible to get the line numbers of selected text to pass to an external command?

Context: I'd like to integrate pyfmt into vim. Ideally, I'd like to be able to select some text and type some shortcut to have the selected text reformatted by pyfmt.

So far I've found that running !pyfmt -i % will format the whole file. pyfmt also supports a --lines START-END option. I'd like to be able to pass the line numbers of the beginning and end of the selected text to pyfmt so that only what I want to reformat gets reformatted. Is this possible?

1

2 Answers 2

8

The line numbers of the selected text are available in the marks < and >. So you can use e.g. echo getpos("'<") and echo getpos("'>") to get the start and end of the selected text.

However I'd like to point out, that you might be over complicating your problem. Your problem can usually be simply achieved, by filtering the selected text through the formatter. Read the help at :h filter. So you could simply visually select your text type !pyfmt and the pyfmt will be run with the selected text as input and whater it outputs will be replaced in your buffer.

This however only works, if the formatter actually takes input from stdin and outputs it to stdout. Not all formatter support that (and it might not even make sense for them), but you might want to check, if pyfmt actually does support this mode.

1
  • If OP is using pypi.python.org/pypi/pyfmt, then I had to use /dev/stdin as the filename. It wouldn't accept -, and without any filenames it simply exits with the help message.
    – muru
    Commented Jul 19, 2017 at 7:18
2

To get line numbers of selected text:

  • Start: line("'<")
  • End: line("'>")

If you want to check it: :echo line("'<") (note: this echo is not the external command echo)

To pass it to an external command:

For example, if you want to run something like git blame -L 18,22 main.py, you can use exe (see: :h execute) like this:

:exe '!git blame -L' line("'<").','.line("'>") 'main.py'

If you're inside main.py:

:exe '!git blame -L' line("'<").','.line("'>") expand('%:t')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.