| @@ -2142,636 +2142,6 @@ use for the buffer. It defaults to \"*recetf-show*\"." | |||||
| (define-key ctl-x-map (kbd "C-r") 'recently-show) | (define-key ctl-x-map (kbd "C-r") 'recently-show) | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| ;; git walktree | |||||
| (defgroup git-walktree nil | |||||
| "Git Walktree." | |||||
| :tag "GitWalktree" | |||||
| :prefix "git-walktree-" | |||||
| :group 'tools) | |||||
| (defvar-local git-walktree-current-committish nil | |||||
| "Committish name of currently browsing.") | |||||
| (defvar-local git-walktree-current-path nil | |||||
| "Path name currently visiting without leading and trailing slash. | |||||
| This path is always relative to repository root.") | |||||
| (defvar-local git-walktree-buffer-file-name nil | |||||
| "Psudo filename of current buffer.") | |||||
| (defvar-local git-walktree-object-full-sha1 nil | |||||
| "Object name in full sha1 format of current buffer.") | |||||
| (defvar-local git-walktree-repository-root nil | |||||
| "Repository root path of current buffer.") | |||||
| (put 'git-walktree-repository-root | |||||
| 'permanent-local | |||||
| t) | |||||
| (defun git-walktree--committish-fordisplay (committish) | |||||
| "Convert COMMITTISH and return is a suitable format for displaying." | |||||
| (if (and committish | |||||
| (string-match-p "\\`[0-9a-f]+\\'" | |||||
| committish) | |||||
| (>= (length committish) 32)) | |||||
| (git-walktree--git-plumbing "rev-parse" | |||||
| "--short" | |||||
| committish) | |||||
| committish)) | |||||
| (defun git-walktree--create-buffer (committish name type) | |||||
| "Create and return buffer for COMMITTISH:NAME. | |||||
| TYPE is target object type." | |||||
| (let* ((root (git-walktree--git-plumbing "rev-parse" | |||||
| "--show-toplevel")) | |||||
| (committish-display (git-walktree--committish-fordisplay committish)) | |||||
| (name (format "%s:%s" | |||||
| (or committish-display "") | |||||
| name))) | |||||
| (if (and git-walktree-reuse-tree-buffer | |||||
| (string= type "tree")) | |||||
| (with-current-buffer (or git-walktree-tree-buffer-for-reuse | |||||
| (setq git-walktree-tree-buffer-for-reuse | |||||
| (generate-new-buffer "gitwalktreebuf"))) | |||||
| (setq git-walktree-repository-root root) | |||||
| (rename-buffer name t) | |||||
| (current-buffer)) | |||||
| (with-current-buffer (get-buffer-create name) | |||||
| (if git-walktree-repository-root | |||||
| (if (string= root | |||||
| git-walktree-repository-root) | |||||
| (current-buffer) | |||||
| ;; If the buffer is for another repository, create new buffer | |||||
| (with-current-buffer (generate-new-buffer name) | |||||
| (setq git-walktree-repository-root root) | |||||
| (current-buffer))) | |||||
| ;; New buffer | |||||
| (setq git-walktree-repository-root root) | |||||
| (current-buffer)))))) | |||||
| (defun git-walktree--replace-into-buffer (target) | |||||
| "Replace TARGET buffer contents with that of current buffer. | |||||
| It also copy text overlays." | |||||
| (let ((src (current-buffer))) | |||||
| (with-current-buffer target | |||||
| (replace-buffer-contents src))) | |||||
| ;; Copy color overlays | |||||
| (let ((overlays (overlays-in (point-min) (point-max)))) | |||||
| (dolist (o overlays) | |||||
| (let ((beg (overlay-start o)) | |||||
| (end (overlay-end o))) | |||||
| (move-overlay (copy-overlay o) | |||||
| beg | |||||
| end | |||||
| target))))) | |||||
| (require 'ansi-color) | |||||
| (defun git-walktree--open-treeish (committish path treeish) | |||||
| "Open git tree buffer of COMMITISH:PATH. | |||||
| TREEISH should be a tree-ish object full-sha1 of COMMITISH:PATH." | |||||
| (cl-assert path) | |||||
| (cl-assert treeish) | |||||
| (let* (point-tree-start | |||||
| (type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | |||||
| treeish)) | |||||
| (buf (git-walktree--create-buffer committish path type)) | |||||
| ) | |||||
| (cl-assert (member type | |||||
| '("commit" "tree"))) | |||||
| (with-current-buffer buf | |||||
| (unless (and (string= treeish | |||||
| git-walktree-object-full-sha1) | |||||
| (or (eq committish | |||||
| git-walktree-current-committish) | |||||
| (string= committish | |||||
| git-walktree-current-committish))) | |||||
| (buffer-disable-undo) | |||||
| ;; For running git command go back to repository root | |||||
| (cd git-walktree-repository-root) | |||||
| (save-excursion | |||||
| (let ((inhibit-read-only t)) | |||||
| ;; Remove existing overlays generated by ansi-color-apply-on-region | |||||
| (remove-overlays) | |||||
| (with-temp-buffer | |||||
| (if committish | |||||
| (progn (git-walktree--call-process nil | |||||
| "show" | |||||
| ;; TODO: Make this args configurable | |||||
| ;; "--no-patch" | |||||
| "--color=always" | |||||
| "--pretty=short" | |||||
| "--decorate" | |||||
| "--stat" | |||||
| committish) | |||||
| (ansi-color-apply-on-region (point-min) | |||||
| (point)) | |||||
| (insert "\n") | |||||
| (insert (format "Contents of '%s:%s':\n" | |||||
| (git-walktree--committish-fordisplay committish) | |||||
| path))) | |||||
| (insert (format "Contents of treeish object '%s:\n" | |||||
| treeish))) | |||||
| (setq point-tree-start (point)) | |||||
| (git-walktree--call-process nil | |||||
| "ls-tree" | |||||
| ;; "-r" | |||||
| "--abbrev" | |||||
| treeish) | |||||
| (git-walktree--replace-into-buffer buf)) | |||||
| )) | |||||
| (git-walktree-mode) | |||||
| (set-buffer-modified-p nil) | |||||
| (setq git-walktree-current-committish committish) | |||||
| (setq git-walktree-current-path path) | |||||
| (setq git-walktree-object-full-sha1 treeish) | |||||
| (let ((dir (expand-file-name path git-walktree-repository-root))) | |||||
| (when (and git-walktree-try-cd | |||||
| (file-directory-p dir)) | |||||
| (cd dir))) | |||||
| (when (= (point) (point-min)) | |||||
| (goto-char point-tree-start) | |||||
| (git-walktree-mode--move-to-file) | |||||
| ) | |||||
| )) | |||||
| buf)) | |||||
| (defun git-walktree--call-process (&optional infile &rest args) | |||||
| "Call git command with input from INFILE and args ARGS. | |||||
| Result will be inserted into current buffer." | |||||
| (let ((status (apply 'call-process | |||||
| git-walktree-git-executable | |||||
| infile | |||||
| t | |||||
| nil | |||||
| args))) | |||||
| (unless (eq 0 | |||||
| status) | |||||
| (error "Failed to call git process %S %S" | |||||
| infile | |||||
| args)))) | |||||
| ?w | |||||
| (defun git-walktree--open-blob (committish path blob) | |||||
| "Open blob object of COMMITISH:PATH. | |||||
| BLOB should be a object full sha1 of COMMITISH:PATH." | |||||
| (cl-assert committish) | |||||
| (cl-assert path) | |||||
| (cl-assert blob) | |||||
| (let* ((type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | |||||
| blob)) | |||||
| (buf (git-walktree--create-buffer committish path type))) | |||||
| (cl-assert (string= type "blob")) | |||||
| (with-current-buffer buf | |||||
| (unless (string= blob | |||||
| git-walktree-object-full-sha1) | |||||
| ;; For running git command go back to repository root | |||||
| (cd git-walktree-repository-root) | |||||
| (let ((inhibit-read-only t)) | |||||
| (with-temp-buffer | |||||
| (git-walktree--call-process nil | |||||
| "cat-file" | |||||
| "-p" | |||||
| blob) | |||||
| (git-walktree--replace-into-buffer buf))) | |||||
| (setq git-walktree-buffer-file-name | |||||
| (concat git-walktree-repository-root "/git@" committish ":" path)) | |||||
| (setq buffer-file-name | |||||
| (concat git-walktree-repository-root "/" path)) | |||||
| (normal-mode t) | |||||
| ;; For asking filename when C-xC-s | |||||
| (setq buffer-file-name nil) | |||||
| (set-buffer-modified-p t) | |||||
| (setq git-walktree-current-committish committish) | |||||
| (setq git-walktree-current-path path) | |||||
| (setq git-walktree-object-full-sha1 blob) | |||||
| (let ((dir (expand-file-name (or (file-name-directory path) | |||||
| ".") | |||||
| git-walktree-repository-root))) | |||||
| (when (and git-walktree-try-cd | |||||
| (file-directory-p dir)) | |||||
| (cd dir))) | |||||
| (view-mode 1) | |||||
| )) | |||||
| buf)) | |||||
| (defun git-walktree--open-noselect-safe-path (committish &optional path) | |||||
| "Open git object of COMMITTISH:PATH. | |||||
| If PATH not found in COMMITTISH tree, go up path and try again until found. | |||||
| When PATH is omitted or nil, it is calculated from current file or directory." | |||||
| (cl-assert committish) | |||||
| (let ((type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | |||||
| committish))) | |||||
| (cl-assert (string= type "commit"))) | |||||
| (setq path | |||||
| (or path | |||||
| (git-walktree--path-in-repository (or buffer-file-name | |||||
| default-directory)))) | |||||
| ;; PATH must not start with and end with slashes | |||||
| (cl-assert (not (string-match-p "\\`/" path))) | |||||
| (cl-assert (not (string-match-p "/\\'" path))) | |||||
| (let ((obj (git-walktree--resolve-object committish path))) | |||||
| (while (not obj) | |||||
| (setq path | |||||
| (git-walktree--parent-directory path)) | |||||
| (setq obj | |||||
| (git-walktree--resolve-object committish path))) | |||||
| (git-walktree--open-noselect committish | |||||
| path | |||||
| obj))) | |||||
| ;; TODO: Store view history | |||||
| (defun git-walktree--open-noselect (committish path object) | |||||
| "Open buffer to view git object of COMMITTISH:PATH. | |||||
| When PATH was given and non-nil open that, otherwise open root tree. | |||||
| When OBJECT was given and non-nil, assume that is the object full sha1 of | |||||
| COMMITTISH:PATH without checking it." | |||||
| (cl-assert committish) | |||||
| (let ((type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | |||||
| committish))) | |||||
| (cl-assert (string= type "commit"))) | |||||
| (setq path (or path | |||||
| ".")) | |||||
| ;; PATH must not start with and end with slashes | |||||
| (cl-assert (not (string-match-p "\\`/" path))) | |||||
| (cl-assert (not (string-match-p "/\\'" path))) | |||||
| (setq object (or object | |||||
| (git-walktree--resolve-object committish path))) | |||||
| (setq object (git-walktree--git-plumbing "rev-parse" | |||||
| object)) | |||||
| (cl-assert object) | |||||
| (let ((type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | |||||
| object))) | |||||
| (pcase type | |||||
| ((or "commit" "tree") | |||||
| (git-walktree--open-treeish committish path object)) | |||||
| ("blob" | |||||
| (git-walktree--open-blob committish path object)) | |||||
| (_ | |||||
| (error "Type cannot handle: %s" type))))) | |||||
| (defun git-walktree--resolve-object (committish path) | |||||
| "Return object full sha1 name of COMMITISIH:PATH. | |||||
| If path is equal to \".\" return COMMITTISH's root tree object. | |||||
| PATH will be always treated as relative to repository root." | |||||
| (cl-assert committish) | |||||
| (cl-assert path) | |||||
| (cl-assert (not (string-match-p "\\`/" path))) | |||||
| (cl-assert (not (string-match-p "/\\'" path))) | |||||
| (if (string= path ".") | |||||
| (git-walktree--git-plumbing "show" | |||||
| "--no-patch" | |||||
| "--pretty=format:%T" | |||||
| committish) | |||||
| (let ((info (git-walktree--parse-lstree-line (git-walktree--git-plumbing "ls-tree" | |||||
| "--full-tree" | |||||
| committish | |||||
| path)))) | |||||
| (plist-get info :object)))) | |||||
| (defun git-walktree-open (committish &optional path) | |||||
| "Open git tree buffer of COMMITTISH. | |||||
| When PATH was given and non-nil open that, otherwise try to open current path. | |||||
| If target path is not found in COMMITISH tree, go up path and try again until found." | |||||
| ;; TODO: Add fallback method for cases where magit is not available | |||||
| (interactive (list (magit-read-branch-or-commit "Revision: "))) | |||||
| (switch-to-buffer (git-walktree--open-noselect-safe-path committish path))) | |||||
| (defalias 'git-walktree 'git-walktree-open) | |||||
| (defun git-walktree--path-in-repository (path) | |||||
| "Convert PATH into relative path to repository root. | |||||
| Result will not have leading and trailing slashes." | |||||
| (with-temp-buffer | |||||
| (cd (if (file-directory-p path) | |||||
| path | |||||
| (file-name-directory path))) | |||||
| (let ((root (git-walktree--git-plumbing "rev-parse" | |||||
| "--show-toplevel"))) | |||||
| (file-relative-name (directory-file-name path) | |||||
| root)))) | |||||
| (defcustom git-walktree-git-executable "git" | |||||
| "Git executable." | |||||
| :type 'string | |||||
| :group 'git-walktree) | |||||
| (defcustom git-walktree-try-cd t | |||||
| "Try to cd if directory exists in current working directory if non-nil. | |||||
| Otherwise use repository root for gitwalktree buffer's `default-directory'." | |||||
| :type 'boolean | |||||
| :group 'git-walktree) | |||||
| (defcustom git-walktree-reuse-tree-buffer t | |||||
| "Non-nil to reuse buffer for treeish object." | |||||
| :type 'boolean | |||||
| :group 'git-walktree) | |||||
| (defvar git-walktree-tree-buffer-for-reuse nil | |||||
| "Buffer to use when `git-walktree-reuse-tree-buffer' is non-nil.") | |||||
| (defun git-walktree--git-plumbing (&rest args) | |||||
| "Run git plubming command with ARGS. | |||||
| Returns first line of output without newline." | |||||
| (with-temp-buffer | |||||
| (let ((status (apply 'call-process | |||||
| git-walktree-git-executable | |||||
| nil | |||||
| t | |||||
| nil | |||||
| args))) | |||||
| (unless (eq 0 | |||||
| status) | |||||
| (error "Faild to run git %S:\n%s" | |||||
| args | |||||
| (buffer-substring-no-properties (point-min) | |||||
| (point-max)))) | |||||
| (buffer-substring-no-properties (point-min) | |||||
| (progn | |||||
| (goto-char (point-min)) | |||||
| (point-at-eol)))))) | |||||
| (defconst git-walktree-ls-tree-line-regexp | |||||
| "^\\([0-9]\\{6\\}\\) \\(\\w+\\) \\([0-9a-f]+\\)\t\\(.*\\)$" | |||||
| "Regexp for one line of output of git ls-tree.") | |||||
| (defconst git-walktree-ls-tree-line-tree-regexp | |||||
| "^\\([0-9]\\{6\\}\\) \\(tree\\) \\([0-9a-f]+\\)\t\\(.*\\)$" | |||||
| "Regexp for tree line of output of git ls-tree.") | |||||
| (defconst git-walktree-ls-tree-line-commit-regexp | |||||
| "^\\([0-9]\\{6\\}\\) \\(commit\\) \\([0-9a-f]+\\)\t\\(.*\\)$" | |||||
| "Regexp for commit line of output of git ls-tree.") | |||||
| (defun git-walktree--parse-lstree-line (str) | |||||
| "Extract object info from STR. | |||||
| STR should be a string like following without newline.: | |||||
| 100644 blob 6fd4d58202d0b46547c6fe43de0f8c878456f966 .editorconfig | |||||
| Returns property list like (:mode MODE :type TYPE :object OBJECT :file FILE)." | |||||
| (let (result mode type object file) | |||||
| (save-match-data | |||||
| (with-temp-buffer | |||||
| (insert str) | |||||
| (goto-char (point-min)) | |||||
| (and (re-search-forward git-walktree-ls-tree-line-regexp | |||||
| nil | |||||
| t) | |||||
| (list :mode (match-string 1) | |||||
| :type (match-string 2) | |||||
| :object (match-string 3) | |||||
| :file (match-string 4))))))) | |||||
| (defun git-walktree-mode-open-this () | |||||
| "Open git object of current line." | |||||
| (interactive) | |||||
| (let ((info (git-walktree--parse-lstree-line (buffer-substring-no-properties (point-at-bol) | |||||
| (point-at-eol))))) | |||||
| (if info | |||||
| (switch-to-buffer | |||||
| (if (string= (plist-get info | |||||
| :type) | |||||
| "commit") | |||||
| ;; For submodule cd to that directory and intialize | |||||
| ;; TODO: Provide way to go back to known "parent" repository | |||||
| (with-temp-buffer | |||||
| (cd (plist-get info :file)) | |||||
| (git-walktree--open-noselect (plist-get info | |||||
| :object) | |||||
| nil | |||||
| (plist-get info | |||||
| :object))) | |||||
| (git-walktree--open-noselect git-walktree-current-committish | |||||
| (git-walktree--join-path (plist-get info | |||||
| :file)) | |||||
| (plist-get info | |||||
| :object)))) | |||||
| (message "No object on current line.")))) | |||||
| (defun git-walktree--join-path (name &optional base) | |||||
| "Make path from NAME and BASE. | |||||
| If base is omitted or nil use value of `git-walktree-current-path'." | |||||
| (setq base (or base | |||||
| git-walktree-current-path)) | |||||
| (cl-assert base) | |||||
| (if (string= base ".") | |||||
| name | |||||
| (concat base "/" name))) | |||||
| (defun git-walktree--parent-directory (path) | |||||
| "Return parent directory of PATH without trailing slash. | |||||
| For root directory return \".\". | |||||
| If PATH is equal to \".\", return nil." | |||||
| (if (string-match-p "/" path) | |||||
| (directory-file-name (file-name-directory path)) | |||||
| (if (string= "." path) | |||||
| nil | |||||
| "."))) | |||||
| (defun git-walktree-up (&optional committish path) | |||||
| "Open parent directory of COMMITTISH and PATH. | |||||
| If not given, value of current buffer will be used." | |||||
| (interactive) | |||||
| (setq committish | |||||
| (or committish git-walktree-current-committish)) | |||||
| (setq path | |||||
| (or path git-walktree-current-path)) | |||||
| (let ((parent (git-walktree--parent-directory path))) | |||||
| (if parent | |||||
| (switch-to-buffer (git-walktree--open-noselect committish | |||||
| parent | |||||
| nil)) | |||||
| (message "Cannot find parent directory for current tree.")))) | |||||
| (defun git-walktree-mode--move-to-file () | |||||
| "Move point to file field of ls-tree output in current line. | |||||
| This function do nothing when current line is not ls-tree output." | |||||
| (interactive) | |||||
| (save-match-data | |||||
| (when (save-excursion | |||||
| (goto-char (point-at-bol)) | |||||
| (re-search-forward git-walktree-ls-tree-line-regexp | |||||
| (point-at-eol) t)) | |||||
| (goto-char (match-beginning 4))))) | |||||
| (defun git-walktree-mode-next-line (&optional arg try-vscroll) | |||||
| "Move cursor vertically down ARG lines and move to file field if found." | |||||
| (interactive "^p\np") | |||||
| (or arg (setq arg 1)) | |||||
| (line-move arg nil nil try-vscroll) | |||||
| (git-walktree-mode--move-to-file) | |||||
| ) | |||||
| (defun git-walktree-mode-previous-line (&optional arg try-vscroll) | |||||
| "Move cursor vertically up ARG lines and move to file field if found." | |||||
| (interactive "^p\np") | |||||
| (or arg (setq arg 1)) | |||||
| (line-move (- arg) nil nil try-vscroll) | |||||
| (git-walktree-mode--move-to-file) | |||||
| ) | |||||
| (defgroup git-walktree-faces nil | |||||
| "Faces used by git-walktree." | |||||
| :group 'git-walktree | |||||
| :group 'faces) | |||||
| (defface git-walktree-tree-face | |||||
| ;; Same as dired-directory | |||||
| '((t (:inherit font-lock-function-name-face))) | |||||
| "Face used for tree objects." | |||||
| :group 'git-walktree-faces) | |||||
| (defface git-walktree-commit-face | |||||
| ;; Same as dired-symlink face | |||||
| '((t (:inherit font-lock-keyword-face))) | |||||
| "Face used for commit objects." | |||||
| :group 'git-walktree-faces) | |||||
| (defvar git-walktree-known-child-revisions (make-hash-table :test 'equal) | |||||
| "Hash of already known pair of commitid -> list of child commitid. | |||||
| Both values should be object full sha1 names.") | |||||
| (defun git-walktree--put-child (parent child) | |||||
| "Register PARENT and CHILD relationship. | |||||
| PARENT should be a full sha1 object name." | |||||
| ;; Any way to check if PARENT is a full SHA-1 object name? | |||||
| (let ((current (gethash parent git-walktree-known-child-revisions))) | |||||
| (unless (member child current) | |||||
| (puthash parent | |||||
| (cons child | |||||
| current) | |||||
| git-walktree-known-child-revisions)))) | |||||
| ;; TODO: Add aggressive search mode | |||||
| ;; https://stackoverflow.com/a/9870218 | |||||
| ;; git log --reverse --pretty=format:%H -n 1 --ancestry-path <PARENT>..HEAD | |||||
| (defun git-walktree--get-children (parent) | |||||
| "Get known children list of PARENT commit. | |||||
| PARENT should be a full sha1 object name." | |||||
| (gethash parent git-walktree-known-child-revisions)) | |||||
| (defun git-walktree--choose-committish (prompt-format collection) | |||||
| "Emit PROMPT-FORMAT and ask user to which committish of COLLECTION to use. | |||||
| When collection has just one element, return the first element without asking." | |||||
| (cl-assert collection) | |||||
| (if (< (length collection) 2) | |||||
| (car collection) | |||||
| (completing-read (format prompt-format | |||||
| (mapconcat 'git-walktree--committish-fordisplay | |||||
| collection | |||||
| " ")) | |||||
| collection | |||||
| nil | |||||
| t))) | |||||
| (defun git-walktree-parent-revision () | |||||
| "Open parent revision of current path. | |||||
| If current path was not found in the parent revision try to go up path." | |||||
| (interactive) | |||||
| (cl-assert git-walktree-current-committish) | |||||
| (let* ((commit-full-sha1 (git-walktree--git-plumbing "rev-parse" | |||||
| git-walktree-current-committish)) | |||||
| (parents (git-walktree--parent-full-sha1 commit-full-sha1))) | |||||
| (dolist (parent parents) | |||||
| (git-walktree--put-child parent | |||||
| commit-full-sha1)) | |||||
| (if (< (length parents) | |||||
| 1) | |||||
| (message "This revision has no parent revision") | |||||
| (let* ((parent (git-walktree--choose-committish "This revision has multiple parents. Which to open? (%s) " | |||||
| parents)) | |||||
| (path git-walktree-current-path)) | |||||
| (cl-assert path) | |||||
| (switch-to-buffer (git-walktree--open-noselect-safe-path parent | |||||
| path)))))) | |||||
| (defun git-walktree--parent-full-sha1 (committish) | |||||
| "Return list of parent commits of COMMITTISH in sha1 string." | |||||
| (let ((type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | |||||
| committish))) | |||||
| (cl-assert (string= type "commit"))) | |||||
| (let ((parents (git-walktree--git-plumbing "show" | |||||
| "--no-patch" | |||||
| "--pretty=format:%P" | |||||
| committish))) | |||||
| (split-string parents))) | |||||
| (defun git-walktree-known-child-revision () | |||||
| "Open known revision of current path." | |||||
| (interactive) | |||||
| (let* ((commit-full-sha1 (git-walktree--git-plumbing "rev-parse" | |||||
| git-walktree-current-committish)) | |||||
| (children (git-walktree--get-children commit-full-sha1))) | |||||
| (if (< (length children) | |||||
| 1) | |||||
| (message "There are no known child revision") | |||||
| (let* ((child (git-walktree--choose-committish "There are multiple known childrens. Which to open? (%s)" | |||||
| children)) | |||||
| (path git-walktree-current-path)) | |||||
| (cl-assert path) | |||||
| (switch-to-buffer (git-walktree--open-noselect-safe-path child | |||||
| path)))))) | |||||
| (defvar git-walktree-mode-map | |||||
| (let ((map (make-sparse-keymap))) | |||||
| (define-key map "n" 'git-walktree-mode-next-line) | |||||
| (define-key map "p" 'git-walktree-mode-previous-line) | |||||
| (define-key map (kbd "C-n") 'git-walktree-mode-next-line) | |||||
| (define-key map (kbd "C-p") 'git-walktree-mode-previous-line) | |||||
| ;; TODO: Review keybind | |||||
| (define-key map "P" 'git-walktree-parent-revision) | |||||
| (define-key map "N" 'git-walktree-known-child-revision) | |||||
| (define-key map "^" 'git-walktree-up) | |||||
| ;; TODO: implement | |||||
| (define-key map (kbd "DEL") 'git-walktree-back) | |||||
| (define-key map (kbd "C-m") 'git-walktree-mode-open-this) | |||||
| map)) | |||||
| (defvar git-walktree-mode-font-lock-keywords | |||||
| `( | |||||
| (,git-walktree-ls-tree-line-regexp . ( | |||||
| (1 'shadow) | |||||
| (3 'shadow) | |||||
| )) | |||||
| (,git-walktree-ls-tree-line-tree-regexp . ( | |||||
| (2 'git-walktree-tree-face) | |||||
| (4 'git-walktree-tree-face) | |||||
| )) | |||||
| (,git-walktree-ls-tree-line-commit-regexp . ( | |||||
| (2 'git-walktree-commit-face) | |||||
| (4 'git-walktree-commit-face) | |||||
| )) | |||||
| ) | |||||
| "Syntax highlighting for git-walktree mode.") | |||||
| (define-derived-mode git-walktree-mode special-mode "GitWalktree" | |||||
| "Major-mode for `git-walktree-open'." | |||||
| (set (make-local-variable 'font-lock-defaults) | |||||
| '(git-walktree-mode-font-lock-keywords | |||||
| nil nil nil nil | |||||
| )) | |||||
| ) | |||||
| (require 'magit nil t) | |||||
| ;; (git-revision--git-plumbing "cat-file" "-t" "HEAD") | |||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;; git-worktree | ;; git-worktree | ||||