Welcome to Vifm Q&A, where you can ask questions about using Vifm. Registration is optional, anonymous posts are moderated. E-mail and GitHub logins are enabled.
0 votes
in vifm by

Let's say I have a directory with media files A.mp4, B.mp4 .. K.mp4. I want to feed three of them to mpv, but want to play them in a particular order, like
:! mpv G.mp4 A.mp4 D.mp4 &

In Midnight Commander I can do that, without manually typing the file names potentially combined with tab expansion, by just putting the cursor on each file I want and then press Alt+Enter, and thus collect the files on the cmdline in any order I want.

In vifm this doesn't seem possible. Macro expansion always seems to impose a default sort order anyway, also on register content I may have edited manually (like after :regedit and ordering files the way I want, %r sorts them anyway). And while cmdline mode knows C-x c for yanking the current file into the command line there isn't any way to move the cursor in that mode and yank another one.

Am I missing something or is that just the way it is?

1 Answer

0 votes
by

Not sure this use case was considered before. Registers might have allowed it in the past before the introduction of sorting to improve performance.

It can still be done in a way similar to MC, but one needs to recognize the differences between the command-lines: while it's independent in MC, it's mutually exclusive with navigation in Vifm. So one way to address the difference is by reentering command-line mode when needed.

If you add a mapping like

nnoremap + :<c-p> <c-x>c

you can start with :!mpv, then press + over a file, then hit Escape and repeat. Alternatively end the mapping with <esc> and execute the command with . (it runs the last command in history even if it wasn't executed before).

Moving in command-line is similarly possible by temporary leaving the mode:

cnoremap <silent> <c-k> <esc>k:<c-p>
cnoremap <silent> <c-j> <esc>j:<c-p>

It's also possible to do it without leaving the mode by implementing such shortcuts in Lua. Can show how, if you would prefer that kind of solution.

by

This is great. Didn't test it yet but can already see how it's supposed to work. Lua implementation you don't need to show me, that it can be done is all I need to know.

Surprised, by the way, to hear that this would be an uncommon question. Wanting to have files processed in a particular order, like when creating an on-the-fly playlist, appears to be a natural thing for me.

Thanks, mate. That was the last obstacle in the way of me feeling confident in making the switch. Much obliged.

by
nnoremap + :<c-p> <c-x>c

the code above works well, I've just tested it

1) :!mpv then enter
2) press + over a file
3) esc
4) repeat + and esc over other files
5) run with .

another possibility

1) :!mpv then enter
2) press char of your choice in this example K
3) use tabs for auto-completion
4) move in the list with arrow up und down
5) select with right arrow - will escape too
6) repeat
7) run with .

Note: if a directory is selected, it is read in order

by

Just a brief followup, in case anyone stumbles upon this and wonders.

The above bindings do work and effectively rely on the same pattern, which is based on the fact that a command line is saved to history even if you escape out of the command line and don't execute it.

They're all variations of entering the command line with : and/or escape out with <esc>, recall the last line from the command line history with <c-p>, and do something with it like insert the current entry with <c-x>c.

The first '+' mapping you use in normal mode, which has the advantage of having all normal mode features available, like jumping around in the list, searching, filtering and so forth. The disadvantage is that you can only append to your list of files on the command line, because the history doesn't memorize cursor positions, so <c-p> always makes the cursor jump to the end of the line.

The other two mappings you use in command line mode to move the cursor up and down in the view, meaning you escape out, move the cursor, then enter command line mode again followed by a <c-p> and can then insert the current entry manually with <c-x>c.

The latter has the disadvantage that you effectively end up re-implementing normal mode motion commands in a very limited fashion, but you can, once you put the cursor on the entry you want, then move the cursor around in the command line and do the insertion anywhere you want, like when you want to preprend to your list of files. So realistically one would probably use all three of those bindings and become accustomed to the workflow.

As to Lua, you can for example implement the cursor motion commands, presumably without leaving command line mode, by assigning to vifm.currview().cursor.pos, but I don't see much of a benefit. How this may work, generally, can be gathered from the 'recent-entry' plugin example in the vifm source tree.

Another approach which seems to have some appeal is to write a wrapper script which allows you to edit/sort the current selection in a file and then use that to run a command on it. Like

#!/bin/sh

# needs command to run plus at least one file argument as params
[ $# -lt 2 ] && exit

file=/tmp/vifm-tmpfile
cmd="$1"
shift

ls -1d "$@" > $file
vi $file

lines=`wc -l $file | cut -d' ' -f1`
[ "$lines" -gt 0 ] || exit

cat $file | xargs -d'\n' "$cmd" &

Call that script vifm-run for example, put in in your scripts directory and then define

command! vmpv vifm-run mpv %f

That way you can run mpv on any selection, with :vmpv, after having edited/rearranged that selection in vi. That may actually end up being my preferred solution.

...