| @@ -1,6 +1,6 @@ | |||||
| ;;; emacs.el --- 10sr emacs initialization | ;;; emacs.el --- 10sr emacs initialization | ||||
| ;; Time-stamp: <2018-10-12 16:34:18 JST 10sr> | |||||
| ;; Time-stamp: <2018-10-12 17:39:33 JST 10sr> | |||||
| ;;; Code: | ;;; Code: | ||||
| @@ -2238,36 +2238,41 @@ 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 revision | |||||
| ;; git walktree | |||||
| (defgroup git-revision nil | |||||
| "Git revision." | |||||
| :tag "GitRevision" | |||||
| :prefix "git-revision-" | |||||
| (defgroup git-walktree nil | |||||
| "Git Walktree." | |||||
| :tag "GitWalktree" | |||||
| :prefix "git-walktree-" | |||||
| :group 'tools) | :group 'tools) | ||||
| (defvar git-revision-current-commitish nil | |||||
| (defvar git-walktree-current-commitish nil | |||||
| "Commitish name of currently browsing.") | "Commitish name of currently browsing.") | ||||
| (make-variable-buffer-local 'git-revision-current-commitish) | |||||
| (make-variable-buffer-local 'git-walktree-current-commitish) | |||||
| (defvar git-revision-current-path nil | |||||
| (defvar git-walktree-current-path nil | |||||
| "Path name currently visiting without leading slash.") | "Path name currently visiting without leading slash.") | ||||
| (make-variable-buffer-local 'git-revision-current-path) | |||||
| (make-variable-buffer-local 'git-walktree-current-path) | |||||
| ;; (defvar git-revision-repository-path nil | |||||
| ;; "Path of current git repository root.") | |||||
| ;; (make-variable-buffer-local 'git-revision-repository-path) | |||||
| (defun git-revision--create-buffer (commitish name) | |||||
| (defun git-walktree--create-buffer (commitish name) | |||||
| ;; TODO: check repository | |||||
| "Create and return buffer for NAME." | "Create and return buffer for NAME." | ||||
| (get-buffer-create (format "*GitRevision<%s:%s>*" (or commitish "") name))) | |||||
| (defun git-revision--open-treeish (commitish path treeish) | |||||
| (when (and commitish | |||||
| (string-match-p "\\`[0-9a-f]+\\'" | |||||
| commitish) | |||||
| (> (length commitish) 32)) | |||||
| (setq commitish | |||||
| (git-walktree--git-plumbing "rev-parse" | |||||
| "--short" | |||||
| commitish))) | |||||
| (get-buffer-create (format "%s:%s" (or commitish "") name))) | |||||
| (defun git-walktree--open-treeish (commitish path treeish) | |||||
| "Open git tree buffer of TREEISH." | "Open git tree buffer of TREEISH." | ||||
| (let (point | (let (point | ||||
| point-tree-start | point-tree-start | ||||
| (buf (git-revision--create-buffer commitish path)) | |||||
| (type (git-revision--git-plumbing "cat-file" | |||||
| (buf (git-walktree--create-buffer commitish path)) | |||||
| (type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | "-t" | ||||
| treeish)) | treeish)) | ||||
| ) | ) | ||||
| @@ -2280,24 +2285,24 @@ use for the buffer. It defaults to \"*recetf-show*\"." | |||||
| (setq point (point)) | (setq point (point)) | ||||
| (erase-buffer) | (erase-buffer) | ||||
| (when commitish | (when commitish | ||||
| (git-revision--call-process nil | |||||
| (git-walktree--call-process nil | |||||
| "show" | "show" | ||||
| "--no-patch" | "--no-patch" | ||||
| "--pretty=short" | "--pretty=short" | ||||
| commitish) | commitish) | ||||
| (insert "\n")) | (insert "\n")) | ||||
| (setq point-tree-start (point)) | (setq point-tree-start (point)) | ||||
| (git-revision--call-process nil | |||||
| (git-walktree--call-process nil | |||||
| "ls-tree" | "ls-tree" | ||||
| ;; "-r" | ;; "-r" | ||||
| "--abbrev" | "--abbrev" | ||||
| treeish))) | treeish))) | ||||
| (git-revision-mode) | |||||
| (git-walktree-mode) | |||||
| (set-buffer-modified-p nil) | (set-buffer-modified-p nil) | ||||
| (setq git-revision-current-commitish commitish) | |||||
| (setq git-revision-current-path path) | |||||
| (setq git-walktree-current-commitish commitish) | |||||
| (setq git-walktree-current-path path) | |||||
| ;; FIXME: Somehow point go back to point-min when reopen the buffer | ;; FIXME: Somehow point go back to point-min when reopen the buffer | ||||
| (if (eq point (point-min)) | (if (eq point (point-min)) | ||||
| (goto-char point-tree-start) | (goto-char point-tree-start) | ||||
| @@ -2306,11 +2311,11 @@ use for the buffer. It defaults to \"*recetf-show*\"." | |||||
| ) | ) | ||||
| buf)) | buf)) | ||||
| (defun git-revision--call-process (&optional infile &rest args) | |||||
| (defun git-walktree--call-process (&optional infile &rest args) | |||||
| "Call git command with input from INFILE and args ARGS. | "Call git command with input from INFILE and args ARGS. | ||||
| Result will be inserted into current buffer." | Result will be inserted into current buffer." | ||||
| (let ((status (apply 'call-process | (let ((status (apply 'call-process | ||||
| git-revision-git-executable | |||||
| git-walktree-git-executable | |||||
| infile | infile | ||||
| t | t | ||||
| nil | nil | ||||
| @@ -2321,25 +2326,25 @@ Result will be inserted into current buffer." | |||||
| infile | infile | ||||
| args)))) | args)))) | ||||
| ?w | ?w | ||||
| (defun git-revision--open-blob (commitish path blob) | |||||
| (defun git-walktree--open-blob (commitish path blob) | |||||
| "Open BLOB object." | "Open BLOB object." | ||||
| (let (point | (let (point | ||||
| (type (git-revision--git-plumbing "cat-file" | |||||
| (type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | "-t" | ||||
| blob)) | blob)) | ||||
| (buf (git-revision--create-buffer commitish path))) | |||||
| (buf (git-walktree--create-buffer commitish path))) | |||||
| (cl-assert (string= type "blob")) | (cl-assert (string= type "blob")) | ||||
| (with-current-buffer buf | (with-current-buffer buf | ||||
| (let ((inhibit-read-only t)) | (let ((inhibit-read-only t)) | ||||
| (setq point (point)) | (setq point (point)) | ||||
| (erase-buffer) | (erase-buffer) | ||||
| (git-revision--call-process nil | |||||
| (git-walktree--call-process nil | |||||
| "cat-file" | "cat-file" | ||||
| "-p" | "-p" | ||||
| blob)) | blob)) | ||||
| ;; FIXME: Ask for file name when C-xC-s is given | ;; FIXME: Ask for file name when C-xC-s is given | ||||
| (setq buffer-file-name | (setq buffer-file-name | ||||
| (concat (git-revision--git-plumbing "rev-parse" | |||||
| (concat (git-walktree--git-plumbing "rev-parse" | |||||
| "--show-toplevel") | "--show-toplevel") | ||||
| "/git@" | "/git@" | ||||
| commitish | commitish | ||||
| @@ -2348,19 +2353,19 @@ Result will be inserted into current buffer." | |||||
| (set-buffer-modified-p nil) | (set-buffer-modified-p nil) | ||||
| (normal-mode t) | (normal-mode t) | ||||
| (setq git-revision-current-commitish commitish) | |||||
| (setq git-revision-current-path path) | |||||
| (setq git-walktree-current-commitish commitish) | |||||
| (setq git-walktree-current-path path) | |||||
| (setq buffer-read-only t) | (setq buffer-read-only t) | ||||
| (goto-char point) | (goto-char point) | ||||
| ) | ) | ||||
| buf)) | buf)) | ||||
| (defun git-revision--open-noselect (commitish path object) | |||||
| (defun git-walktree--open-noselect (commitish path object) | |||||
| "Open git tree buffer of COMMITISH. | "Open git tree buffer of COMMITISH. | ||||
| When PATH was given and non-nil open that, otherwise open root tree. | 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 of COMMITISH:PATH | When OBJECT was given and non-nil, assume that is the object of COMMITISH:PATH | ||||
| without checking it." | without checking it." | ||||
| (let ((type (git-revision--git-plumbing "cat-file" | |||||
| (let ((type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | "-t" | ||||
| commitish))) | commitish))) | ||||
| (cl-assert (string= type "commit"))) | (cl-assert (string= type "commit"))) | ||||
| @@ -2375,47 +2380,47 @@ without checking it." | |||||
| (setq object (or object | (setq object (or object | ||||
| commitish)) | commitish)) | ||||
| (setq object (or object | (setq object (or object | ||||
| (git-revision--resolve-object commitish path)))) | |||||
| (git-walktree--resolve-object commitish path)))) | |||||
| (cl-assert object) | (cl-assert object) | ||||
| (let ((type (git-revision--git-plumbing "cat-file" | |||||
| (let ((type (git-walktree--git-plumbing "cat-file" | |||||
| "-t" | "-t" | ||||
| object))) | object))) | ||||
| (pcase type | (pcase type | ||||
| ((or "commit" "tree") | ((or "commit" "tree") | ||||
| (git-revision--open-treeish commitish path object)) | |||||
| (git-walktree--open-treeish commitish path object)) | |||||
| ("blob" | ("blob" | ||||
| (git-revision--open-blob commitish path object)) | |||||
| (git-walktree--open-blob commitish path object)) | |||||
| (_ | (_ | ||||
| (error "Type cannot handle: %s" type))))) | (error "Type cannot handle: %s" type))))) | ||||
| (defun git-revision--resolve-object (commitish path) | |||||
| (defun git-walktree--resolve-object (commitish path) | |||||
| "Return object id of COMMITISIH:PATH." | "Return object id of COMMITISIH:PATH." | ||||
| (let ((info (git-revision--parse-lstree-line (git-revision--git-plumbing "ls-tree" | |||||
| (let ((info (git-walktree--parse-lstree-line (git-walktree--git-plumbing "ls-tree" | |||||
| commitish | commitish | ||||
| path)))) | path)))) | ||||
| (plist-get info :object))) | (plist-get info :object))) | ||||
| (defun git-revision-open (commitish &optional path object) | |||||
| (defun git-walktree-open (commitish &optional path object) | |||||
| "Open git tree buffer of COMMITISH. | "Open git tree buffer of COMMITISH. | ||||
| When PATH was given and non-nil open that, otherwise open root tree. | 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 of COMMITISH:PATH without | When OBJECT was given and non-nil, assume that is the object of COMMITISH:PATH without | ||||
| checking it." | checking it." | ||||
| (interactive (list (magit-read-branch-or-commit "Revision: "))) | (interactive (list (magit-read-branch-or-commit "Revision: "))) | ||||
| (pop-to-buffer (git-revision--open-noselect commitish path object))) | |||||
| (defalias 'git-revision 'git-revision-open) | |||||
| (pop-to-buffer (git-walktree--open-noselect commitish path object))) | |||||
| (defalias 'git-walktree 'git-walktree-open) | |||||
| (defcustom git-revision-git-executable "git" | |||||
| (defcustom git-walktree-git-executable "git" | |||||
| "Git executable." | "Git executable." | ||||
| :type 'string | :type 'string | ||||
| :group 'git-revision) | |||||
| :group 'git-walktree) | |||||
| (defun git-revision--git-plumbing (&rest args) | |||||
| (defun git-walktree--git-plumbing (&rest args) | |||||
| "Run git plubming command with ARGS. | "Run git plubming command with ARGS. | ||||
| Returns first line of output without newline." | Returns first line of output without newline." | ||||
| (with-temp-buffer | (with-temp-buffer | ||||
| (let ((status (apply 'call-process | (let ((status (apply 'call-process | ||||
| git-revision-git-executable | |||||
| git-walktree-git-executable | |||||
| nil | nil | ||||
| t | t | ||||
| nil | nil | ||||
| @@ -2430,13 +2435,13 @@ Returns first line of output without newline." | |||||
| (progn | (progn | ||||
| (goto-char (point-min)) | (goto-char (point-min)) | ||||
| (point-at-eol)))))) | (point-at-eol)))))) | ||||
| (defconst git-revision-ls-tree-line-regexp | |||||
| (defconst git-walktree-ls-tree-line-regexp | |||||
| "^\\([0-9]\\{6\\}\\) \\(\\w+\\) \\([0-9a-f]+\\)\t\\(.*\\)$" | "^\\([0-9]\\{6\\}\\) \\(\\w+\\) \\([0-9a-f]+\\)\t\\(.*\\)$" | ||||
| "Regexp for one line of output of git ls-tree.") | "Regexp for one line of output of git ls-tree.") | ||||
| (defconst git-revision-ls-tree-line-tree-regexp | |||||
| (defconst git-walktree-ls-tree-line-tree-regexp | |||||
| "^\\([0-9]\\{6\\}\\) \\(tree\\) \\([0-9a-f]+\\)\t\\(.*\\)$" | "^\\([0-9]\\{6\\}\\) \\(tree\\) \\([0-9a-f]+\\)\t\\(.*\\)$" | ||||
| "Regexp for tree line of output of git ls-tree.") | "Regexp for tree line of output of git ls-tree.") | ||||
| (defun git-revision--parse-lstree-line (str) | |||||
| (defun git-walktree--parse-lstree-line (str) | |||||
| "Extract object info from STR. | "Extract object info from STR. | ||||
| STR should be a string like following without newline.: | STR should be a string like following without newline.: | ||||
| @@ -2449,41 +2454,39 @@ Returns property list like (:mode MODE :type TYPE :object OBJECT :file FILE)." | |||||
| (with-temp-buffer | (with-temp-buffer | ||||
| (insert str) | (insert str) | ||||
| (goto-char (point-min)) | (goto-char (point-min)) | ||||
| (and (re-search-forward git-revision-ls-tree-line-regexp | |||||
| (and (re-search-forward git-walktree-ls-tree-line-regexp | |||||
| nil | nil | ||||
| t) | t) | ||||
| (list :mode (match-string 1) | (list :mode (match-string 1) | ||||
| :type (match-string 2) | :type (match-string 2) | ||||
| :object (match-string 3) | :object (match-string 3) | ||||
| :file (match-string 4))))))) | :file (match-string 4))))))) | ||||
| ;; (plist-get (git-revision--extract-object-info "100644 blob 6fd4d58202d0b46547c6fe43de0f8c878456f966 .editorconfig") :mode) | |||||
| ;; (git-revision--extract-object-info "100644 blob 6fd4d58202d0b46547c6fe43de0f8c878456f966") | |||||
| (defun git-revision-mode-open-this () | |||||
| (defun git-walktree-mode-open-this () | |||||
| "Open current object." | "Open current object." | ||||
| (interactive) | (interactive) | ||||
| (let ((info (git-revision--parse-lstree-line (buffer-substring-no-properties (point-at-bol) | |||||
| (let ((info (git-walktree--parse-lstree-line (buffer-substring-no-properties (point-at-bol) | |||||
| (point-at-eol))))) | (point-at-eol))))) | ||||
| (if info | (if info | ||||
| (switch-to-buffer (git-revision--open-noselect | |||||
| git-revision-current-commitish | |||||
| (git-revision--join-path (plist-get info | |||||
| (switch-to-buffer (git-walktree--open-noselect | |||||
| git-walktree-current-commitish | |||||
| (git-walktree--join-path (plist-get info | |||||
| :file)) | :file)) | ||||
| (plist-get info | (plist-get info | ||||
| :object))) | :object))) | ||||
| (message "No object on current line.")))) | (message "No object on current line.")))) | ||||
| (defun git-revision--join-path (name &optional base) | |||||
| (defun git-walktree--join-path (name &optional base) | |||||
| "Make path from NAME and BASE. | "Make path from NAME and BASE. | ||||
| If base is omitted or nil use value of `git-revision-current-path'." | |||||
| If base is omitted or nil use value of `git-walktree-current-path'." | |||||
| (setq base (or base | (setq base (or base | ||||
| git-revision-current-path)) | |||||
| git-walktree-current-path)) | |||||
| (cl-assert base) | (cl-assert base) | ||||
| (if (string= base ".") | (if (string= base ".") | ||||
| name | name | ||||
| (concat base "/" name))) | (concat base "/" name))) | ||||
| (defun git-revision--parent-directory (path) | |||||
| (defun git-walktree--parent-directory (path) | |||||
| "Return parent directory of PATH without trailing slash. | "Return parent directory of PATH without trailing slash. | ||||
| For root directory return \".\". | For root directory return \".\". | ||||
| If PATH is equal to \".\", return nil." | If PATH is equal to \".\", return nil." | ||||
| @@ -2493,55 +2496,53 @@ If PATH is equal to \".\", return nil." | |||||
| nil | nil | ||||
| "."))) | "."))) | ||||
| (defun git-revision-up (&optional commitish path) | |||||
| (defun git-walktree-parent (&optional commitish path) | |||||
| "Open parent directory of COMMITISH and PATH. | "Open parent directory of COMMITISH and PATH. | ||||
| If not given, value of current buffer will be used." | If not given, value of current buffer will be used." | ||||
| (interactive) | (interactive) | ||||
| (setq commitish | (setq commitish | ||||
| (or commitish git-revision-current-commitish)) | |||||
| (or commitish git-walktree-current-commitish)) | |||||
| (setq path | (setq path | ||||
| (or path git-revision-current-path)) | |||||
| (let ((parent (git-revision--parent-directory path))) | |||||
| (or path git-walktree-current-path)) | |||||
| (let ((parent (git-walktree--parent-directory path))) | |||||
| (if parent | (if parent | ||||
| (switch-to-buffer (git-revision--open-noselect commitish | |||||
| (switch-to-buffer (git-walktree--open-noselect commitish | |||||
| parent | parent | ||||
| nil)) | nil)) | ||||
| (message "Cannot find parent for current buffer.")))) | |||||
| (message "Cannot find parent for current tree.")))) | |||||
| (defgroup git-revision-faces nil | |||||
| "Faces used by git-revision." | |||||
| :group 'git-revision | |||||
| (defgroup git-walktree-faces nil | |||||
| "Faces used by git-walktree." | |||||
| :group 'git-walktree | |||||
| :group 'faces) | :group 'faces) | ||||
| (defface git-revision-tree-face | |||||
| (defface git-walktree-tree-face | |||||
| '((t (:inherit font-lock-function-name-face))) | '((t (:inherit font-lock-function-name-face))) | ||||
| "Face used for tree objects." | "Face used for tree objects." | ||||
| :group 'git-revision-faces) | |||||
| (defvar git-revision-tree-face 'git-revision-tree-face | |||||
| :group 'git-walktree-faces) | |||||
| (defvar git-walktree-tree-face 'git-walktree-tree-face | |||||
| "Face used for tree objects.") | "Face used for tree objects.") | ||||
| (defvar git-revision-mode-map | |||||
| (defvar git-walktree-mode-map | |||||
| (let ((map (make-sparse-keymap))) | (let ((map (make-sparse-keymap))) | ||||
| (define-key map "n" 'next-line) | (define-key map "n" 'next-line) | ||||
| (define-key map "p" 'previous-line) | (define-key map "p" 'previous-line) | ||||
| (define-key map "^" 'git-revision-up) | |||||
| (define-key map (kbd "C-m") 'git-revision-mode-open-this) | |||||
| (define-key map "^" 'git-walktree-parent) | |||||
| (define-key map (kbd "C-m") 'git-walktree-mode-open-this) | |||||
| map)) | map)) | ||||
| (defvar git-revision-mode-font-lock-keywords | |||||
| (defvar git-walktree-mode-font-lock-keywords | |||||
| `( | `( | ||||
| (,git-revision-ls-tree-line-tree-regexp . (4 'git-revision-tree-face)) | |||||
| (,git-walktree-ls-tree-line-tree-regexp . (4 'git-walktree-tree-face)) | |||||
| ) | ) | ||||
| "Syntax highlighting for git-revision mode.") | |||||
| "Syntax highlighting for git-walktree mode.") | |||||
| (define-derived-mode git-revision-mode special-mode "git-revision" | |||||
| "Major-mode for `git-revision-open'." | |||||
| (define-derived-mode git-walktree-mode special-mode "git-walktree" | |||||
| "Major-mode for `git-walktree-open'." | |||||
| (set (make-local-variable 'font-lock-defaults) | (set (make-local-variable 'font-lock-defaults) | ||||
| '(git-revision-mode-font-lock-keywords | |||||
| '(git-walktree-mode-font-lock-keywords | |||||
| nil nil nil nil | nil nil nil nil | ||||
| )) | )) | ||||
| ;; (add-to-list 'font-lock-value | |||||
| ;; ) | |||||
| ) | ) | ||||
| (require 'magit nil t) | (require 'magit nil t) | ||||