xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit 2a628bc8bed48ee9ad7828a8c4b524783ef092dc

git: add :Gmap command
Adds a simple replacement rule for Git statuses.
Author: xaizek
Author date (UTC): 2026-03-30 09:18
Committer name: xaizek
Committer date (UTC): 2026-03-30 10:49
Parent(s): c0efa1983a0215d5cc015487aec1ecfee8b5a936
Signing key: 99DC5E4DB05F6BE2
Tree: 4f06de06640fac8ac63e1f3f6cb3bad2febb1937
File Lines added Lines deleted
data/plugins/git/README.md 18 0
data/plugins/git/init.lua 50 7
File data/plugins/git/README.md changed (mode: 100644) (index fe36a9c0e..6cc7e5af2)
... ... dialog.
26 26 2. Destination (optional). Derived from the last component of the URL removing 2. Destination (optional). Derived from the last component of the URL removing
27 27 `.git` suffix. `.git` suffix.
28 28
29 ### `:Gmap` command
30
31 Adds a simple replacement rule for Git statuses. Each new rule is appended to
32 the list. The rules are processed in the order of their definition, therefore
33 earlier ones have higher priority and rules with wildcards should follow more
34 specific ones.
35
36 **Examples:**
37
38 * `:Gmap D* x` marks files that are deleted in index (`D ` and `DU`) with `x`.
39 * `:Gmap ?? —` replaces `??` with `—`.
40
41 **Parameters:**
42
43 1. Pattern (required). A two-character sequence where `*` is used as a
44 wildcard that matches any character.
45 2. Replacement (required).
46
29 47 ### `GitStatus` view column ### `GitStatus` view column
30 48
31 49 When inside a Git repository, displays status of files and directories in a way When inside a Git repository, displays status of files and directories in a way
File data/plugins/git/init.lua changed (mode: 100644) (index 781f54fe2..1005241ab)
... ... local statuses = vifm.plugin.require('statuses')
2 2
3 3 local M = {} local M = {}
4 4
5 -- array of {pattern, replacement}
6 local map_rules = { }
7
5 8 local function clone_command(info) local function clone_command(info)
6 9 local url = info.argv[1] local url = info.argv[1]
7 10
 
... ... local function clone_command(info)
34 37 end end
35 38 end end
36 39
40 local function map_command(info)
41 for _, entry in ipairs(map_rules) do
42 if entry[1] == info.argv[1] and entry[2] == info.argv[2] then
43 -- don't add duplicates
44 return
45 end
46 end
47
48 map_rules[#map_rules + 1] = info.argv
49 end
50
51 local function char_matches(char, pattern)
52 return pattern == '*' or char == pattern
53 end
54
55 local function status_matches(status, pattern)
56 return char_matches(status:sub(1, 1), pattern:sub(1, 1))
57 and char_matches(status:sub(2, 2), pattern:sub(2, 2))
58 end
59
60 local function map_status(status)
61 for _, entry in ipairs(map_rules) do
62 if status_matches(status, entry[1]) then
63 return entry[2]
64 end
65 end
66 return status
67 end
68
37 69 local function status_column(info) local function status_column(info)
38 70 local e = info.entry local e = info.entry
39 71
 
... ... local function status_column(info)
44 76
45 77 local status = node.items[e.name] local status = node.items[e.name]
46 78 if status ~= nil then if status ~= nil then
47 return { text = status }
79 return { text = map_status(status) }
48 80 end end
49 81
50 82 local sub = node.subs[e.name] local sub = node.subs[e.name]
51 83 if sub ~= nil and sub.status ~= nil then if sub ~= nil and sub.status ~= nil then
52 return { text = sub.status }
84 return { text = map_status(sub.status) }
53 85 end end
54 86
55 87 return { text = '' } return { text = '' }
56 88 end end
57 89
58 local added = vifm.cmds.add {
90 local function add_cmd(info)
91 -- this does NOT overwrite pre-existing user command
92 local added = vifm.cmds.add(info)
93 if not added then
94 vifm.sb.error(string.format("Failed to register %s", info.name))
95 end
96 end
97
98 add_cmd {
59 99 name = "Gclone", name = "Gclone",
60 100 description = "clone a repository and enter it", description = "clone a repository and enter it",
61 101 handler = clone_command, handler = clone_command,
62 102 minargs = 1, minargs = 1,
63 103 maxargs = 2, maxargs = 2,
64 104 } }
65 if not added then
66 vifm.sb.error("Failed to register :Gclone")
67 end
105
106 add_cmd {
107 name = "Gmap",
108 description = "map status to a custom value",
109 handler = map_command,
110 minargs = 2,
111 }
68 112
69 113 local added = vifm.addcolumntype { local added = vifm.addcolumntype {
70 114 name = "GitStatus", name = "GitStatus",
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master