Skip to content

Commit

Permalink
Add completions for reg.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisant996 committed Mar 22, 2024
1 parent ebf2bf0 commit 04150b0
Showing 1 changed file with 249 additions and 0 deletions.
249 changes: 249 additions & 0 deletions completions/reg.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
require("arghelper")

local function keyname_impl(restricted, _, word_index, line_state, builder, _)
local matches = {}
local info = line_state:getwordinfo(word_index)
if info then
local word = line_state:getline():sub(info.offset, line_state:getcursor() - 1) or ""

local machine = word:match("^(\\\\[^\\]+\\)") or ""
word = word:sub(#machine + 1)

if not word:find("\\") then
matches.nosort = true
if word:match("^[Hh][Kk][LlCcUu]") then
if restricted then
table.insert(matches, machine.."HKLM")
else
table.insert(matches, machine.."HKCU")
table.insert(matches, machine.."HKLM")
table.insert(matches, machine.."HKCC")
table.insert(matches, machine.."HKCR")
table.insert(matches, machine.."HKU")
end
else
if restricted then
table.insert(matches, machine.."HKEY_LOCAL_MACHINE")
else
table.insert(matches, machine.."HKEY_CURRENT_USER")
table.insert(matches, machine.."HKEY_LOCAL_MACHINE")
table.insert(matches, machine.."HKEY_CURRENT_CONFIG")
table.insert(matches, machine.."HKEY_CLASSES_ROOT")
table.insert(matches, machine.."HKEY_USERS")
end
end
elseif restricted and word:upper():find("^HKLM\\+[^\\]*$") then
table.insert(matches, machine.."HKLM\\SOFTWARE")
elseif restricted and word:upper():find("^HKEY_LOCAL_MACHINE\\+[^\\]*$") then
table.insert(matches, machine.."HKEY_LOCAL_MACHINE\\SOFTWARE")
elseif not restricted or
word:upper():find("^HKLM\\SOFTWARE\\") or
word:upper():find("^HKEY_LOCAL_MACHINE\\SOFTWARE\\") then
local lookup = word:gsub("\\+[^\\]*$", "")
local command = string.format('2>nul reg.exe query "%s"', lookup)
local f = io.popen(command)
if f then
clink.matches_are_files(true)
local root = (word:match("^([^\\]+)\\?") or ""):upper()
for line in f:lines() do
if line ~= "" then
if line:sub(1, #machine) == machine then
line = line:sub(#machine + 1)
end
if root then
line = line:gsub("^[^\\]+", "")
end
local key = root and root..line or line
table.insert(matches, machine..key)
end
end
f:close()
end
end
builder:setsuppressappend()
end
return matches
end

local function keyname(word, word_index, line_state, builder, user_data)
return keyname_impl(false, word, word_index, line_state, builder, user_data)
end

local function keyname_hklm_software(word, word_index, line_state, builder, user_data)
return keyname_impl(true, word, word_index, line_state, builder, user_data)
end

-- FUTURE: use onarg and user_data to list existing value names.
local valuename = clink.argmatcher():addarg({fromhistory=true})

local sep = clink.argmatcher():addarg({fromhistory=true})
local find = clink.argmatcher():addarg({fromhistory=true})
local data = clink.argmatcher():addarg({fromhistory=true})
local types = clink.argmatcher():addarg({
nosort=true,
"REG_DWORD",
"REG_SZ",
"REG_EXPAND_SZ",
"REG_QWORD",
"REG_MULTI_SZ",
"REG_BINARY",
"REG_NONE",
})

local common_flags = {
{ "/?", "Show help" },
{ "/reg:32", "Specifies the key should be accessed using the 32-bit registry view" },
{ "/reg:64", "Specifies the key should be accessed using the 64-bit registry view" },
{ hide=true, "/reg:"..clink.argmatcher():_addexarg({
{ "32", "Specifies the key should be accessed using the 32-bit registry view" },
{ "64", "Specifies the key should be accessed using the 64-bit registry view" },
}) },
}

local query = clink.argmatcher():_addexflags({
})
:addarg(keyname)
:_addexflags({
common_flags,
{ "/v", "Queries for a specific registry key values" },
{ "/ve", "Queries for the default value or empty value name (Default)" },
{ "/s", "Queries all subkeys and values recursively (like dir /s)" },
{ "/se"..sep, " Sep", "Specifies the separator (1 char) for REG_MULTI_SZ (Default is \\0)" },
{ "/f"..find, " Data", "Specifies the data or pattern to search for (Default is *)" },
{ "/k", "Search in key names only" },
{ "/d", "Search in data only" },
{ "/c", "Use case sensitive search" },
{ "/e", "Only return exact matches from search" },
{ "/t"..types, " Type", "Specifies registry value data type (Default is all types)" },
{ "/z", "Verbose: Shows the numeric equivalent for the type of the valuename" },
})
:nofiles()

local add = clink.argmatcher():_addexflags({
common_flags,
{ "/v"..valuename, " ValueName", "The value name to add under the selected key" },
{ "/ve", "Adds an empty value name (Default) for the key" },
{ "/t"..types, " Type", "Type to add (Default is REG_SZ)" },
{ "/s"..sep, " Sep", "Specify one character as the separator for REG_MULTI_SZ (Default is \\0)" },
{ "/d"..data, " Data", "The data to assign to the registry ValueName being added" },
{ "/f", "Force overwriting the existing registry entry without prompt" },
})
:addarg(keyname)
:nofiles()

local delete = clink.argmatcher():_addexflags({
common_flags,
{ "/ve", "Delete the value of empty value name (Default)" },
{ "/va", "Delete all values under the specified key" },
{ "/f", "Forces deletion without prompt" },
})
:addarg(keyname)
:nofiles()

local copy = clink.argmatcher():_addexflags({
common_flags,
{ "/s", "Copies all subkeys and values" },
{ "/f", "Forces the copy without prompt" },
})
:addarg(keyname)
:addarg(keyname)
:nofiles()

local save = clink.argmatcher():_addexflags({
common_flags,
{ "/y", "Force overwriting the existing file without prompt" },
})
:addarg(keyname)
:addarg(clink.filematches)
:nofiles()

local restore = clink.argmatcher():_addexflags({
common_flags,
})
:addarg(keyname)
:addarg(clink.filematches)
:nofiles()

local load = clink.argmatcher():_addexflags({
common_flags,
})
:addarg(keyname)
:addarg(clink.filematches)
:nofiles()

local unload = clink.argmatcher():_addexflags({
{ "/?", "Show help" },
})
:addarg(keyname)
:nofiles()

local compare = clink.argmatcher():_addexflags({
common_flags,
{ "/v"..valuename, " ValueName", "The value name to compare under the selected key (Default is all)" },
{ "/ve", "Compare the value of empty value name (Default)" },
{ "/s", "Compare all subkeys and values" },
{ "/oa", "Output all of differences and matches" },
{ "/od", "Output only differences (Default)" },
{ "/os", "Output only matches" },
{ "/on", "No output (exit code 0=identical, 1=failed, 2=different)" },
})
:addarg(keyname)
:addarg(keyname)
:nofiles()

local export = clink.argmatcher():_addexflags({
common_flags,
{ "/y", "Force overwriting the existing file without prompt" },
})
:addarg(keyname)
:addarg(clink.filematches)
:nofiles()

local import = clink.argmatcher():_addexflags({
common_flags,
})
:addarg(clink.filematches)
:nofiles()

local flags_query = clink.argmatcher():_addexflags({
common_flags,
{ "/s", "Queries all subkeys and values recursively (like dir /s)" },
})
:nofiles()

local flags_set = clink.argmatcher():_addexflags({
common_flags,
{ "/s", "Sets flags on subkeys recursively" },
})
:addarg("dont_virtualize", "dont_silent_fail", "recurse_flag")
:loop()

local flags_commands = {
"query" .. flags_query,
"set" .. flags_set,
}

local flags = clink.argmatcher():_addexflags({
})
:addarg(keyname_hklm_software)
:addarg(flags_commands)
:nofiles()

local commands = {
{ "query" .. query, " keyname", "Query keys or values" },
{ "add" .. add, " keyname", "Add a key or value" },
{ "delete" .. delete, " keyname", "Delete keys or values" },
{ "copy" .. copy, " keyname1 keyname2", "Copy keys and values" },
{ "save" .. save, " keyname filename", "Save a hive to a file" },
{ "restore" .. restore, " keyname filename", "Restore a hive from a file" },
{ "load" .. load, " keyname filename", "Load a hive file into a key name" },
{ "unload" .. unload, " keyname", "Unload a loaded hive file from a key name" },
{ "compare" .. compare, " keyname1 keyname2", "Compare keys and values" },
{ "export" .. export, " keyname filename", "Export keys and values to a .reg file" },
{ "import" .. import, " filename", "Import keys and values from a .reg file" },
{ "flags" .. flags, " keyname [query|set]", "Query or set flags for keys" },
}

clink.argmatcher("reg")
:addflags("/?")
:_addexarg(commands)

0 comments on commit 04150b0

Please sign in to comment.