diff options
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-mode.el')
-rw-r--r-- | configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-mode.el | 1384 |
1 files changed, 0 insertions, 1384 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-mode.el b/configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-mode.el deleted file mode 100644 index ab787f3cde4d..000000000000 --- a/configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-mode.el +++ /dev/null @@ -1,1384 +0,0 @@ -;;; magit-mode.el --- create and refresh Magit buffers -*- lexical-binding: t -*- - -;; Copyright (C) 2010-2018 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli <jonas@bernoul.li> -;; Maintainer: Jonas Bernoulli <jonas@bernoul.li> - -;; Magit is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see http://www.gnu.org/licenses. - -;;; Commentary: - -;; This library implements the abstract major-mode `magit-mode' from -;; which almost all other Magit major-modes derive. The code in here -;; is mostly concerned with creating and refreshing Magit buffers. - -;;; Code: - -(require 'cl-lib) -(require 'dash) - -(require 'magit-section) -(require 'magit-git) -(require 'magit-popup) - -;; For `magit-display-buffer-fullcolumn-most-v1' from `git-commit' -(defvar git-commit-mode) -;; For `magit-xref-insert-buttons' from `magit' -(defvar magit-diff-show-xref-buttons) -(defvar magit-revision-show-xref-buttons) -;; For `magit-refresh' and `magit-refresh-all' -(declare-function magit-auto-revert-buffers "magit-autorevert" ()) -;; For `magit-refresh-buffer' -(declare-function magit-process-unset-mode-line-error-status "magit-process" ()) -;; For `magit-mode-setup-internal' -(declare-function magit-status-goto-initial-section "magit-status" ()) - -(require 'format-spec) -(require 'help-mode) - -;;; Options - -(defcustom magit-mode-hook - '(magit-load-config-extensions - magit-xref-setup) - "Hook run when entering a mode derived from Magit mode." - :group 'magit-modes - :type 'hook - :options '(magit-load-config-extensions - magit-xref-setup - bug-reference-mode)) - -(defcustom magit-mode-setup-hook - '(magit-maybe-save-repository-buffers - magit-set-buffer-margin) - "Hook run by `magit-mode-setup'. - -This is run right after displaying the buffer and right before -generating or updating its content. `magit-mode-hook' and other, -more specific, `magit-mode-*-hook's on the other hand are run -right before displaying the buffer. Usually one of these hooks -should be used instead of this one." - :package-version '(magit . "2.3.0") - :group 'magit-modes - :type 'hook - :options '(magit-maybe-save-repository-buffers - magit-set-buffer-margin)) - -(defcustom magit-pre-refresh-hook '(magit-maybe-save-repository-buffers) - "Hook run before refreshing in `magit-refresh'. - -This hook, or `magit-post-refresh-hook', should be used -for functions that are not tied to a particular buffer. - -To run a function with a particular buffer current, use -`magit-refresh-buffer-hook' and use `derived-mode-p' -inside your function." - :package-version '(magit . "2.4.0") - :group 'magit-refresh - :type 'hook - :options '(magit-maybe-save-repository-buffers)) - -(defcustom magit-post-refresh-hook nil - "Hook run after refreshing in `magit-refresh'. - -This hook, or `magit-pre-refresh-hook', should be used -for functions that are not tied to a particular buffer. - -To run a function with a particular buffer current, use -`magit-refresh-buffer-hook' and use `derived-mode-p' -inside your function." - :package-version '(magit . "2.4.0") - :group 'magit-refresh - :type 'hook) - -(defcustom magit-display-buffer-function 'magit-display-buffer-traditional - "The function used display a Magit buffer. - -All Magit buffers (buffers whose major-modes derive from -`magit-mode') are displayed using `magit-display-buffer', -which in turn uses the function specified here." - :package-version '(magit . "2.3.0") - :group 'magit-buffers - :type '(radio (function-item magit-display-buffer-traditional) - (function-item magit-display-buffer-same-window-except-diff-v1) - (function-item magit-display-buffer-fullframe-status-v1) - (function-item magit-display-buffer-fullframe-status-topleft-v1) - (function-item magit-display-buffer-fullcolumn-most-v1) - (function-item display-buffer) - (function :tag "Function"))) - -(defcustom magit-pre-display-buffer-hook '(magit-save-window-configuration) - "Hook run by `magit-display-buffer' before displaying the buffer." - :package-version '(magit . "2.3.0") - :group 'magit-buffers - :type 'hook - :get 'magit-hook-custom-get - :options '(magit-save-window-configuration)) - -(defcustom magit-post-display-buffer-hook '(magit-maybe-set-dedicated) - "Hook run by `magit-display-buffer' after displaying the buffer." - :package-version '(magit . "2.3.0") - :group 'magit-buffers - :type 'hook - :get 'magit-hook-custom-get - :options '(magit-maybe-set-dedicated)) - -(defcustom magit-generate-buffer-name-function - 'magit-generate-buffer-name-default-function - "The function used to generate the name for a Magit buffer." - :package-version '(magit . "2.3.0") - :group 'magit-buffers - :type '(radio (function-item magit-generate-buffer-name-default-function) - (function :tag "Function"))) - -(defcustom magit-buffer-name-format "%x%M%v: %t%x" - "The format string used to name Magit buffers. - -The following %-sequences are supported: - -`%m' The name of the major-mode, but with the `-mode' suffix - removed. - -`%M' Like \"%m\" but abbreviate `magit-status-mode' as `magit'. - -`%v' The value the buffer is locked to, in parentheses, or an - empty string if the buffer is not locked to a value. - -`%V' Like \"%v\", but the string is prefixed with a space, unless - it is an empty string. - -`%t' The top-level directory of the working tree of the - repository, or if `magit-uniquify-buffer-names' is non-nil - an abbreviation of that. - -`%x' If `magit-uniquify-buffer-names' is nil \"*\", otherwise the - empty string. Due to limitations of the `uniquify' package, - buffer names must end with the path. - -`%T' Obsolete, use \"%t%x\" instead. Like \"%t\", but append an - asterisk if and only if `magit-uniquify-buffer-names' is nil. - -The value should always contain \"%m\" or \"%M\", \"%v\" or -\"%V\", and \"%t\" (or the obsolete \"%T\"). - -If `magit-uniquify-buffer-names' is non-nil, then the value must -end with \"%t\" or \"%t%x\" (or the obsolete \"%T\"). See issue -#2841. - -This is used by `magit-generate-buffer-name-default-function'. -If another `magit-generate-buffer-name-function' is used, then -it may not respect this option, or on the contrary it may -support additional %-sequences." - :package-version '(magit . "2.12.0") - :group 'magit-buffers - :type 'string) - -(defcustom magit-uniquify-buffer-names t - "Whether to uniquify the names of Magit buffers." - :package-version '(magit . "2.3.0") - :group 'magit-buffers - :type 'boolean) - -(defcustom magit-bury-buffer-function 'magit-restore-window-configuration - "The function used to bury or kill the current Magit buffer." - :package-version '(magit . "2.3.0") - :group 'magit-buffers - :type '(radio (function-item quit-window) - (function-item magit-mode-quit-window) - (function-item magit-restore-window-configuration) - (function :tag "Function"))) - -(defcustom magit-use-sticky-arguments t - "How to reuse arguments from existing diff and log buffers. - -nil Always use the default value of the variable - `magit-log-arguments' for log commands. Likewise, - always use the default value of the variable - `magit-diff-arguments' for diff command calls. - -current If the mode of the current buffer is derived from - `magit-log-mode' or `magit-diff-mode', reuse the - arguments from that buffer instead of those given by - the variable `magit-log-arguments' or - `magit-diff-arguments', respectively. - -t Like `current', but if the mode of the current buffer - is not derived from `magit-log-mode' or - `magit-diff-mode', use the arguments from the current - repository's active (i.e. non-locked) `magit-log-mode' - or `magit-diff-mode' buffer, respectively, if it - exists. - - Note that commands that generate a - `magit-revision-mode' or `magit-stash-mode' buffer will - also collect their diff arguments from the active - `magit-diff-mode' buffer. - -In general, there is a separation between the \"sticky\" -arguments for log and diff buffers, but there is one special -case: if the current buffer is a log buffer, -`magit-show-commit' (considered a diff command) uses the file -filter from the log buffer." - :package-version '(magit . "2.11.0") - :group 'magit-buffers - :type '(choice (const :tag "disabled" nil) - (const :tag "sticky for current" current) - (const :tag "sticky" t))) - -(defcustom magit-region-highlight-hook - '(magit-section-update-region magit-diff-update-hunk-region) - "Functions used to highlight the region. - -Each function is run with the current section as only argument -until one of them returns non-nil. If all functions return nil, -then fall back to regular region highlighting." - :package-version '(magit . "2.1.0") - :group 'magit-refresh - :type 'hook - :options '(magit-section-update-region magit-diff-update-hunk-region)) - -(defcustom magit-create-buffer-hook nil - "Normal hook run after creating a new `magit-mode' buffer." - :package-version '(magit . "2.90.0") - :group 'magit-refresh - :type 'hook) - -(defcustom magit-refresh-buffer-hook nil - "Normal hook for `magit-refresh-buffer' to run after refreshing." - :package-version '(magit . "2.1.0") - :group 'magit-refresh - :type 'hook) - -(defcustom magit-refresh-status-buffer t - "Whether the status buffer is refreshed after running git. - -When this is non-nil, then the status buffer is automatically -refreshed after running git for side-effects, in addition to the -current Magit buffer, which is always refreshed automatically. - -Only set this to nil after exhausting all other options to -improve performance." - :package-version '(magit . "2.4.0") - :group 'magit-refresh - :group 'magit-status - :type 'boolean) - -(defcustom magit-refresh-verbose nil - "Whether to revert Magit buffers verbosely." - :package-version '(magit . "2.1.0") - :group 'magit-refresh - :type 'boolean) - -(defcustom magit-save-repository-buffers t - "Whether to save file-visiting buffers when appropriate. - -If non-nil, then all modified file-visiting buffers belonging -to the current repository may be saved before running Magit -commands and before creating or refreshing Magit buffers. -If `dontask', then this is done without user intervention, for -any other non-nil value the user has to confirm each save. - -The default is t to avoid surprises, but `dontask' is the -recommended value." - :group 'magit-essentials - :group 'magit-buffers - :type '(choice (const :tag "Never" nil) - (const :tag "Ask" t) - (const :tag "Save without asking" dontask))) - -(defcustom magit-keep-region-overlay nil - "Whether to keep the region overlay when there is a valid selection. - -By default Magit removes the regular region overlay if, and only -if, that region constitutes a valid selection as understood by -Magit commands. Otherwise it does not remove that overlay, and -the region looks like it would in other buffers. - -There are two types of such valid selections: hunk-internal -regions and regions that select two or more sibling sections. -In such cases Magit removes the region overlay and instead -highlights a slightly larger range. All text (for hunk-internal -regions) or the headings of all sections (for sibling selections) -that are inside that range (not just inside the region) are acted -on by commands such as the staging command. This buffer range -begins at the beginning of the line on which the region begins -and ends at the end of the line on which the region ends. - -Because Magit acts on this larger range and not the region, it is -actually quite important to visualize that larger range. If we -don't do that, then one might think that these commands act on -the region instead. If you want to *also* visualize the region, -then set this option to t. But please note that when the region -does *not* constitute a valid selection, then the region is -*always* visualized as usual, and that it is usually under such -circumstances that you want to use a non-magit command to act on -the region. - -Besides keeping the region overlay, setting this option to t also -causes all face properties, except for `:foreground', to be -ignored for the faces used to highlight headings of selected -sections. This avoids the worst conflicts that result from -displaying the region and the selection overlays at the same -time. We are not interested in dealing with other conflicts. -In fact we *already* provide a way to avoid all of these -conflicts: *not* changing the value of this option. - -It should be clear by now that we consider it a mistake to set -this to display the region when the Magit selection is also -visualized, but since it has been requested a few times and -because it doesn't cost much to offer this option we do so. -However that might change. If the existence of this option -starts complicating other things, then it will be removed." - :package-version '(magit . "2.3.0") - :group 'magit-miscellaneous - :type 'boolean) - -;;; Magit Mode - -(defvar magit-mode-map - (let ((map (make-keymap))) - (suppress-keymap map t) - (cond ((featurep 'jkl) - (define-key map [return] 'magit-visit-thing) - (define-key map [C-return] 'magit-dired-jump) - (define-key map [tab] 'magit-section-toggle) - (define-key map [C-tab] 'magit-section-cycle) - (define-key map [M-tab] 'magit-section-cycle-diffs) - (define-key map [S-tab] 'magit-section-cycle-global) - (define-key map (kbd "M-o") 'magit-section-up) - (define-key map (kbd "i") 'magit-section-backward) - (define-key map (kbd "k") 'magit-section-forward) - (define-key map (kbd "M-i") 'magit-section-backward-sibling) - (define-key map (kbd "M-k") 'magit-section-forward-sibling) - (define-key map (kbd "p") 'magit-push-popup) - (define-key map (kbd ",") 'magit-delete-thing) - (define-key map (kbd ";") 'magit-file-untrack) - (define-key map (kbd "C-c C-i") 'magit-gitignore-popup)) - (t - (define-key map [C-return] 'magit-visit-thing) - (define-key map (kbd "C-m") 'magit-visit-thing) - (define-key map (kbd "C-M-i") 'magit-dired-jump) - (define-key map (kbd "C-i") 'magit-section-toggle) - (define-key map [C-tab] 'magit-section-cycle) - (define-key map [M-tab] 'magit-section-cycle-diffs) - ;; [backtab] is the most portable binding for Shift+Tab. - (define-key map [backtab] 'magit-section-cycle-global) - (define-key map (kbd "^") 'magit-section-up) - (define-key map (kbd "p") 'magit-section-backward) - (define-key map (kbd "n") 'magit-section-forward) - (define-key map (kbd "M-p") 'magit-section-backward-sibling) - (define-key map (kbd "M-n") 'magit-section-forward-sibling) - (define-key map (kbd "P") 'magit-push-popup) - (define-key map (kbd "k") 'magit-delete-thing) - (define-key map (kbd "K") 'magit-file-untrack) - (define-key map (kbd "i") 'magit-gitignore) - (define-key map (kbd "I") 'magit-gitignore-popup))) - (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up) - (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down) - (define-key map "+" 'magit-diff-more-context) - (define-key map "-" 'magit-diff-less-context) - (define-key map "0" 'magit-diff-default-context) - (define-key map "1" 'magit-section-show-level-1) - (define-key map "2" 'magit-section-show-level-2) - (define-key map "3" 'magit-section-show-level-3) - (define-key map "4" 'magit-section-show-level-4) - (define-key map (kbd "M-1") 'magit-section-show-level-1-all) - (define-key map (kbd "M-2") 'magit-section-show-level-2-all) - (define-key map (kbd "M-3") 'magit-section-show-level-3-all) - (define-key map (kbd "M-4") 'magit-section-show-level-4-all) - (define-key map "$" 'magit-process-buffer) - (define-key map "%" 'magit-worktree-popup) - (define-key map "a" 'magit-cherry-apply) - (define-key map "A" 'magit-cherry-pick-popup) - (define-key map "b" 'magit-branch-popup) - (define-key map "B" 'magit-bisect-popup) - (define-key map "c" 'magit-commit-popup) - (define-key map "d" 'magit-diff-popup) - (define-key map "D" 'magit-diff-refresh-popup) - (define-key map "e" 'magit-ediff-dwim) - (define-key map "E" 'magit-ediff-popup) - (define-key map "f" 'magit-fetch-popup) - (define-key map "F" 'magit-pull-popup) - (define-key map "g" 'magit-refresh) - (define-key map "G" 'magit-refresh-all) - (define-key map "h" 'magit-dispatch-popup) - (define-key map "?" 'magit-dispatch-popup) - (define-key map "l" 'magit-log-popup) - (define-key map "L" 'magit-log-refresh-popup) - (define-key map "m" 'magit-merge-popup) - (define-key map "M" 'magit-remote-popup) - (define-key map "o" 'magit-submodule-popup) - (define-key map "O" 'magit-subtree-popup) - (define-key map "q" 'magit-mode-bury-buffer) - (define-key map "r" 'magit-rebase-popup) - (define-key map "R" 'magit-file-rename) - (define-key map "t" 'magit-tag-popup) - (define-key map "T" 'magit-notes-popup) - (define-key map "s" 'magit-stage-file) - (define-key map "S" 'magit-stage-modified) - (define-key map "u" 'magit-unstage-file) - (define-key map "U" 'magit-unstage-all) - (define-key map "v" 'magit-revert-no-commit) - (define-key map "V" 'magit-revert-popup) - (define-key map "w" 'magit-am-popup) - (define-key map "W" 'magit-patch-popup) - (define-key map "x" 'magit-reset) - (define-key map "X" 'magit-reset-popup) - (define-key map "y" 'magit-show-refs-popup) - (define-key map "Y" 'magit-cherry) - (define-key map "z" 'magit-stash-popup) - (define-key map "Z" 'magit-stash-popup) - (define-key map ":" 'magit-git-command) - (define-key map "!" 'magit-run-popup) - (define-key map (kbd "C-c C-b") 'magit-browse-thing) - (define-key map (kbd "C-c C-c") 'magit-dispatch-popup) - (define-key map (kbd "C-c C-e") 'magit-dispatch-popup) - (define-key map (kbd "C-x a") 'magit-add-change-log-entry) - (define-key map (kbd "C-x 4 a") 'magit-add-change-log-entry-other-window) - (define-key map (kbd "C-w") 'magit-copy-section-value) - (define-key map (kbd "M-w") 'magit-copy-buffer-revision) - (define-key map [remap evil-previous-line] 'evil-previous-visual-line) - (define-key map [remap evil-next-line] 'evil-next-visual-line) - map) - "Parent keymap for all keymaps of modes derived from `magit-mode'.") - -(defun magit-delete-thing () - "This is a placeholder command. -Where applicable, section-specific keymaps bind another command -which deletes the thing at point." - (interactive) - (user-error "There is no thing at point that could be deleted")) - -(defun magit-visit-thing () - "This is a placeholder command. -Where applicable, section-specific keymaps bind another command -which visits the thing at point." - (interactive) - (if (eq magit-current-popup 'magit-dispatch-popup) - (progn (setq magit-current-popup nil) - (call-interactively (key-binding (this-command-keys)))) - (user-error "There is no thing at point that could be visited"))) - -(defun magit-edit-thing () - "This is a placeholder command. -Where applicable, section-specific keymaps bind another command -which lets you edit the thing at point, likely in another buffer." - (interactive) - (if (eq magit-current-popup 'magit-dispatch-popup) - (progn (setq magit-current-popup nil) - (call-interactively (key-binding (this-command-keys)))) - (user-error "There is no thing at point that could be visited"))) - -(defun magit-browse-thing () - "This is a placeholder command. -Where applicable, section-specific keymaps bind another command -which visits the thing at point using `browse-url'." - (interactive) - (user-error "There is no thing at point that could be browsed")) - -(easy-menu-define magit-mode-menu magit-mode-map - "Magit menu" - '("Magit" - ["Refresh" magit-refresh t] - ["Refresh all" magit-refresh-all t] - "---" - ["Stage" magit-stage t] - ["Stage modified" magit-stage-modified t] - ["Unstage" magit-unstage t] - ["Reset index" magit-reset-index t] - ["Commit" magit-commit-popup t] - ["Add log entry" magit-commit-add-log t] - ["Tag" magit-tag t] - "---" - ["Diff working tree" magit-diff-working-tree t] - ["Diff" magit-diff t] - ("Log" - ["Log" magit-log t] - ["Reflog" magit-reflog t] - ["Extended..." magit-log-popup t]) - "---" - ["Cherry pick" magit-cherry-pick t] - ["Revert commit" magit-revert-popup t] - "---" - ["Ignore" magit-gitignore t] - ["Ignore locally" magit-gitignore-locally t] - ["Discard" magit-discard t] - ["Reset head" magit-reset-head t] - ["Stash" magit-stash t] - ["Snapshot" magit-snapshot t] - "---" - ["Branch..." magit-checkout t] - ["Merge" magit-merge t] - ["Ediff resolve" magit-ediff-resolve t] - ["Rebase..." magit-rebase-popup t] - "---" - ["Push" magit-push t] - ["Pull" magit-pull t] - ["Remote update" magit-fetch-all t] - ("Submodule" - ["Submodule update" magit-submodule-update t] - ["Submodule update and init" magit-submodule-setup t] - ["Submodule init" magit-submodule-init t] - ["Submodule sync" magit-submodule-sync t]) - "---" - ("Extensions") - "---" - ["Display Git output" magit-process-buffer t] - ["Quit Magit" magit-mode-bury-buffer t])) - -(defun magit-load-config-extensions () - "Load Magit extensions that are defined at the Git config layer." - (dolist (ext (magit-get-all "magit.extension")) - (let ((sym (intern (format "magit-%s-mode" ext)))) - (when (fboundp sym) - (funcall sym 1))))) - -(define-derived-mode magit-mode special-mode "Magit" - "Parent major mode from which Magit major modes inherit. - -Magit is documented in info node `(magit)'." - :group 'magit-modes - (buffer-disable-undo) - (setq truncate-lines t) - (setq buffer-read-only t) - (setq-local line-move-visual t) ; see #1771 - (setq show-trailing-whitespace nil) - (setq list-buffers-directory (abbreviate-file-name default-directory)) - (hack-dir-local-variables-non-file-buffer) - (make-local-variable 'text-property-default-nonsticky) - (push (cons 'keymap t) text-property-default-nonsticky) - (add-hook 'post-command-hook #'magit-section-update-highlight t t) - (add-hook 'deactivate-mark-hook #'magit-section-update-highlight t t) - (setq-local redisplay-highlight-region-function 'magit-highlight-region) - (setq-local redisplay-unhighlight-region-function 'magit-unhighlight-region) - (when (bound-and-true-p global-linum-mode) - (linum-mode -1)) - (when (and (fboundp 'nlinum-mode) - (bound-and-true-p global-nlinum-mode)) - (nlinum-mode -1)) - (when (and (fboundp 'display-line-numbers-mode) - (bound-and-true-p global-display-line-numbers-mode)) - (display-line-numbers-mode -1)) - (add-hook 'kill-buffer-hook 'magit-preserve-section-visibility-cache)) - -(defvar-local magit-region-overlays nil) - -(defun magit-delete-region-overlays () - (mapc #'delete-overlay magit-region-overlays) - (setq magit-region-overlays nil)) - -(defun magit-highlight-region (start end window rol) - (magit-delete-region-overlays) - (if (and (run-hook-with-args-until-success 'magit-region-highlight-hook - (magit-current-section)) - (not magit-keep-region-overlay) - (not (= (line-number-at-pos start) - (line-number-at-pos end))) - ;; (not (eq (car-safe last-command-event) 'mouse-movement)) - ) - (funcall (default-value 'redisplay-unhighlight-region-function) rol) - (funcall (default-value 'redisplay-highlight-region-function) - start end window rol))) - -(defun magit-unhighlight-region (rol) - (setq magit-section-highlighted-section nil) - (magit-delete-region-overlays) - (funcall (default-value 'redisplay-unhighlight-region-function) rol)) - -(defvar-local magit-refresh-args nil - "The arguments used to refresh the current buffer.") -(put 'magit-refresh-args 'permanent-local t) - -(defvar-local magit-previous-section nil) -(put 'magit-previous-section 'permanent-local t) - -(defun magit-mode-setup (mode &rest args) - "Setup up a MODE buffer using ARGS to generate its content." - (magit-mode-setup-internal mode args)) - -(defun magit-mode-setup-internal (mode args &optional locked) - "Setup up a MODE buffer using ARGS to generate its content. -When optional LOCKED is non-nil, then create a buffer that is -locked to its value, which is derived from MODE and ARGS." - (let* ((value (and locked (magit-buffer-lock-value mode args))) - (buffer (magit-mode-get-buffer mode nil nil value)) - (section (and buffer (magit-current-section))) - (created (not buffer))) - (unless buffer - (setq buffer (magit-with-toplevel - (magit-generate-new-buffer mode value)))) - (with-current-buffer buffer - (setq magit-previous-section section) - (setq magit-refresh-args args) - (funcall mode) - (when created - (magit-status-goto-initial-section) - (run-hooks 'magit-create-buffer-hook))) - (magit-display-buffer buffer) - (with-current-buffer buffer - (run-hooks 'magit-mode-setup-hook) - (magit-refresh-buffer)))) - -(defvar magit-display-buffer-noselect nil - "If non-nil, then `magit-display-buffer' doesn't call `select-window'.") - -(defun magit-display-buffer (buffer) - "Display BUFFER in some window and maybe select it. - -Display the buffer using `magit-display-buffer-function' and -then, unless `magit-display-buffer-noselect' is non-nil, select -the window which was used to display the buffer. - -Also run the hooks `magit-pre-display-buffer-hook' -and `magit-post-display-buffer-hook'." - (with-current-buffer buffer - (run-hooks 'magit-pre-display-buffer-hook)) - (let ((window (funcall magit-display-buffer-function buffer))) - (unless magit-display-buffer-noselect - (select-frame-set-input-focus - (window-frame - (select-window window))))) - (with-current-buffer buffer - (run-hooks 'magit-post-display-buffer-hook))) - -(defun magit-display-buffer-traditional (buffer) - "Display BUFFER the way this has traditionally been done." - (display-buffer - buffer (if (and (derived-mode-p 'magit-mode) - (not (memq (with-current-buffer buffer major-mode) - '(magit-process-mode - magit-revision-mode - magit-diff-mode - magit-stash-mode - magit-status-mode)))) - '(display-buffer-same-window) - nil))) ; display in another window - -(defun magit-display-buffer-same-window-except-diff-v1 (buffer) - "Display BUFFER in the selected window except for some modes. -If a buffer's `major-mode' derives from `magit-diff-mode' or -`magit-process-mode', display it in another window. Display all -other buffers in the selected window." - (display-buffer - buffer (if (with-current-buffer buffer - (derived-mode-p 'magit-diff-mode 'magit-process-mode)) - nil ; display in another window - '(display-buffer-same-window)))) - -(defun magit--display-buffer-fullframe (buffer alist) - (when-let ((window (or (display-buffer-reuse-window buffer alist) - (display-buffer-same-window buffer alist) - (display-buffer-pop-up-window buffer alist) - (display-buffer-use-some-window buffer alist)))) - (delete-other-windows window) - window)) - -(defun magit-display-buffer-fullframe-status-v1 (buffer) - "Display BUFFER, filling entire frame if BUFFER is a status buffer. -Otherwise, behave like `magit-display-buffer-traditional'." - (if (eq (with-current-buffer buffer major-mode) - 'magit-status-mode) - (display-buffer buffer '(magit--display-buffer-fullframe)) - (magit-display-buffer-traditional buffer))) - -(defun magit--display-buffer-topleft (buffer alist) - (or (display-buffer-reuse-window buffer alist) - (when-let ((window2 (display-buffer-pop-up-window buffer alist))) - (let ((window1 (get-buffer-window)) - (buffer1 (current-buffer)) - (buffer2 (window-buffer window2)) - (w2-quit-restore (window-parameter window2 'quit-restore))) - (set-window-buffer window1 buffer2) - (set-window-buffer window2 buffer1) - (select-window window2) - ;; Swap some window state that `magit-mode-quit-window' and - ;; `quit-restore-window' inspect. - (set-window-prev-buffers window2 (cdr (window-prev-buffers window1))) - (set-window-prev-buffers window1 nil) - (set-window-parameter window2 'magit-dedicated - (window-parameter window1 'magit-dedicated)) - (set-window-parameter window1 'magit-dedicated t) - (set-window-parameter window1 'quit-restore - (list 'window 'window - (nth 2 w2-quit-restore) - (nth 3 w2-quit-restore))) - (set-window-parameter window2 'quit-restore nil) - window1)))) - -(defun magit-display-buffer-fullframe-status-topleft-v1 (buffer) - "Display BUFFER, filling entire frame if BUFFER is a status buffer. -When BUFFER derives from `magit-diff-mode' or -`magit-process-mode', try to display BUFFER to the top or left of -the current buffer rather than to the bottom or right, as -`magit-display-buffer-fullframe-status-v1' would. Whether the -split is made vertically or horizontally is determined by -`split-window-preferred-function'." - (display-buffer - buffer - (cond ((eq (with-current-buffer buffer major-mode) - 'magit-status-mode) - '(magit--display-buffer-fullframe)) - ((with-current-buffer buffer - (derived-mode-p 'magit-diff-mode 'magit-process-mode)) - '(magit--display-buffer-topleft)) - (t - '(display-buffer-same-window))))) - -(defun magit--display-buffer-fullcolumn (buffer alist) - (when-let ((window (or (display-buffer-reuse-window buffer alist) - (display-buffer-same-window buffer alist) - (display-buffer-below-selected buffer alist)))) - (delete-other-windows-vertically window) - window)) - -(defun magit-display-buffer-fullcolumn-most-v1 (buffer) - "Display BUFFER using the full column except in some cases. -For most cases where BUFFER's `major-mode' derives from -`magit-mode', display it in the selected window and grow that -window to the full height of the frame, deleting other windows in -that column as necessary. However, display BUFFER in another -window if 1) BUFFER's mode derives from `magit-process-mode', or -2) BUFFER's mode derives from `magit-diff-mode', provided that -the mode of the current buffer derives from `magit-log-mode' or -`magit-cherry-mode'." - (display-buffer - buffer - (cond ((and (or git-commit-mode - (derived-mode-p 'magit-log-mode 'magit-cherry-mode)) - (with-current-buffer buffer - (derived-mode-p 'magit-diff-mode))) - nil) - ((with-current-buffer buffer - (derived-mode-p 'magit-process-mode)) - nil) - (t - '(magit--display-buffer-fullcolumn))))) - -(defun magit-maybe-set-dedicated () - "Mark the selected window as dedicated if appropriate. - -If a new window was created to display the buffer, then remember -that fact. That information is used by `magit-mode-quit-window', -to determine whether the window should be deleted when its last -Magit buffer is buried." - (let ((window (get-buffer-window (current-buffer)))) - (when (and (window-live-p window) - (not (window-prev-buffers window))) - (set-window-parameter window 'magit-dedicated t)))) - -(defvar-local magit--default-directory nil - "Value of `default-directory' when buffer is generated. -This exists to prevent a let-bound `default-directory' from -tricking `magit-mode-get-buffer' or `magit-mode-get-buffers' into -thinking a buffer belongs to a repo that it doesn't.") -(put 'magit--default-directory 'permanent-local t) - -(defun magit-mode-get-buffers () - (let ((topdir (magit-toplevel))) - (--filter (with-current-buffer it - (and (derived-mode-p 'magit-mode) - (equal magit--default-directory topdir))) - (buffer-list)))) - -(defvar-local magit-buffer-locked-p nil) -(put 'magit-buffer-locked-p 'permanent-local t) - -(defun magit-mode-get-buffer (mode &optional create frame value) - (when create - (error "`magit-mode-get-buffer's CREATE argument is obsolete")) - (if-let ((topdir (magit-toplevel))) - (--first (with-current-buffer it - (and (eq major-mode mode) - (equal magit--default-directory topdir) - (if value - (and magit-buffer-locked-p - (equal (magit-buffer-lock-value) value)) - (not magit-buffer-locked-p)))) - (if frame - (mapcar #'window-buffer - (window-list (unless (eq frame t) frame))) - (buffer-list))) - (magit--not-inside-repository-error))) - -(defun magit-generate-new-buffer (mode &optional value) - (let* ((name (funcall magit-generate-buffer-name-function mode value)) - (buffer (generate-new-buffer name))) - (with-current-buffer buffer - (setq magit--default-directory default-directory) - (setq magit-buffer-locked-p (and value t)) - (magit-restore-section-visibility-cache mode)) - (when magit-uniquify-buffer-names - (add-to-list 'uniquify-list-buffers-directory-modes mode) - (with-current-buffer buffer - (setq list-buffers-directory (abbreviate-file-name default-directory))) - (let ((uniquify-buffer-name-style - (if (memq uniquify-buffer-name-style '(nil forward)) - 'post-forward-angle-brackets - uniquify-buffer-name-style))) - (uniquify-rationalize-file-buffer-names - name (file-name-directory (directory-file-name default-directory)) - buffer))) - buffer)) - -(defun magit-generate-buffer-name-default-function (mode &optional value) - "Generate buffer name for a MODE buffer in the current repository. -The returned name is based on `magit-buffer-name-format' and -takes `magit-uniquify-buffer-names' and VALUE, if non-nil, into -account." - (let ((m (substring (symbol-name mode) 0 -5)) - (v (and value (format "%s" (if (listp value) value (list value))))) - (n (if magit-uniquify-buffer-names - (file-name-nondirectory - (directory-file-name default-directory)) - (abbreviate-file-name default-directory)))) - (format-spec - magit-buffer-name-format - `((?m . ,m) - (?M . ,(if (eq mode 'magit-status-mode) "magit" m)) - (?v . ,(or v "")) - (?V . ,(if v (concat " " v) "")) - (?t . ,n) - (?x . ,(if magit-uniquify-buffer-names "" "*")) - (?T . ,(if magit-uniquify-buffer-names n (concat n "*"))))))) - -(defun magit-toggle-buffer-lock () - "Lock the current buffer to its value or unlock it. - -Locking a buffer to its value prevents it from being reused to -display another value. The name of a locked buffer contains its -value, which allows telling it apart from other locked buffers -and the unlocked buffer. - -Not all Magit buffers can be locked to their values, for example -it wouldn't make sense to lock a status buffer. - -There can only be a single unlocked buffer using a certain -major-mode per repository. So when a buffer is being unlocked -and another unlocked buffer already exists for that mode and -repository, then the former buffer is instead deleted and the -latter is displayed in its place." - (interactive) - (if magit-buffer-locked-p - (if-let ((unlocked (magit-mode-get-buffer major-mode))) - (let ((locked (current-buffer))) - (switch-to-buffer unlocked nil t) - (kill-buffer locked)) - (setq magit-buffer-locked-p nil) - (rename-buffer (funcall magit-generate-buffer-name-function - major-mode))) - (if-let ((value (magit-buffer-lock-value))) - (if-let ((locked (magit-mode-get-buffer major-mode nil nil value))) - (let ((unlocked (current-buffer))) - (switch-to-buffer locked nil t) - (kill-buffer unlocked)) - (setq magit-buffer-locked-p t) - (rename-buffer (funcall magit-generate-buffer-name-function - major-mode value))) - (user-error "Buffer has no value it could be locked to")))) - -(defvar magit-buffer-lock-functions nil - "Provide buffer-locking support for third-party modes. -An alist of symbols to functions. - -The symbol must be the major-mode the locked buffer will have. - -The function must take a single argument, a list of refresh -arguments (the value of `magit-refresh-args') and return a -value that identifies the buffer (i.e., its 'lock value'). -If the third-party mode is invoked as - - (magit-mode-setup-internal #\\='my-mode \\='(1 2 3) t) - -the function will be invoked as - - (funcall lock-func \\='(1 2 3)) - -if the cons (my-mode . lock-func) is in this list. - -This variable is intended for third-party extensions; -`magit-buffer-lock-value' implements all built-in behavior. - -See also `magit-toggle-buffer-lock'.") - -(cl-defun magit-buffer-lock-value - (&optional (mode major-mode) - (args magit-refresh-args)) - "Find an appropriate buffer lock value for MODE under ARGS. -See also `magit-buffer-lock-functions'." - (cl-case mode - (magit-cherry-mode - (pcase-let ((`(,upstream ,head) args)) - (concat head ".." upstream))) - (magit-diff-mode - (pcase-let ((`(,rev-or-range ,const ,_args ,files) args)) - (nconc (cons (or rev-or-range - (if (member "--cached" const) - (progn (setq const (delete "--cached" const)) - 'staged) - 'unstaged)) - const) - (and files (cons "--" files))))) - (magit-log-mode - (pcase-let ((`(,revs ,_args ,files) args)) - (if (and revs files) - (append revs (cons "--" files)) - (append revs files)))) - (magit-refs-mode - (pcase-let ((`(,ref ,args) args)) - (cons (or ref "HEAD") args))) - (magit-revision-mode - (pcase-let ((`(,rev ,_const ,_args ,files) args)) - (if files (cons rev files) (list rev)))) - ((magit-reflog-mode ; (ref ~args) - magit-stash-mode ; (stash _const _args _files) - magit-stashes-mode) ; (ref) - (car args)) - (t - (--when-let (cdr (assq mode magit-buffer-lock-functions)) - (funcall it args))))) - -(defun magit-mode-bury-buffer (&optional kill-buffer) - "Bury the current buffer. -With a prefix argument, kill the buffer instead. -This is done using `magit-bury-buffer-function'." - (interactive "P") - (funcall magit-bury-buffer-function kill-buffer)) - -(defun magit-mode-quit-window (kill-buffer) - "Quit the selected window and bury its buffer. - -This behaves similar to `quit-window', but when the window -was originally created to display a Magit buffer and the -current buffer is the last remaining Magit buffer that was -ever displayed in the selected window, then delete that -window." - (if (or (one-window-p) - (--first (let ((buffer (car it))) - (and (not (eq buffer (current-buffer))) - (buffer-live-p buffer) - (or (not (window-parameter nil 'magit-dedicated)) - (with-current-buffer buffer - (derived-mode-p 'magit-mode - 'magit-process-mode))))) - (window-prev-buffers))) - (quit-window kill-buffer) - (let ((window (selected-window))) - (quit-window kill-buffer) - (when (window-live-p window) - (delete-window window))))) - -;;; Refresh Magit Buffers - -(defvar inhibit-magit-refresh nil) - -(defun magit-refresh () - "Refresh some buffers belonging to the current repository. - -Refresh the current buffer if its major mode derives from -`magit-mode', and refresh the corresponding status buffer. - -Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." - (interactive) - (unless inhibit-magit-refresh - (unwind-protect - (let ((start (current-time)) - (magit--refresh-cache (or magit--refresh-cache - (list (cons 0 0))))) - (when magit-refresh-verbose - (message "Refreshing magit...")) - (magit-run-hook-with-benchmark 'magit-pre-refresh-hook) - (when (derived-mode-p 'magit-mode) - (magit-refresh-buffer)) - (--when-let (and magit-refresh-status-buffer - (not (derived-mode-p 'magit-status-mode)) - (magit-mode-get-buffer 'magit-status-mode)) - (with-current-buffer it - (magit-refresh-buffer))) - (magit-auto-revert-buffers) - (magit-run-hook-with-benchmark 'magit-post-refresh-hook) - (when magit-refresh-verbose - (message "Refreshing magit...done (%.3fs, cached %s/%s)" - (float-time (time-subtract (current-time) start)) - (caar magit--refresh-cache) - (+ (caar magit--refresh-cache) - (cdar magit--refresh-cache))))) - (run-hooks 'magit-unwind-refresh-hook)))) - -(defun magit-refresh-all () - "Refresh all buffers belonging to the current repository. - -Refresh all Magit buffers belonging to the current repository, -and revert buffers that visit files located inside the current -repository. - -Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." - (interactive) - (magit-run-hook-with-benchmark 'magit-pre-refresh-hook) - (dolist (buffer (magit-mode-get-buffers)) - (with-current-buffer buffer (magit-refresh-buffer))) - (magit-auto-revert-buffers) - (magit-run-hook-with-benchmark 'magit-post-refresh-hook)) - -(defvar-local magit-refresh-start-time nil) - -(defun magit-refresh-buffer () - "Refresh the current Magit buffer." - (setq magit-refresh-start-time (current-time)) - (let ((refresh (intern (format "%s-refresh-buffer" - (substring (symbol-name major-mode) 0 -5)))) - (magit--refresh-cache (or magit--refresh-cache (list (cons 0 0))))) - (when (functionp refresh) - (when magit-refresh-verbose - (message "Refreshing buffer `%s'..." (buffer-name))) - (let* ((buffer (current-buffer)) - (windows - (--mapcat (with-selected-window it - (with-current-buffer buffer - (when-let ((section (magit-current-section))) - (list - (nconc (list it section) - (magit-refresh-get-relative-position)))))) - (or (get-buffer-window-list buffer nil t) - (list (selected-window)))))) - (deactivate-mark) - (setq magit-section-highlight-overlays nil) - (setq magit-section-highlighted-section nil) - (setq magit-section-highlighted-sections nil) - (setq magit-section-unhighlight-sections nil) - (magit-process-unset-mode-line-error-status) - (let ((inhibit-read-only t)) - (erase-buffer) - (save-excursion - (apply refresh magit-refresh-args))) - (dolist (window windows) - (with-selected-window (car window) - (with-current-buffer buffer - (apply #'magit-section-goto-successor (cdr window))))) - (run-hooks 'magit-refresh-buffer-hook) - (magit-section-update-highlight) - (set-buffer-modified-p nil)) - (when magit-refresh-verbose - (message "Refreshing buffer `%s'...done (%.3fs)" (buffer-name) - (float-time (time-subtract (current-time) - magit-refresh-start-time))))))) - -(defun magit-refresh-get-relative-position () - (when-let ((section (magit-current-section))) - (let ((start (oref section start))) - (list (count-lines start (point)) - (- (point) (line-beginning-position)) - (and (magit-hunk-section-p section) - (region-active-p) - (progn (goto-char (line-beginning-position)) - (when (looking-at "^[-+]") (forward-line)) - (while (looking-at "^[ @]") (forward-line)) - (let ((beg (point))) - (cond ((looking-at "^[-+]") - (forward-line) - (while (looking-at "^[-+]") (forward-line)) - (while (looking-at "^ ") (forward-line)) - (forward-line -1) - (regexp-quote (buffer-substring-no-properties - beg (line-end-position)))) - (t t))))))))) - -;;; Save File-Visiting Buffers - -(defvar disable-magit-save-buffers nil) - -(defun magit-pre-command-hook () - (setq disable-magit-save-buffers nil)) -(add-hook 'pre-command-hook #'magit-pre-command-hook) - -(defvar magit-after-save-refresh-buffers nil) - -(defun magit-after-save-refresh-buffers () - (dolist (buffer magit-after-save-refresh-buffers) - (when (buffer-live-p buffer) - (with-current-buffer buffer - (magit-refresh-buffer)))) - (setq magit-after-save-refresh-buffers nil) - (remove-hook 'post-command-hook 'magit-after-save-refresh-buffers)) - -(defun magit-after-save-refresh-status () - "Refresh the status buffer of the current repository. - -This function is intended to be added to `after-save-hook'. - -If the status buffer does not exist or the file being visited in -the current buffer isn't inside the working tree of a repository, -then do nothing. - -Note that refreshing a Magit buffer is done by re-creating its -contents from scratch, which can be slow in large repositories. -If you are not satisfied with Magit's performance, then you -should obviously not add this function to that hook." - (when (and (not disable-magit-save-buffers) - (magit-inside-worktree-p t)) - (--when-let (ignore-errors (magit-mode-get-buffer 'magit-status-mode)) - (add-to-list 'magit-after-save-refresh-buffers it) - (add-hook 'post-command-hook 'magit-after-save-refresh-buffers)))) - -(defun magit-maybe-save-repository-buffers () - "Maybe save file-visiting buffers belonging to the current repository. -Do so if `magit-save-repository-buffers' is non-nil. You should -not remove this from any hooks, instead set that variable to nil -if you so desire." - (when (and magit-save-repository-buffers - (not disable-magit-save-buffers)) - (setq disable-magit-save-buffers t) - (let ((msg (current-message))) - (magit-save-repository-buffers - (eq magit-save-repository-buffers 'dontask)) - (when (and msg - (current-message) - (not (equal msg (current-message)))) - (message "%s" msg))))) - -(add-hook 'magit-pre-refresh-hook #'magit-maybe-save-repository-buffers) -(add-hook 'magit-pre-call-git-hook #'magit-maybe-save-repository-buffers) -(add-hook 'magit-pre-start-git-hook #'magit-maybe-save-repository-buffers) - -(defvar-local magit-inhibit-refresh-save nil) - -(defun magit-save-repository-buffers (&optional arg) - "Save file-visiting buffers belonging to the current repository. -After any buffer where `buffer-save-without-query' is non-nil -is saved without asking, the user is asked about each modified -buffer which visits a file in the current repository. Optional -argument (the prefix) non-nil means save all with no questions." - (interactive "P") - (when-let ((topdir (magit-rev-parse-safe "--show-toplevel"))) - (let ((remote (file-remote-p topdir)) - (save-some-buffers-action-alist - `((?Y (lambda (buffer) - (with-current-buffer buffer - (setq buffer-save-without-query t) - (save-buffer))) - "to save the current buffer and remember choice") - (?N (lambda (buffer) - (with-current-buffer buffer - (setq magit-inhibit-refresh-save t))) - "to skip the current buffer and remember choice") - ,@save-some-buffers-action-alist))) - (save-some-buffers - arg (lambda () - (and (not magit-inhibit-refresh-save) - buffer-file-name - (file-exists-p (file-name-directory buffer-file-name)) - ;; Avoid needlessly connecting to unrelated remotes. - (equal (file-remote-p buffer-file-name) - remote) - (string-prefix-p topdir (file-truename buffer-file-name)) - (equal (magit-rev-parse-safe "--show-toplevel") - topdir))))))) - -;;; Restore Window Configuration - -(defvar magit-inhibit-save-previous-winconf nil) - -(defvar-local magit-previous-window-configuration nil) -(put 'magit-previous-window-configuration 'permanent-local t) - -(defun magit-save-window-configuration () - "Save the current window configuration. - -Later, when the buffer is buried, it may be restored by -`magit-restore-window-configuration'." - (if magit-inhibit-save-previous-winconf - (when (eq magit-inhibit-save-previous-winconf 'unset) - (setq magit-previous-window-configuration nil)) - (unless (get-buffer-window (current-buffer) (selected-frame)) - (setq magit-previous-window-configuration - (current-window-configuration))))) - -(defun magit-restore-window-configuration (&optional kill-buffer) - "Bury or kill the current buffer and restore previous window configuration." - (let ((winconf magit-previous-window-configuration) - (buffer (current-buffer)) - (frame (selected-frame))) - (quit-window kill-buffer (selected-window)) - (when (and winconf (equal frame (window-configuration-frame winconf))) - (set-window-configuration winconf) - (when (buffer-live-p buffer) - (with-current-buffer buffer - (setq magit-previous-window-configuration nil)))))) - -;;; Buffer History - -(defun magit-go-backward () - "Move backward in current buffer's history." - (interactive) - (if help-xref-stack - (help-xref-go-back (current-buffer)) - (user-error "No previous entry in buffer's history"))) - -(defun magit-go-forward () - "Move forward in current buffer's history." - (interactive) - (if help-xref-forward-stack - (help-xref-go-forward (current-buffer)) - (user-error "No next entry in buffer's history"))) - -(defun magit-insert-xref-buttons (&optional _) - "Insert xref buttons." - (when (or help-xref-stack help-xref-forward-stack) - (when help-xref-stack - (magit-xref-insert-button help-back-label 'magit-xref-backward)) - (when help-xref-forward-stack - (when help-xref-stack - (insert " ")) - (magit-xref-insert-button help-forward-label 'magit-xref-forward)))) - -(defun magit-xref-insert-button (label type) - (magit-insert-section (button label) - (insert-text-button label 'type type - 'help-args (list (current-buffer))))) - -(define-button-type 'magit-xref-backward - :supertype 'help-back - 'mouse-face 'magit-section-highlight - 'help-echo (purecopy "mouse-2, RET: go back to previous history entry")) - -(define-button-type 'magit-xref-forward - :supertype 'help-forward - 'mouse-face 'magit-section-highlight - 'help-echo (purecopy "mouse-2, RET: go back to next history entry")) - -(defun magit-xref-setup () - "Insert backward/forward buttons if the major-mode supports it. -Currently `magit-log-mode', `magit-reflog-mode', -`magit-diff-mode', and `magit-revision-mode' support it" - (when (memq major-mode '(magit-log-mode - magit-reflog-mode - magit-diff-mode - magit-revision-mode)) - (when help-xref-stack-item - (push (cons (point) help-xref-stack-item) help-xref-stack) - (setq help-xref-forward-stack nil)) - (when (called-interactively-p 'interactive) - (--when-let (nthcdr 10 help-xref-stack) - (setcdr it nil))) - (setq help-xref-stack-item - `(magit-xref-restore ,default-directory ,@magit-refresh-args)))) - -(defun magit-xref-restore (&rest args) - (magit-xref-setup) - (setq default-directory (car args)) - (setq magit-refresh-args (cdr args)) - (magit-refresh-buffer)) - -;;; Repository-Local Cache - -(defvar magit-repository-local-cache nil - "Alist mapping `magit-toplevel' paths to alists of key/value pairs.") - -(defun magit-repository-local-repository () - "Return the key for the current repository." - (or (bound-and-true-p magit--default-directory) - (magit-toplevel))) - -(defun magit-repository-local-set (key value &optional repository) - "Set the repository-local VALUE for KEY. - -Unless specified, REPOSITORY is the current buffer's repository. - -If REPOSITORY is nil (meaning there is no current repository), -then the value is not cached, and we return nil." - (let* ((repokey (or repository (magit-repository-local-repository))) - (cache (assoc repokey magit-repository-local-cache))) - ;; Don't cache values for a nil REPOSITORY, as the 'set' and 'get' - ;; calls for some KEY may happen in unrelated contexts. - (when repokey - (if cache - (let ((keyvalue (assoc key (cdr cache)))) - (if keyvalue - ;; Update pre-existing value for key. - (setcdr keyvalue value) - ;; No such key in repository-local cache. - (push (cons key value) (cdr cache)))) - ;; No cache for this repository. - (push (cons repokey (list (cons key value))) - magit-repository-local-cache))))) - -(defun magit-repository-local-exists-p (key &optional repository) - "Non-nil when a repository-local value exists for KEY. - -Returns a (KEY . value) cons cell. - -The KEY is matched using `equal'. - -Unless specified, REPOSITORY is the current buffer's repository." - (let* ((repokey (or repository (magit-repository-local-repository))) - (cache (assoc repokey magit-repository-local-cache))) - (and cache - (assoc key (cdr cache))))) - -(defun magit-repository-local-get (key &optional default repository) - "Return the repository-local value for KEY. - -Return DEFAULT if no value for KEY exists. - -The KEY is matched using `equal'. - -Unless specified, REPOSITORY is the current buffer's repository." - (let ((keyvalue (magit-repository-local-exists-p key repository))) - (if keyvalue - (cdr keyvalue) - default))) - -(defun magit-repository-local-delete (key &optional repository) - "Delete the repository-local value for KEY. - -Unless specified, REPOSITORY is the current buffer's repository." - (let* ((repokey (or repository (magit-repository-local-repository))) - (cache (assoc repokey magit-repository-local-cache))) - (when cache - ;; There is no `assoc-delete-all'. - (setf (cdr cache) - (cl-delete key (cdr cache) :key #'car :test #'equal))))) - -(defun magit-zap-caches () - "Zap caches for the current repository. -Remove the repository's entry from `magit-repository-local-cache' -and set `magit-section-visibility-cache' to nil in all of the -repository's Magit buffers." - (interactive) - (magit-with-toplevel - (setq magit-repository-local-cache - (cl-delete default-directory - magit-repository-local-cache - :key #'car :test #'equal))) - (dolist (buffer (magit-mode-get-buffers)) - (with-current-buffer buffer - (setq magit-section-visibility-cache nil)))) - -;;; Utilities - -(defun magit-run-hook-with-benchmark (hook) - (when hook - (if magit-refresh-verbose - (let ((start (current-time))) - (message "Running %s..." hook) - (run-hooks hook) - (message "Running %s...done (%.3fs)" hook - (float-time (time-subtract (current-time) start)))) - (run-hooks hook)))) - -(provide 'magit-mode) -;;; magit-mode.el ends here |