diff options
| author | Akshay Nair <phenax5@gmail.com> | 2026-06-26 13:50:48 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2026-06-26 13:50:48 +0530 |
| commit | d2f4982e389431b74357bbc108567ae0e1d912a5 (patch) | |
| tree | d9e18402fda762f5f8840d6974b89981625ce5f0 | |
| parent | d2995bc1d5968b5e8d018135748c6768f920d3c8 (diff) | |
| download | kakoune-config-d2f4982e389431b74357bbc108567ae0e1d912a5.tar.gz kakoune-config-d2f4982e389431b74357bbc108567ae0e1d912a5.zip | |
Add open selection in git remote url
| -rw-r--r-- | autoload/git.kak | 15 | ||||
| -rwxr-xr-x | scripts/git.clj | 71 |
2 files changed, 84 insertions, 2 deletions
diff --git a/autoload/git.kak b/autoload/git.kak index 59ac173..775cf0d 100644 --- a/autoload/git.kak +++ b/autoload/git.kak @@ -6,8 +6,6 @@ define-command gitui -params .. %{ gitu %arg{@} } -# TODO: Script to open git remote url (github/srht/gitlab/etc) - declare-user-mode git declare-user-mode git-r declare-user-mode git-d @@ -16,6 +14,7 @@ map global git s ': gitui<ret>' -docstring 'Git tui' map global git A ': git add %val{buffile}<ret>' -docstring 'Add file' map global git m ': git-line-blame<ret>' -docstring 'Blame selection lines' map global git M ': git-file-blame<ret>' -docstring 'Blame buffer file' +map global git l ': git-link<ret>' -docstring 'Open remote link to selection in file' map global git d ': enter-user-mode git-d<ret>' -docstring 'Diff mode' map global git-d d ': git-open-diff<ret>' -docstring 'Open staged files' @@ -53,3 +52,15 @@ define-command git-open-diff -params 0..1 %{ define-command git-open-commit -params 0..1 %{ eval %sh{ git show --name-only --pretty="" "$@" | sed 's/^/edit /' } } + +define-command git-link %{ + eval %sh{ + line_start=${kak_selection_desc%%.*} + tmp=${kak_selection_desc#*,} + line_end=${tmp%%.*} + link=$("$kak_config/scripts/git.clj" link "$kak_buffile" "$line_start" "$line_end") + xdg-open "$link" || true >/dev/null + echo "info '$link'" + } +} + diff --git a/scripts/git.clj b/scripts/git.clj new file mode 100755 index 0000000..c1e450b --- /dev/null +++ b/scripts/git.clj @@ -0,0 +1,71 @@ +#!/usr/bin/env bb + +(require '[clojure.java.shell :refer [sh]]) +(require '[clojure.string :as str]) +(require '[clojure.java.io :as io]) + +(defn dirname [path] (.getParent (io/file path))) + +(defn git [dir & args] + (let [proc (apply sh "git" "-C" (or dir ".") args)] + (when (= (:exit proc) 0) + (str/trim (:out proc))))) + +(defn git-remote-origin [dir] + (not-empty (git dir "remote" "get-url" "origin"))) + +(defn git-first-remote [dir] + (some->> (git dir "remote" "-v") + str/split-lines + (keep #(re-matches #"^\w+\s+(.*)\s+\(fetch\)" %)) + first + second)) + +(defn prepare-link [remote-url rev file-path & [line-start line-end]] + (let [parse-path #(some->> (re-matches % remote-url) second) + line-hash (cond + (nil? line-start) nil + (= line-start line-end) (str "#L" line-start) + (some? line-end) (str "#L" line-start "-L" line-end) + (nil? line-end) (str "#L" line-start))] + (some->> + (cond + (empty? remote-url) nil + (.contains remote-url "github.com:") ["https://github.com" (parse-path #".*github.com:(.*)\.git$") "blob" rev (str file-path line-hash)] + (.contains remote-url "github.com/") ["https://github.com" (parse-path #".*github.com/(.*)(\.git)?$") "blob" rev (str file-path line-hash)] + (.contains remote-url "gitlab.com:") ["https://gitlab.com" (parse-path #".*gitlab.com:(.*)\.git$") "-/blob" rev (str file-path line-hash)] + (.contains remote-url "gitlab.com/") ["https://gitlab.com" (parse-path #".*gitlab.com/(.*)(\.git)?$") "-/blob" rev (str file-path line-hash)] + (.contains remote-url "git.sr.ht:") ["https://git.sr.ht" (parse-path #".*git.sr.ht:(.*)\.git$") "tree" rev (str file-path line-hash)] + (.contains remote-url "git.sr.ht/") ["https://git.sr.ht" (parse-path #".*git.sr.ht/(.*)(\.git)?$") "tree" rev (str file-path line-hash)] + :else nil) + (remove nil?) + (str/join "/")))) + +(defn git-current-rev [dir] (git dir "rev-parse" "--short" "HEAD")) + +(defn git-remote-url [dir file-path revision line-start line-end] + (some-> (or (git-remote-origin dir) (git-first-remote dir)) + (prepare-link revision file-path line-start line-end))) + +(defn git-root [path] + (let [file-dir (if (empty? path) "." (dirname path))] + (some->> (git file-dir "rev-parse" "--absolute-git-dir") + dirname))) + +(defn cmd-link [[file-path line-start line-end rev]] + (let [dir (git-root file-path) + revision (or rev (git-current-rev dir) "main") + relative-file-path (str/trim (:out (sh "realpath" "--relative-to" dir file-path))) + remote-url (git-remote-url dir relative-file-path revision line-start line-end)] + (println remote-url))) + +(def commands + {"link" cmd-link}) + +(let [[cmd & args] *command-line-args*] + (if-let [command-fn (commands cmd)] + (command-fn args) + (binding [*out* *err*] + (println (str "invalid command: " (or cmd ""))) + (println (str "Valid commands: " (keys commands)))))) + |
