branch: externals/vc-jj
commit 0a3e850aed91b66e92554df6a2a9d29d710c56cd
Author: Rob <bruno.rob...@gmail.com>
Commit: Rudi Schlatte <r...@constantly.at>

    Improve vc-jj-print-log
    
    Use standard log commands and add more supporting, in this case `new`, 
`edit` and `abandon`
---
 vc-jj.el | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 200 insertions(+), 12 deletions(-)

diff --git a/vc-jj.el b/vc-jj.el
index 8cd6e03769..e2cb7896d7 100644
--- a/vc-jj.el
+++ b/vc-jj.el
@@ -56,7 +56,36 @@
   "Control whether to have jj colorize the log."
   :type 'boolean)
 
-(defcustom vc-jj-log-template "builtin_log_compact"
+(defvar vc-jj--log-default-template
+  "
+if(root,
+  format_root_commit(self),
+  label(if(current_working_copy, \"working_copy\"),
+    concat(
+      separate(\" \",
+        change_id.shortest(8).prefix() ++ \"​\" ++ 
change_id.shortest(8).rest(),
+        if(author.name(), author.name(), if(author.email(), 
author.email().local(), email_placeholder)),
+        commit_timestamp(self).format(\"%Y-%m-%d\"),
+        bookmarks,
+        tags,
+        working_copies,
+        if(git_head, label(\"git_head\", \"git_head()\")),
+        format_short_commit_id(commit_id),
+        if(conflict, label(\"conflict\", \"conflict\")),
+        if(config(\"ui.show-cryptographic-signatures\").as_boolean(),
+          format_short_cryptographic_signature(signature)),
+        if(empty, label(\"empty\", \"(empty)\")),
+        if(description,
+          description.first_line(),
+          label(if(empty, \"empty\"), description_placeholder),
+        ),
+      ) ++ \"\n\",
+    ),
+  )
+)
+")
+
+(defcustom vc-jj-log-template "cap_oneline"
   "The template to use for `vc-print-log'."
   :type '(radio (const "builtin_log_oneline")
                 (const "builtin_log_compact")
@@ -426,21 +455,21 @@ If REV is not specified, revert the file as with 
`vc-jj-revert'."
   "Print commit log associated with FILES into specified BUFFER."
   ;; FIXME: limit can be a revision string, in which case we should
   ;; print revisions between start-revision and limit
+  (vc-setup-buffer buffer)
   (let ((inhibit-read-only t)
         (args (append
                (and limit
                     (list "-n" (number-to-string limit)))
-               (and start-revision
-                    (list "-r" (concat ".." start-revision)))
-               (and vc-jj-colorize-log (list "--color" "always"))
-               (list "-T" vc-jj-log-template "--")
-               files)))
-    (with-current-buffer buffer (erase-buffer))
-    (apply #'call-process vc-jj-program nil buffer nil "log" args)
-    (when vc-jj-colorize-log
-      (with-current-buffer buffer
-        (ansi-color-apply-on-region (point-min) (point-max)))))
-  (goto-char (point-min)))
+               (if start-revision
+                 (list "-r" (concat "::" start-revision))
+                 (list "-r" "::"))
+               (list "-T" vc-jj--log-default-template "--")
+               (unless (string-equal (vc-jj-root (car files)) (car files))
+                 files))))
+    (with-current-buffer buffer
+      (apply #'vc-jj-command buffer
+        'async nil
+        args))))
 
 (defun vc-jj-show-log-entry (revision)
   "Move to the log entry for REVISION."
@@ -460,6 +489,165 @@ If REV is not specified, revert the file as with 
`vc-jj-revert'."
 ;;   ;; TODO
 ;;   )
 
+(defvar log-view-message-re)
+(defvar log-view-file-re)
+(defvar log-view-font-lock-keywords)
+(defvar log-view-per-file-logs)
+(defvar log-view-expanded-log-entry-function)
+
+(defvar vc-jj--logline-re
+  (rx
+    line-start
+    ;; graph
+    (+? nonl)
+    " "
+    ;; change-id
+    (group (+ (any "K-Zk-z")))
+    space
+    (group (+ (any "K-Zk-z")))
+    " "
+    ;; author
+    (group (* nonl))
+    " "
+    ;; time
+    (group
+      (= 4 (any num)) "-" (= 2 (any num)) "-" (= 2 (any num)))
+      ;; " "
+      ;; (= 2 (any num)) ":" (= 2 (any num)) ":" (= 2 (any num)))
+    ;; tags, bookmarks, commit-id
+    (group
+      (*? nonl))
+
+    " "
+    ;; commit-id
+    (group
+      (+ (any hex)))
+    " "
+    ;; special states
+    (? (group (or (: "(empty) ")
+                "")))
+    (? (group (or (: "(no description set)" (* nonl))
+                "")))
+    ;; regular description
+    (* nonl)
+    line-end))
+
+(define-derived-mode vc-jj-log-view-mode log-view-mode "JJ-Log-View"
+  (require 'add-log) ;; We need the faces add-log.
+  ;; Don't have file markers, so use impossible regexp.
+  (setq-local log-view-file-re regexp-unmatchable)
+  (setq-local log-view-per-file-logs nil)
+  (setq-local log-view-message-re vc-jj--logline-re)
+  ;; Allow expanding short log entries.
+  (setq truncate-lines t)
+  (setq-local log-view-expanded-log-entry-function
+    'vc-jj-expanded-log-entry)
+  (setq-local log-view-font-lock-keywords
+    `((,vc-jj--logline-re
+        (1 'log-view-message)
+        (2 'change-log-list)
+        (3 'change-log-name)
+        (4 'change-log-date)
+        (5 'change-log-file)
+        (6 'change-log-list)
+        (7 'change-log-function)
+        (8 'change-log-function))))
+
+  (keymap-set vc-jj-log-view-mode-map "r" #'vc-jj-edit-change)
+  (keymap-set vc-jj-log-view-mode-map "x" #'vc-jj-abandon-change)
+  (keymap-set vc-jj-log-view-mode-map "i" #'vc-jj-new-change))
+
+
+(defun vc-jj-expanded-log-entry (revision)
+  (with-temp-buffer
+    (vc-jj-command t 0 nil
+      "log"
+      "-r" revision
+      "-T" "builtin_log_detailed"
+      "--color" "never"
+      "--no-graph"
+      "--")
+    (buffer-string)))
+
+(defun vc-jj-previous-revision (file rev)
+  "JJ-specific version of `vc-previous-revision'."
+  (if file
+    (with-temp-buffer
+      (apply #'vc-jj-command t 0 nil "log"
+        (list "-r" (concat ".." rev "-")
+          "-T" "change_id.shortest()"
+          "--no-graph"
+            "-n" "1"
+          "--" file))
+      (let ((s (buffer-string)))
+        (unless (string-blank-p s)
+          s)))
+    (with-output-to-string
+      (vc-jj-command standard-output 1 nil
+        "log" "--no-graph" "-n" "1"
+        "-T" "change_id.shortest()"
+        "-r" (concat rev "-")))))
+
+(defun vc-jj-next-revision (file rev)
+  "JJ-specific version of `vc-next-revision'."
+  (if file
+    (with-temp-buffer
+      (apply #'vc-jj-command (current-buffer) 0 nil "log"
+        (list "-r" (format "roots(files(\"%s\") ~ ::%s)" file rev)
+          "-T" "change_id.shortest()"
+          "--no-graph"
+          "-n" "1"))
+      (let ((s (buffer-string)))
+        (unless (string-blank-p s)
+          s)))
+    (with-output-to-string
+      (vc-jj-command standard-output 1 nil
+        "log" "--no-graph" "-n" "1"
+        "-T" "change_id.shortest()"
+        "-r" (concat rev "+")))))
+
+(defun vc-jj-get-change-comment (_files rev)
+  (with-output-to-string
+    (vc-jj-command standard-output 1 nil
+      "log" "--no-graph" "-n" "1" "-T" "description" "-r" rev)))
+
+(declare-function log-edit-mode "log-edit" ())
+(declare-function log-edit-toggle-header "log-edit" (header value))
+(declare-function log-edit-extract-headers "log-edit" (headers string))
+(declare-function log-edit--toggle-amend "log-edit" (last-msg-fn))
+
+;; TODO: protect immutable changes
+(defun vc-jj-modify-change-comment (_files rev comment)
+  (let ((args (log-edit-extract-headers () comment)))
+    (vc-jj-command nil 0 nil "desc" rev "-m" (pop args) "--quiet")))
+
+(defun vc-jj--reload-log-buffers ()
+  (and vc-parent-buffer
+    (with-current-buffer vc-parent-buffer
+      (revert-buffer)))
+  (with-current-buffer (revert-buffer)))
+
+(defun vc-jj-edit-change ()
+  (interactive)
+  (let ((rev (log-view-current-tag)))
+    (vc-jj-command nil 0 nil "edit" rev "--quiet")
+    (vc-jj--reload-log-buffers)))
+
+(defun vc-jj-abandon-change ()
+  (interactive)
+  ;; TODO: should probably ask for confirmation, although this would be
+  ;; different from the cli
+  (let ((rev (log-view-current-tag)))
+    (vc-jj-command nil 0 nil "abandon" rev "--quiet")
+    (vc-jj--reload-log-buffers)))
+
+(defun vc-jj-new-change ()
+  (interactive)
+  (let ((rev (log-view-current-tag)))
+    (vc-jj-command nil 0 nil "new" rev "--quiet")
+    (with-current-buffer (revert-buffer))
+    (vc-jj--reload-log-buffers)))
+
 (defun vc-jj-root (file)
   "Return the root of the repository containing FILE.
 Return NIL if FILE is not in a jj repository."

Reply via email to