diff --git a/src/common/closh/zero/builtin.cljc b/src/common/closh/zero/builtin.cljc index 448d1586..a0005894 100644 --- a/src/common/closh/zero/builtin.cljc +++ b/src/common/closh/zero/builtin.cljc @@ -33,12 +33,46 @@ (fn [[k v]] (process/setenv k v)) (partition 2 args)))) +(def ^:private dir-stack (atom (list (getenv "PWD")))) + +;;; Push and entry on the directory stack +(defn- push-dir + [dir] + (swap! dir-stack (comp distinct conj) dir)) + +(defn dh + "Show the current directory stack" + [] + (println + (clojure.string/join "\n" (map-indexed #(str %1 " " %2) @dir-stack)))) + (defn cd - "Changes current working directory to a path of a first given argument." + "Changes current working directory to a path of a first given argument. + If the first arg is like - it will use the Nth entry on the directory + stack. A '-' changes directory to the previous directory." [& args] ;; flatten is used because we can get arguments from expand which are collections - (let [dir (or (first args) - (getenv "HOME"))] - (process/chdir dir) - (setenv "PWD" (process/cwd)) - env/success)) + (let [arg (first args)] + (if-let [dir (cond (nil? arg) ;go home if no arg + (getenv "HOME") + + ;; a lone '-' will change to the last directory + (= arg "-") + (nth @dir-stack 1) + + ;; a - shows up in the arg list as a negative number + (and (integer? arg) + (< arg 1)) + (nth @dir-stack (- arg)) + + ;; just use the arg + :else arg)] + (do (process/chdir dir) + (let [cwd (process/cwd)] + ;; save the directory on the directory stack + (push-dir cwd) + (setenv "PWD" cwd)) + env/success) + ;; if we don't have a directory then fail (shouldn't really get + ;; here). + env/failure))) diff --git a/src/common/closh/zero/compiler.cljc b/src/common/closh/zero/compiler.cljc index 1ffd453c..5a04a1b4 100644 --- a/src/common/closh/zero/compiler.cljc +++ b/src/common/closh/zero/compiler.cljc @@ -5,7 +5,7 @@ (def ^:no-doc builtins "Set of symbols of builtin functions" - #{'cd 'exit 'quit 'getenv 'setenv}) + #{'cd 'exit 'quit 'getenv 'setenv 'dh}) (def ^:no-doc pipes "Maps shorthand symbols of pipe functions to full name" diff --git a/src/common/closh/zero/env.cljc b/src/common/closh/zero/env.cljc index 0a9435da..e1f8c74d 100644 --- a/src/common/closh/zero/env.cljc +++ b/src/common/closh/zero/env.cljc @@ -13,7 +13,7 @@ '[closh.zero.compiler] '[closh.zero.parser] '[closh.zero.core :refer [shx expand]] - '[closh.zero.builtin :refer [cd exit quit getenv setenv]] + '[closh.zero.builtin :refer [cd exit quit getenv setenv dh]] '[closh.zero.platform.process] '[closh.zero.pipeline] '[clojure.string :as str]