zoxide
zoxide copied to clipboard
Support for cmd.exe
Usually I use cmder as a shell which mostly wraps cmd in Windows -- and I'm really happy with it -- i.e.: https://cmder.net/ (https://github.com/cmderdev/cmder).
Is it possible to use zoxide in it? I only found instructions for power shell in windows, not really cmd, but maybe I missed something...
Hey @fabioz, cmd.exe is not supported at the moment, you'd only be able to use cmder with the Bash and PowerShell modes. I don't know cmd.exe, so I can't be very helpful here -- but if you're proficient with it, it shouldn't take very long to implement:
zcallszoxide querycdcallszoxide addzoxide init <SHELL>is a useful reference for how this is implemented in other shells.
Unless this issue gains a lot of traction, I'd be hesitant to support it officially:
- Microsoft is moving everything over to PowerShell as the new default
- cmd.exe has been deprecated for years now
However, if you do end up implementing it on your own, do post it here -- I'm sure other cmd.exe users would find it helpful.
I use cmd too and I would like support for zoxide. Powershell is terrible.
@ajeetdsouza FWIW, cmd on its own isn't very configurable. Cmder uses a framework called Clink which adds Bash's Readline support to it and makes it highly extensible (there's a comprehensive documentation available here).
However, if z and cd are the only two commands/functions as you specified above, then they can be easily added through doskey aliases:
doskey z=zoxide query $*doskey cd=zoxide add $1 $T cd /d $1
Yeah, is it possible to get clink support for this?
It's quite powerful and I think z.lua already does support it.
Here's a lua script I wrote for cmd.exe with clink. Put this into a zoxide.lua file in clink's lua scripts location. For cmder you can put it in %cmder_root%\config\zoxide.lua.
I only did some manual testing but it should be able to support many of zoxide's features including:
zoxide initoptions--cmd,--hook, and--no-alias(using clink settings)_ZO_ECHOenvironment variable- fzf integration via
zicommand
-- =============================================================================
--
-- Settings copied from 'zoxide init'. Run `clink set` to modify these options, e.g. `clink set zoxide.cmd f`
--
settings.add('zoxide.cmd', 'z', 'Changes the prefix of the aliases')
settings.add('zoxide.hook', { 'pwd', 'prompt', 'none' }, 'Changes when directory scores are incremented')
settings.add('zoxide.no_aliases', false, "Don't define aliases")
-- =============================================================================
--
-- Utility functions for zoxide.
--
-- Generate `cd` command
local function __zoxide_cd(dir)
if os.getenv '_ZO_ECHO' == '1' then
print(dir)
end
-- 'cd /d -' doesn't work for clink versions before v1.2.41 (https://github.com/chrisant996/clink/issues/191)
-- lastest cmder release (v1.3.18) uses clink v1.1.45
if dir == '-' and (clink.version_encoded or 0) < 10020042 then
return 'cd -'
end
return 'cd /d ' .. dir
end
-- Run `zoxide query` and generate `cd` command from result
local function __zoxide_query(options, keywords)
options = table.concat(options, ' ')
keywords = table.concat(keywords, ' ')
local file = io.popen('zoxide query ' .. options .. ' -- ' .. keywords)
local result = file:read '*line'
local ok = file:close()
if ok then
return __zoxide_cd(result)
else
return 'call' -- no-op that just sets %ERRORLEVEL% to 1
end
end
-- Add directory to the database.
local function __zoxide_add(dir)
os.execute('zoxide add -- "' .. dir .. '"')
end
-- =============================================================================
--
-- Hook configuration for zoxide.
--
local __zoxide_oldpwd
local __zoxide_prompt = clink.promptfilter()
function __zoxide_prompt:filter()
local zoxide_hook = settings.get 'zoxide.hook'
if zoxide_hook == 'none' then
-- do nothing
return
elseif zoxide_hook == 'prompt' then
-- run `zoxide add` on every prompt
__zoxide_add(os.getcwd())
elseif zoxide_hook == 'pwd' then
-- run `zoxide add` when the working directory changes
local cwd = os.getcwd()
if __zoxide_oldpwd and __zoxide_oldpwd ~= cwd then
__zoxide_add(cwd)
end
__zoxide_oldpwd = cwd
end
end
-- =============================================================================
--
-- Define aliases.
--
-- 'z' alias
local function __zoxide_z(keywords)
if #keywords == 0 then
return __zoxide_cd(os.getenv 'USERPROFILE')
elseif #keywords == 1 then
local keyword = keywords[1]
if keyword == '-' then
return __zoxide_cd '-'
elseif os.isdir(keyword) then
return __zoxide_cd(keyword)
end
end
local cwd = '"' .. os.getcwd() .. '"'
return __zoxide_query({ '--exclude', cwd }, keywords)
end
-- 'zi' alias
local function __zoxide_zi(keywords)
return __zoxide_query({ '--interactive' }, keywords)
end
-- =============================================================================
--
-- Clink input text filter.
--
local function onfilterinput(text)
args = string.explode(text, ' ', '"')
if #args == 0 then
return
end
-- settings
zoxide_cmd = settings.get 'zoxide.cmd'
zoxide_no_aliases = settings.get 'zoxide.no_aliases'
-- edge case:
-- * zoxide command prefix is 'cd'
-- * clink converted 'cd -' -> 'cd /d "some_directory"'
local cd_regex = '^%s*cd%s+/d%s+"(.-)"%s*$'
if zoxide_cmd == 'cd' and text:match(cd_regex) then
if zoxide_no_aliases then
-- clink handles it
return
else
-- zoxide handles it
return __zoxide_cd(text:gsub(cd_regex, '%1')), false
end
end
local cmd = table.remove(args, 1)
if cmd == '__zoxide_z' or (cmd == zoxide_cmd and not zoxide_no_aliases) then
return __zoxide_z(args), false
elseif cmd == '__zoxide_zi' or (cmd == zoxide_cmd .. 'i' and not zoxide_no_aliases) then
return __zoxide_zi(args), false
else
return
end
end
if clink.onfilterinput then
clink.onfilterinput(onfilterinput)
else
clink.onendedit(onfilterinput)
end
-- =============================================================================
--
-- To initalize zoxide, add this script to one of clink's lua script locations (e.g. zoxide.lua)
-- (see https://chrisant996.github.io/clink/clink.html#location-of-lua-scripts)
It can definitely be optimized some more, especially if the script was rendered using a template like the other shells supported by zoxide. @ajeetdsouza if you ever feel like you want to officially support cmd.exe, I would be happy to try to submit a PR for this.
Wow, beautiful script.
@shunsambongi in the meanwhile you can also share this script on the Clink repo (maybe the author will mention it in Clink's docs) :)
Wow, beautiful script.
@shunsambongi in the meanwhile you can also share this script on the Clink repo (maybe the author will mention it in Clink's docs) :)
Yes, I think this would be really helpful too!
@rashil2000 @Lunchb0ne I'm glad you like the script! I shared the script in clink's repo like you suggested. I also put the script in its own repo so people might find it easier. https://github.com/shunsambongi/clink-zoxide
I have added your lua script but there is an issue not having the clink settings.
%CMDER_ROOT%\config\zoxide.lua:6: attempt to index global 'settings' (a nil value)
Are there additional steps using this script?
Edit: Never mind, my cmder installation was outdated. I thought the cmder updater would update cmder but it is only conemu.
Its already working.now
rashil2000 commented Aug 5, 2021 •
@ajeetdsouza FWIW, cmd on its own isn't very configurable. Cmder uses a framework called Clink which adds Bash's Readline support to it and makes it highly extensible (there's a comprehensive documentation available here).
However, if z and cd are the only two commands/functions as you specified above, then they can be easily added through doskey aliases:
doskey z=zoxide query $*
doskey cd=zoxide add $1 $T cd /d $1
for example X:\XJava\apps>z X:\apps\inpath\lang
as you can see the z shortcut is perfectly working.it suggest a path i used before but is totally at other place.
maybe someone can just do a documentation pr and can close this issue.
it however has this repeatedly echo currentdir when cd .. bug. X:\XJava>cd ..
X:\XJava> X:>
maybe a small patch when cd .. will not call zoxide add or just simply make zoxide not respond to cd .. ??
I'm interested in getting this running; I actually have a prototype that's working... almost.
zcallszoxide querycdcallszoxide add
What path format do these commands expect? I can't use UNC as cmd.exe does not support it:
C:\Users\user>2>&1 chdir \\?\C:\Users
'\\?\C:\Users'
CMD does not support UNC paths as current directories.
@mataha zoxide add takes in any kind of path and handles the normalization on its own. Most shells just use something like zoxide add "$PWD" or zoxide add "$(pwd -L)", but you could even use zoxide add . and it should work correctly.
zoxide query is just simple query strings, it does not take a path as an argument.