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.
+1 vote
in vifm by
edited by

Is it possible to mark files in Sxiv and get them selected in Vifm?

I have tried this:

fileviewer *.bmp,*.jpg,*.jpeg,*.png,*.gif,*.xpm,*.svg
         \ sxiv -rot -q * | :normal t  &,

It does not work.

Any ideas?

1 Answer

+1 vote
by

You need to use :select command for that:

select! !sxiv -oqt *

This will select only visible files, you might want to use %u macro with recursion:

!sxiv -roqt * %u
by

Hi xaizek,

I'm currently attempting to add the command above to filextype, so when I open sxiv automatically by selecting the file in Vifm, I can mark the file and the selection is reflected in Vifm.

However I'm strugling with the following points:
- The command in the answer above works from the Vifm commandline, however I cannot get it to work from the filextype in vifmrc

-Ideally I would like to combine it with the script to scroll through all images availabe at this forum in https://q2a.vifm.info/431/sxiv-scroll-through-all-images?show=431#q431

What I have done so far is the following:
- Modified the original script to scroll through all images because I couldn't get it to work
- Added the options to return the files marked as a list in sxiv
- The script is working as expected when ran from bash, opens sxiv at the selected file, and scrolls through the files in the correct order, and returns the list of files marked. I also observed that the sorting of the files in Vifm and bash ls differs when the file names have spaces, so in that case the order is slightly diferent, as sxiv takes the file order from bash in the modified script.

The main issue im strugling with is passing the output list to the select command in filextype in vifmrc.

Please find the code samples for the modified bash script and excerpt from vifmrc bellow:

#!/bin/bash

shopt -s nullglob

file=$(basename -- "$1")
dir=$(dirname -- "$1")
arr=()
shift

cd -- "$dir"

for i in *; do
    [[ -f "$i" ]] || continue
    arr+=("$i")
    [[ "$i" == "$file" ]] && n=${#arr[@]}
done

exec sxiv -n "$n" -oq "$dir"

Variant 1

filextype *.bmp,*.jpg,*.jpeg,*.png,*.gif,*.xpm,
    \ {View in feh}
    \:select! play_images %c %i &,

Variant 2

filextype *.bmp,*.jpg,*.jpeg,*.png,*.gif,*.xpm,
        \ {View in feh}
        \ play_images %c %i \| :select &,

Both variants are not working as expected in Vifm, they open sxiv, scroll in the correct order, but don't return the selection.
Could you please advise on how to get this functionallity.

Regards and thanks.

by

Hello,

:filextype isn't meant to process output of external command and can't run builtin :commands. And it wouldn't run such command in background. Maybe calling vifm --remote +'select ...' from the script can serve as a workaround.

Development version supports file viewers written in Lua, file opening might be done in Lua as well (not yet). Lua API is lacking and unstable, but that's probably how this needs to be done (bash script wouldn't be necessary then).

by

Thanks for the prompt reply xaizek, will give it a shot.

by

Any news about that? ;-)

by
edited by

Any news about that? ;-)

Can be improved, but here is a quick version:

--[[

Usage example:

    filextype {*.bmp,*.jpg,*.jpeg,*.png,*.gif,*.xpm} #sxiv#run

--]]

local M = { }

function map(table, functor)
    local result = {}
    for key, value in pairs(table) do
        result[key] = functor(value)
    end
    return result
end

indexMap = { }

local function onExit(job)
    local indices = { }
    for line in job:stdout():lines() do
        table.insert(indices, indexMap[line])
    end

    if job:exitcode() ~= 0 then
        vifm.errordialog("plugin: " .. vifm.plugin.name, "sxiv has failed")
        return
    end

    vifm.currview():select { indexes = indices }
end

local function run(info)
    local view = vifm.currview()

    local files = { }
    indexMap = { }

    local n = 0
    for i = 1, view.entrycount do
        local e = view:entry(i)
        if e.isdir then
            goto continue
        end

        if i == view.currententry then
            n = i
        end

        table.insert(files, e.name)
        indexMap[e.name] = i

        ::continue::
    end

    local job = vifm.startjob {
        cmd = string.format("sxiv -oq -n %d %s", n,
                            table.concat(map(files, vifm.escape), ' ')),
        onexit = onExit,
    }
end

local added = vifm.addhandler {
    name = "run",
    handler = run,
}
if not added then
    vifm.sb.error(string.format("Failed to register #%s#run", vifm.plugin.name))
end

return M

Save it as ~/.config/vifm/plugins/sxiv/init.lua and hook as a file handler like shown at the top comment.

by

Thank you – nice clean code.

Even if we can do the most jobs in vimscript i like the idea of neovims concept of lua implementation since it attracted a lot of new people and invited them to write plugins.

In general all the theming and the plugin system is quite great with lua.

Despite that I love C, vimscript and regexes ¯_(ツ)_/¯

...