summaryrefslogtreecommitdiff
path: root/vimulti.clj
blob: 30c6c2543fc3abf1f5f3e15a9f58b3a8ecccafc5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env bb

(require '[babashka.tasks :refer [shell]]
         '[babashka.fs :as fs]
         '[clojure.edn :as edn]
         '[clojure.string :as str])

(def default-config
  {:editor-command "nvim"
   :default-branch "master"})

;; configuration helpers
(defn- config-path []
  (let [env-vimnulti-config (System/getenv "VIMULTI_CONFIG")
        env-xdg-config-home (System/getenv "XDG_CONFIG_HOME")
        config-filename "config.edn"]
    (or env-vimnulti-config
        (if env-xdg-config-home
          (str env-xdg-config-home "/vimulti/" config-filename)
          config-filename))))

(defn- init-config [path]
  (when-not (fs/exists? path)
    (fs/create-dirs (fs/parent path))
    (fs/create-file path)
    (spit path default-config))
  path)

(def config (-> (config-path) init-config slurp edn/read-string))

;; git helpers
(defn- get-current-branch [dir]
  (shell {:dir dir
          :out :string}
         "git branch --show-current"))

;; target should be a string like "app-name:branch" or "app-name@tag"
;; returns a map with keys :app-name :branch :tag...
(defn- parse-target-string [target]
  (let [branch-style? (str/includes? target ":")
        tag-style? (str/includes? target "@")
        alias-style? (and (not branch-style?) (not tag-style?))]
    (if alias-style?
      ;; if use alias style
      (if-let [alias-config (get (:aliases config) target)]
        alias-config
        (do (println "No such alias or invalid target.")
            (System/exit 1)))
      ;; if not alias style
      (let [separator (if branch-style? #":" (if tag-style? #"@" #" "))
            target-array (str/split target separator)
            app-name (if (= (first target-array) "") "nvim" (first target-array))
            repo (fs/path (System/getProperty "user.home") ".config" app-name)
            no-mark (= (count target-array) 1)]
        (when (> (count target-array) 2) 
          (println "Invalid target string.")
          (System/exit 1))
        (cond-> {:app-name app-name}
          branch-style? (assoc :branch (when-not no-mark (last target-array)))
          tag-style? (assoc :tag (when-not no-mark (last target-array)))
          (fs/exists? repo) (assoc :repo repo))))))

;; main
;; target should be a string like "app-name:branch" or "app-name@tag"
(let [[target & args] *command-line-args*
      target-map (parse-target-string target)]
  (let [current-branch (or
                        (get-current-branch (:repo target-map))
                        (:default-branch config))]
    (when-let [switch-to (or (:branch target-map)
                             (:tag target-map))]
      (let [tag? (boolean (:tag target-map))]
        (shell {:dir (:repo target-map)}
               (str "git switch " switch-to (if tag? "--detach" "")))))
    (shell {:extra-env {"NVIM_APPNAME" (:app-name target-map)}} 
           (:editor-command config) (apply str args))
    (shell {:dir (:repo target-map)}
           (str "git switch " current-branch))))