changelog shortlog graph tags branches files raw help

Mercurial > infra > home / changeset: sbcl

changeset 43: d70be963bfb1
parent 40: 2d74d85d7031 (diff)
parent 42: b9e2f76128bb (current diff)
child 44: 3b1dfa0741c8
child 45: cd44192f8af5
author: Richard Westhaver <ellis@rwest.io>
date: Sat, 15 Jun 2024 19:57:38 -0400
files: .sbclrc
description: sbcl
     1.1--- a/.config/containers/storage.conf	Sat Jun 15 19:53:29 2024 -0400
     1.2+++ b/.config/containers/storage.conf	Sat Jun 15 19:57:38 2024 -0400
     1.3@@ -1,5 +1,5 @@
     1.4 [storage]
     1.5 driver = "btrfs"
     1.6-graphroot = "/mnt/y/data/containers/storage"
     1.7+# graphroot = "/mnt/y/data/containers/storage"
     1.8 [storage.options]
     1.9 pull_options = {enable_partial_images = "true", use_hard_links = "false", ostree_repos=""}
    1.10\ No newline at end of file
     2.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2+++ b/.emacs.d/lib/mercurial.el	Sat Jun 15 19:57:38 2024 -0400
     2.3@@ -0,0 +1,1293 @@
     2.4+;;; mercurial.el --- Emacs support for the Mercurial distributed SCM
     2.5+
     2.6+;; Copyright (C) 2005, 2006 Bryan O'Sullivan
     2.7+
     2.8+;; Author: Bryan O'Sullivan <bos@serpentine.com>
     2.9+
    2.10+;; mercurial.el is free software; you can redistribute it and/or
    2.11+;; modify it under the terms of the GNU General Public License version
    2.12+;; 2 or any later version.
    2.13+
    2.14+;; mercurial.el is distributed in the hope that it will be useful, but
    2.15+;; WITHOUT ANY WARRANTY; without even the implied warranty of
    2.16+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.17+;; General Public License for more details.
    2.18+
    2.19+;; You should have received a copy of the GNU General Public License
    2.20+;; along with mercurial.el, GNU Emacs, or XEmacs; see the file COPYING
    2.21+;; (`C-h C-l').  If not, see <http://www.gnu.org/licenses/>.
    2.22+
    2.23+;;; Commentary:
    2.24+
    2.25+;; mercurial.el builds upon Emacs's VC mode to provide flexible
    2.26+;; integration with the Mercurial distributed SCM tool.
    2.27+
    2.28+;; To get going as quickly as possible, load mercurial.el into Emacs and
    2.29+;; type `C-c h h'; this runs hg-help-overview, which prints a helpful
    2.30+;; usage overview.
    2.31+
    2.32+;; Much of the inspiration for mercurial.el comes from Rajesh
    2.33+;; Vaidheeswarran's excellent p4.el, which does an admirably thorough
    2.34+;; job for the commercial Perforce SCM product.  In fact, substantial
    2.35+;; chunks of code are adapted from p4.el.
    2.36+
    2.37+;; This code has been developed under XEmacs 21.5, and may not work as
    2.38+;; well under GNU Emacs (albeit tested under 21.4).  Patches to
    2.39+;; enhance the portability of this code, fix bugs, and add features
    2.40+;; are most welcome.
    2.41+
    2.42+;; As of version 22.3, GNU Emacs's VC mode has direct support for
    2.43+;; Mercurial, so this package may not prove as useful there.
    2.44+
    2.45+;; Please send problem reports and suggestions to bos@serpentine.com.
    2.46+
    2.47+
    2.48+;;; Code:
    2.49+
    2.50+(eval-when-compile (require 'cl))
    2.51+(require 'diff-mode)
    2.52+(require 'easymenu)
    2.53+(require 'executable)
    2.54+(require 'vc)
    2.55+
    2.56+(defmacro hg-feature-cond (&rest clauses)
    2.57+  "Test CLAUSES for feature at compile time.
    2.58+Each clause is (FEATURE BODY...)."
    2.59+  (dolist (x clauses)
    2.60+    (let ((feature (car x))
    2.61+	  (body (cdr x)))
    2.62+      (when (or (eq feature t)
    2.63+		(featurep feature))
    2.64+	(return (cons 'progn body))))))
    2.65+
    2.66+
    2.67+;;; XEmacs has view-less, while GNU Emacs has view.  Joy.
    2.68+
    2.69+(hg-feature-cond
    2.70+ (xemacs (require 'view-less))
    2.71+ (t (require 'view)))
    2.72+
    2.73+
    2.74+;;; Variables accessible through the custom system.
    2.75+
    2.76+(defgroup mercurial nil
    2.77+  "Mercurial distributed SCM."
    2.78+  :group 'tools)
    2.79+
    2.80+(defcustom hg-binary
    2.81+    (or (executable-find "hg")
    2.82+	(dolist (path '("~/bin/hg" "/usr/bin/hg" "/usr/local/bin/hg"))
    2.83+	  (when (file-executable-p path)
    2.84+	    (return path))))
    2.85+  "The path to Mercurial's hg executable."
    2.86+  :type '(file :must-match t)
    2.87+  :group 'mercurial)
    2.88+
    2.89+(defcustom hg-mode-hook nil
    2.90+  "Hook run when a buffer enters hg-mode."
    2.91+  :type 'sexp
    2.92+  :group 'mercurial)
    2.93+
    2.94+(defcustom hg-commit-mode-hook nil
    2.95+  "Hook run when a buffer is created to prepare a commit."
    2.96+  :type 'sexp
    2.97+  :group 'mercurial)
    2.98+
    2.99+(defcustom hg-pre-commit-hook nil
   2.100+  "Hook run before a commit is performed.
   2.101+If you want to prevent the commit from proceeding, raise an error."
   2.102+  :type 'sexp
   2.103+  :group 'mercurial)
   2.104+
   2.105+(defcustom hg-log-mode-hook nil
   2.106+  "Hook run after a buffer is filled with log information."
   2.107+  :type 'sexp
   2.108+  :group 'mercurial)
   2.109+
   2.110+(defcustom hg-global-prefix "\C-ch"
   2.111+  "The global prefix for Mercurial keymap bindings."
   2.112+  :type 'sexp
   2.113+  :group 'mercurial)
   2.114+
   2.115+(defcustom hg-commit-allow-empty-message nil
   2.116+  "Whether to allow changes to be committed with empty descriptions."
   2.117+  :type 'boolean
   2.118+  :group 'mercurial)
   2.119+
   2.120+(defcustom hg-commit-allow-empty-file-list nil
   2.121+  "Whether to allow changes to be committed without any modified files."
   2.122+  :type 'boolean
   2.123+  :group 'mercurial)
   2.124+
   2.125+(defcustom hg-rev-completion-limit 100
   2.126+  "The maximum number of revisions that hg-read-rev will offer to complete.
   2.127+This affects memory usage and performance when prompting for revisions
   2.128+in a repository with a lot of history."
   2.129+  :type 'integer
   2.130+  :group 'mercurial)
   2.131+
   2.132+(defcustom hg-log-limit 50
   2.133+  "The maximum number of revisions that hg-log will display."
   2.134+  :type 'integer
   2.135+  :group 'mercurial)
   2.136+
   2.137+(defcustom hg-update-modeline t
   2.138+  "Whether to update the modeline with the status of a file after every save.
   2.139+Set this to nil on platforms with poor process management, such as Windows."
   2.140+  :type 'boolean
   2.141+  :group 'mercurial)
   2.142+
   2.143+(defcustom hg-incoming-repository "default"
   2.144+  "The repository from which changes are pulled from by default.
   2.145+This should be a symbolic repository name, since it is used for all
   2.146+repository-related commands."
   2.147+  :type 'string
   2.148+  :group 'mercurial)
   2.149+
   2.150+(defcustom hg-outgoing-repository ""
   2.151+  "The repository to which changes are pushed to by default.
   2.152+This should be a symbolic repository name, since it is used for all
   2.153+repository-related commands."
   2.154+  :type 'string
   2.155+  :group 'mercurial)
   2.156+
   2.157+
   2.158+;;; Other variables.
   2.159+
   2.160+(defvar hg-mode nil
   2.161+  "Is this file managed by Mercurial?")
   2.162+(make-variable-buffer-local 'hg-mode)
   2.163+(put 'hg-mode 'permanent-local t)
   2.164+
   2.165+(defvar hg-status nil)
   2.166+(make-variable-buffer-local 'hg-status)
   2.167+(put 'hg-status 'permanent-local t)
   2.168+
   2.169+(defvar hg-prev-buffer nil)
   2.170+(make-variable-buffer-local 'hg-prev-buffer)
   2.171+(put 'hg-prev-buffer 'permanent-local t)
   2.172+
   2.173+(defvar hg-root nil)
   2.174+(make-variable-buffer-local 'hg-root)
   2.175+(put 'hg-root 'permanent-local t)
   2.176+
   2.177+(defvar hg-view-mode nil)
   2.178+(make-variable-buffer-local 'hg-view-mode)
   2.179+(put 'hg-view-mode 'permanent-local t)
   2.180+
   2.181+(defvar hg-view-file-name nil)
   2.182+(make-variable-buffer-local 'hg-view-file-name)
   2.183+(put 'hg-view-file-name 'permanent-local t)
   2.184+
   2.185+(defvar hg-output-buffer-name "*Hg*"
   2.186+  "The name to use for Mercurial output buffers.")
   2.187+
   2.188+(defvar hg-file-history nil)
   2.189+(defvar hg-repo-history nil)
   2.190+(defvar hg-rev-history nil)
   2.191+(defvar hg-repo-completion-table nil)	; shut up warnings
   2.192+
   2.193+
   2.194+;;; Random constants.
   2.195+
   2.196+(defconst hg-commit-message-start
   2.197+  "--- Enter your commit message.  Type `C-c C-c' to commit. ---\n")
   2.198+
   2.199+(defconst hg-commit-message-end
   2.200+  "--- Files in bold will be committed.  Click to toggle selection. ---\n")
   2.201+
   2.202+(defconst hg-state-alist
   2.203+  '((?M . modified)
   2.204+    (?A . added)
   2.205+    (?R . removed)
   2.206+    (?! . deleted)
   2.207+    (?C . normal)
   2.208+    (?I . ignored)
   2.209+    (?? . nil)))
   2.210+
   2.211+;;; hg-mode keymap.
   2.212+
   2.213+(defvar hg-prefix-map
   2.214+  (let ((map (make-sparse-keymap)))
   2.215+    (hg-feature-cond (xemacs (set-keymap-name map 'hg-prefix-map))) ; XEmacs
   2.216+    (set-keymap-parent map vc-prefix-map)
   2.217+    (define-key map "=" 'hg-diff)
   2.218+    (define-key map "c" 'hg-undo)
   2.219+    (define-key map "g" 'hg-annotate)
   2.220+    (define-key map "i" 'hg-add)
   2.221+    (define-key map "l" 'hg-log)
   2.222+    (define-key map "n" 'hg-commit-start)
   2.223+    ;; (define-key map "r" 'hg-update)
   2.224+    (define-key map "u" 'hg-revert-buffer)
   2.225+    (define-key map "~" 'hg-version-other-window)
   2.226+    map)
   2.227+  "This keymap overrides some default vc-mode bindings.")
   2.228+
   2.229+(defvar hg-mode-map
   2.230+  (let ((map (make-sparse-keymap)))
   2.231+    (define-key map "\C-xv" hg-prefix-map)
   2.232+    map))
   2.233+
   2.234+(add-minor-mode 'hg-mode 'hg-mode hg-mode-map)
   2.235+
   2.236+
   2.237+;;; Global keymap.
   2.238+
   2.239+(defvar hg-global-map
   2.240+  (let ((map (make-sparse-keymap)))
   2.241+    (define-key map "," 'hg-incoming)
   2.242+    (define-key map "." 'hg-outgoing)
   2.243+    (define-key map "<" 'hg-pull)
   2.244+    (define-key map "=" 'hg-diff-repo)
   2.245+    (define-key map ">" 'hg-push)
   2.246+    (define-key map "?" 'hg-help-overview)
   2.247+    (define-key map "A" 'hg-addremove)
   2.248+    (define-key map "U" 'hg-revert)
   2.249+    (define-key map "a" 'hg-add)
   2.250+    (define-key map "c" 'hg-commit-start)
   2.251+    (define-key map "f" 'hg-forget)
   2.252+    (define-key map "h" 'hg-help-overview)
   2.253+    (define-key map "i" 'hg-init)
   2.254+    (define-key map "l" 'hg-log-repo)
   2.255+    (define-key map "r" 'hg-root)
   2.256+    (define-key map "s" 'hg-status)
   2.257+    (define-key map "u" 'hg-update)
   2.258+    map))
   2.259+
   2.260+(global-set-key hg-global-prefix hg-global-map)
   2.261+
   2.262+;;; View mode keymap.
   2.263+
   2.264+(defvar hg-view-mode-map
   2.265+  (let ((map (make-sparse-keymap)))
   2.266+    (hg-feature-cond (xemacs (set-keymap-name map 'hg-view-mode-map))) ; XEmacs
   2.267+    (define-key map (hg-feature-cond (xemacs [button2])
   2.268+				     (t [mouse-2]))
   2.269+      'hg-buffer-mouse-clicked)
   2.270+    map))
   2.271+
   2.272+(add-minor-mode 'hg-view-mode "" hg-view-mode-map)
   2.273+
   2.274+
   2.275+;;; Commit mode keymaps.
   2.276+
   2.277+(defvar hg-commit-mode-map
   2.278+  (let ((map (make-sparse-keymap)))
   2.279+    (define-key map "\C-c\C-c" 'hg-commit-finish)
   2.280+    (define-key map "\C-c\C-k" 'hg-commit-kill)
   2.281+    (define-key map "\C-xv=" 'hg-diff-repo)
   2.282+    map))
   2.283+
   2.284+(defvar hg-commit-mode-file-map
   2.285+  (let ((map (make-sparse-keymap)))
   2.286+    (define-key map (hg-feature-cond (xemacs [button2])
   2.287+				     (t [mouse-2]))
   2.288+      'hg-commit-mouse-clicked)
   2.289+    (define-key map " " 'hg-commit-toggle-file)
   2.290+    (define-key map "\r" 'hg-commit-toggle-file)
   2.291+    map))
   2.292+
   2.293+
   2.294+;;; Convenience functions.
   2.295+
   2.296+(defsubst hg-binary ()
   2.297+  (if hg-binary
   2.298+      hg-binary
   2.299+    (error "No `hg' executable found!")))
   2.300+
   2.301+(defsubst hg-replace-in-string (str regexp newtext &optional literal)
   2.302+  "Replace all matches in STR for REGEXP with NEWTEXT string.
   2.303+Return the new string.  Optional LITERAL non-nil means do a literal
   2.304+replacement.
   2.305+
   2.306+This function bridges yet another pointless impedance gap between
   2.307+XEmacs and GNU Emacs."
   2.308+  (hg-feature-cond
   2.309+   (xemacs (replace-in-string str regexp newtext literal))
   2.310+   (t (replace-regexp-in-string regexp newtext str nil literal))))
   2.311+
   2.312+(defsubst hg-strip (str)
   2.313+  "Strip leading and trailing blank lines from a string."
   2.314+  (hg-replace-in-string (hg-replace-in-string str "[\r\n][ \t\r\n]*\\'" "")
   2.315+			"\\`[ \t\r\n]*[\r\n]" ""))
   2.316+
   2.317+(defsubst hg-chomp (str)
   2.318+  "Strip trailing newlines from a string."
   2.319+  (hg-replace-in-string str "[\r\n]+\\'" ""))
   2.320+
   2.321+(defun hg-run-command (command &rest args)
   2.322+  "Run the shell command COMMAND, returning (EXIT-CODE . COMMAND-OUTPUT).
   2.323+The list ARGS contains a list of arguments to pass to the command."
   2.324+  (let* (exit-code
   2.325+	 (output
   2.326+	  (with-output-to-string
   2.327+	    (with-current-buffer
   2.328+		standard-output
   2.329+	      (setq exit-code
   2.330+		    (apply 'call-process command nil t nil args))))))
   2.331+    (cons exit-code output)))
   2.332+
   2.333+(defun hg-run (command &rest args)
   2.334+  "Run the Mercurial command COMMAND, returning (EXIT-CODE . COMMAND-OUTPUT)."
   2.335+  (apply 'hg-run-command (hg-binary) command args))
   2.336+
   2.337+(defun hg-run0 (command &rest args)
   2.338+  "Run the Mercurial command COMMAND, returning its output.
   2.339+If the command does not exit with a zero status code, raise an error."
   2.340+  (let ((res (apply 'hg-run-command (hg-binary) command args)))
   2.341+    (if (not (eq (car res) 0))
   2.342+	(error "Mercurial command failed %s - exit code %s"
   2.343+	       (cons command args)
   2.344+	       (car res))
   2.345+      (cdr res))))
   2.346+
   2.347+(defmacro hg-do-across-repo (path &rest body)
   2.348+  (let ((root-name (make-symbol "root-"))
   2.349+	(buf-name (make-symbol "buf-")))
   2.350+    `(let ((,root-name (hg-root ,path)))
   2.351+       (save-excursion
   2.352+	 (dolist (,buf-name (buffer-list))
   2.353+	   (set-buffer ,buf-name)
   2.354+	   (when (and hg-status (equal (hg-root buffer-file-name) ,root-name))
   2.355+	     ,@body))))))
   2.356+
   2.357+(put 'hg-do-across-repo 'lisp-indent-function 1)
   2.358+
   2.359+(defun hg-sync-buffers (path)
   2.360+  "Sync buffers visiting PATH with their on-disk copies.
   2.361+If PATH is not being visited, but is under the repository root, sync
   2.362+all buffers visiting files in the repository."
   2.363+  (let ((buf (find-buffer-visiting path)))
   2.364+    (if buf
   2.365+	(with-current-buffer buf
   2.366+	  (vc-buffer-sync))
   2.367+      (hg-do-across-repo path
   2.368+	(vc-buffer-sync)))))
   2.369+
   2.370+(defun hg-buffer-commands (pnt)
   2.371+  "Use the properties of a character to do something sensible."
   2.372+  (interactive "d")
   2.373+  (let ((rev (get-char-property pnt 'rev))
   2.374+	(file (get-char-property pnt 'file)))
   2.375+    (cond
   2.376+     (file
   2.377+      (find-file-other-window file))
   2.378+     (rev
   2.379+      (hg-diff hg-view-file-name rev rev))
   2.380+     ((message "I don't know how to do that yet")))))
   2.381+
   2.382+(defsubst hg-event-point (event)
   2.383+  "Return the character position of the mouse event EVENT."
   2.384+  (hg-feature-cond (xemacs (event-point event))
   2.385+		   (t (posn-point (event-start event)))))
   2.386+
   2.387+(defsubst hg-event-window (event)
   2.388+  "Return the window over which mouse event EVENT occurred."
   2.389+  (hg-feature-cond (xemacs (event-window event))
   2.390+		   (t (posn-window (event-start event)))))
   2.391+
   2.392+(defun hg-buffer-mouse-clicked (event)
   2.393+  "Translate the mouse clicks in a HG log buffer to character events.
   2.394+These are then handed off to `hg-buffer-commands'.
   2.395+
   2.396+Handle frickin' frackin' gratuitous event-related incompatibilities."
   2.397+  (interactive "e")
   2.398+  (select-window (hg-event-window event))
   2.399+  (hg-buffer-commands (hg-event-point event)))
   2.400+
   2.401+(defsubst hg-abbrev-file-name (file)
   2.402+  "Portable wrapper around abbreviate-file-name."
   2.403+  (hg-feature-cond (xemacs (abbreviate-file-name file t))
   2.404+		   (t (abbreviate-file-name file))))
   2.405+
   2.406+(defun hg-read-file-name (&optional prompt default)
   2.407+  "Read a file or directory name, or a pattern, to use with a command."
   2.408+  (save-excursion
   2.409+    (while hg-prev-buffer
   2.410+      (set-buffer hg-prev-buffer))
   2.411+    (let ((path (or default
   2.412+                    (buffer-file-name)
   2.413+                    (expand-file-name default-directory))))
   2.414+      (if (or (not path) current-prefix-arg)
   2.415+          (expand-file-name
   2.416+           (eval (list* 'read-file-name
   2.417+                        (format "File, directory or pattern%s: "
   2.418+                                (or prompt ""))
   2.419+                        (and path (file-name-directory path))
   2.420+                        nil nil
   2.421+                        (and path (file-name-nondirectory path))
   2.422+                        (hg-feature-cond
   2.423+			 (xemacs (cons (quote 'hg-file-history) nil))
   2.424+			 (t nil)))))
   2.425+        path))))
   2.426+
   2.427+(defun hg-read-number (&optional prompt default)
   2.428+  "Read a integer value."
   2.429+  (save-excursion
   2.430+    (if (or (not default) current-prefix-arg)
   2.431+        (string-to-number
   2.432+         (eval (list* 'read-string
   2.433+                      (or prompt "")
   2.434+                      (if default (cons (format "%d" default) nil) nil))))
   2.435+      default)))
   2.436+
   2.437+(defun hg-read-config ()
   2.438+  "Return an alist of (key . value) pairs of Mercurial config data.
   2.439+Each key is of the form (section . name)."
   2.440+  (let (items)
   2.441+    (dolist (line (split-string (hg-chomp (hg-run0 "debugconfig")) "\n") items)
   2.442+      (string-match "^\\([^=]*\\)=\\(.*\\)" line)
   2.443+      (let* ((left (substring line (match-beginning 1) (match-end 1)))
   2.444+	     (right (substring line (match-beginning 2) (match-end 2)))
   2.445+	     (key (split-string left "\\."))
   2.446+	     (value (hg-replace-in-string right "\\\\n" "\n" t)))
   2.447+	(setq items (cons (cons (cons (car key) (cadr key)) value) items))))))
   2.448+
   2.449+(defun hg-config-section (section config)
   2.450+  "Return an alist of (name . value) pairs for SECTION of CONFIG."
   2.451+  (let (items)
   2.452+    (dolist (item config items)
   2.453+      (when (equal (caar item) section)
   2.454+	(setq items (cons (cons (cdar item) (cdr item)) items))))))
   2.455+
   2.456+(defun hg-string-starts-with (sub str)
   2.457+  "Indicate whether string STR starts with the substring or character SUB."
   2.458+  (if (not (stringp sub))
   2.459+      (and (> (length str) 0) (equal (elt str 0) sub))
   2.460+    (let ((sub-len (length sub)))
   2.461+      (and (<= sub-len (length str))
   2.462+	   (string= sub (substring str 0 sub-len))))))
   2.463+
   2.464+(defun hg-complete-repo (string predicate all)
   2.465+  "Attempt to complete a repository name.
   2.466+We complete on either symbolic names from Mercurial's config or real
   2.467+directory names from the file system.  We do not penalize URLs."
   2.468+  (or (if all
   2.469+	  (all-completions string hg-repo-completion-table predicate)
   2.470+	(try-completion string hg-repo-completion-table predicate))
   2.471+      (let* ((str (expand-file-name string))
   2.472+	     (dir (file-name-directory str))
   2.473+	     (file (file-name-nondirectory str)))
   2.474+	(if all
   2.475+	    (let (completions)
   2.476+	      (dolist (name (delete "./" (file-name-all-completions file dir))
   2.477+			    completions)
   2.478+		(let ((path (concat dir name)))
   2.479+		  (when (file-directory-p path)
   2.480+		    (setq completions (cons name completions))))))
   2.481+	  (let ((comp (file-name-completion file dir)))
   2.482+	    (if comp
   2.483+		(hg-abbrev-file-name (concat dir comp))))))))
   2.484+
   2.485+(defun hg-read-repo-name (&optional prompt initial-contents default)
   2.486+  "Read the location of a repository."
   2.487+  (save-excursion
   2.488+    (while hg-prev-buffer
   2.489+      (set-buffer hg-prev-buffer))
   2.490+    (let (hg-repo-completion-table)
   2.491+      (if current-prefix-arg
   2.492+	  (progn
   2.493+	    (dolist (path (hg-config-section "paths" (hg-read-config)))
   2.494+	      (setq hg-repo-completion-table
   2.495+		    (cons (cons (car path) t) hg-repo-completion-table))
   2.496+	      (unless (hg-string-starts-with (hg-feature-cond
   2.497+					      (xemacs directory-sep-char)
   2.498+					      (t ?/))
   2.499+					     (cdr path))
   2.500+		(setq hg-repo-completion-table
   2.501+		      (cons (cons (cdr path) t) hg-repo-completion-table))))
   2.502+	    (completing-read (format "Repository%s: " (or prompt ""))
   2.503+			     'hg-complete-repo
   2.504+			     nil
   2.505+			     nil
   2.506+			     initial-contents
   2.507+			     'hg-repo-history
   2.508+			     default))
   2.509+	default))))
   2.510+
   2.511+(defun hg-read-rev (&optional prompt default)
   2.512+  "Read a revision or tag, offering completions."
   2.513+  (save-excursion
   2.514+    (while hg-prev-buffer
   2.515+      (set-buffer hg-prev-buffer))
   2.516+    (let ((rev (or default "tip")))
   2.517+      (if current-prefix-arg
   2.518+	  (let ((revs (split-string
   2.519+		       (hg-chomp
   2.520+			(hg-run0 "-q" "log" "-l"
   2.521+				 (format "%d" hg-rev-completion-limit)))
   2.522+		       "[\n:]")))
   2.523+	    (dolist (line (split-string (hg-chomp (hg-run0 "tags")) "\n"))
   2.524+	      (setq revs (cons (car (split-string line "\\s-")) revs)))
   2.525+	    (completing-read (format "Revision%s (%s): "
   2.526+				     (or prompt "")
   2.527+				     (or default "tip"))
   2.528+			     (mapcar (lambda (x) (cons x x)) revs)
   2.529+			     nil
   2.530+			     nil
   2.531+			     nil
   2.532+			     'hg-rev-history
   2.533+			     (or default "tip")))
   2.534+	rev))))
   2.535+
   2.536+(defun hg-parents-for-mode-line (root)
   2.537+  "Format the parents of the working directory for the mode line."
   2.538+  (let ((parents (split-string (hg-chomp
   2.539+				(hg-run0 "--cwd" root "parents" "--template"
   2.540+					 "{rev}\n")) "\n")))
   2.541+    (mapconcat 'identity parents "+")))
   2.542+
   2.543+(defun hg-buffers-visiting-repo (&optional path)
   2.544+  "Return a list of buffers visiting the repository containing PATH."
   2.545+  (let ((root-name (hg-root (or path (buffer-file-name))))
   2.546+	bufs)
   2.547+    (save-excursion
   2.548+      (dolist (buf (buffer-list) bufs)
   2.549+	(set-buffer buf)
   2.550+	(let ((name (buffer-file-name)))
   2.551+	  (when (and hg-status name (equal (hg-root name) root-name))
   2.552+	    (setq bufs (cons buf bufs))))))))
   2.553+
   2.554+(defun hg-update-mode-lines (path)
   2.555+  "Update the mode lines of all buffers visiting the same repository as PATH."
   2.556+  (let* ((root (hg-root path))
   2.557+	 (parents (hg-parents-for-mode-line root)))
   2.558+    (save-excursion
   2.559+      (dolist (info (hg-path-status
   2.560+		     root
   2.561+		     (mapcar
   2.562+		      (function
   2.563+		       (lambda (buf)
   2.564+			 (substring (buffer-file-name buf) (length root))))
   2.565+		      (hg-buffers-visiting-repo root))))
   2.566+	(let* ((name (car info))
   2.567+	       (status (cdr info))
   2.568+	       (buf (find-buffer-visiting (concat root name))))
   2.569+	  (when buf
   2.570+	    (set-buffer buf)
   2.571+	    (hg-mode-line-internal status parents)))))))
   2.572+
   2.573+
   2.574+;;; View mode bits.
   2.575+
   2.576+(defun hg-exit-view-mode (buf)
   2.577+  "Exit from hg-view-mode.
   2.578+We delete the current window if entering hg-view-mode split the
   2.579+current frame."
   2.580+  (when (and (eq buf (current-buffer))
   2.581+	     (> (length (window-list)) 1))
   2.582+    (delete-window))
   2.583+  (when (buffer-live-p buf)
   2.584+    (kill-buffer buf)))
   2.585+
   2.586+(defun hg-view-mode (prev-buffer &optional file-name)
   2.587+  (goto-char (point-min))
   2.588+  (set-buffer-modified-p nil)
   2.589+  (toggle-read-only t)
   2.590+  (hg-feature-cond (xemacs (view-minor-mode prev-buffer 'hg-exit-view-mode))
   2.591+		   (t (view-mode-enter nil 'hg-exit-view-mode)))
   2.592+  (setq hg-view-mode t)
   2.593+  (setq truncate-lines t)
   2.594+  (when file-name
   2.595+    (setq hg-view-file-name
   2.596+	  (hg-abbrev-file-name file-name))))
   2.597+
   2.598+(defun hg-file-status (file)
   2.599+  "Return status of FILE, or nil if FILE does not exist or is unmanaged."
   2.600+  (let* ((s (hg-run "status" file))
   2.601+	 (exit (car s))
   2.602+	 (output (cdr s)))
   2.603+    (if (= exit 0)
   2.604+	(let ((state (and (>= (length output) 2)
   2.605+			  (= (aref output 1) ? )
   2.606+			  (assq (aref output 0) hg-state-alist))))
   2.607+	  (if state
   2.608+	      (cdr state)
   2.609+	    'normal)))))
   2.610+
   2.611+(defun hg-path-status (root paths)
   2.612+  "Return status of PATHS in repo ROOT as an alist.
   2.613+Each entry is a pair (FILE-NAME . STATUS)."
   2.614+  (let ((s (apply 'hg-run "--cwd" root "status" "-marduc" paths))
   2.615+	result)
   2.616+    (dolist (entry (split-string (hg-chomp (cdr s)) "\n") (nreverse result))
   2.617+      (let (state name)
   2.618+	(cond ((= (aref entry 1) ? )
   2.619+	       (setq state (assq (aref entry 0) hg-state-alist)
   2.620+		     name (substring entry 2)))
   2.621+	      ((string-match "\\(.*\\): " entry)
   2.622+	       (setq name (match-string 1 entry))))
   2.623+	(setq result (cons (cons name state) result))))))
   2.624+
   2.625+(defmacro hg-view-output (args &rest body)
   2.626+  "Execute BODY in a clean buffer, then quickly display that buffer.
   2.627+If the buffer contains one line, its contents are displayed in the
   2.628+minibuffer.  Otherwise, the buffer is displayed in view-mode.
   2.629+ARGS is of the form (BUFFER-NAME &optional FILE), where BUFFER-NAME is
   2.630+the name of the buffer to create, and FILE is the name of the file
   2.631+being viewed."
   2.632+  (let ((prev-buf (make-symbol "prev-buf-"))
   2.633+	(v-b-name (car args))
   2.634+	(v-m-rest (cdr args)))
   2.635+    `(let ((view-buf-name ,v-b-name)
   2.636+	   (,prev-buf (current-buffer)))
   2.637+       (get-buffer-create view-buf-name)
   2.638+       (kill-buffer view-buf-name)
   2.639+       (get-buffer-create view-buf-name)
   2.640+       (set-buffer view-buf-name)
   2.641+       (save-excursion
   2.642+	 ,@body)
   2.643+       (case (count-lines (point-min) (point-max))
   2.644+	 ((0)
   2.645+	  (kill-buffer view-buf-name)
   2.646+	  (message "(No output)"))
   2.647+	 ((1)
   2.648+	  (let ((msg (hg-chomp (buffer-substring (point-min) (point-max)))))
   2.649+	    (kill-buffer view-buf-name)
   2.650+	    (message "%s" msg)))
   2.651+	 (t
   2.652+	  (pop-to-buffer view-buf-name)
   2.653+	  (setq hg-prev-buffer ,prev-buf)
   2.654+	  (hg-view-mode ,prev-buf ,@v-m-rest))))))
   2.655+
   2.656+(put 'hg-view-output 'lisp-indent-function 1)
   2.657+
   2.658+;;; Context save and restore across revert and other operations.
   2.659+
   2.660+(defun hg-position-context (pos)
   2.661+  "Return information to help find the given position again."
   2.662+  (let* ((end (min (point-max) (+ pos 98))))
   2.663+    (list pos
   2.664+	  (buffer-substring (max (point-min) (- pos 2)) end)
   2.665+	  (- end pos))))
   2.666+
   2.667+(defun hg-buffer-context ()
   2.668+  "Return information to help restore a user's editing context.
   2.669+This is useful across reverts and merges, where a context is likely
   2.670+to have moved a little, but not really changed."
   2.671+  (let ((point-context (hg-position-context (point)))
   2.672+	(mark-context (let ((mark (mark-marker)))
   2.673+			(and mark
   2.674+			     ;; make sure active mark
   2.675+			     (marker-buffer mark)
   2.676+			     (marker-position mark)
   2.677+			     (hg-position-context mark)))))
   2.678+    (list point-context mark-context)))
   2.679+
   2.680+(defun hg-find-context (ctx)
   2.681+  "Attempt to find a context in the given buffer.
   2.682+Always returns a valid, hopefully sane, position."
   2.683+  (let ((pos (nth 0 ctx))
   2.684+	(str (nth 1 ctx))
   2.685+	(fixup (nth 2 ctx)))
   2.686+    (save-excursion
   2.687+      (goto-char (max (point-min) (- pos 15000)))
   2.688+      (if (and (not (equal str ""))
   2.689+	       (search-forward str nil t))
   2.690+	  (- (point) fixup)
   2.691+	(max pos (point-min))))))
   2.692+
   2.693+(defun hg-restore-context (ctx)
   2.694+  "Attempt to restore the user's editing context."
   2.695+  (let ((point-context (nth 0 ctx))
   2.696+	(mark-context (nth 1 ctx)))
   2.697+    (goto-char (hg-find-context point-context))
   2.698+    (when mark-context
   2.699+      (set-mark (hg-find-context mark-context)))))
   2.700+
   2.701+
   2.702+;;; Hooks.
   2.703+
   2.704+(defun hg-mode-line-internal (status parents)
   2.705+  (setq hg-status status
   2.706+	hg-mode (and status (concat " Hg:"
   2.707+				    parents
   2.708+				    (cdr (assq status
   2.709+					       '((normal . "")
   2.710+						 (removed . "r")
   2.711+						 (added . "a")
   2.712+						 (deleted . "!")
   2.713+						 (modified . "m"))))))))
   2.714+
   2.715+(defun hg-mode-line (&optional force)
   2.716+  "Update the modeline with the current status of a file.
   2.717+An update occurs if optional argument FORCE is non-nil,
   2.718+hg-update-modeline is non-nil, or we have not yet checked the state of
   2.719+the file."
   2.720+  (let ((root (hg-root)))
   2.721+    (when (and root (or force hg-update-modeline (not hg-mode)))
   2.722+      (let ((status (hg-file-status buffer-file-name))
   2.723+	    (parents (hg-parents-for-mode-line root)))
   2.724+	(hg-mode-line-internal status parents)
   2.725+	status))))
   2.726+
   2.727+(defun hg-mode (&optional toggle)
   2.728+  "Minor mode for Mercurial distributed SCM integration.
   2.729+
   2.730+The Mercurial mode user interface is based on that of VC mode, so if
   2.731+you're already familiar with VC, the same keybindings and functions
   2.732+will generally work.
   2.733+
   2.734+Below is a list of many common SCM tasks.  In the list, `G/L\'
   2.735+indicates whether a key binding is global (G) to a repository or
   2.736+local (L) to a file.  Many commands take a prefix argument.
   2.737+
   2.738+SCM Task                              G/L  Key Binding  Command Name
   2.739+--------                              ---  -----------  ------------
   2.740+Help overview (what you are reading)  G    C-c h h      hg-help-overview
   2.741+
   2.742+Tell Mercurial to manage a file       G    C-c h a      hg-add
   2.743+Commit changes to current file only   L    C-x v n      hg-commit-start
   2.744+Undo changes to file since commit     L    C-x v u      hg-revert-buffer
   2.745+
   2.746+Diff file vs last checkin             L    C-x v =      hg-diff
   2.747+
   2.748+View file change history              L    C-x v l      hg-log
   2.749+View annotated file                   L    C-x v a      hg-annotate
   2.750+
   2.751+Diff repo vs last checkin             G    C-c h =      hg-diff-repo
   2.752+View status of files in repo          G    C-c h s      hg-status
   2.753+Commit all changes                    G    C-c h c      hg-commit-start
   2.754+
   2.755+Undo all changes since last commit    G    C-c h U      hg-revert
   2.756+View repo change history              G    C-c h l      hg-log-repo
   2.757+
   2.758+See changes that can be pulled        G    C-c h ,      hg-incoming
   2.759+Pull changes                          G    C-c h <      hg-pull
   2.760+Update working directory after pull   G    C-c h u      hg-update
   2.761+See changes that can be pushed        G    C-c h .      hg-outgoing
   2.762+Push changes                          G    C-c h >      hg-push"
   2.763+  (unless vc-make-backup-files
   2.764+    (set (make-local-variable 'backup-inhibited) t))
   2.765+  (run-hooks 'hg-mode-hook))
   2.766+
   2.767+(defun hg-find-file-hook ()
   2.768+  (ignore-errors
   2.769+    (when (hg-mode-line)
   2.770+      (hg-mode))))
   2.771+
   2.772+(add-hook 'find-file-hooks 'hg-find-file-hook)
   2.773+
   2.774+(defun hg-after-save-hook ()
   2.775+  (ignore-errors
   2.776+    (let ((old-status hg-status))
   2.777+      (hg-mode-line)
   2.778+      (if (and (not old-status) hg-status)
   2.779+	  (hg-mode)))))
   2.780+
   2.781+(add-hook 'after-save-hook 'hg-after-save-hook)
   2.782+
   2.783+
   2.784+;;; User interface functions.
   2.785+
   2.786+(defun hg-help-overview ()
   2.787+  "This is an overview of the Mercurial SCM mode for Emacs.
   2.788+
   2.789+You can find the source code, license (GPLv2+), and credits for this
   2.790+code by typing `M-x find-library mercurial RET'."
   2.791+  (interactive)
   2.792+  (hg-view-output ("Mercurial Help Overview")
   2.793+    (insert (documentation 'hg-help-overview))
   2.794+    (let ((pos (point)))
   2.795+      (insert (documentation 'hg-mode))
   2.796+      (goto-char pos)
   2.797+      (end-of-line 1)
   2.798+      (delete-region pos (point)))
   2.799+    (let ((hg-root-dir (hg-root)))
   2.800+      (if (not hg-root-dir)
   2.801+	  (error "error: %s: directory is not part of a Mercurial repository."
   2.802+		 default-directory)
   2.803+	(cd hg-root-dir)))))
   2.804+
   2.805+(defun hg-fix-paths ()
   2.806+  "Fix paths reported by some Mercurial commands."
   2.807+  (save-excursion
   2.808+    (goto-char (point-min))
   2.809+    (while (re-search-forward " \\.\\.." nil t)
   2.810+      (replace-match " " nil nil))))
   2.811+
   2.812+(defun hg-add (path)
   2.813+  "Add PATH to the Mercurial repository on the next commit.
   2.814+With a prefix argument, prompt for the path to add."
   2.815+  (interactive (list (hg-read-file-name " to add")))
   2.816+  (let ((buf (current-buffer))
   2.817+	(update (equal buffer-file-name path)))
   2.818+    (hg-view-output (hg-output-buffer-name)
   2.819+      (apply 'call-process (hg-binary) nil t nil (list "add" path))
   2.820+      (hg-fix-paths)
   2.821+      (goto-char (point-min))
   2.822+      (cd (hg-root path)))
   2.823+    (when update
   2.824+      (unless vc-make-backup-files
   2.825+	(set (make-local-variable 'backup-inhibited) t))
   2.826+      (with-current-buffer buf
   2.827+	(hg-mode-line)))))
   2.828+
   2.829+(defun hg-addremove ()
   2.830+  (interactive)
   2.831+  (error "not implemented"))
   2.832+
   2.833+(defun hg-annotate ()
   2.834+  (interactive)
   2.835+  (error "not implemented"))
   2.836+
   2.837+(defun hg-commit-toggle-file (pos)
   2.838+  "Toggle whether or not the file at POS will be committed."
   2.839+  (interactive "d")
   2.840+  (save-excursion
   2.841+    (goto-char pos)
   2.842+    (let (face
   2.843+	  (inhibit-read-only t)
   2.844+	  bol)
   2.845+      (beginning-of-line)
   2.846+      (setq bol (+ (point) 4))
   2.847+      (setq face (get-text-property bol 'face))
   2.848+      (end-of-line)
   2.849+      (if (eq face 'bold)
   2.850+	  (progn
   2.851+	    (remove-text-properties bol (point) '(face nil))
   2.852+	    (message "%s will not be committed"
   2.853+		     (buffer-substring bol (point))))
   2.854+	(add-text-properties bol (point) '(face bold))
   2.855+	(message "%s will be committed"
   2.856+		 (buffer-substring bol (point)))))))
   2.857+
   2.858+(defun hg-commit-mouse-clicked (event)
   2.859+  "Toggle whether or not the file at POS will be committed."
   2.860+  (interactive "@e")
   2.861+  (hg-commit-toggle-file (hg-event-point event)))
   2.862+
   2.863+(defun hg-commit-kill ()
   2.864+  "Kill the commit currently being prepared."
   2.865+  (interactive)
   2.866+  (when (or (not (buffer-modified-p)) (y-or-n-p "Really kill this commit? "))
   2.867+    (let ((buf hg-prev-buffer))
   2.868+      (kill-buffer nil)
   2.869+      (switch-to-buffer buf))))
   2.870+
   2.871+(defun hg-commit-finish ()
   2.872+  "Finish preparing a commit, and perform the actual commit.
   2.873+The hook hg-pre-commit-hook is run before anything else is done.  If
   2.874+the commit message is empty and hg-commit-allow-empty-message is nil,
   2.875+an error is raised.  If the list of files to commit is empty and
   2.876+hg-commit-allow-empty-file-list is nil, an error is raised."
   2.877+  (interactive)
   2.878+  (let ((root hg-root))
   2.879+    (save-excursion
   2.880+      (run-hooks 'hg-pre-commit-hook)
   2.881+      (goto-char (point-min))
   2.882+      (search-forward hg-commit-message-start)
   2.883+      (let (message files)
   2.884+	(let ((start (point)))
   2.885+	  (goto-char (point-max))
   2.886+	  (search-backward hg-commit-message-end)
   2.887+	  (setq message (hg-strip (buffer-substring start (point)))))
   2.888+	(when (and (= (length message) 0)
   2.889+		   (not hg-commit-allow-empty-message))
   2.890+	  (error "Cannot proceed - commit message is empty"))
   2.891+	(forward-line 1)
   2.892+	(beginning-of-line)
   2.893+	(while (< (point) (point-max))
   2.894+	  (let ((pos (+ (point) 4)))
   2.895+	    (end-of-line)
   2.896+	    (when (eq (get-text-property pos 'face) 'bold)
   2.897+	      (end-of-line)
   2.898+	      (setq files (cons (buffer-substring pos (point)) files))))
   2.899+	  (forward-line 1))
   2.900+	(when (and (= (length files) 0)
   2.901+		   (not hg-commit-allow-empty-file-list))
   2.902+	  (error "Cannot proceed - no files to commit"))
   2.903+	(setq message (concat message "\n"))
   2.904+	(apply 'hg-run0 "--cwd" hg-root "commit" "-m" message files))
   2.905+      (let ((buf hg-prev-buffer))
   2.906+	(kill-buffer nil)
   2.907+	(switch-to-buffer buf))
   2.908+      (hg-update-mode-lines root))))
   2.909+
   2.910+(defun hg-commit-mode ()
   2.911+  "Mode for describing a commit of changes to a Mercurial repository.
   2.912+This involves two actions: describing the changes with a commit
   2.913+message, and choosing the files to commit.
   2.914+
   2.915+To describe the commit, simply type some text in the designated area.
   2.916+
   2.917+By default, all modified, added and removed files are selected for
   2.918+committing.  Files that will be committed are displayed in bold face\;
   2.919+those that will not are displayed in normal face.
   2.920+
   2.921+To toggle whether a file will be committed, move the cursor over a
   2.922+particular file and hit space or return.  Alternatively, middle click
   2.923+on the file.
   2.924+
   2.925+Key bindings
   2.926+------------
   2.927+\\[hg-commit-finish]		proceed with commit
   2.928+\\[hg-commit-kill]		kill commit
   2.929+
   2.930+\\[hg-diff-repo]		view diff of pending changes"
   2.931+  (interactive)
   2.932+  (use-local-map hg-commit-mode-map)
   2.933+  (set-syntax-table text-mode-syntax-table)
   2.934+  (setq local-abbrev-table text-mode-abbrev-table
   2.935+	major-mode 'hg-commit-mode
   2.936+	mode-name "Hg-Commit")
   2.937+  (set-buffer-modified-p nil)
   2.938+  (setq buffer-undo-list nil)
   2.939+  (run-hooks 'text-mode-hook 'hg-commit-mode-hook))
   2.940+
   2.941+(defun hg-commit-start ()
   2.942+  "Prepare a commit of changes to the repository containing the current file."
   2.943+  (interactive)
   2.944+  (while hg-prev-buffer
   2.945+    (set-buffer hg-prev-buffer))
   2.946+  (let ((root (hg-root))
   2.947+	(prev-buffer (current-buffer))
   2.948+	modified-files)
   2.949+    (unless root
   2.950+      (error "Cannot commit outside a repository!"))
   2.951+    (hg-sync-buffers root)
   2.952+    (setq modified-files (hg-chomp (hg-run0 "--cwd" root "status" "-arm")))
   2.953+    (when (and (= (length modified-files) 0)
   2.954+	       (not hg-commit-allow-empty-file-list))
   2.955+      (error "No pending changes to commit"))
   2.956+    (let* ((buf-name (format "*Mercurial: Commit %s*" root)))
   2.957+      (pop-to-buffer (get-buffer-create buf-name))
   2.958+      (when (= (point-min) (point-max))
   2.959+	(set (make-local-variable 'hg-root) root)
   2.960+	(setq hg-prev-buffer prev-buffer)
   2.961+	(insert "\n")
   2.962+	(let ((bol (point)))
   2.963+	  (insert hg-commit-message-end)
   2.964+	  (add-text-properties bol (point) '(face bold-italic)))
   2.965+	(let ((file-area (point)))
   2.966+	  (insert modified-files)
   2.967+	  (goto-char file-area)
   2.968+	  (while (< (point) (point-max))
   2.969+	    (let ((bol (point)))
   2.970+	      (forward-char 1)
   2.971+	      (insert "  ")
   2.972+	      (end-of-line)
   2.973+	      (add-text-properties (+ bol 4) (point)
   2.974+				   '(face bold mouse-face highlight)))
   2.975+	    (forward-line 1))
   2.976+	  (goto-char file-area)
   2.977+	  (add-text-properties (point) (point-max)
   2.978+			       `(keymap ,hg-commit-mode-file-map))
   2.979+	  (goto-char (point-min))
   2.980+	  (insert hg-commit-message-start)
   2.981+	  (add-text-properties (point-min) (point) '(face bold-italic))
   2.982+	  (insert "\n\n")
   2.983+	  (forward-line -1)
   2.984+	  (save-excursion
   2.985+	    (goto-char (point-max))
   2.986+	    (search-backward hg-commit-message-end)
   2.987+	    (add-text-properties (match-beginning 0) (point-max)
   2.988+				 '(read-only t))
   2.989+	    (goto-char (point-min))
   2.990+	    (search-forward hg-commit-message-start)
   2.991+	    (add-text-properties (match-beginning 0) (match-end 0)
   2.992+				 '(read-only t)))
   2.993+	  (hg-commit-mode)
   2.994+          (cd root))))))
   2.995+
   2.996+(defun hg-diff (path &optional rev1 rev2)
   2.997+  "Show the differences between REV1 and REV2 of PATH.
   2.998+When called interactively, the default behaviour is to treat REV1 as
   2.999+the \"parent\" revision, REV2 as the current edited version of the file, and
  2.1000+PATH as the file edited in the current buffer.
  2.1001+With a prefix argument, prompt for all of these."
  2.1002+  (interactive (list (hg-read-file-name " to diff")
  2.1003+                     (let ((rev1 (hg-read-rev " to start with" 'parent)))
  2.1004+		       (and (not (eq rev1 'parent)) rev1))
  2.1005+		     (let ((rev2 (hg-read-rev " to end with" 'working-dir)))
  2.1006+		       (and (not (eq rev2 'working-dir)) rev2))))
  2.1007+  (hg-sync-buffers path)
  2.1008+  (let ((a-path (hg-abbrev-file-name path))
  2.1009+        ;; none revision is specified explicitly
  2.1010+        (none (and (not rev1) (not rev2)))
  2.1011+        ;; only one revision is specified explicitly
  2.1012+        (one (or (and (or (equal rev1 rev2) (not rev2)) rev1)
  2.1013+                 (and (not rev1) rev2)))
  2.1014+	diff)
  2.1015+    (hg-view-output ((cond
  2.1016+		      (none
  2.1017+		       (format "Mercurial: Diff against parent of %s" a-path))
  2.1018+		      (one
  2.1019+		       (format "Mercurial: Diff of rev %s of %s" one a-path))
  2.1020+		      (t
  2.1021+		       (format "Mercurial: Diff from rev %s to %s of %s"
  2.1022+			       rev1 rev2 a-path))))
  2.1023+      (cond
  2.1024+       (none
  2.1025+        (call-process (hg-binary) nil t nil "diff" path))
  2.1026+       (one
  2.1027+        (call-process (hg-binary) nil t nil "diff" "-r" one path))
  2.1028+       (t
  2.1029+        (call-process (hg-binary) nil t nil "diff" "-r" rev1 "-r" rev2 path)))
  2.1030+      (diff-mode)
  2.1031+      (setq diff (not (= (point-min) (point-max))))
  2.1032+      (font-lock-fontify-buffer)
  2.1033+      (cd (hg-root path)))
  2.1034+    diff))
  2.1035+
  2.1036+(defun hg-diff-repo (path &optional rev1 rev2)
  2.1037+  "Show the differences between REV1 and REV2 of repository containing PATH.
  2.1038+When called interactively, the default behaviour is to treat REV1 as
  2.1039+the \"parent\" revision, REV2 as the current edited version of the file, and
  2.1040+PATH as the `hg-root' of the current buffer.
  2.1041+With a prefix argument, prompt for all of these."
  2.1042+  (interactive (list (hg-read-file-name " to diff")
  2.1043+                     (let ((rev1 (hg-read-rev " to start with" 'parent)))
  2.1044+		       (and (not (eq rev1 'parent)) rev1))
  2.1045+		     (let ((rev2 (hg-read-rev " to end with" 'working-dir)))
  2.1046+		       (and (not (eq rev2 'working-dir)) rev2))))
  2.1047+  (hg-diff (hg-root path) rev1 rev2))
  2.1048+
  2.1049+(defun hg-forget (path)
  2.1050+  "Lose track of PATH, which has been added, but not yet committed.
  2.1051+This will prevent the file from being incorporated into the Mercurial
  2.1052+repository on the next commit.
  2.1053+With a prefix argument, prompt for the path to forget."
  2.1054+  (interactive (list (hg-read-file-name " to forget")))
  2.1055+  (let ((buf (current-buffer))
  2.1056+	(update (equal buffer-file-name path)))
  2.1057+    (hg-view-output (hg-output-buffer-name)
  2.1058+      (apply 'call-process (hg-binary) nil t nil (list "forget" path))
  2.1059+      ;; "hg forget" shows pathes relative NOT TO ROOT BUT TO REPOSITORY
  2.1060+      (hg-fix-paths)
  2.1061+      (goto-char (point-min))
  2.1062+      (cd (hg-root path)))
  2.1063+    (when update
  2.1064+      (with-current-buffer buf
  2.1065+        (when (local-variable-p 'backup-inhibited)
  2.1066+          (kill-local-variable 'backup-inhibited))
  2.1067+	(hg-mode-line)))))
  2.1068+
  2.1069+(defun hg-incoming (&optional repo)
  2.1070+  "Display changesets present in REPO that are not present locally."
  2.1071+  (interactive (list (hg-read-repo-name " where changes would come from")))
  2.1072+  (hg-view-output ((format "Mercurial: Incoming from %s to %s"
  2.1073+			   (hg-abbrev-file-name (hg-root))
  2.1074+			   (hg-abbrev-file-name
  2.1075+			    (or repo hg-incoming-repository))))
  2.1076+    (call-process (hg-binary) nil t nil "incoming"
  2.1077+		  (or repo hg-incoming-repository))
  2.1078+    (hg-log-mode)
  2.1079+    (cd (hg-root))))
  2.1080+
  2.1081+(defun hg-init ()
  2.1082+  (interactive)
  2.1083+  (error "not implemented"))
  2.1084+
  2.1085+(defun hg-log-mode ()
  2.1086+  "Mode for viewing a Mercurial change log."
  2.1087+  (goto-char (point-min))
  2.1088+  (when (looking-at "^searching for changes.*$")
  2.1089+    (delete-region (match-beginning 0) (match-end 0)))
  2.1090+  (run-hooks 'hg-log-mode-hook))
  2.1091+
  2.1092+(defun hg-log (path &optional rev1 rev2 log-limit)
  2.1093+  "Display the revision history of PATH.
  2.1094+History is displayed between REV1 and REV2.
  2.1095+Number of displayed changesets is limited to LOG-LIMIT.
  2.1096+REV1 defaults to the tip, while REV2 defaults to 0.
  2.1097+LOG-LIMIT defaults to `hg-log-limit'.
  2.1098+With a prefix argument, prompt for each parameter."
  2.1099+  (interactive (list (hg-read-file-name " to log")
  2.1100+                     (hg-read-rev " to start with"
  2.1101+                                  "tip")
  2.1102+                     (hg-read-rev " to end with"
  2.1103+				  "0")
  2.1104+                     (hg-read-number "Output limited to: "
  2.1105+                                     hg-log-limit)))
  2.1106+  (let ((a-path (hg-abbrev-file-name path))
  2.1107+        (r1 (or rev1 "tip"))
  2.1108+        (r2 (or rev2 "0"))
  2.1109+        (limit (format "%d" (or log-limit hg-log-limit))))
  2.1110+    (hg-view-output ((if (equal r1 r2)
  2.1111+                         (format "Mercurial: Log of rev %s of %s" rev1 a-path)
  2.1112+                       (format
  2.1113+                        "Mercurial: at most %s log(s) from rev %s to %s of %s"
  2.1114+                        limit r1 r2 a-path)))
  2.1115+      (eval (list* 'call-process (hg-binary) nil t nil
  2.1116+                   "log"
  2.1117+                   "-r" (format "%s:%s" r1 r2)
  2.1118+                   "-l" limit
  2.1119+                   (if (> (length path) (length (hg-root path)))
  2.1120+                       (cons path nil)
  2.1121+                     nil)))
  2.1122+      (hg-log-mode)
  2.1123+      (cd (hg-root path)))))
  2.1124+
  2.1125+(defun hg-log-repo (path &optional rev1 rev2 log-limit)
  2.1126+  "Display the revision history of the repository containing PATH.
  2.1127+History is displayed between REV1 and REV2.
  2.1128+Number of displayed changesets is limited to LOG-LIMIT,
  2.1129+REV1 defaults to the tip, while REV2 defaults to 0.
  2.1130+LOG-LIMIT defaults to `hg-log-limit'.
  2.1131+With a prefix argument, prompt for each parameter."
  2.1132+  (interactive (list (hg-read-file-name " to log")
  2.1133+                     (hg-read-rev " to start with"
  2.1134+                                  "tip")
  2.1135+                     (hg-read-rev " to end with"
  2.1136+				  "0")
  2.1137+                     (hg-read-number "Output limited to: "
  2.1138+                                     hg-log-limit)))
  2.1139+  (hg-log (hg-root path) rev1 rev2 log-limit))
  2.1140+
  2.1141+(defun hg-outgoing (&optional repo)
  2.1142+  "Display changesets present locally that are not present in REPO."
  2.1143+  (interactive (list (hg-read-repo-name " where changes would go to" nil
  2.1144+					hg-outgoing-repository)))
  2.1145+  (hg-view-output ((format "Mercurial: Outgoing from %s to %s"
  2.1146+			   (hg-abbrev-file-name (hg-root))
  2.1147+			   (hg-abbrev-file-name
  2.1148+			    (or repo hg-outgoing-repository))))
  2.1149+    (call-process (hg-binary) nil t nil "outgoing"
  2.1150+		  (or repo hg-outgoing-repository))
  2.1151+    (hg-log-mode)
  2.1152+    (cd (hg-root))))
  2.1153+
  2.1154+(defun hg-pull (&optional repo)
  2.1155+  "Pull changes from repository REPO.
  2.1156+This does not update the working directory."
  2.1157+  (interactive (list (hg-read-repo-name " to pull from")))
  2.1158+  (hg-view-output ((format "Mercurial: Pull to %s from %s"
  2.1159+			   (hg-abbrev-file-name (hg-root))
  2.1160+			   (hg-abbrev-file-name
  2.1161+			    (or repo hg-incoming-repository))))
  2.1162+    (call-process (hg-binary) nil t nil "pull"
  2.1163+		  (or repo hg-incoming-repository))
  2.1164+    (cd (hg-root))))
  2.1165+
  2.1166+(defun hg-push (&optional repo)
  2.1167+  "Push changes to repository REPO."
  2.1168+  (interactive (list (hg-read-repo-name " to push to")))
  2.1169+  (hg-view-output ((format "Mercurial: Push from %s to %s"
  2.1170+			   (hg-abbrev-file-name (hg-root))
  2.1171+			   (hg-abbrev-file-name
  2.1172+			    (or repo hg-outgoing-repository))))
  2.1173+    (call-process (hg-binary) nil t nil "push"
  2.1174+		  (or repo hg-outgoing-repository))
  2.1175+    (cd (hg-root))))
  2.1176+
  2.1177+(defun hg-revert-buffer-internal ()
  2.1178+  (let ((ctx (hg-buffer-context)))
  2.1179+    (message "Reverting %s..." buffer-file-name)
  2.1180+    (hg-run0 "revert" buffer-file-name)
  2.1181+    (revert-buffer t t t)
  2.1182+    (hg-restore-context ctx)
  2.1183+    (hg-mode-line)
  2.1184+    (message "Reverting %s...done" buffer-file-name)))
  2.1185+
  2.1186+(defun hg-revert-buffer ()
  2.1187+  "Revert current buffer's file back to the latest committed version.
  2.1188+If the file has not changed, nothing happens.  Otherwise, this
  2.1189+displays a diff and asks for confirmation before reverting."
  2.1190+  (interactive)
  2.1191+  (let ((vc-suppress-confirm nil)
  2.1192+	(obuf (current-buffer))
  2.1193+	diff)
  2.1194+    (vc-buffer-sync)
  2.1195+    (unwind-protect
  2.1196+	(setq diff (hg-diff buffer-file-name))
  2.1197+      (when diff
  2.1198+	(unless (yes-or-no-p "Discard changes? ")
  2.1199+	  (error "Revert cancelled")))
  2.1200+      (when diff
  2.1201+	(let ((buf (current-buffer)))
  2.1202+	  (delete-window (selected-window))
  2.1203+	  (kill-buffer buf))))
  2.1204+    (set-buffer obuf)
  2.1205+    (when diff
  2.1206+      (hg-revert-buffer-internal))))
  2.1207+
  2.1208+(defun hg-root (&optional path)
  2.1209+  "Return the root of the repository that contains the given path.
  2.1210+If the path is outside a repository, return nil.
  2.1211+When called interactively, the root is printed.  A prefix argument
  2.1212+prompts for a path to check."
  2.1213+  (interactive (list (hg-read-file-name)))
  2.1214+  (if (or path (not hg-root))
  2.1215+      (let ((root (do ((prev nil dir)
  2.1216+		       (dir (file-name-directory
  2.1217+                             (or
  2.1218+                              path
  2.1219+                              buffer-file-name
  2.1220+                              (expand-file-name default-directory)))
  2.1221+			    (file-name-directory (directory-file-name dir))))
  2.1222+		      ((equal prev dir))
  2.1223+		    (when (file-directory-p (concat dir ".hg"))
  2.1224+		      (return dir)))))
  2.1225+	(when (interactive-p)
  2.1226+	  (if root
  2.1227+	      (message "The root of this repository is `%s'." root)
  2.1228+	    (message "The path `%s' is not in a Mercurial repository."
  2.1229+		     (hg-abbrev-file-name path))))
  2.1230+	root)
  2.1231+    hg-root))
  2.1232+
  2.1233+(defun hg-cwd (&optional path)
  2.1234+  "Return the current directory of PATH within the repository."
  2.1235+  (do ((stack nil (cons (file-name-nondirectory
  2.1236+			 (directory-file-name dir))
  2.1237+			stack))
  2.1238+       (prev nil dir)
  2.1239+       (dir (file-name-directory (or path buffer-file-name
  2.1240+				     (expand-file-name default-directory)))
  2.1241+	    (file-name-directory (directory-file-name dir))))
  2.1242+      ((equal prev dir))
  2.1243+    (when (file-directory-p (concat dir ".hg"))
  2.1244+      (let ((cwd (mapconcat 'identity stack "/")))
  2.1245+	(unless (equal cwd "")
  2.1246+	  (return (file-name-as-directory cwd)))))))
  2.1247+
  2.1248+(defun hg-status (path)
  2.1249+  "Print revision control status of a file or directory.
  2.1250+With prefix argument, prompt for the path to give status for.
  2.1251+Names are displayed relative to the repository root."
  2.1252+  (interactive (list (hg-read-file-name " for status" (hg-root))))
  2.1253+  (let ((root (hg-root)))
  2.1254+    (hg-view-output ((format "Mercurial: Status of %s in %s"
  2.1255+			     (let ((name (substring (expand-file-name path)
  2.1256+						    (length root))))
  2.1257+			       (if (> (length name) 0)
  2.1258+				   name
  2.1259+				 "*"))
  2.1260+			     (hg-abbrev-file-name root)))
  2.1261+      (apply 'call-process (hg-binary) nil t nil
  2.1262+	     (list "--cwd" root "status" path))
  2.1263+      (cd (hg-root path)))))
  2.1264+
  2.1265+(defun hg-undo ()
  2.1266+  (interactive)
  2.1267+  (error "not implemented"))
  2.1268+
  2.1269+(defun hg-update ()
  2.1270+  (interactive)
  2.1271+  (error "not implemented"))
  2.1272+
  2.1273+(defun hg-version-other-window (rev)
  2.1274+  "Visit version REV of the current file in another window.
  2.1275+If the current file is named `F', the version is named `F.~REV~'.
  2.1276+If `F.~REV~' already exists, use it instead of checking it out again."
  2.1277+  (interactive "sVersion to visit (default is workfile version): ")
  2.1278+  (let* ((file buffer-file-name)
  2.1279+       	 (version (if (string-equal rev "")
  2.1280+		       "tip"
  2.1281+		        rev))
  2.1282+ 	 (automatic-backup (vc-version-backup-file-name file version))
  2.1283+          (manual-backup (vc-version-backup-file-name file version 'manual)))
  2.1284+     (unless (file-exists-p manual-backup)
  2.1285+       (if (file-exists-p automatic-backup)
  2.1286+           (rename-file automatic-backup manual-backup nil)
  2.1287+         (hg-run0 "-q" "cat" "-r" version "-o" manual-backup file)))
  2.1288+     (find-file-other-window manual-backup)))
  2.1289+
  2.1290+
  2.1291+(provide 'mercurial)
  2.1292+
  2.1293+
  2.1294+;;; Local Variables:
  2.1295+;;; prompt-to-byte-compile: nil
  2.1296+;;; end:
     3.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2+++ b/.emacs.d/lib/mq.el	Sat Jun 15 19:57:38 2024 -0400
     3.3@@ -0,0 +1,417 @@
     3.4+;;; mq.el --- Emacs support for Mercurial Queues
     3.5+
     3.6+;; Copyright (C) 2006 Bryan O'Sullivan
     3.7+
     3.8+;; Author: Bryan O'Sullivan <bos@serpentine.com>
     3.9+
    3.10+;; mq.el is free software; you can redistribute it and/or modify it
    3.11+;; under the terms of the GNU General Public License version 2 or any
    3.12+;; later version.
    3.13+
    3.14+;; mq.el is distributed in the hope that it will be useful, but
    3.15+;; WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    3.17+;; General Public License for more details.
    3.18+
    3.19+;; You should have received a copy of the GNU General Public License
    3.20+;; along with mq.el, GNU Emacs, or XEmacs; see the file COPYING (`C-h
    3.21+;; C-l').  If not, see <http://www.gnu.org/licenses/>.
    3.22+
    3.23+(eval-when-compile (require 'cl))
    3.24+(require 'mercurial)
    3.25+
    3.26+
    3.27+(defcustom mq-mode-hook nil
    3.28+  "Hook run when a buffer enters mq-mode."
    3.29+  :type 'sexp
    3.30+  :group 'mercurial)
    3.31+
    3.32+(defcustom mq-global-prefix "\C-cq"
    3.33+  "The global prefix for Mercurial Queues keymap bindings."
    3.34+  :type 'sexp
    3.35+  :group 'mercurial)
    3.36+
    3.37+(defcustom mq-edit-mode-hook nil
    3.38+  "Hook run after a buffer is populated to edit a patch description."
    3.39+  :type 'sexp
    3.40+  :group 'mercurial)
    3.41+
    3.42+(defcustom mq-edit-finish-hook nil
    3.43+  "Hook run before a patch description is finished up with."
    3.44+  :type 'sexp
    3.45+  :group 'mercurial)
    3.46+
    3.47+(defcustom mq-signoff-address nil
    3.48+  "Address with which to sign off on a patch."
    3.49+  :type 'string
    3.50+  :group 'mercurial)
    3.51+
    3.52+
    3.53+;;; Internal variables.
    3.54+
    3.55+(defvar mq-mode nil
    3.56+  "Is this file managed by MQ?")
    3.57+(make-variable-buffer-local 'mq-mode)
    3.58+(put 'mq-mode 'permanent-local t)
    3.59+
    3.60+(defvar mq-patch-history nil)
    3.61+
    3.62+(defvar mq-top-patch '(nil))
    3.63+
    3.64+(defvar mq-prev-buffer nil)
    3.65+(make-variable-buffer-local 'mq-prev-buffer)
    3.66+(put 'mq-prev-buffer 'permanent-local t)
    3.67+
    3.68+(defvar mq-top nil)
    3.69+(make-variable-buffer-local 'mq-top)
    3.70+(put 'mq-top 'permanent-local t)
    3.71+
    3.72+;;; Global keymap.
    3.73+
    3.74+(defvar mq-global-map
    3.75+  (let ((map (make-sparse-keymap)))
    3.76+    (define-key map "." 'mq-push)
    3.77+    (define-key map ">" 'mq-push-all)
    3.78+    (define-key map "," 'mq-pop)
    3.79+    (define-key map "<" 'mq-pop-all)
    3.80+    (define-key map "=" 'mq-diff)
    3.81+    (define-key map "r" 'mq-refresh)
    3.82+    (define-key map "e" 'mq-refresh-edit)
    3.83+    (define-key map "i" 'mq-new)
    3.84+    (define-key map "n" 'mq-next)
    3.85+    (define-key map "o" 'mq-signoff)
    3.86+    (define-key map "p" 'mq-previous)
    3.87+    (define-key map "s" 'mq-edit-series)
    3.88+    (define-key map "t" 'mq-top)
    3.89+    map))
    3.90+
    3.91+(global-set-key mq-global-prefix mq-global-map)
    3.92+
    3.93+(add-minor-mode 'mq-mode 'mq-mode)
    3.94+
    3.95+
    3.96+;;; Refresh edit mode keymap.
    3.97+
    3.98+(defvar mq-edit-mode-map
    3.99+  (let ((map (make-sparse-keymap)))
   3.100+    (define-key map "\C-c\C-c" 'mq-edit-finish)
   3.101+    (define-key map "\C-c\C-k" 'mq-edit-kill)
   3.102+    (define-key map "\C-c\C-s" 'mq-signoff)
   3.103+    map))
   3.104+
   3.105+
   3.106+;;; Helper functions.
   3.107+
   3.108+(defun mq-read-patch-name (&optional source prompt force)
   3.109+  "Read a patch name to use with a command.
   3.110+May return nil, meaning \"use the default\"."
   3.111+  (let ((patches (split-string
   3.112+		  (hg-chomp (hg-run0 (or source "qseries"))) "\n")))
   3.113+    (when force
   3.114+      (completing-read (format "Patch%s: " (or prompt ""))
   3.115+		       (mapcar (lambda (x) (cons x x)) patches)
   3.116+		       nil
   3.117+		       nil
   3.118+		       nil
   3.119+		       'mq-patch-history))))
   3.120+
   3.121+(defun mq-refresh-buffers (root)
   3.122+  (save-excursion
   3.123+    (dolist (buf (hg-buffers-visiting-repo root))
   3.124+      (when (not (verify-visited-file-modtime buf))
   3.125+	(set-buffer buf)
   3.126+	(let ((ctx (hg-buffer-context)))
   3.127+	  (message "Refreshing %s..." (buffer-name))
   3.128+	  (revert-buffer t t t)
   3.129+	  (hg-restore-context ctx)
   3.130+	  (message "Refreshing %s...done" (buffer-name))))))
   3.131+  (hg-update-mode-lines root)
   3.132+  (mq-update-mode-lines root))
   3.133+
   3.134+(defun mq-last-line ()
   3.135+  (goto-char (point-max))
   3.136+  (beginning-of-line)
   3.137+  (when (looking-at "^$")
   3.138+    (forward-line -1))
   3.139+  (let ((bol (point)))
   3.140+    (end-of-line)
   3.141+    (let ((line (buffer-substring bol (point))))
   3.142+      (when (> (length line) 0)
   3.143+	line))))
   3.144+
   3.145+(defun mq-push (&optional patch)
   3.146+  "Push patches until PATCH is reached.
   3.147+If PATCH is nil, push at most one patch."
   3.148+  (interactive (list (mq-read-patch-name "qunapplied" " to push"
   3.149+					 current-prefix-arg)))
   3.150+  (let ((root (hg-root))
   3.151+	(prev-buf (current-buffer))
   3.152+	last-line ok)
   3.153+    (unless root
   3.154+      (error "Cannot push outside a repository!"))
   3.155+    (hg-sync-buffers root)
   3.156+    (let ((buf-name (format "MQ: Push %s" (or patch "next patch"))))
   3.157+      (kill-buffer (get-buffer-create buf-name))
   3.158+      (split-window-vertically)
   3.159+      (other-window 1)
   3.160+      (switch-to-buffer (get-buffer-create buf-name))
   3.161+      (cd root)
   3.162+      (message "Pushing...")
   3.163+      (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpush"
   3.164+			   (if patch (list patch))))
   3.165+	    last-line (mq-last-line))
   3.166+      (let ((lines (count-lines (point-min) (point-max))))
   3.167+	(if (or (<= lines 1)
   3.168+		(and (equal lines 2) (string-match "Now at:" last-line)))
   3.169+	    (progn
   3.170+	      (kill-buffer (current-buffer))
   3.171+	      (delete-window))
   3.172+	  (hg-view-mode prev-buf))))
   3.173+    (mq-refresh-buffers root)
   3.174+    (sit-for 0)
   3.175+    (when last-line
   3.176+      (if ok
   3.177+	  (message "Pushing... %s" last-line)
   3.178+	(error "Pushing... %s" last-line)))))
   3.179+
   3.180+(defun mq-push-all ()
   3.181+  "Push patches until all are applied."
   3.182+  (interactive)
   3.183+  (mq-push "-a"))
   3.184+
   3.185+(defun mq-pop (&optional patch)
   3.186+  "Pop patches until PATCH is reached.
   3.187+If PATCH is nil, pop at most one patch."
   3.188+  (interactive (list (mq-read-patch-name "qapplied" " to pop to"
   3.189+					 current-prefix-arg)))
   3.190+  (let ((root (hg-root))
   3.191+	last-line ok)
   3.192+    (unless root
   3.193+      (error "Cannot pop outside a repository!"))
   3.194+    (hg-sync-buffers root)
   3.195+    (set-buffer (generate-new-buffer "qpop"))
   3.196+    (cd root)
   3.197+    (message "Popping...")
   3.198+    (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpop"
   3.199+			 (if patch (list patch))))
   3.200+	  last-line (mq-last-line))
   3.201+    (kill-buffer (current-buffer))
   3.202+    (mq-refresh-buffers root)
   3.203+    (sit-for 0)
   3.204+    (when last-line
   3.205+      (if ok
   3.206+	  (message "Popping... %s" last-line)
   3.207+	(error "Popping... %s" last-line)))))
   3.208+
   3.209+(defun mq-pop-all ()
   3.210+  "Push patches until none are applied."
   3.211+  (interactive)
   3.212+  (mq-pop "-a"))
   3.213+
   3.214+(defun mq-refresh-internal (root &rest args)
   3.215+  (hg-sync-buffers root)
   3.216+  (let ((patch (mq-patch-info "qtop")))
   3.217+    (message "Refreshing %s..." patch)
   3.218+    (let ((ret (apply 'hg-run "qrefresh" args)))
   3.219+      (if (equal (car ret) 0)
   3.220+	  (message "Refreshing %s... done." patch)
   3.221+	(error "Refreshing %s... %s" patch (hg-chomp (cdr ret)))))))
   3.222+
   3.223+(defun mq-refresh (&optional git)
   3.224+  "Refresh the topmost applied patch.
   3.225+With a prefix argument, generate a git-compatible patch."
   3.226+  (interactive "P")
   3.227+  (let ((root (hg-root)))
   3.228+    (unless root
   3.229+      (error "Cannot refresh outside of a repository!"))
   3.230+    (apply 'mq-refresh-internal root (if git '("--git")))))
   3.231+
   3.232+(defun mq-patch-info (cmd &optional msg)
   3.233+  (let* ((ret (hg-run cmd))
   3.234+	 (info (hg-chomp (cdr ret))))
   3.235+    (if (equal (car ret) 0)
   3.236+	(if msg
   3.237+	    (message "%s patch: %s" msg info)
   3.238+	  info)
   3.239+      (error "%s" info))))
   3.240+
   3.241+(defun mq-top ()
   3.242+  "Print the name of the topmost applied patch."
   3.243+  (interactive)
   3.244+  (mq-patch-info "qtop" "Top"))
   3.245+
   3.246+(defun mq-next ()
   3.247+  "Print the name of the next patch to be pushed."
   3.248+  (interactive)
   3.249+  (mq-patch-info "qnext" "Next"))
   3.250+
   3.251+(defun mq-previous ()
   3.252+  "Print the name of the first patch below the topmost applied patch.
   3.253+This would become the active patch if popped to."
   3.254+  (interactive)
   3.255+  (mq-patch-info "qprev" "Previous"))
   3.256+
   3.257+(defun mq-edit-finish ()
   3.258+  "Finish editing the description of this patch, and refresh the patch."
   3.259+  (interactive)
   3.260+  (unless (equal (mq-patch-info "qtop") mq-top)
   3.261+    (error "Topmost patch has changed!"))
   3.262+  (hg-sync-buffers hg-root)
   3.263+  (run-hooks 'mq-edit-finish-hook)
   3.264+  (mq-refresh-internal hg-root "-m" (buffer-substring (point-min) (point-max)))
   3.265+  (let ((buf mq-prev-buffer))
   3.266+    (kill-buffer nil)
   3.267+    (switch-to-buffer buf)))
   3.268+
   3.269+(defun mq-edit-kill ()
   3.270+  "Kill the edit currently being prepared."
   3.271+  (interactive)
   3.272+  (when (or (not (buffer-modified-p)) (y-or-n-p "Really kill this edit? "))
   3.273+    (let ((buf mq-prev-buffer))
   3.274+      (kill-buffer nil)
   3.275+      (switch-to-buffer buf))))
   3.276+
   3.277+(defun mq-get-top (root)
   3.278+  (let ((entry (assoc root mq-top-patch)))
   3.279+    (if entry
   3.280+        (cdr entry))))
   3.281+
   3.282+(defun mq-set-top (root patch)
   3.283+  (let ((entry (assoc root mq-top-patch)))
   3.284+    (if entry
   3.285+        (if patch
   3.286+            (setcdr entry patch)
   3.287+          (setq mq-top-patch (delq entry mq-top-patch)))
   3.288+      (setq mq-top-patch (cons (cons root patch) mq-top-patch)))))
   3.289+
   3.290+(defun mq-update-mode-lines (root)
   3.291+  (let ((cwd default-directory))
   3.292+    (cd root)
   3.293+    (condition-case nil
   3.294+        (mq-set-top root (mq-patch-info "qtop"))
   3.295+      (error (mq-set-top root nil)))
   3.296+    (cd cwd))
   3.297+  (let ((patch (mq-get-top root)))
   3.298+    (save-excursion
   3.299+      (dolist (buf (hg-buffers-visiting-repo root))
   3.300+        (set-buffer buf)
   3.301+        (if mq-mode
   3.302+            (setq mq-mode (or (and patch (concat " MQ:" patch)) " MQ")))))))
   3.303+	
   3.304+(defun mq-mode (&optional arg)
   3.305+  "Minor mode for Mercurial repositories with an MQ patch queue"
   3.306+  (interactive "i")
   3.307+  (cond ((hg-root)
   3.308+         (setq mq-mode (if (null arg) (not mq-mode)
   3.309+                         arg))
   3.310+         (mq-update-mode-lines (hg-root))))
   3.311+  (run-hooks 'mq-mode-hook))
   3.312+
   3.313+(defun mq-edit-mode ()
   3.314+  "Mode for editing the description of a patch.
   3.315+
   3.316+Key bindings
   3.317+------------
   3.318+\\[mq-edit-finish]	use this description
   3.319+\\[mq-edit-kill]	abandon this description"
   3.320+  (interactive)
   3.321+  (use-local-map mq-edit-mode-map)
   3.322+  (set-syntax-table text-mode-syntax-table)
   3.323+  (setq local-abbrev-table text-mode-abbrev-table
   3.324+	major-mode 'mq-edit-mode
   3.325+	mode-name "MQ-Edit")
   3.326+  (set-buffer-modified-p nil)
   3.327+  (setq buffer-undo-list nil)
   3.328+  (run-hooks 'text-mode-hook 'mq-edit-mode-hook))
   3.329+
   3.330+(defun mq-refresh-edit ()
   3.331+  "Refresh the topmost applied patch, editing the patch description."
   3.332+  (interactive)
   3.333+  (while mq-prev-buffer
   3.334+    (set-buffer mq-prev-buffer))
   3.335+  (let ((root (hg-root))
   3.336+	(prev-buffer (current-buffer))
   3.337+	(patch (mq-patch-info "qtop")))
   3.338+    (hg-sync-buffers root)
   3.339+    (let ((buf-name (format "*MQ: Edit description of %s*" patch)))
   3.340+      (switch-to-buffer (get-buffer-create buf-name))
   3.341+      (when (= (point-min) (point-max))
   3.342+	(set (make-local-variable 'hg-root) root)
   3.343+	(set (make-local-variable 'mq-top) patch)
   3.344+	(setq mq-prev-buffer prev-buffer)
   3.345+	(insert (hg-run0 "qheader"))
   3.346+	(goto-char (point-min)))
   3.347+      (mq-edit-mode)
   3.348+      (cd root)))
   3.349+  (message "Type `C-c C-c' to finish editing and refresh the patch."))
   3.350+
   3.351+(defun mq-new (name)
   3.352+  "Create a new empty patch named NAME.
   3.353+The patch is applied on top of the current topmost patch.
   3.354+With a prefix argument, forcibly create the patch even if the working
   3.355+directory is modified."
   3.356+  (interactive (list (mq-read-patch-name "qseries" " to create" t)))
   3.357+  (message "Creating patch...")
   3.358+  (let ((ret (if current-prefix-arg
   3.359+		 (hg-run "qnew" "-f" name)
   3.360+	       (hg-run "qnew" name))))
   3.361+    (if (equal (car ret) 0)
   3.362+	(progn
   3.363+	  (hg-update-mode-lines (buffer-file-name))
   3.364+	  (message "Creating patch... done."))
   3.365+      (error "Creating patch... %s" (hg-chomp (cdr ret))))))
   3.366+
   3.367+(defun mq-edit-series ()
   3.368+  "Edit the MQ series file directly."
   3.369+  (interactive)
   3.370+  (let ((root (hg-root)))
   3.371+    (unless root
   3.372+      (error "Not in an MQ repository!"))
   3.373+    (find-file (concat root ".hg/patches/series"))))
   3.374+
   3.375+(defun mq-diff (&optional git)
   3.376+  "Display a diff of the topmost applied patch.
   3.377+With a prefix argument, display a git-compatible diff."
   3.378+  (interactive "P")
   3.379+  (hg-view-output ((format "MQ: Diff of %s" (mq-patch-info "qtop")))
   3.380+    (if git
   3.381+	(call-process (hg-binary) nil t nil "qdiff" "--git")
   3.382+    (call-process (hg-binary) nil t nil "qdiff"))
   3.383+    (diff-mode)
   3.384+    (font-lock-fontify-buffer)))
   3.385+
   3.386+(defun mq-signoff ()
   3.387+  "Sign off on the current patch, in the style used by the Linux kernel.
   3.388+If the variable mq-signoff-address is non-nil, it will be used, otherwise
   3.389+the value of the ui.username item from your hgrc will be used."
   3.390+  (interactive)
   3.391+  (let ((was-editing (eq major-mode 'mq-edit-mode))
   3.392+	signed)
   3.393+    (unless was-editing
   3.394+      (mq-refresh-edit))
   3.395+    (save-excursion
   3.396+      (let* ((user (or mq-signoff-address
   3.397+		       (hg-run0 "debugconfig" "ui.username")))
   3.398+	     (signoff (concat "Signed-off-by: " user)))
   3.399+	(if (search-forward signoff nil t)
   3.400+	    (message "You have already signed off on this patch.")
   3.401+	  (goto-char (point-max))
   3.402+	  (let ((case-fold-search t))
   3.403+	    (if (re-search-backward "^Signed-off-by: " nil t)
   3.404+		(forward-line 1)
   3.405+	      (insert "\n")))
   3.406+	  (insert signoff)
   3.407+	  (message "%s" signoff)
   3.408+	  (setq signed t))))
   3.409+    (unless was-editing
   3.410+      (if signed
   3.411+	  (mq-edit-finish)
   3.412+	(mq-edit-kill)))))
   3.413+
   3.414+
   3.415+(provide 'mq)
   3.416+
   3.417+
   3.418+;;; Local Variables:
   3.419+;;; prompt-to-byte-compile: nil
   3.420+;;; end: