Klimi's new dotfiles with stow.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

1520 行
61 KiB

  1. ;;; magit-mode.el --- create and refresh Magit buffers -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2010-2019 The Magit Project Contributors
  3. ;;
  4. ;; You should have received a copy of the AUTHORS.md file which
  5. ;; lists all contributors. If not, see http://magit.vc/authors.
  6. ;; Author: Jonas Bernoulli <jonas@bernoul.li>
  7. ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
  8. ;; Magit is free software; you can redistribute it and/or modify it
  9. ;; under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 3, or (at your option)
  11. ;; any later version.
  12. ;;
  13. ;; Magit is distributed in the hope that it will be useful, but WITHOUT
  14. ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  15. ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  16. ;; License for more details.
  17. ;;
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with Magit. If not, see http://www.gnu.org/licenses.
  20. ;;; Commentary:
  21. ;; This library implements the abstract major-mode `magit-mode' from
  22. ;; which almost all other Magit major-modes derive. The code in here
  23. ;; is mostly concerned with creating and refreshing Magit buffers.
  24. ;;; Code:
  25. (require 'cl-lib)
  26. (require 'dash)
  27. (eval-when-compile
  28. (require 'subr-x))
  29. (require 'transient)
  30. (require 'magit-section)
  31. (require 'magit-git)
  32. ;; For `magit-display-buffer-fullcolumn-most-v1' from `git-commit'
  33. (defvar git-commit-mode)
  34. ;; For `magit-refresh'
  35. (defvar magit-post-commit-hook-commands)
  36. (defvar magit-post-stage-hook-commands)
  37. (defvar magit-post-unstage-hook-commands)
  38. ;; For `magit-refresh' and `magit-refresh-all'
  39. (declare-function magit-auto-revert-buffers "magit-autorevert" ())
  40. ;; For `magit-refresh-buffer'
  41. (declare-function magit-process-unset-mode-line-error-status "magit-process" ())
  42. ;; For `magit-mode-setup-internal'
  43. (declare-function magit-status-goto-initial-section "magit-status" ())
  44. ;; For `magit-mode' from `bookmark'
  45. (defvar bookmark-make-record-function)
  46. (require 'format-spec)
  47. (require 'help-mode)
  48. ;;; Options
  49. (defcustom magit-mode-hook
  50. '(magit-load-config-extensions)
  51. "Hook run when entering a mode derived from Magit mode."
  52. :package-version '(magit . "2.91.0")
  53. :group 'magit-modes
  54. :type 'hook
  55. :options '(magit-load-config-extensions
  56. bug-reference-mode))
  57. (defcustom magit-setup-buffer-hook
  58. '(magit-maybe-save-repository-buffers
  59. magit-set-buffer-margin)
  60. "Hook run by `magit-setup-buffer'.
  61. This is run right after displaying the buffer and right before
  62. generating or updating its content. `magit-mode-hook' and other,
  63. more specific, `magit-mode-*-hook's on the other hand are run
  64. right before displaying the buffer. Usually one of these hooks
  65. should be used instead of this one."
  66. :package-version '(magit . "2.3.0")
  67. :group 'magit-modes
  68. :type 'hook
  69. :options '(magit-maybe-save-repository-buffers
  70. magit-set-buffer-margin))
  71. (defcustom magit-pre-refresh-hook '(magit-maybe-save-repository-buffers)
  72. "Hook run before refreshing in `magit-refresh'.
  73. This hook, or `magit-post-refresh-hook', should be used
  74. for functions that are not tied to a particular buffer.
  75. To run a function with a particular buffer current, use
  76. `magit-refresh-buffer-hook' and use `derived-mode-p'
  77. inside your function."
  78. :package-version '(magit . "2.4.0")
  79. :group 'magit-refresh
  80. :type 'hook
  81. :options '(magit-maybe-save-repository-buffers))
  82. (defcustom magit-post-refresh-hook nil
  83. "Hook run after refreshing in `magit-refresh'.
  84. This hook, or `magit-pre-refresh-hook', should be used
  85. for functions that are not tied to a particular buffer.
  86. To run a function with a particular buffer current, use
  87. `magit-refresh-buffer-hook' and use `derived-mode-p'
  88. inside your function."
  89. :package-version '(magit . "2.4.0")
  90. :group 'magit-refresh
  91. :type 'hook)
  92. (defcustom magit-display-buffer-function 'magit-display-buffer-traditional
  93. "The function used display a Magit buffer.
  94. All Magit buffers (buffers whose major-modes derive from
  95. `magit-mode') are displayed using `magit-display-buffer',
  96. which in turn uses the function specified here."
  97. :package-version '(magit . "2.3.0")
  98. :group 'magit-buffers
  99. :type '(radio (function-item magit-display-buffer-traditional)
  100. (function-item magit-display-buffer-same-window-except-diff-v1)
  101. (function-item magit-display-buffer-fullframe-status-v1)
  102. (function-item magit-display-buffer-fullframe-status-topleft-v1)
  103. (function-item magit-display-buffer-fullcolumn-most-v1)
  104. (function-item display-buffer)
  105. (function :tag "Function")))
  106. (defcustom magit-pre-display-buffer-hook '(magit-save-window-configuration)
  107. "Hook run by `magit-display-buffer' before displaying the buffer."
  108. :package-version '(magit . "2.3.0")
  109. :group 'magit-buffers
  110. :type 'hook
  111. :get 'magit-hook-custom-get
  112. :options '(magit-save-window-configuration))
  113. (defcustom magit-post-display-buffer-hook '(magit-maybe-set-dedicated)
  114. "Hook run by `magit-display-buffer' after displaying the buffer."
  115. :package-version '(magit . "2.3.0")
  116. :group 'magit-buffers
  117. :type 'hook
  118. :get 'magit-hook-custom-get
  119. :options '(magit-maybe-set-dedicated))
  120. (defcustom magit-generate-buffer-name-function
  121. 'magit-generate-buffer-name-default-function
  122. "The function used to generate the name for a Magit buffer."
  123. :package-version '(magit . "2.3.0")
  124. :group 'magit-buffers
  125. :type '(radio (function-item magit-generate-buffer-name-default-function)
  126. (function :tag "Function")))
  127. (defcustom magit-buffer-name-format "%x%M%v: %t%x"
  128. "The format string used to name Magit buffers.
  129. The following %-sequences are supported:
  130. `%m' The name of the major-mode, but with the `-mode' suffix
  131. removed.
  132. `%M' Like \"%m\" but abbreviate `magit-status-mode' as `magit'.
  133. `%v' The value the buffer is locked to, in parentheses, or an
  134. empty string if the buffer is not locked to a value.
  135. `%V' Like \"%v\", but the string is prefixed with a space, unless
  136. it is an empty string.
  137. `%t' The top-level directory of the working tree of the
  138. repository, or if `magit-uniquify-buffer-names' is non-nil
  139. an abbreviation of that.
  140. `%x' If `magit-uniquify-buffer-names' is nil \"*\", otherwise the
  141. empty string. Due to limitations of the `uniquify' package,
  142. buffer names must end with the path.
  143. `%T' Obsolete, use \"%t%x\" instead. Like \"%t\", but append an
  144. asterisk if and only if `magit-uniquify-buffer-names' is nil.
  145. The value should always contain \"%m\" or \"%M\", \"%v\" or
  146. \"%V\", and \"%t\" (or the obsolete \"%T\").
  147. If `magit-uniquify-buffer-names' is non-nil, then the value must
  148. end with \"%t\" or \"%t%x\" (or the obsolete \"%T\"). See issue
  149. #2841.
  150. This is used by `magit-generate-buffer-name-default-function'.
  151. If another `magit-generate-buffer-name-function' is used, then
  152. it may not respect this option, or on the contrary it may
  153. support additional %-sequences."
  154. :package-version '(magit . "2.12.0")
  155. :group 'magit-buffers
  156. :type 'string)
  157. (defcustom magit-uniquify-buffer-names t
  158. "Whether to uniquify the names of Magit buffers."
  159. :package-version '(magit . "2.3.0")
  160. :group 'magit-buffers
  161. :type 'boolean)
  162. (defcustom magit-bury-buffer-function 'magit-restore-window-configuration
  163. "The function used to bury or kill the current Magit buffer."
  164. :package-version '(magit . "2.3.0")
  165. :group 'magit-buffers
  166. :type '(radio (function-item quit-window)
  167. (function-item magit-mode-quit-window)
  168. (function-item magit-restore-window-configuration)
  169. (function :tag "Function")))
  170. (defcustom magit-prefix-use-buffer-arguments 'selected
  171. "Whether certain prefix commands reuse arguments active in relevant buffer.
  172. This affects the transient prefix commands `magit-diff',
  173. `magit-log' and `magit-show-refs'.
  174. Valid values are:
  175. `always': Always use the set of arguments that is currently
  176. active in the respective buffer, provided that buffer exists
  177. of course.
  178. `selected' or t: Use the set of arguments from the respective
  179. buffer, but only if it is displayed in a window of the current
  180. frame. This is the default.
  181. `current': Use the set of arguments from the respective buffer,
  182. but only if it is the current buffer.
  183. `never': Never use the set of arguments from the respective
  184. buffer.
  185. For more information see info node `(magit)Transient Arguments
  186. and Buffer Arguments'."
  187. :package-version '(magit . "2.91.0")
  188. :group 'magit-buffers
  189. :group 'magit-commands
  190. :type '(choice (const :tag "always use args from buffer" always)
  191. (const :tag "use args from buffer if it is current" current)
  192. (const :tag "never use args from buffer" never)))
  193. (defcustom magit-direct-use-buffer-arguments 'selected
  194. "Whether certain commands reuse arguments active in relevant buffer.
  195. This affects certain commands such as `magit-show-commit' that
  196. are suffixes of the diff or log transient prefix commands, but
  197. only if they are invoked directly, i.e. *not* as a suffix.
  198. Valid values are:
  199. `always': Always use the set of arguments that is currently
  200. active in the respective buffer, provided that buffer exists
  201. of course.
  202. `selected' or t: Use the set of arguments from the respective
  203. buffer, but only if it is displayed in a window of the current
  204. frame. This is the default.
  205. `current': Use the set of arguments from the respective buffer,
  206. but only if it is the current buffer.
  207. `never': Never use the set of arguments from the respective
  208. buffer.
  209. For more information see info node `(magit)Transient Arguments
  210. and Buffer Arguments'."
  211. :package-version '(magit . "2.91.0")
  212. :group 'magit-buffers
  213. :group 'magit-commands
  214. :type '(choice (const :tag "always use args from buffer" always)
  215. (const :tag "use args from buffer if it is current" current)
  216. (const :tag "never use args from buffer" never)))
  217. (defcustom magit-region-highlight-hook
  218. '(magit-section-update-region magit-diff-update-hunk-region)
  219. "Functions used to highlight the region.
  220. Each function is run with the current section as only argument
  221. until one of them returns non-nil. If all functions return nil,
  222. then fall back to regular region highlighting."
  223. :package-version '(magit . "2.1.0")
  224. :group 'magit-refresh
  225. :type 'hook
  226. :options '(magit-section-update-region magit-diff-update-hunk-region))
  227. (defcustom magit-create-buffer-hook nil
  228. "Normal hook run after creating a new `magit-mode' buffer."
  229. :package-version '(magit . "2.90.0")
  230. :group 'magit-refresh
  231. :type 'hook)
  232. (defcustom magit-refresh-buffer-hook nil
  233. "Normal hook for `magit-refresh-buffer' to run after refreshing."
  234. :package-version '(magit . "2.1.0")
  235. :group 'magit-refresh
  236. :type 'hook)
  237. (defcustom magit-refresh-status-buffer t
  238. "Whether the status buffer is refreshed after running git.
  239. When this is non-nil, then the status buffer is automatically
  240. refreshed after running git for side-effects, in addition to the
  241. current Magit buffer, which is always refreshed automatically.
  242. Only set this to nil after exhausting all other options to
  243. improve performance."
  244. :package-version '(magit . "2.4.0")
  245. :group 'magit-refresh
  246. :group 'magit-status
  247. :type 'boolean)
  248. (defcustom magit-refresh-verbose nil
  249. "Whether to revert Magit buffers verbosely."
  250. :package-version '(magit . "2.1.0")
  251. :group 'magit-refresh
  252. :type 'boolean)
  253. (defcustom magit-save-repository-buffers t
  254. "Whether to save file-visiting buffers when appropriate.
  255. If non-nil, then all modified file-visiting buffers belonging
  256. to the current repository may be saved before running Magit
  257. commands and before creating or refreshing Magit buffers.
  258. If `dontask', then this is done without user intervention, for
  259. any other non-nil value the user has to confirm each save.
  260. The default is t to avoid surprises, but `dontask' is the
  261. recommended value."
  262. :group 'magit-essentials
  263. :group 'magit-buffers
  264. :type '(choice (const :tag "Never" nil)
  265. (const :tag "Ask" t)
  266. (const :tag "Save without asking" dontask)))
  267. (defcustom magit-keep-region-overlay nil
  268. "Whether to keep the region overlay when there is a valid selection.
  269. By default Magit removes the regular region overlay if, and only
  270. if, that region constitutes a valid selection as understood by
  271. Magit commands. Otherwise it does not remove that overlay, and
  272. the region looks like it would in other buffers.
  273. There are two types of such valid selections: hunk-internal
  274. regions and regions that select two or more sibling sections.
  275. In such cases Magit removes the region overlay and instead
  276. highlights a slightly larger range. All text (for hunk-internal
  277. regions) or the headings of all sections (for sibling selections)
  278. that are inside that range (not just inside the region) are acted
  279. on by commands such as the staging command. This buffer range
  280. begins at the beginning of the line on which the region begins
  281. and ends at the end of the line on which the region ends.
  282. Because Magit acts on this larger range and not the region, it is
  283. actually quite important to visualize that larger range. If we
  284. don't do that, then one might think that these commands act on
  285. the region instead. If you want to *also* visualize the region,
  286. then set this option to t. But please note that when the region
  287. does *not* constitute a valid selection, then the region is
  288. *always* visualized as usual, and that it is usually under such
  289. circumstances that you want to use a non-magit command to act on
  290. the region.
  291. Besides keeping the region overlay, setting this option to t also
  292. causes all face properties, except for `:foreground', to be
  293. ignored for the faces used to highlight headings of selected
  294. sections. This avoids the worst conflicts that result from
  295. displaying the region and the selection overlays at the same
  296. time. We are not interested in dealing with other conflicts.
  297. In fact we *already* provide a way to avoid all of these
  298. conflicts: *not* changing the value of this option.
  299. It should be clear by now that we consider it a mistake to set
  300. this to display the region when the Magit selection is also
  301. visualized, but since it has been requested a few times and
  302. because it doesn't cost much to offer this option we do so.
  303. However that might change. If the existence of this option
  304. starts complicating other things, then it will be removed."
  305. :package-version '(magit . "2.3.0")
  306. :group 'magit-miscellaneous
  307. :type 'boolean)
  308. ;;; Key Bindings
  309. (defvar magit-mode-map
  310. (let ((map (make-keymap)))
  311. (suppress-keymap map t)
  312. (cond ((featurep 'jkl)
  313. (define-key map [return] 'magit-visit-thing)
  314. (define-key map [C-return] 'magit-dired-jump)
  315. (define-key map [tab] 'magit-section-toggle)
  316. (define-key map [C-tab] 'magit-section-cycle)
  317. (define-key map [M-tab] 'magit-section-cycle-diffs)
  318. (define-key map [S-tab] 'magit-section-cycle-global)
  319. (define-key map (kbd "M-o") 'magit-section-up)
  320. (define-key map (kbd "i") 'magit-section-backward)
  321. (define-key map (kbd "k") 'magit-section-forward)
  322. (define-key map (kbd "M-i") 'magit-section-backward-sibling)
  323. (define-key map (kbd "M-k") 'magit-section-forward-sibling)
  324. (define-key map (kbd "p") 'magit-push)
  325. (define-key map (kbd ",") 'magit-delete-thing)
  326. (define-key map (kbd ";") 'magit-file-untrack)
  327. (define-key map (kbd "C-c C-i") 'magit-gitignore))
  328. (t
  329. (define-key map [C-return] 'magit-visit-thing)
  330. (define-key map (kbd "C-m") 'magit-visit-thing)
  331. (define-key map (kbd "C-M-i") 'magit-dired-jump)
  332. (define-key map (kbd "C-i") 'magit-section-toggle)
  333. (define-key map [C-tab] 'magit-section-cycle)
  334. (define-key map [M-tab] 'magit-section-cycle-diffs)
  335. ;; [backtab] is the most portable binding for Shift+Tab.
  336. (define-key map [backtab] 'magit-section-cycle-global)
  337. (define-key map (kbd "^") 'magit-section-up)
  338. (define-key map (kbd "p") 'magit-section-backward)
  339. (define-key map (kbd "n") 'magit-section-forward)
  340. (define-key map (kbd "M-p") 'magit-section-backward-sibling)
  341. (define-key map (kbd "M-n") 'magit-section-forward-sibling)
  342. (define-key map (kbd "P") 'magit-push)
  343. (define-key map (kbd "k") 'magit-delete-thing)
  344. (define-key map (kbd "K") 'magit-file-untrack)
  345. (define-key map (kbd "i") 'magit-gitignore)
  346. (define-key map (kbd "I") 'magit-gitignore)))
  347. (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up)
  348. (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down)
  349. (define-key map "+" 'magit-diff-more-context)
  350. (define-key map "-" 'magit-diff-less-context)
  351. (define-key map "0" 'magit-diff-default-context)
  352. (define-key map "1" 'magit-section-show-level-1)
  353. (define-key map "2" 'magit-section-show-level-2)
  354. (define-key map "3" 'magit-section-show-level-3)
  355. (define-key map "4" 'magit-section-show-level-4)
  356. (define-key map (kbd "M-1") 'magit-section-show-level-1-all)
  357. (define-key map (kbd "M-2") 'magit-section-show-level-2-all)
  358. (define-key map (kbd "M-3") 'magit-section-show-level-3-all)
  359. (define-key map (kbd "M-4") 'magit-section-show-level-4-all)
  360. (define-key map "$" 'magit-process-buffer)
  361. (define-key map "%" 'magit-worktree)
  362. (define-key map "a" 'magit-cherry-apply)
  363. (define-key map "A" 'magit-cherry-pick)
  364. (define-key map "b" 'magit-branch)
  365. (define-key map "B" 'magit-bisect)
  366. (define-key map "c" 'magit-commit)
  367. (define-key map "C" 'magit-clone)
  368. (define-key map "d" 'magit-diff)
  369. (define-key map "D" 'magit-diff-refresh)
  370. (define-key map "e" 'magit-ediff-dwim)
  371. (define-key map "E" 'magit-ediff)
  372. (define-key map "f" 'magit-fetch)
  373. (define-key map "F" 'magit-pull)
  374. (define-key map "g" 'magit-refresh)
  375. (define-key map "G" 'magit-refresh-all)
  376. (define-key map "h" 'magit-dispatch)
  377. (define-key map "?" 'magit-dispatch)
  378. (define-key map "l" 'magit-log)
  379. (define-key map "L" 'magit-log-refresh)
  380. (define-key map "m" 'magit-merge)
  381. (define-key map "M" 'magit-remote)
  382. (define-key map "o" 'magit-submodule)
  383. (define-key map "O" 'magit-subtree)
  384. (define-key map "q" 'magit-mode-bury-buffer)
  385. (define-key map "r" 'magit-rebase)
  386. (define-key map "R" 'magit-file-rename)
  387. (define-key map "t" 'magit-tag)
  388. (define-key map "T" 'magit-notes)
  389. (define-key map "s" 'magit-stage-file)
  390. (define-key map "S" 'magit-stage-modified)
  391. (define-key map "u" 'magit-unstage-file)
  392. (define-key map "U" 'magit-unstage-all)
  393. (define-key map "v" 'magit-revert-no-commit)
  394. (define-key map "V" 'magit-revert)
  395. (define-key map "w" 'magit-am)
  396. (define-key map "W" 'magit-patch)
  397. (define-key map "x" 'magit-reset-quickly)
  398. (define-key map "X" 'magit-reset)
  399. (define-key map "y" 'magit-show-refs)
  400. (define-key map "Y" 'magit-cherry)
  401. (define-key map "z" 'magit-stash)
  402. (define-key map "Z" 'magit-stash)
  403. (define-key map ":" 'magit-git-command)
  404. (define-key map "!" 'magit-run)
  405. (define-key map (kbd "C-c C-c") 'magit-dispatch)
  406. (define-key map (kbd "C-c C-e") 'magit-edit-thing)
  407. (define-key map (kbd "C-c C-o") 'magit-browse-thing)
  408. (define-key map (kbd "C-c C-w") 'magit-browse-thing)
  409. (define-key map (kbd "C-x a") 'magit-add-change-log-entry)
  410. (define-key map (kbd "C-x 4 a") 'magit-add-change-log-entry-other-window)
  411. (define-key map (kbd "C-w") 'magit-copy-section-value)
  412. (define-key map (kbd "M-w") 'magit-copy-buffer-revision)
  413. (define-key map [remap previous-line] 'magit-previous-line)
  414. (define-key map [remap next-line] 'magit-next-line)
  415. (define-key map [remap evil-previous-line] 'evil-previous-visual-line)
  416. (define-key map [remap evil-next-line] 'evil-next-visual-line)
  417. map)
  418. "Parent keymap for all keymaps of modes derived from `magit-mode'.")
  419. (defun magit-delete-thing ()
  420. "This is a placeholder command.
  421. Where applicable, section-specific keymaps bind another command
  422. which deletes the thing at point."
  423. (interactive)
  424. (user-error "There is no thing at point that could be deleted"))
  425. (defun magit-visit-thing ()
  426. "This is a placeholder command.
  427. Where applicable, section-specific keymaps bind another command
  428. which visits the thing at point."
  429. (interactive)
  430. (if (eq current-transient-command 'magit-dispatch)
  431. (call-interactively (key-binding (this-command-keys)))
  432. (user-error "There is no thing at point that could be visited")))
  433. (defun magit-edit-thing ()
  434. "This is a placeholder command.
  435. Where applicable, section-specific keymaps bind another command
  436. which lets you edit the thing at point, likely in another buffer."
  437. (interactive)
  438. (if (eq current-transient-command 'magit-dispatch)
  439. (call-interactively (key-binding (this-command-keys)))
  440. (user-error "There is no thing at point that could be edited")))
  441. (defun magit-browse-thing ()
  442. "This is a placeholder command.
  443. Where applicable, section-specific keymaps bind another command
  444. which visits the thing at point using `browse-url'."
  445. (interactive)
  446. (user-error "There is no thing at point that could be browsed"))
  447. (easy-menu-define magit-mode-menu magit-mode-map
  448. "Magit menu"
  449. '("Magit"
  450. ["Refresh" magit-refresh t]
  451. ["Refresh all" magit-refresh-all t]
  452. "---"
  453. ["Stage" magit-stage t]
  454. ["Stage modified" magit-stage-modified t]
  455. ["Unstage" magit-unstage t]
  456. ["Reset index" magit-reset-index t]
  457. ["Commit" magit-commit t]
  458. ["Add log entry" magit-commit-add-log t]
  459. ["Tag" magit-tag-create t]
  460. "---"
  461. ["Diff working tree" magit-diff-working-tree t]
  462. ["Diff" magit-diff t]
  463. ("Log"
  464. ["Log" magit-log-other t]
  465. ["Reflog" magit-reflog-other t]
  466. ["Extended..." magit-log t])
  467. "---"
  468. ["Cherry pick" magit-cherry-pick t]
  469. ["Revert commit" magit-revert t]
  470. "---"
  471. ["Ignore globally" magit-gitignore-globally t]
  472. ["Ignore locally" magit-gitignore-locally t]
  473. ["Discard" magit-discard t]
  474. ["Reset head and index" magit-reset-mixed t]
  475. ["Stash" magit-stash-both t]
  476. ["Snapshot" magit-snapshot-both t]
  477. "---"
  478. ["Branch..." magit-checkout t]
  479. ["Merge" magit-merge t]
  480. ["Ediff resolve" magit-ediff-resolve t]
  481. ["Rebase..." magit-rebase t]
  482. "---"
  483. ["Push" magit-push t]
  484. ["Pull" magit-pull-branch t]
  485. ["Remote update" magit-fetch-all t]
  486. ("Submodule"
  487. ["Submodule update" magit-submodule-update t]
  488. ["Submodule update and init" magit-submodule-setup t]
  489. ["Submodule init" magit-submodule-init t]
  490. ["Submodule sync" magit-submodule-sync t])
  491. "---"
  492. ("Extensions")
  493. "---"
  494. ["Display Git output" magit-process-buffer t]
  495. ["Quit Magit" magit-mode-bury-buffer t]))
  496. ;;; Mode
  497. (defun magit-load-config-extensions ()
  498. "Load Magit extensions that are defined at the Git config layer."
  499. (dolist (ext (magit-get-all "magit.extension"))
  500. (let ((sym (intern (format "magit-%s-mode" ext))))
  501. (when (fboundp sym)
  502. (funcall sym 1)))))
  503. (define-derived-mode magit-mode special-mode "Magit"
  504. "Parent major mode from which Magit major modes inherit.
  505. Magit is documented in info node `(magit)'."
  506. :group 'magit-modes
  507. (buffer-disable-undo)
  508. (setq truncate-lines t)
  509. (setq buffer-read-only t)
  510. (setq-local line-move-visual t) ; see #1771
  511. (setq show-trailing-whitespace nil)
  512. (setq list-buffers-directory (abbreviate-file-name default-directory))
  513. (hack-dir-local-variables-non-file-buffer)
  514. (make-local-variable 'text-property-default-nonsticky)
  515. (push (cons 'keymap t) text-property-default-nonsticky)
  516. (add-hook 'post-command-hook #'magit-section-update-highlight t t)
  517. (add-hook 'deactivate-mark-hook #'magit-section-update-highlight t t)
  518. (setq-local redisplay-highlight-region-function 'magit-highlight-region)
  519. (setq-local redisplay-unhighlight-region-function 'magit-unhighlight-region)
  520. (setq mode-line-process (magit-repository-local-get 'mode-line-process))
  521. (when (bound-and-true-p global-linum-mode)
  522. (linum-mode -1))
  523. (when (and (fboundp 'nlinum-mode)
  524. (bound-and-true-p global-nlinum-mode))
  525. (nlinum-mode -1))
  526. (when (and (fboundp 'display-line-numbers-mode)
  527. (bound-and-true-p global-display-line-numbers-mode))
  528. (display-line-numbers-mode -1))
  529. (add-hook 'kill-buffer-hook 'magit-preserve-section-visibility-cache)
  530. (setq-local bookmark-make-record-function 'magit--make-bookmark))
  531. ;;; Highlighting
  532. (defvar-local magit-region-overlays nil)
  533. (defun magit-delete-region-overlays ()
  534. (mapc #'delete-overlay magit-region-overlays)
  535. (setq magit-region-overlays nil))
  536. (defun magit-highlight-region (start end window rol)
  537. (magit-delete-region-overlays)
  538. (if (and (run-hook-with-args-until-success 'magit-region-highlight-hook
  539. (magit-current-section))
  540. (not magit-keep-region-overlay)
  541. (not (= (line-number-at-pos start)
  542. (line-number-at-pos end)))
  543. ;; (not (eq (car-safe last-command-event) 'mouse-movement))
  544. )
  545. (funcall (default-value 'redisplay-unhighlight-region-function) rol)
  546. (funcall (default-value 'redisplay-highlight-region-function)
  547. start end window rol)))
  548. (defun magit-unhighlight-region (rol)
  549. (setq magit-section-highlighted-section nil)
  550. (magit-delete-region-overlays)
  551. (funcall (default-value 'redisplay-unhighlight-region-function) rol))
  552. ;;; Local Variables
  553. (defvar-local magit-buffer-arguments nil)
  554. (defvar-local magit-buffer-diff-args nil)
  555. (defvar-local magit-buffer-diff-files nil)
  556. (defvar-local magit-buffer-diff-files-suspended nil)
  557. (defvar-local magit-buffer-file-name nil)
  558. (defvar-local magit-buffer-files nil)
  559. (defvar-local magit-buffer-log-args nil)
  560. (defvar-local magit-buffer-log-files nil)
  561. (defvar-local magit-buffer-range nil)
  562. (defvar-local magit-buffer-range-hashed nil)
  563. (defvar-local magit-buffer-refname nil)
  564. (defvar-local magit-buffer-revision nil)
  565. (defvar-local magit-buffer-revision-hash nil)
  566. (defvar-local magit-buffer-revisions nil)
  567. (defvar-local magit-buffer-typearg nil)
  568. (defvar-local magit-buffer-upstream nil)
  569. ;; These variables are also used in file-visiting buffers.
  570. ;; Because the user may change the major-mode, they have
  571. ;; to be permanent buffer-local.
  572. (put 'magit-buffer-file-name 'permanent-local t)
  573. (put 'magit-buffer-refname 'permanent-local t)
  574. (put 'magit-buffer-revision 'permanent-local t)
  575. (put 'magit-buffer-revision-hash 'permanent-local t)
  576. (defvar-local magit-refresh-args nil
  577. "Obsolete. Possibly the arguments used to refresh the current buffer.
  578. Some third-party packages might still use this, but Magit does not.")
  579. (put 'magit-refresh-args 'permanent-local t)
  580. (make-obsolete-variable 'magit-refresh-args nil "Magit 2.91.0")
  581. (defvar magit-buffer-lock-functions nil
  582. "Obsolete buffer-locking support for third-party modes.
  583. Implement the generic function `magit-buffer-value' for
  584. your mode instead of adding an entry to this variable.")
  585. (make-obsolete-variable 'magit-buffer-lock-functions nil "Magit 2.91.0")
  586. (cl-defgeneric magit-buffer-value ()
  587. (when-let ((fn (cdr (assq major-mode magit-buffer-lock-functions))))
  588. (funcall fn (with-no-warnings magit-refresh-args))))
  589. (defvar-local magit-previous-section nil)
  590. (put 'magit-previous-section 'permanent-local t)
  591. ;;; Setup Buffer
  592. (defmacro magit-setup-buffer (mode &optional locked &rest bindings)
  593. (declare (indent 2))
  594. `(magit-setup-buffer-internal
  595. ,mode ,locked
  596. ,(cons 'list (mapcar (pcase-lambda (`(,var ,form))
  597. `(list ',var ,form))
  598. bindings))))
  599. (defun magit-setup-buffer-internal (mode locked bindings)
  600. (let* ((value (and locked
  601. (with-temp-buffer
  602. (pcase-dolist (`(,var ,val) bindings)
  603. (set (make-local-variable var) val))
  604. (let ((major-mode mode))
  605. (magit-buffer-value)))))
  606. (buffer (magit-get-mode-buffer mode value))
  607. (section (and buffer (magit-current-section)))
  608. (created (not buffer)))
  609. (unless buffer
  610. (setq buffer (magit-with-toplevel
  611. (magit-generate-new-buffer mode value))))
  612. (with-current-buffer buffer
  613. (setq magit-previous-section section)
  614. (funcall mode)
  615. (magit-xref-setup 'magit-setup-buffer-internal bindings)
  616. (pcase-dolist (`(,var ,val) bindings)
  617. (set (make-local-variable var) val))
  618. (when created
  619. (magit-status-goto-initial-section)
  620. (run-hooks 'magit-create-buffer-hook)))
  621. (magit-display-buffer buffer)
  622. (with-current-buffer buffer
  623. (run-hooks 'magit-setup-buffer-hook)
  624. (magit-refresh-buffer))
  625. buffer))
  626. (defun magit-mode-setup (mode &rest args)
  627. "Setup up a MODE buffer using ARGS to generate its content."
  628. (declare (obsolete magit-setup-buffer "Magit 2.91.0"))
  629. (with-no-warnings
  630. (magit-mode-setup-internal mode args)))
  631. (defun magit-mode-setup-internal (mode args &optional locked)
  632. "Setup up a MODE buffer using ARGS to generate its content.
  633. When optional LOCKED is non-nil, then create a buffer that is
  634. locked to its value, which is derived from MODE and ARGS."
  635. (declare (obsolete magit-setup-buffer "Magit 2.91.0"))
  636. (let* ((value (and locked
  637. (with-temp-buffer
  638. (with-no-warnings
  639. (setq magit-refresh-args args))
  640. (let ((major-mode mode))
  641. (magit-buffer-value)))))
  642. (buffer (magit-get-mode-buffer mode value))
  643. (section (and buffer (magit-current-section)))
  644. (created (not buffer)))
  645. (unless buffer
  646. (setq buffer (magit-with-toplevel
  647. (magit-generate-new-buffer mode value))))
  648. (with-current-buffer buffer
  649. (setq magit-previous-section section)
  650. (with-no-warnings
  651. (setq magit-refresh-args args))
  652. (funcall mode)
  653. (magit-xref-setup 'magit-mode-setup-internal args)
  654. (when created
  655. (magit-status-goto-initial-section)
  656. (run-hooks 'magit-create-buffer-hook)))
  657. (magit-display-buffer buffer)
  658. (with-current-buffer buffer
  659. (run-hooks 'magit-mode-setup-hook)
  660. (magit-refresh-buffer))))
  661. ;;; Display Buffer
  662. (defvar magit-display-buffer-noselect nil
  663. "If non-nil, then `magit-display-buffer' doesn't call `select-window'.")
  664. (defun magit-display-buffer (buffer &optional display-function)
  665. "Display BUFFER in some window and maybe select it.
  666. If optional DISPLAY-FUNCTION is non-nil, then use that to display
  667. the buffer. Otherwise use `magit-display-buffer-function', which
  668. is the normal case.
  669. Then, unless `magit-display-buffer-noselect' is non-nil, select
  670. the window which was used to display the buffer.
  671. Also run the hooks `magit-pre-display-buffer-hook'
  672. and `magit-post-display-buffer-hook'."
  673. (with-current-buffer buffer
  674. (run-hooks 'magit-pre-display-buffer-hook))
  675. (let ((window (funcall (or display-function magit-display-buffer-function)
  676. buffer)))
  677. (unless magit-display-buffer-noselect
  678. (let* ((old-frame (selected-frame))
  679. (new-frame (window-frame window)))
  680. (select-window window)
  681. (unless (eq old-frame new-frame)
  682. (select-frame-set-input-focus new-frame)))))
  683. (with-current-buffer buffer
  684. (run-hooks 'magit-post-display-buffer-hook)))
  685. (defun magit-display-buffer-traditional (buffer)
  686. "Display BUFFER the way this has traditionally been done."
  687. (display-buffer
  688. buffer (if (and (derived-mode-p 'magit-mode)
  689. (not (memq (with-current-buffer buffer major-mode)
  690. '(magit-process-mode
  691. magit-revision-mode
  692. magit-diff-mode
  693. magit-stash-mode
  694. magit-status-mode))))
  695. '(display-buffer-same-window)
  696. nil))) ; display in another window
  697. (defun magit-display-buffer-same-window-except-diff-v1 (buffer)
  698. "Display BUFFER in the selected window except for some modes.
  699. If a buffer's `major-mode' derives from `magit-diff-mode' or
  700. `magit-process-mode', display it in another window. Display all
  701. other buffers in the selected window."
  702. (display-buffer
  703. buffer (if (with-current-buffer buffer
  704. (derived-mode-p 'magit-diff-mode 'magit-process-mode))
  705. nil ; display in another window
  706. '(display-buffer-same-window))))
  707. (defun magit--display-buffer-fullframe (buffer alist)
  708. (when-let ((window (or (display-buffer-reuse-window buffer alist)
  709. (display-buffer-same-window buffer alist)
  710. (display-buffer-pop-up-window buffer alist)
  711. (display-buffer-use-some-window buffer alist))))
  712. (delete-other-windows window)
  713. window))
  714. (defun magit-display-buffer-fullframe-status-v1 (buffer)
  715. "Display BUFFER, filling entire frame if BUFFER is a status buffer.
  716. Otherwise, behave like `magit-display-buffer-traditional'."
  717. (if (eq (with-current-buffer buffer major-mode)
  718. 'magit-status-mode)
  719. (display-buffer buffer '(magit--display-buffer-fullframe))
  720. (magit-display-buffer-traditional buffer)))
  721. (defun magit--display-buffer-topleft (buffer alist)
  722. (or (display-buffer-reuse-window buffer alist)
  723. (when-let ((window2 (display-buffer-pop-up-window buffer alist)))
  724. (let ((window1 (get-buffer-window))
  725. (buffer1 (current-buffer))
  726. (buffer2 (window-buffer window2))
  727. (w2-quit-restore (window-parameter window2 'quit-restore)))
  728. (set-window-buffer window1 buffer2)
  729. (set-window-buffer window2 buffer1)
  730. (select-window window2)
  731. ;; Swap some window state that `magit-mode-quit-window' and
  732. ;; `quit-restore-window' inspect.
  733. (set-window-prev-buffers window2 (cdr (window-prev-buffers window1)))
  734. (set-window-prev-buffers window1 nil)
  735. (set-window-parameter window2 'magit-dedicated
  736. (window-parameter window1 'magit-dedicated))
  737. (set-window-parameter window1 'magit-dedicated t)
  738. (set-window-parameter window1 'quit-restore
  739. (list 'window 'window
  740. (nth 2 w2-quit-restore)
  741. (nth 3 w2-quit-restore)))
  742. (set-window-parameter window2 'quit-restore nil)
  743. window1))))
  744. (defun magit-display-buffer-fullframe-status-topleft-v1 (buffer)
  745. "Display BUFFER, filling entire frame if BUFFER is a status buffer.
  746. When BUFFER derives from `magit-diff-mode' or
  747. `magit-process-mode', try to display BUFFER to the top or left of
  748. the current buffer rather than to the bottom or right, as
  749. `magit-display-buffer-fullframe-status-v1' would. Whether the
  750. split is made vertically or horizontally is determined by
  751. `split-window-preferred-function'."
  752. (display-buffer
  753. buffer
  754. (cond ((eq (with-current-buffer buffer major-mode)
  755. 'magit-status-mode)
  756. '(magit--display-buffer-fullframe))
  757. ((with-current-buffer buffer
  758. (derived-mode-p 'magit-diff-mode 'magit-process-mode))
  759. '(magit--display-buffer-topleft))
  760. (t
  761. '(display-buffer-same-window)))))
  762. (defun magit--display-buffer-fullcolumn (buffer alist)
  763. (when-let ((window (or (display-buffer-reuse-window buffer alist)
  764. (display-buffer-same-window buffer alist)
  765. (display-buffer-below-selected buffer alist))))
  766. (delete-other-windows-vertically window)
  767. window))
  768. (defun magit-display-buffer-fullcolumn-most-v1 (buffer)
  769. "Display BUFFER using the full column except in some cases.
  770. For most cases where BUFFER's `major-mode' derives from
  771. `magit-mode', display it in the selected window and grow that
  772. window to the full height of the frame, deleting other windows in
  773. that column as necessary. However, display BUFFER in another
  774. window if 1) BUFFER's mode derives from `magit-process-mode', or
  775. 2) BUFFER's mode derives from `magit-diff-mode', provided that
  776. the mode of the current buffer derives from `magit-log-mode' or
  777. `magit-cherry-mode'."
  778. (display-buffer
  779. buffer
  780. (cond ((and (or git-commit-mode
  781. (derived-mode-p 'magit-log-mode
  782. 'magit-cherry-mode
  783. 'magit-reflog-mode))
  784. (with-current-buffer buffer
  785. (derived-mode-p 'magit-diff-mode)))
  786. nil)
  787. ((with-current-buffer buffer
  788. (derived-mode-p 'magit-process-mode))
  789. nil)
  790. (t
  791. '(magit--display-buffer-fullcolumn)))))
  792. (defun magit-maybe-set-dedicated ()
  793. "Mark the selected window as dedicated if appropriate.
  794. If a new window was created to display the buffer, then remember
  795. that fact. That information is used by `magit-mode-quit-window',
  796. to determine whether the window should be deleted when its last
  797. Magit buffer is buried."
  798. (let ((window (get-buffer-window (current-buffer))))
  799. (when (and (window-live-p window)
  800. (not (window-prev-buffers window)))
  801. (set-window-parameter window 'magit-dedicated t))))
  802. ;;; Get Buffer
  803. (defvar-local magit--default-directory nil
  804. "Value of `default-directory' when buffer is generated.
  805. This exists to prevent a let-bound `default-directory' from
  806. tricking `magit-get-mode-buffer' or `magit-mode-get-buffers'
  807. into thinking a buffer belongs to a repo that it doesn't.")
  808. (put 'magit--default-directory 'permanent-local t)
  809. (defun magit-mode-get-buffers ()
  810. (let ((topdir (magit-toplevel)))
  811. (--filter (with-current-buffer it
  812. (and (derived-mode-p 'magit-mode)
  813. (equal magit--default-directory topdir)))
  814. (buffer-list))))
  815. (defvar-local magit-buffer-locked-p nil)
  816. (put 'magit-buffer-locked-p 'permanent-local t)
  817. (defun magit-get-mode-buffer (mode &optional value frame)
  818. "Return buffer belonging to the current repository whose major-mode is MODE.
  819. If no such buffer exists then return nil. Multiple buffers with
  820. the same major-mode may exist for a repository but only one can
  821. exist that hasn't been looked to its value. Return that buffer
  822. \(or nil if there is no such buffer) unless VALUE is non-nil, in
  823. which case return the buffer that has been looked to that value.
  824. If FRAME nil or omitted, then consider all buffers. Otherwise
  825. only consider buffers that are displayed in some live window
  826. on some frame.
  827. If `all', then consider all buffers on all frames.
  828. If `visible', then only consider buffers on all visible frames.
  829. If `selected' or t, then only consider buffers on the selected
  830. frame.
  831. If a frame, then only consider buffers on that frame."
  832. (if-let ((topdir (magit-toplevel)))
  833. (cl-flet* ((b (buffer)
  834. (with-current-buffer buffer
  835. (and (eq major-mode mode)
  836. (equal magit--default-directory topdir)
  837. (if value
  838. (and magit-buffer-locked-p
  839. (equal (magit-buffer-value) value))
  840. (not magit-buffer-locked-p))
  841. buffer)))
  842. (w (window)
  843. (b (window-buffer window)))
  844. (f (frame)
  845. (-some #'w (window-list frame 'no-minibuf))))
  846. (pcase-exhaustive frame
  847. (`nil (-some #'b (buffer-list)))
  848. (`all (-some #'f (frame-list)))
  849. (`visible (-some #'f (visible-frame-list)))
  850. ((or `selected `t) (-some #'w (window-list (selected-frame))))
  851. ((guard (framep frame)) (-some #'w (window-list frame)))))
  852. (magit--not-inside-repository-error)))
  853. (defun magit-mode-get-buffer (mode &optional create frame value)
  854. (declare (obsolete magit-get-mode-buffer "Magit 2.91.0"))
  855. (when create
  856. (error "`magit-mode-get-buffer's CREATE argument is obsolete"))
  857. (if-let ((topdir (magit-toplevel)))
  858. (--first (with-current-buffer it
  859. (and (eq major-mode mode)
  860. (equal magit--default-directory topdir)
  861. (if value
  862. (and magit-buffer-locked-p
  863. (equal (magit-buffer-value) value))
  864. (not magit-buffer-locked-p))))
  865. (if frame
  866. (mapcar #'window-buffer
  867. (window-list (unless (eq frame t) frame)))
  868. (buffer-list)))
  869. (magit--not-inside-repository-error)))
  870. (defun magit-generate-new-buffer (mode &optional value)
  871. (let* ((name (funcall magit-generate-buffer-name-function mode value))
  872. (buffer (generate-new-buffer name)))
  873. (with-current-buffer buffer
  874. (setq magit--default-directory default-directory)
  875. (setq magit-buffer-locked-p (and value t))
  876. (magit-restore-section-visibility-cache mode))
  877. (when magit-uniquify-buffer-names
  878. (add-to-list 'uniquify-list-buffers-directory-modes mode)
  879. (with-current-buffer buffer
  880. (setq list-buffers-directory (abbreviate-file-name default-directory)))
  881. (let ((uniquify-buffer-name-style
  882. (if (memq uniquify-buffer-name-style '(nil forward))
  883. 'post-forward-angle-brackets
  884. uniquify-buffer-name-style)))
  885. (uniquify-rationalize-file-buffer-names
  886. name (file-name-directory (directory-file-name default-directory))
  887. buffer)))
  888. buffer))
  889. (defun magit-generate-buffer-name-default-function (mode &optional value)
  890. "Generate buffer name for a MODE buffer in the current repository.
  891. The returned name is based on `magit-buffer-name-format' and
  892. takes `magit-uniquify-buffer-names' and VALUE, if non-nil, into
  893. account."
  894. (let ((m (substring (symbol-name mode) 0 -5))
  895. (v (and value (format "%s" (if (listp value) value (list value)))))
  896. (n (if magit-uniquify-buffer-names
  897. (file-name-nondirectory
  898. (directory-file-name default-directory))
  899. (abbreviate-file-name default-directory))))
  900. (format-spec
  901. magit-buffer-name-format
  902. `((?m . ,m)
  903. (?M . ,(if (eq mode 'magit-status-mode) "magit" m))
  904. (?v . ,(or v ""))
  905. (?V . ,(if v (concat " " v) ""))
  906. (?t . ,n)
  907. (?x . ,(if magit-uniquify-buffer-names "" "*"))
  908. (?T . ,(if magit-uniquify-buffer-names n (concat n "*")))))))
  909. ;;; Buffer Lock
  910. (defun magit-toggle-buffer-lock ()
  911. "Lock the current buffer to its value or unlock it.
  912. Locking a buffer to its value prevents it from being reused to
  913. display another value. The name of a locked buffer contains its
  914. value, which allows telling it apart from other locked buffers
  915. and the unlocked buffer.
  916. Not all Magit buffers can be locked to their values, for example
  917. it wouldn't make sense to lock a status buffer.
  918. There can only be a single unlocked buffer using a certain
  919. major-mode per repository. So when a buffer is being unlocked
  920. and another unlocked buffer already exists for that mode and
  921. repository, then the former buffer is instead deleted and the
  922. latter is displayed in its place."
  923. (interactive)
  924. (if magit-buffer-locked-p
  925. (if-let ((unlocked (magit-get-mode-buffer major-mode)))
  926. (let ((locked (current-buffer)))
  927. (switch-to-buffer unlocked nil t)
  928. (kill-buffer locked))
  929. (setq magit-buffer-locked-p nil)
  930. (rename-buffer (funcall magit-generate-buffer-name-function
  931. major-mode)))
  932. (if-let ((value (magit-buffer-value)))
  933. (if-let ((locked (magit-get-mode-buffer major-mode value)))
  934. (let ((unlocked (current-buffer)))
  935. (switch-to-buffer locked nil t)
  936. (kill-buffer unlocked))
  937. (setq magit-buffer-locked-p t)
  938. (rename-buffer (funcall magit-generate-buffer-name-function
  939. major-mode value)))
  940. (user-error "Buffer has no value it could be locked to"))))
  941. ;;; Bury Buffer
  942. (defun magit-mode-bury-buffer (&optional kill-buffer)
  943. "Bury the current buffer.
  944. With a prefix argument, kill the buffer instead.
  945. With two prefix arguments, also kill all Magit buffers associated
  946. with this repository.
  947. This is done using `magit-bury-buffer-function'."
  948. (interactive "P")
  949. ;; Kill all associated Magit buffers when a double prefix arg is given.
  950. (when (>= (prefix-numeric-value kill-buffer) 16)
  951. (let ((current (current-buffer)))
  952. (dolist (buf (magit-mode-get-buffers))
  953. (unless (eq buf current)
  954. (kill-buffer buf)))))
  955. (funcall magit-bury-buffer-function kill-buffer))
  956. (defun magit-mode-quit-window (kill-buffer)
  957. "Quit the selected window and bury its buffer.
  958. This behaves similar to `quit-window', but when the window
  959. was originally created to display a Magit buffer and the
  960. current buffer is the last remaining Magit buffer that was
  961. ever displayed in the selected window, then delete that
  962. window."
  963. (if (or (one-window-p)
  964. (--first (let ((buffer (car it)))
  965. (and (not (eq buffer (current-buffer)))
  966. (buffer-live-p buffer)
  967. (or (not (window-parameter nil 'magit-dedicated))
  968. (with-current-buffer buffer
  969. (derived-mode-p 'magit-mode
  970. 'magit-process-mode)))))
  971. (window-prev-buffers)))
  972. (quit-window kill-buffer)
  973. (let ((window (selected-window)))
  974. (quit-window kill-buffer)
  975. (when (window-live-p window)
  976. (delete-window window)))))
  977. ;;; Refresh Buffers
  978. (defvar inhibit-magit-refresh nil)
  979. (defun magit-refresh ()
  980. "Refresh some buffers belonging to the current repository.
  981. Refresh the current buffer if its major mode derives from
  982. `magit-mode', and refresh the corresponding status buffer.
  983. Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
  984. (interactive)
  985. (unless inhibit-magit-refresh
  986. (unwind-protect
  987. (let ((start (current-time))
  988. (magit--refresh-cache (or magit--refresh-cache
  989. (list (cons 0 0)))))
  990. (when magit-refresh-verbose
  991. (message "Refreshing magit..."))
  992. (magit-run-hook-with-benchmark 'magit-pre-refresh-hook)
  993. (cond ((derived-mode-p 'magit-mode)
  994. (magit-refresh-buffer))
  995. ((derived-mode-p 'tabulated-list-mode)
  996. (revert-buffer)))
  997. (--when-let (and magit-refresh-status-buffer
  998. (not (derived-mode-p 'magit-status-mode))
  999. (magit-get-mode-buffer 'magit-status-mode))
  1000. (with-current-buffer it
  1001. (magit-refresh-buffer)))
  1002. (magit-auto-revert-buffers)
  1003. (cond
  1004. ((and (not this-command)
  1005. (memq last-command magit-post-commit-hook-commands))
  1006. (magit-run-hook-with-benchmark 'magit-post-commit-hook))
  1007. ((memq this-command magit-post-stage-hook-commands)
  1008. (magit-run-hook-with-benchmark 'magit-post-stage-hook))
  1009. ((memq this-command magit-post-unstage-hook-commands)
  1010. (magit-run-hook-with-benchmark 'magit-post-unstage-hook)))
  1011. (magit-run-hook-with-benchmark 'magit-post-refresh-hook)
  1012. (when magit-refresh-verbose
  1013. (message "Refreshing magit...done (%.3fs, cached %s/%s)"
  1014. (float-time (time-subtract (current-time) start))
  1015. (caar magit--refresh-cache)
  1016. (+ (caar magit--refresh-cache)
  1017. (cdar magit--refresh-cache)))))
  1018. (run-hooks 'magit-unwind-refresh-hook))))
  1019. (defun magit-refresh-all ()
  1020. "Refresh all buffers belonging to the current repository.
  1021. Refresh all Magit buffers belonging to the current repository,
  1022. and revert buffers that visit files located inside the current
  1023. repository.
  1024. Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
  1025. (interactive)
  1026. (magit-run-hook-with-benchmark 'magit-pre-refresh-hook)
  1027. (dolist (buffer (magit-mode-get-buffers))
  1028. (with-current-buffer buffer (magit-refresh-buffer)))
  1029. (magit-auto-revert-buffers)
  1030. (magit-run-hook-with-benchmark 'magit-post-refresh-hook))
  1031. (defvar-local magit-refresh-start-time nil)
  1032. (defun magit-refresh-buffer ()
  1033. "Refresh the current Magit buffer."
  1034. (setq magit-refresh-start-time (current-time))
  1035. (let ((refresh (intern (format "%s-refresh-buffer"
  1036. (substring (symbol-name major-mode) 0 -5))))
  1037. (magit--refresh-cache (or magit--refresh-cache (list (cons 0 0)))))
  1038. (when (functionp refresh)
  1039. (when magit-refresh-verbose
  1040. (message "Refreshing buffer `%s'..." (buffer-name)))
  1041. (let* ((buffer (current-buffer))
  1042. (windows
  1043. (--mapcat (with-selected-window it
  1044. (with-current-buffer buffer
  1045. (when-let ((section (magit-current-section)))
  1046. (list
  1047. (nconc (list it section)
  1048. (magit-refresh-get-relative-position))))))
  1049. (or (get-buffer-window-list buffer nil t)
  1050. (list (selected-window))))))
  1051. (deactivate-mark)
  1052. (setq magit-section-highlight-overlays nil)
  1053. (setq magit-section-highlighted-section nil)
  1054. (setq magit-section-highlighted-sections nil)
  1055. (setq magit-section-unhighlight-sections nil)
  1056. (magit-process-unset-mode-line-error-status)
  1057. (let ((inhibit-read-only t))
  1058. (erase-buffer)
  1059. (save-excursion
  1060. (apply refresh (with-no-warnings magit-refresh-args))))
  1061. (dolist (window windows)
  1062. (with-selected-window (car window)
  1063. (with-current-buffer buffer
  1064. (apply #'magit-section-goto-successor (cdr window)))))
  1065. (run-hooks 'magit-refresh-buffer-hook)
  1066. (magit-section-update-highlight)
  1067. (set-buffer-modified-p nil))
  1068. (when magit-refresh-verbose
  1069. (message "Refreshing buffer `%s'...done (%.3fs)" (buffer-name)
  1070. (float-time (time-subtract (current-time)
  1071. magit-refresh-start-time)))))))
  1072. (defun magit-refresh-get-relative-position ()
  1073. (when-let ((section (magit-current-section)))
  1074. (let ((start (oref section start)))
  1075. (list (count-lines start (point))
  1076. (- (point) (line-beginning-position))
  1077. (and (magit-hunk-section-p section)
  1078. (region-active-p)
  1079. (progn (goto-char (line-beginning-position))
  1080. (when (looking-at "^[-+]") (forward-line))
  1081. (while (looking-at "^[ @]") (forward-line))
  1082. (let ((beg (point)))
  1083. (cond ((looking-at "^[-+]")
  1084. (forward-line)
  1085. (while (looking-at "^[-+]") (forward-line))
  1086. (while (looking-at "^ ") (forward-line))
  1087. (forward-line -1)
  1088. (regexp-quote (buffer-substring-no-properties
  1089. beg (line-end-position))))
  1090. (t t)))))))))
  1091. ;;; Save File-Visiting Buffers
  1092. (defvar disable-magit-save-buffers nil)
  1093. (defun magit-pre-command-hook ()
  1094. (setq disable-magit-save-buffers nil))
  1095. (add-hook 'pre-command-hook #'magit-pre-command-hook)
  1096. (defvar magit-after-save-refresh-buffers nil)
  1097. (defun magit-after-save-refresh-buffers ()
  1098. (dolist (buffer magit-after-save-refresh-buffers)
  1099. (when (buffer-live-p buffer)
  1100. (with-current-buffer buffer
  1101. (magit-refresh-buffer))))
  1102. (setq magit-after-save-refresh-buffers nil)
  1103. (remove-hook 'post-command-hook 'magit-after-save-refresh-buffers))
  1104. (defun magit-after-save-refresh-status ()
  1105. "Refresh the status buffer of the current repository.
  1106. This function is intended to be added to `after-save-hook'.
  1107. If the status buffer does not exist or the file being visited in
  1108. the current buffer isn't inside the working tree of a repository,
  1109. then do nothing.
  1110. Note that refreshing a Magit buffer is done by re-creating its
  1111. contents from scratch, which can be slow in large repositories.
  1112. If you are not satisfied with Magit's performance, then you
  1113. should obviously not add this function to that hook."
  1114. (when (and (not disable-magit-save-buffers)
  1115. (magit-inside-worktree-p t))
  1116. (--when-let (ignore-errors (magit-get-mode-buffer 'magit-status-mode))
  1117. (add-to-list 'magit-after-save-refresh-buffers it)
  1118. (add-hook 'post-command-hook 'magit-after-save-refresh-buffers))))
  1119. (defun magit-maybe-save-repository-buffers ()
  1120. "Maybe save file-visiting buffers belonging to the current repository.
  1121. Do so if `magit-save-repository-buffers' is non-nil. You should
  1122. not remove this from any hooks, instead set that variable to nil
  1123. if you so desire."
  1124. (when (and magit-save-repository-buffers
  1125. (not disable-magit-save-buffers))
  1126. (setq disable-magit-save-buffers t)
  1127. (let ((msg (current-message)))
  1128. (magit-save-repository-buffers
  1129. (eq magit-save-repository-buffers 'dontask))
  1130. (when (and msg
  1131. (current-message)
  1132. (not (equal msg (current-message))))
  1133. (message "%s" msg)))))
  1134. (add-hook 'magit-pre-refresh-hook #'magit-maybe-save-repository-buffers)
  1135. (add-hook 'magit-pre-call-git-hook #'magit-maybe-save-repository-buffers)
  1136. (add-hook 'magit-pre-start-git-hook #'magit-maybe-save-repository-buffers)
  1137. (defvar-local magit-inhibit-refresh-save nil)
  1138. (defun magit-save-repository-buffers (&optional arg)
  1139. "Save file-visiting buffers belonging to the current repository.
  1140. After any buffer where `buffer-save-without-query' is non-nil
  1141. is saved without asking, the user is asked about each modified
  1142. buffer which visits a file in the current repository. Optional
  1143. argument (the prefix) non-nil means save all with no questions."
  1144. (interactive "P")
  1145. (when-let ((topdir (magit-rev-parse-safe "--show-toplevel")))
  1146. (let ((remote (file-remote-p topdir))
  1147. (save-some-buffers-action-alist
  1148. `((?Y (lambda (buffer)
  1149. (with-current-buffer buffer
  1150. (setq buffer-save-without-query t)
  1151. (save-buffer)))
  1152. "to save the current buffer and remember choice")
  1153. (?N (lambda (buffer)
  1154. (with-current-buffer buffer
  1155. (setq magit-inhibit-refresh-save t)))
  1156. "to skip the current buffer and remember choice")
  1157. ,@save-some-buffers-action-alist)))
  1158. (save-some-buffers
  1159. arg (lambda ()
  1160. (and (not magit-inhibit-refresh-save)
  1161. buffer-file-name
  1162. (file-exists-p (file-name-directory buffer-file-name))
  1163. ;; Avoid needlessly connecting to unrelated remotes.
  1164. (equal (file-remote-p buffer-file-name)
  1165. remote)
  1166. (string-prefix-p topdir (file-truename buffer-file-name))
  1167. (equal (magit-rev-parse-safe "--show-toplevel")
  1168. topdir)))))))
  1169. ;;; Restore Window Configuration
  1170. (defvar magit-inhibit-save-previous-winconf nil)
  1171. (defvar-local magit-previous-window-configuration nil)
  1172. (put 'magit-previous-window-configuration 'permanent-local t)
  1173. (defun magit-save-window-configuration ()
  1174. "Save the current window configuration.
  1175. Later, when the buffer is buried, it may be restored by
  1176. `magit-restore-window-configuration'."
  1177. (if magit-inhibit-save-previous-winconf
  1178. (when (eq magit-inhibit-save-previous-winconf 'unset)
  1179. (setq magit-previous-window-configuration nil))
  1180. (unless (get-buffer-window (current-buffer) (selected-frame))
  1181. (setq magit-previous-window-configuration
  1182. (current-window-configuration)))))
  1183. (defun magit-restore-window-configuration (&optional kill-buffer)
  1184. "Bury or kill the current buffer and restore previous window configuration."
  1185. (let ((winconf magit-previous-window-configuration)
  1186. (buffer (current-buffer))
  1187. (frame (selected-frame)))
  1188. (quit-window kill-buffer (selected-window))
  1189. (when (and winconf (equal frame (window-configuration-frame winconf)))
  1190. (set-window-configuration winconf)
  1191. (when (buffer-live-p buffer)
  1192. (with-current-buffer buffer
  1193. (setq magit-previous-window-configuration nil))))))
  1194. ;;; Buffer History
  1195. (defun magit-go-backward ()
  1196. "Move backward in current buffer's history."
  1197. (interactive)
  1198. (if help-xref-stack
  1199. (help-xref-go-back (current-buffer))
  1200. (user-error "No previous entry in buffer's history")))
  1201. (defun magit-go-forward ()
  1202. "Move forward in current buffer's history."
  1203. (interactive)
  1204. (if help-xref-forward-stack
  1205. (help-xref-go-forward (current-buffer))
  1206. (user-error "No next entry in buffer's history")))
  1207. (defun magit-insert-xref-buttons ()
  1208. "Insert xref buttons."
  1209. (when (or help-xref-stack help-xref-forward-stack)
  1210. (when help-xref-stack
  1211. (magit-xref-insert-button help-back-label 'magit-xref-backward))
  1212. (when help-xref-forward-stack
  1213. (when help-xref-stack
  1214. (insert " "))
  1215. (magit-xref-insert-button help-forward-label 'magit-xref-forward))))
  1216. (defun magit-xref-insert-button (label type)
  1217. (magit-insert-section (button label)
  1218. (insert-text-button label 'type type
  1219. 'help-args (list (current-buffer)))))
  1220. (define-button-type 'magit-xref-backward
  1221. :supertype 'help-back
  1222. 'mouse-face 'magit-section-highlight
  1223. 'help-echo (purecopy "mouse-2, RET: go back to previous history entry"))
  1224. (define-button-type 'magit-xref-forward
  1225. :supertype 'help-forward
  1226. 'mouse-face 'magit-section-highlight
  1227. 'help-echo (purecopy "mouse-2, RET: go back to next history entry"))
  1228. (defvar magit-xref-modes
  1229. '(magit-log-mode
  1230. magit-reflog-mode
  1231. magit-diff-mode
  1232. magit-revision-mode)
  1233. "List of modes for which to insert navigation buttons.")
  1234. (defun magit-xref-setup (fn args)
  1235. (when (memq major-mode magit-xref-modes)
  1236. (when help-xref-stack-item
  1237. (push (cons (point) help-xref-stack-item) help-xref-stack)
  1238. (setq help-xref-forward-stack nil))
  1239. (when (called-interactively-p 'interactive)
  1240. (--when-let (nthcdr 10 help-xref-stack)
  1241. (setcdr it nil)))
  1242. (setq help-xref-stack-item
  1243. (list 'magit-xref-restore fn default-directory args))))
  1244. (defun magit-xref-restore (fn dir args)
  1245. (setq default-directory dir)
  1246. (funcall fn major-mode nil args)
  1247. (magit-refresh-buffer))
  1248. ;;; Repository-Local Cache
  1249. (defvar magit-repository-local-cache nil
  1250. "Alist mapping `magit-toplevel' paths to alists of key/value pairs.")
  1251. (defun magit-repository-local-repository ()
  1252. "Return the key for the current repository."
  1253. (or (bound-and-true-p magit--default-directory)
  1254. (magit-toplevel)))
  1255. (defun magit-repository-local-set (key value &optional repository)
  1256. "Set the repository-local VALUE for KEY.
  1257. Unless specified, REPOSITORY is the current buffer's repository.
  1258. If REPOSITORY is nil (meaning there is no current repository),
  1259. then the value is not cached, and we return nil."
  1260. (let* ((repokey (or repository (magit-repository-local-repository)))
  1261. (cache (assoc repokey magit-repository-local-cache)))
  1262. ;; Don't cache values for a nil REPOSITORY, as the 'set' and 'get'
  1263. ;; calls for some KEY may happen in unrelated contexts.
  1264. (when repokey
  1265. (if cache
  1266. (let ((keyvalue (assoc key (cdr cache))))
  1267. (if keyvalue
  1268. ;; Update pre-existing value for key.
  1269. (setcdr keyvalue value)
  1270. ;; No such key in repository-local cache.
  1271. (push (cons key value) (cdr cache))))
  1272. ;; No cache for this repository.
  1273. (push (cons repokey (list (cons key value)))
  1274. magit-repository-local-cache)))))
  1275. (defun magit-repository-local-exists-p (key &optional repository)
  1276. "Non-nil when a repository-local value exists for KEY.
  1277. Returns a (KEY . value) cons cell.
  1278. The KEY is matched using `equal'.
  1279. Unless specified, REPOSITORY is the current buffer's repository."
  1280. (let* ((repokey (or repository (magit-repository-local-repository)))
  1281. (cache (assoc repokey magit-repository-local-cache)))
  1282. (and cache
  1283. (assoc key (cdr cache)))))
  1284. (defun magit-repository-local-get (key &optional default repository)
  1285. "Return the repository-local value for KEY.
  1286. Return DEFAULT if no value for KEY exists.
  1287. The KEY is matched using `equal'.
  1288. Unless specified, REPOSITORY is the current buffer's repository."
  1289. (let ((keyvalue (magit-repository-local-exists-p key repository)))
  1290. (if keyvalue
  1291. (cdr keyvalue)
  1292. default)))
  1293. (defun magit-repository-local-delete (key &optional repository)
  1294. "Delete the repository-local value for KEY.
  1295. Unless specified, REPOSITORY is the current buffer's repository."
  1296. (let* ((repokey (or repository (magit-repository-local-repository)))
  1297. (cache (assoc repokey magit-repository-local-cache)))
  1298. (when cache
  1299. ;; There is no `assoc-delete-all'.
  1300. (setf (cdr cache)
  1301. (cl-delete key (cdr cache) :key #'car :test #'equal)))))
  1302. (defun magit-zap-caches ()
  1303. "Zap caches for the current repository.
  1304. Remove the repository's entry from `magit-repository-local-cache'
  1305. and set `magit-section-visibility-cache' to nil in all of the
  1306. repository's Magit buffers."
  1307. (interactive)
  1308. (magit-with-toplevel
  1309. (setq magit-repository-local-cache
  1310. (cl-delete default-directory
  1311. magit-repository-local-cache
  1312. :key #'car :test #'equal)))
  1313. (dolist (buffer (magit-mode-get-buffers))
  1314. (with-current-buffer buffer
  1315. (setq magit-section-visibility-cache nil)))
  1316. (setq magit--libgit-available-p eieio-unbound))
  1317. ;;; Utilities
  1318. (defun magit-run-hook-with-benchmark (hook)
  1319. (when hook
  1320. (if magit-refresh-verbose
  1321. (let ((start (current-time)))
  1322. (message "Running %s..." hook)
  1323. (run-hooks hook)
  1324. (message "Running %s...done (%.3fs)" hook
  1325. (float-time (time-subtract (current-time) start))))
  1326. (run-hooks hook))))
  1327. ;;; _
  1328. (provide 'magit-mode)
  1329. ;;; magit-mode.el ends here