From 090516588918c1924698b09e660357aaf3f04a71 Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Sat, 27 Aug 2022 21:12:16 -0700 Subject: [PATCH] Allow `z -b` to do fuzzy matching If `z -b foo bar` finds no exact match in the path to the current directory, it tries a "fuzzy" substitution with a frecent directory. For example, if we are in `~/github/jekyll/test` and run `z -b jek gh`, it will try to substitute the entire `jekyll` path component with `gh`. The result will be equivalent to running `z ~/github gh test`. --- README.md | 6 ++++++ z.lua | 17 ++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e8a35a..e3b0bb0 100644 --- a/README.md +++ b/README.md @@ -319,6 +319,7 @@ New option `"-b"` can quickly go back to a specific parent directory in bash ins - **(No argument)**: `cd` into the project root, the project root the nearest parent directory with `.git`/`.hg`/`.svn` in it. - **(One argument)**: `cd` into the closest parent starting with keyword, if not find, go to the parent containing keyword. - **(Two arguments)**: replace the first value with the second one (in the current path). + If simple substitution does not work, falls back to fuzzily replacing path components. Let's start by aliasing `z -b` to `zb`: @@ -338,6 +339,11 @@ Let's start by aliasing `z -b` to `zb`: # substitute jekyll with ghost ~/github/jekyll/test$ zb jekyll ghost => cd ~/github/ghost/test + +# same as above, but fuzzy +~/github/jekyll/test$ zb jek gh + => z ~/github/ gh /test + => cd ~/github/ghost/test # Assuming that's the most frecent match ``` Backward jumping can also be used with `$_ZL_ECHO` option (echo $PWD after cd), which makes it possible to combine them with other tools without actually changing the working directory (eg. ``ls `zb git` ``). diff --git a/z.lua b/z.lua index f47fc1d..e9dc4ff 100755 --- a/z.lua +++ b/z.lua @@ -1759,7 +1759,7 @@ function cd_backward(args, options, pwd) end return nil end - else + elseif nargs == 2 then local test = windows and pwd:gsub('\\', '/') or pwd local src = args[1] local dst = args[2] @@ -1770,10 +1770,21 @@ function cd_backward(args, options, pwd) if not start then return pwd end + local lhs = pwd:sub(1, start - 1) local rhs = pwd:sub(ends + 1) - return lhs .. dst .. rhs + local newpath = lhs .. dst .. rhs + if os.path.isdir(newpath) then + return newpath + end + + lhs = lhs:gsub("[^/]*$", "") + rhs = rhs:gsub("^[^/]*", "") + return z_cd({lhs, dst, rhs}) end + + io.stderr:write("Error: " .. Z_CMD .. " -b takes at most 2 arguments.\n") + return nil end @@ -1922,7 +1933,7 @@ function main(argv) if options['--cd'] or options['-e'] then local path = '' if options['-b'] then - if Z_INTERACTIVE == 0 then + if #args > 0 or Z_INTERACTIVE == 0 then path = cd_backward(args, options) else path = cd_breadcrumbs('', Z_INTERACTIVE)