added typscript and completion, git and dumbgo
This commit is contained in:
@@ -131,7 +131,7 @@
|
|||||||
("John Wiegley" . "jwiegley@gmail.com"))
|
("John Wiegley" . "jwiegley@gmail.com"))
|
||||||
(:keywords "async"))])
|
(:keywords "async"))])
|
||||||
(auctex .
|
(auctex .
|
||||||
[(12 1 2)
|
[(12 2 0)
|
||||||
((emacs
|
((emacs
|
||||||
(24 1))
|
(24 1))
|
||||||
(cl-lib
|
(cl-lib
|
||||||
@@ -1992,7 +1992,7 @@
|
|||||||
("Oleh Krehel" . "ohwoeowho@gmail.com"))
|
("Oleh Krehel" . "ohwoeowho@gmail.com"))
|
||||||
(:keywords "convenience"))])
|
(:keywords "convenience"))])
|
||||||
(tramp .
|
(tramp .
|
||||||
[(2 4 2 3)
|
[(2 4 2 4)
|
||||||
((emacs
|
((emacs
|
||||||
(24 4)))
|
(24 4)))
|
||||||
"Transparent Remote Access, Multiple Protocol" tar
|
"Transparent Remote Access, Multiple Protocol" tar
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2019-10-27T10:10:02+0100 using RSA
|
Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2019-11-02T10:10:05+0100 using RSA
|
||||||
File diff suppressed because it is too large
Load Diff
50
elpa/company-20191029.2116/company-abbrev.el
Normal file
50
elpa/company-20191029.2116/company-abbrev.el
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
;;; company-abbrev.el --- company-mode completion backend for abbrev
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
(require 'abbrev)
|
||||||
|
|
||||||
|
(defun company-abbrev-insert (match)
|
||||||
|
"Replace MATCH with the expanded abbrev."
|
||||||
|
(expand-abbrev))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-abbrev (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for abbrev."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-abbrev
|
||||||
|
'company-abbrev-insert))
|
||||||
|
(prefix (company-grab-symbol))
|
||||||
|
(candidates (nconc
|
||||||
|
(delete "" (all-completions arg global-abbrev-table))
|
||||||
|
(delete "" (all-completions arg local-abbrev-table))))
|
||||||
|
(meta (abbrev-expansion arg))))
|
||||||
|
|
||||||
|
(provide 'company-abbrev)
|
||||||
|
;;; company-abbrev.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-abbrev.elc
Normal file
BIN
elpa/company-20191029.2116/company-abbrev.elc
Normal file
Binary file not shown.
383
elpa/company-20191029.2116/company-autoloads.el
Normal file
383
elpa/company-20191029.2116/company-autoloads.el
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
;;; company-autoloads.el --- automatically extracted autoloads
|
||||||
|
;;
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(add-to-list 'load-path (directory-file-name
|
||||||
|
(or (file-name-directory #$) (car load-path))))
|
||||||
|
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company" "company.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company.el
|
||||||
|
|
||||||
|
(autoload 'company-mode "company" "\
|
||||||
|
\"complete anything\"; is an in-buffer completion framework.
|
||||||
|
Completion starts automatically, depending on the values
|
||||||
|
`company-idle-delay' and `company-minimum-prefix-length'.
|
||||||
|
|
||||||
|
Completion can be controlled with the commands:
|
||||||
|
`company-complete-common', `company-complete-selection', `company-complete',
|
||||||
|
`company-select-next', `company-select-previous'. If these commands are
|
||||||
|
called before `company-idle-delay', completion will also start.
|
||||||
|
|
||||||
|
Completions can be searched with `company-search-candidates' or
|
||||||
|
`company-filter-candidates'. These can be used while completion is
|
||||||
|
inactive, as well.
|
||||||
|
|
||||||
|
The completion data is retrieved using `company-backends' and displayed
|
||||||
|
using `company-frontends'. If you want to start a specific backend, call
|
||||||
|
it interactively or use `company-begin-backend'.
|
||||||
|
|
||||||
|
By default, the completions list is sorted alphabetically, unless the
|
||||||
|
backend chooses otherwise, or `company-transformers' changes it later.
|
||||||
|
|
||||||
|
regular keymap (`company-mode-map'):
|
||||||
|
|
||||||
|
\\{company-mode-map}
|
||||||
|
keymap during active completions (`company-active-map'):
|
||||||
|
|
||||||
|
\\{company-active-map}
|
||||||
|
|
||||||
|
\(fn &optional ARG)" t nil)
|
||||||
|
|
||||||
|
(defvar global-company-mode nil "\
|
||||||
|
Non-nil if Global Company mode is enabled.
|
||||||
|
See the `global-company-mode' command
|
||||||
|
for a description of this minor mode.
|
||||||
|
Setting this variable directly does not take effect;
|
||||||
|
either customize it (see the info node `Easy Customization')
|
||||||
|
or call the function `global-company-mode'.")
|
||||||
|
|
||||||
|
(custom-autoload 'global-company-mode "company" nil)
|
||||||
|
|
||||||
|
(autoload 'global-company-mode "company" "\
|
||||||
|
Toggle Company mode in all buffers.
|
||||||
|
With prefix ARG, enable Global Company mode if ARG is positive;
|
||||||
|
otherwise, disable it. If called from Lisp, enable the mode if
|
||||||
|
ARG is omitted or nil.
|
||||||
|
|
||||||
|
Company mode is enabled in all buffers where
|
||||||
|
`company-mode-on' would do it.
|
||||||
|
See `company-mode' for more information on Company mode.
|
||||||
|
|
||||||
|
\(fn &optional ARG)" t nil)
|
||||||
|
|
||||||
|
(autoload 'company-manual-begin "company" "\
|
||||||
|
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(autoload 'company-complete "company" "\
|
||||||
|
Insert the common part of all candidates or the current selection.
|
||||||
|
The first time this is called, the common part is inserted, the second
|
||||||
|
time, or when the selection has been changed, the selected candidate is
|
||||||
|
inserted.
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company" '("company-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-abbrev" "company-abbrev.el" (0 0 0
|
||||||
|
;;;;;; 0))
|
||||||
|
;;; Generated autoloads from company-abbrev.el
|
||||||
|
|
||||||
|
(autoload 'company-abbrev "company-abbrev" "\
|
||||||
|
`company-mode' completion backend for abbrev.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-abbrev" '("company-abbrev-insert")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-bbdb" "company-bbdb.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-bbdb.el
|
||||||
|
|
||||||
|
(autoload 'company-bbdb "company-bbdb" "\
|
||||||
|
`company-mode' completion backend for BBDB.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORE)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-bbdb" '("company-bbdb-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-capf" "company-capf.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-capf.el
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-capf" '("company-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-clang" "company-clang.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-clang.el
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-clang" '("company-clang")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-cmake" "company-cmake.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-cmake.el
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-cmake" '("company-cmake")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-css" "company-css.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-css.el
|
||||||
|
|
||||||
|
(autoload 'company-css "company-css" "\
|
||||||
|
`company-mode' completion backend for `css-mode'.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-css" '("company-css-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-dabbrev" "company-dabbrev.el" (0 0
|
||||||
|
;;;;;; 0 0))
|
||||||
|
;;; Generated autoloads from company-dabbrev.el
|
||||||
|
|
||||||
|
(autoload 'company-dabbrev "company-dabbrev" "\
|
||||||
|
dabbrev-like `company-mode' completion backend.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-dabbrev" '("company-dabbrev-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-dabbrev-code" "company-dabbrev-code.el"
|
||||||
|
;;;;;; (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-dabbrev-code.el
|
||||||
|
|
||||||
|
(autoload 'company-dabbrev-code "company-dabbrev-code" "\
|
||||||
|
dabbrev-like `company-mode' backend for code.
|
||||||
|
The backend looks for all symbols in the current buffer that aren't in
|
||||||
|
comments or strings.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-dabbrev-code" '("company-dabbrev-code-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-eclim" "company-eclim.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-eclim.el
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-eclim" '("company-eclim")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-elisp" "company-elisp.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-elisp.el
|
||||||
|
|
||||||
|
(autoload 'company-elisp "company-elisp" "\
|
||||||
|
`company-mode' completion backend for Emacs Lisp.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-elisp" '("company-elisp-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-etags" "company-etags.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-etags.el
|
||||||
|
|
||||||
|
(autoload 'company-etags "company-etags" "\
|
||||||
|
`company-mode' completion backend for etags.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-etags" '("company-etags-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-files" "company-files.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-files.el
|
||||||
|
|
||||||
|
(autoload 'company-files "company-files" "\
|
||||||
|
`company-mode' completion backend existing file names.
|
||||||
|
Completions works for proper absolute and relative files paths.
|
||||||
|
File paths with spaces are only supported inside strings.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-files" '("company-file")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-gtags" "company-gtags.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-gtags.el
|
||||||
|
|
||||||
|
(autoload 'company-gtags "company-gtags" "\
|
||||||
|
`company-mode' completion backend for GNU Global.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-gtags" '("company-gtags-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-ispell" "company-ispell.el" (0 0 0
|
||||||
|
;;;;;; 0))
|
||||||
|
;;; Generated autoloads from company-ispell.el
|
||||||
|
|
||||||
|
(autoload 'company-ispell "company-ispell" "\
|
||||||
|
`company-mode' completion backend using Ispell.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-ispell" '("company-ispell-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-keywords" "company-keywords.el" (0
|
||||||
|
;;;;;; 0 0 0))
|
||||||
|
;;; Generated autoloads from company-keywords.el
|
||||||
|
|
||||||
|
(autoload 'company-keywords "company-keywords" "\
|
||||||
|
`company-mode' backend for programming language keywords.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-keywords" '("company-keywords-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-nxml" "company-nxml.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-nxml.el
|
||||||
|
|
||||||
|
(autoload 'company-nxml "company-nxml" "\
|
||||||
|
`company-mode' completion backend for `nxml-mode'.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-nxml" '("company-nxml-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-oddmuse" "company-oddmuse.el" (0 0
|
||||||
|
;;;;;; 0 0))
|
||||||
|
;;; Generated autoloads from company-oddmuse.el
|
||||||
|
|
||||||
|
(autoload 'company-oddmuse "company-oddmuse" "\
|
||||||
|
`company-mode' completion backend for `oddmuse-mode'.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-oddmuse" '("company-oddmuse-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-semantic" "company-semantic.el" (0
|
||||||
|
;;;;;; 0 0 0))
|
||||||
|
;;; Generated autoloads from company-semantic.el
|
||||||
|
|
||||||
|
(autoload 'company-semantic "company-semantic" "\
|
||||||
|
`company-mode' completion backend using CEDET Semantic.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-semantic" '("company-semantic-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-template" "company-template.el" (0
|
||||||
|
;;;;;; 0 0 0))
|
||||||
|
;;; Generated autoloads from company-template.el
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-template" '("company-template-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-tempo" "company-tempo.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-tempo.el
|
||||||
|
|
||||||
|
(autoload 'company-tempo "company-tempo" "\
|
||||||
|
`company-mode' completion backend for tempo.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-tempo" '("company-tempo-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-tng" "company-tng.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-tng.el
|
||||||
|
|
||||||
|
(autoload 'company-tng-frontend "company-tng" "\
|
||||||
|
When the user changes the selection at least once, this
|
||||||
|
frontend will display the candidate in the buffer as if it's
|
||||||
|
already there and any key outside of `company-active-map' will
|
||||||
|
confirm the selection and finish the completion.
|
||||||
|
|
||||||
|
\(fn COMMAND)" nil nil)
|
||||||
|
|
||||||
|
(autoload 'company-tng-configure-default "company-tng" "\
|
||||||
|
Applies the default configuration to enable company-tng.
|
||||||
|
|
||||||
|
\(fn)" nil nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-tng" '("company-tng--")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-xcode" "company-xcode.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-xcode.el
|
||||||
|
|
||||||
|
(autoload 'company-xcode "company-xcode" "\
|
||||||
|
`company-mode' completion backend for Xcode projects.
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-xcode" '("company-xcode-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil "company-yasnippet" "company-yasnippet.el"
|
||||||
|
;;;;;; (0 0 0 0))
|
||||||
|
;;; Generated autoloads from company-yasnippet.el
|
||||||
|
|
||||||
|
(autoload 'company-yasnippet "company-yasnippet" "\
|
||||||
|
`company-mode' backend for `yasnippet'.
|
||||||
|
|
||||||
|
This backend should be used with care, because as long as there are
|
||||||
|
snippets defined for the current major mode, this backend will always
|
||||||
|
shadow backends that come after it. Recommended usages:
|
||||||
|
|
||||||
|
* In a buffer-local value of `company-backends', grouped with a backend or
|
||||||
|
several that provide actual text completions.
|
||||||
|
|
||||||
|
(add-hook 'js-mode-hook
|
||||||
|
(lambda ()
|
||||||
|
(set (make-local-variable 'company-backends)
|
||||||
|
'((company-dabbrev-code company-yasnippet)))))
|
||||||
|
|
||||||
|
* After keyword `:with', grouped with other backends.
|
||||||
|
|
||||||
|
(push '(company-semantic :with company-yasnippet) company-backends)
|
||||||
|
|
||||||
|
* Not in `company-backends', just bound to a key.
|
||||||
|
|
||||||
|
(global-set-key (kbd \"C-c y\") 'company-yasnippet)
|
||||||
|
|
||||||
|
\(fn COMMAND &optional ARG &rest IGNORE)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "company-yasnippet" '("company-yasnippet--")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;;;### (autoloads nil nil ("company-pkg.el") (0 0 0 0))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;; Local Variables:
|
||||||
|
;; version-control: never
|
||||||
|
;; no-byte-compile: t
|
||||||
|
;; no-update-autoloads: t
|
||||||
|
;; coding: utf-8
|
||||||
|
;; End:
|
||||||
|
;;; company-autoloads.el ends here
|
||||||
61
elpa/company-20191029.2116/company-bbdb.el
Normal file
61
elpa/company-20191029.2116/company-bbdb.el
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
;;; company-bbdb.el --- company-mode completion backend for BBDB in message-mode
|
||||||
|
|
||||||
|
;; Copyright (C) 2013-2014, 2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Jan Tatarik <jan.tatarik@gmail.com>
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(declare-function bbdb-record-get-field "bbdb")
|
||||||
|
(declare-function bbdb-records "bbdb")
|
||||||
|
(declare-function bbdb-dwim-mail "bbdb-com")
|
||||||
|
(declare-function bbdb-search "bbdb-com")
|
||||||
|
|
||||||
|
(defgroup company-bbdb nil
|
||||||
|
"Completion backend for BBDB."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-bbdb-modes '(message-mode)
|
||||||
|
"Major modes in which `company-bbdb' may complete."
|
||||||
|
:type '(repeat (symbol :tag "Major mode"))
|
||||||
|
:package-version '(company . "0.8.8"))
|
||||||
|
|
||||||
|
(defun company-bbdb--candidates (arg)
|
||||||
|
(cl-mapcan (lambda (record)
|
||||||
|
(mapcar (lambda (mail) (bbdb-dwim-mail record mail))
|
||||||
|
(bbdb-record-get-field record 'mail)))
|
||||||
|
(eval '(bbdb-search (bbdb-records) arg nil arg))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-bbdb (command &optional arg &rest ignore)
|
||||||
|
"`company-mode' completion backend for BBDB."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-bbdb))
|
||||||
|
(prefix (and (memq major-mode company-bbdb-modes)
|
||||||
|
(featurep 'bbdb-com)
|
||||||
|
(looking-back "^\\(To\\|Cc\\|Bcc\\): *.*? *\\([^,;]*\\)"
|
||||||
|
(line-beginning-position))
|
||||||
|
(match-string-no-properties 2)))
|
||||||
|
(candidates (company-bbdb--candidates arg))
|
||||||
|
(sorted t)
|
||||||
|
(no-cache t)))
|
||||||
|
|
||||||
|
(provide 'company-bbdb)
|
||||||
|
;;; company-bbdb.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-bbdb.elc
Normal file
BIN
elpa/company-20191029.2116/company-bbdb.elc
Normal file
Binary file not shown.
201
elpa/company-20191029.2116/company-capf.el
Normal file
201
elpa/company-20191029.2116/company-capf.el
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
;;; company-capf.el --- company-mode completion-at-point-functions backend -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2013-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; The CAPF back-end provides a bridge to the standard
|
||||||
|
;; completion-at-point-functions facility, and thus can support any major mode
|
||||||
|
;; that defines a proper completion function, including emacs-lisp-mode,
|
||||||
|
;; css-mode and nxml-mode.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defvar company--capf-cache nil)
|
||||||
|
|
||||||
|
;; FIXME: Provide a way to save this info once in Company itself
|
||||||
|
;; (https://github.com/company-mode/company-mode/pull/845).
|
||||||
|
(defvar-local company-capf--current-completion-data nil
|
||||||
|
"Value last returned by `company-capf' when called with `candidates'.
|
||||||
|
For most properties/actions, this is just what we need: the exact values
|
||||||
|
that accompanied the completion table that's currently is use.")
|
||||||
|
|
||||||
|
(defun company--capf-data ()
|
||||||
|
(let ((cache company--capf-cache))
|
||||||
|
(if (and (equal (current-buffer) (car cache))
|
||||||
|
(equal (point) (car (setq cache (cdr cache))))
|
||||||
|
(equal (buffer-chars-modified-tick) (car (setq cache (cdr cache)))))
|
||||||
|
(cadr cache)
|
||||||
|
(let ((data (company--capf-data-real)))
|
||||||
|
(setq company--capf-cache
|
||||||
|
(list (current-buffer) (point) (buffer-chars-modified-tick) data))
|
||||||
|
data))))
|
||||||
|
|
||||||
|
(defun company--capf-data-real ()
|
||||||
|
(cl-letf* (((default-value 'completion-at-point-functions)
|
||||||
|
;; Ignore tags-completion-at-point-function because it subverts
|
||||||
|
;; company-etags in the default value of company-backends, where
|
||||||
|
;; the latter comes later.
|
||||||
|
(remove 'tags-completion-at-point-function
|
||||||
|
(default-value 'completion-at-point-functions)))
|
||||||
|
(completion-at-point-functions (company--capf-workaround))
|
||||||
|
(data (run-hook-wrapped 'completion-at-point-functions
|
||||||
|
;; Ignore misbehaving functions.
|
||||||
|
#'completion--capf-wrapper 'optimist)))
|
||||||
|
(when (and (consp (cdr data)) (integer-or-marker-p (nth 1 data))) data)))
|
||||||
|
|
||||||
|
(declare-function python-shell-get-process "python")
|
||||||
|
|
||||||
|
(defun company--capf-workaround ()
|
||||||
|
;; For http://debbugs.gnu.org/cgi/bugreport.cgi?bug=18067
|
||||||
|
(if (or (not (listp completion-at-point-functions))
|
||||||
|
(not (memq 'python-completion-complete-at-point completion-at-point-functions))
|
||||||
|
(python-shell-get-process))
|
||||||
|
completion-at-point-functions
|
||||||
|
(remq 'python-completion-complete-at-point completion-at-point-functions)))
|
||||||
|
|
||||||
|
(defun company-capf--save-current-data (data)
|
||||||
|
(setq company-capf--current-completion-data data)
|
||||||
|
(add-hook 'company-after-completion-hook
|
||||||
|
#'company-capf--clear-current-data nil t))
|
||||||
|
|
||||||
|
(defun company-capf--clear-current-data (_ignored)
|
||||||
|
(setq company-capf--current-completion-data nil))
|
||||||
|
|
||||||
|
(defvar-local company-capf--sorted nil)
|
||||||
|
|
||||||
|
(defun company-capf (command &optional arg &rest _args)
|
||||||
|
"`company-mode' backend using `completion-at-point-functions'."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(pcase command
|
||||||
|
(`interactive (company-begin-backend 'company-capf))
|
||||||
|
(`prefix
|
||||||
|
(let ((res (company--capf-data)))
|
||||||
|
(when res
|
||||||
|
(let ((length (plist-get (nthcdr 4 res) :company-prefix-length))
|
||||||
|
(prefix (buffer-substring-no-properties (nth 1 res) (point))))
|
||||||
|
(cond
|
||||||
|
((> (nth 2 res) (point)) 'stop)
|
||||||
|
(length (cons prefix length))
|
||||||
|
(t prefix))))))
|
||||||
|
(`candidates
|
||||||
|
(company-capf--candidates arg))
|
||||||
|
(`sorted
|
||||||
|
company-capf--sorted)
|
||||||
|
(`match
|
||||||
|
;; Ask the for the `:company-match' function. If that doesn't help,
|
||||||
|
;; fallback to sniffing for face changes to get a suitable value.
|
||||||
|
(let ((f (plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||||
|
:company-match)))
|
||||||
|
(if f (funcall f arg)
|
||||||
|
(let* ((match-start nil) (pos -1)
|
||||||
|
(prop-value nil) (faces nil)
|
||||||
|
(has-face-p nil) chunks
|
||||||
|
(limit (length arg)))
|
||||||
|
(while (< pos limit)
|
||||||
|
(setq pos
|
||||||
|
(if (< pos 0) 0 (next-property-change pos arg limit)))
|
||||||
|
(setq prop-value (or
|
||||||
|
(get-text-property pos 'face arg)
|
||||||
|
(get-text-property pos 'font-lock-face arg))
|
||||||
|
faces (if (listp prop-value) prop-value (list prop-value))
|
||||||
|
has-face-p (memq 'completions-common-part faces))
|
||||||
|
(cond ((and (not match-start) has-face-p)
|
||||||
|
(setq match-start pos))
|
||||||
|
((and match-start (not has-face-p))
|
||||||
|
(push (cons match-start pos) chunks)
|
||||||
|
(setq match-start nil))))
|
||||||
|
(nreverse chunks)))))
|
||||||
|
(`duplicates t)
|
||||||
|
(`no-cache t) ;Not much can be done here, as long as we handle
|
||||||
|
;non-prefix matches.
|
||||||
|
(`meta
|
||||||
|
(let ((f (plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||||
|
:company-docsig)))
|
||||||
|
(when f (funcall f arg))))
|
||||||
|
(`doc-buffer
|
||||||
|
(let ((f (plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||||
|
:company-doc-buffer)))
|
||||||
|
(when f (funcall f arg))))
|
||||||
|
(`location
|
||||||
|
(let ((f (plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||||
|
:company-location)))
|
||||||
|
(when f (funcall f arg))))
|
||||||
|
(`annotation
|
||||||
|
(let ((f (plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||||
|
:annotation-function)))
|
||||||
|
(when f (funcall f arg))))
|
||||||
|
(`require-match
|
||||||
|
(plist-get (nthcdr 4 (company--capf-data)) :company-require-match))
|
||||||
|
(`init nil) ;Don't bother: plenty of other ways to initialize the code.
|
||||||
|
(`post-completion
|
||||||
|
(company--capf-post-completion arg))
|
||||||
|
))
|
||||||
|
|
||||||
|
(defun company-capf--candidates (input)
|
||||||
|
(let ((res (company--capf-data)))
|
||||||
|
(company-capf--save-current-data res)
|
||||||
|
(when res
|
||||||
|
(let* ((table (nth 3 res))
|
||||||
|
(pred (plist-get (nthcdr 4 res) :predicate))
|
||||||
|
(meta (completion-metadata
|
||||||
|
(buffer-substring (nth 1 res) (nth 2 res))
|
||||||
|
table pred))
|
||||||
|
(candidates (completion-all-completions input table pred
|
||||||
|
(length input)
|
||||||
|
meta))
|
||||||
|
(sortfun (cdr (assq 'display-sort-function meta)))
|
||||||
|
(last (last candidates))
|
||||||
|
(base-size (and (numberp (cdr last)) (cdr last))))
|
||||||
|
(when base-size
|
||||||
|
(setcdr last nil))
|
||||||
|
(setq company-capf--sorted (functionp sortfun))
|
||||||
|
(when sortfun
|
||||||
|
(setq candidates (funcall sortfun candidates)))
|
||||||
|
(if (not (zerop (or base-size 0)))
|
||||||
|
(let ((before (substring input 0 base-size)))
|
||||||
|
(mapcar (lambda (candidate)
|
||||||
|
(concat before candidate))
|
||||||
|
candidates))
|
||||||
|
candidates)))))
|
||||||
|
|
||||||
|
(defun company--capf-post-completion (arg)
|
||||||
|
(let* ((res company-capf--current-completion-data)
|
||||||
|
(exit-function (plist-get (nthcdr 4 res) :exit-function))
|
||||||
|
(table (nth 3 res))
|
||||||
|
(pred (plist-get (nthcdr 4 res) :predicate)))
|
||||||
|
(if exit-function
|
||||||
|
;; Follow the example of `completion--done'.
|
||||||
|
(funcall exit-function arg
|
||||||
|
;; FIXME: Should probably use an additional heuristic:
|
||||||
|
;; completion-at-point doesn't know when the user picked a
|
||||||
|
;; particular candidate explicitly (it only checks whether
|
||||||
|
;; futher completions exist). Whereas company user can press
|
||||||
|
;; RET (or use implicit completion with company-tng).
|
||||||
|
(if (eq (try-completion arg table pred) t)
|
||||||
|
'finished 'sole)))))
|
||||||
|
|
||||||
|
(provide 'company-capf)
|
||||||
|
|
||||||
|
;;; company-capf.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-capf.elc
Normal file
BIN
elpa/company-20191029.2116/company-capf.elc
Normal file
Binary file not shown.
351
elpa/company-20191029.2116/company-clang.el
Normal file
351
elpa/company-20191029.2116/company-clang.el
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
;;; company-clang.el --- company-mode completion backend for Clang -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2011, 2013-2019 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'company-template)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-clang nil
|
||||||
|
"Completion backend for Clang."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-clang-executable
|
||||||
|
(executable-find "clang")
|
||||||
|
"Location of clang executable."
|
||||||
|
:type 'file)
|
||||||
|
|
||||||
|
(defcustom company-clang-begin-after-member-access t
|
||||||
|
"When non-nil, automatic completion will start whenever the current
|
||||||
|
symbol is preceded by \".\", \"->\" or \"::\", ignoring
|
||||||
|
`company-minimum-prefix-length'.
|
||||||
|
|
||||||
|
If `company-begin-commands' is a list, it should include `c-electric-lt-gt'
|
||||||
|
and `c-electric-colon', for automatic completion right after \">\" and
|
||||||
|
\":\"."
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom company-clang-arguments nil
|
||||||
|
"Additional arguments to pass to clang when completing.
|
||||||
|
Prefix files (-include ...) can be selected with `company-clang-set-prefix'
|
||||||
|
or automatically through a custom `company-clang-prefix-guesser'."
|
||||||
|
:type '(repeat (string :tag "Argument")))
|
||||||
|
|
||||||
|
(defcustom company-clang-prefix-guesser 'company-clang-guess-prefix
|
||||||
|
"A function to determine the prefix file for the current buffer."
|
||||||
|
:type '(function :tag "Guesser function" nil))
|
||||||
|
|
||||||
|
(defvar company-clang-modes '(c-mode c++-mode objc-mode)
|
||||||
|
"Major modes which clang may complete.")
|
||||||
|
|
||||||
|
(defcustom company-clang-insert-arguments t
|
||||||
|
"When non-nil, insert function arguments as a template after completion."
|
||||||
|
:type 'boolean
|
||||||
|
:package-version '(company . "0.8.0"))
|
||||||
|
|
||||||
|
;; prefix ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defvar company-clang--prefix nil)
|
||||||
|
|
||||||
|
(defsubst company-clang--guess-pch-file (file)
|
||||||
|
(let ((dir (directory-file-name (file-name-directory file))))
|
||||||
|
(when (equal (file-name-nondirectory dir) "Classes")
|
||||||
|
(setq dir (file-name-directory dir)))
|
||||||
|
(car (directory-files dir t "\\([^.]h\\|[^h]\\).pch\\'" t))))
|
||||||
|
|
||||||
|
(defsubst company-clang--file-substring (file beg end)
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert-file-contents-literally file nil beg end)
|
||||||
|
(buffer-string)))
|
||||||
|
|
||||||
|
(defun company-clang-guess-prefix ()
|
||||||
|
"Try to guess the prefix file for the current buffer."
|
||||||
|
;; Prefixes seem to be called .pch. Pre-compiled headers do, too.
|
||||||
|
;; So we look at the magic number to rule them out.
|
||||||
|
(let* ((file (company-clang--guess-pch-file buffer-file-name))
|
||||||
|
(magic-number (and file (company-clang--file-substring file 0 4))))
|
||||||
|
(unless (member magic-number '("CPCH" "gpch"))
|
||||||
|
file)))
|
||||||
|
|
||||||
|
(defun company-clang-set-prefix (&optional prefix)
|
||||||
|
"Use PREFIX as a prefix (-include ...) file for clang completion."
|
||||||
|
(interactive (let ((def (funcall company-clang-prefix-guesser)))
|
||||||
|
(unless (stringp def)
|
||||||
|
(setq def default-directory))
|
||||||
|
(list (read-file-name "Prefix file: "
|
||||||
|
(when def (file-name-directory def))
|
||||||
|
def t (when def (file-name-nondirectory def))))))
|
||||||
|
;; TODO: pre-compile?
|
||||||
|
(setq company-clang--prefix (and (stringp prefix)
|
||||||
|
(file-regular-p prefix)
|
||||||
|
prefix)))
|
||||||
|
|
||||||
|
;; Clean-up on exit.
|
||||||
|
(add-hook 'kill-emacs-hook 'company-clang-set-prefix)
|
||||||
|
|
||||||
|
;; parsing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; TODO: Handle Pattern (syntactic hints would be neat).
|
||||||
|
;; Do we ever see OVERLOAD (or OVERRIDE)?
|
||||||
|
(defconst company-clang--completion-pattern
|
||||||
|
"^COMPLETION: \\_<\\(%s[a-zA-Z0-9_:]*\\)\\(?:\\(?: (InBase)\\)? : \\(.*\\)$\\)?$")
|
||||||
|
|
||||||
|
(defconst company-clang--error-buffer-name "*clang-error*")
|
||||||
|
|
||||||
|
(defun company-clang--lang-option ()
|
||||||
|
(if (eq major-mode 'objc-mode)
|
||||||
|
(if (string= "m" (file-name-extension buffer-file-name))
|
||||||
|
"objective-c" "objective-c++")
|
||||||
|
(substring (symbol-name major-mode) 0 -5)))
|
||||||
|
|
||||||
|
(defun company-clang--parse-output (prefix _objc)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(let ((pattern (format company-clang--completion-pattern
|
||||||
|
(regexp-quote prefix)))
|
||||||
|
(case-fold-search nil)
|
||||||
|
lines match)
|
||||||
|
(while (re-search-forward pattern nil t)
|
||||||
|
(setq match (match-string-no-properties 1))
|
||||||
|
(unless (equal match "Pattern")
|
||||||
|
(save-match-data
|
||||||
|
(when (string-match ":" match)
|
||||||
|
(setq match (substring match 0 (match-beginning 0)))))
|
||||||
|
(let ((meta (match-string-no-properties 2)))
|
||||||
|
(when (and meta (not (string= match meta)))
|
||||||
|
(put-text-property 0 1 'meta
|
||||||
|
(company-clang--strip-formatting meta)
|
||||||
|
match)))
|
||||||
|
(push match lines)))
|
||||||
|
lines))
|
||||||
|
|
||||||
|
(defun company-clang--meta (candidate)
|
||||||
|
(get-text-property 0 'meta candidate))
|
||||||
|
|
||||||
|
(defun company-clang--annotation (candidate)
|
||||||
|
(let ((ann (company-clang--annotation-1 candidate)))
|
||||||
|
(if (not (and ann (string-prefix-p "(*)" ann)))
|
||||||
|
ann
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert ann)
|
||||||
|
(search-backward ")")
|
||||||
|
(let ((pt (1+ (point))))
|
||||||
|
(re-search-forward ".\\_>" nil t)
|
||||||
|
(delete-region pt (point)))
|
||||||
|
(buffer-string)))))
|
||||||
|
|
||||||
|
(defun company-clang--annotation-1 (candidate)
|
||||||
|
(let ((meta (company-clang--meta candidate)))
|
||||||
|
(cond
|
||||||
|
((null meta) nil)
|
||||||
|
((string-match "[^:]:[^:]" meta)
|
||||||
|
(substring meta (1+ (match-beginning 0))))
|
||||||
|
((string-match "(anonymous)" meta) nil)
|
||||||
|
((string-match "\\((.*)[ a-z]*\\'\\)" meta)
|
||||||
|
(let ((paren (match-beginning 1)))
|
||||||
|
(if (not (eq (aref meta (1- paren)) ?>))
|
||||||
|
(match-string 1 meta)
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert meta)
|
||||||
|
(goto-char paren)
|
||||||
|
(substring meta (1- (search-backward "<"))))))))))
|
||||||
|
|
||||||
|
(defun company-clang--strip-formatting (text)
|
||||||
|
(replace-regexp-in-string
|
||||||
|
"#]" " "
|
||||||
|
(replace-regexp-in-string "[<{[]#\\|#[>}]" "" text t)
|
||||||
|
t))
|
||||||
|
|
||||||
|
(defun company-clang--handle-error (res args)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(let* ((buf (get-buffer-create company-clang--error-buffer-name))
|
||||||
|
(cmd (concat company-clang-executable " " (mapconcat 'identity args " ")))
|
||||||
|
(pattern (format company-clang--completion-pattern ""))
|
||||||
|
(message-truncate-lines t)
|
||||||
|
(err (if (re-search-forward pattern nil t)
|
||||||
|
(buffer-substring-no-properties (point-min)
|
||||||
|
(1- (match-beginning 0)))
|
||||||
|
;; Warn the user more aggressively if no match was found.
|
||||||
|
(message "clang failed with error %d: %s" res cmd)
|
||||||
|
(buffer-string))))
|
||||||
|
|
||||||
|
(with-current-buffer buf
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(erase-buffer)
|
||||||
|
(insert (current-time-string)
|
||||||
|
(format "\nclang failed with error %d:\n" res)
|
||||||
|
cmd "\n\n")
|
||||||
|
(insert err)
|
||||||
|
(setq buffer-read-only t)
|
||||||
|
(goto-char (point-min))))))
|
||||||
|
|
||||||
|
(defun company-clang--start-process (prefix callback &rest args)
|
||||||
|
(let* ((objc (derived-mode-p 'objc-mode))
|
||||||
|
(buf (get-buffer-create "*clang-output*"))
|
||||||
|
;; Looks unnecessary in Emacs 25.1 and later.
|
||||||
|
(process-adaptive-read-buffering nil)
|
||||||
|
(existing-process (get-buffer-process buf)))
|
||||||
|
(when existing-process
|
||||||
|
(kill-process existing-process))
|
||||||
|
(with-current-buffer buf
|
||||||
|
(erase-buffer)
|
||||||
|
(setq buffer-undo-list t))
|
||||||
|
(let* ((process-connection-type nil)
|
||||||
|
(process (apply #'start-file-process "company-clang" buf
|
||||||
|
company-clang-executable args)))
|
||||||
|
(set-process-sentinel
|
||||||
|
process
|
||||||
|
(lambda (proc status)
|
||||||
|
(unless (string-match-p "hangup\\|killed" status)
|
||||||
|
(funcall
|
||||||
|
callback
|
||||||
|
(let ((res (process-exit-status proc)))
|
||||||
|
(with-current-buffer buf
|
||||||
|
(unless (eq 0 res)
|
||||||
|
(company-clang--handle-error res args))
|
||||||
|
;; Still try to get any useful input.
|
||||||
|
(company-clang--parse-output prefix objc)))))))
|
||||||
|
(unless (company-clang--auto-save-p)
|
||||||
|
(send-region process (point-min) (point-max))
|
||||||
|
(send-string process "\n")
|
||||||
|
(process-send-eof process)))))
|
||||||
|
|
||||||
|
(defsubst company-clang--build-location (pos)
|
||||||
|
(save-excursion
|
||||||
|
(goto-char pos)
|
||||||
|
(format "%s:%d:%d"
|
||||||
|
(if (company-clang--auto-save-p) buffer-file-name "-")
|
||||||
|
(line-number-at-pos)
|
||||||
|
(1+ (length
|
||||||
|
(encode-coding-region
|
||||||
|
(line-beginning-position)
|
||||||
|
(point)
|
||||||
|
'utf-8
|
||||||
|
t))))))
|
||||||
|
|
||||||
|
(defsubst company-clang--build-complete-args (pos)
|
||||||
|
(append '("-fsyntax-only" "-Xclang" "-code-completion-macros")
|
||||||
|
(unless (company-clang--auto-save-p)
|
||||||
|
(list "-x" (company-clang--lang-option)))
|
||||||
|
company-clang-arguments
|
||||||
|
(when (stringp company-clang--prefix)
|
||||||
|
(list "-include" (expand-file-name company-clang--prefix)))
|
||||||
|
(list "-Xclang" (format "-code-completion-at=%s"
|
||||||
|
(company-clang--build-location pos)))
|
||||||
|
(list (if (company-clang--auto-save-p) buffer-file-name "-"))))
|
||||||
|
|
||||||
|
(defun company-clang--candidates (prefix callback)
|
||||||
|
(and (company-clang--auto-save-p)
|
||||||
|
(buffer-modified-p)
|
||||||
|
(basic-save-buffer))
|
||||||
|
(when (null company-clang--prefix)
|
||||||
|
(company-clang-set-prefix (or (funcall company-clang-prefix-guesser)
|
||||||
|
'none)))
|
||||||
|
(apply 'company-clang--start-process
|
||||||
|
prefix
|
||||||
|
callback
|
||||||
|
(company-clang--build-complete-args
|
||||||
|
(if (company-clang--check-version 4.0 9.0)
|
||||||
|
(point)
|
||||||
|
(- (point) (length prefix))))))
|
||||||
|
|
||||||
|
(defun company-clang--prefix ()
|
||||||
|
(if company-clang-begin-after-member-access
|
||||||
|
(company-grab-symbol-cons "\\.\\|->\\|::" 2)
|
||||||
|
(company-grab-symbol)))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defconst company-clang-required-version 1.1)
|
||||||
|
|
||||||
|
(defvar company-clang--version nil)
|
||||||
|
|
||||||
|
(defun company-clang--auto-save-p ()
|
||||||
|
(not
|
||||||
|
(company-clang--check-version 2.9 3.1)))
|
||||||
|
|
||||||
|
(defun company-clang--check-version (min apple-min)
|
||||||
|
(pcase company-clang--version
|
||||||
|
(`(apple . ,ver) (>= ver apple-min))
|
||||||
|
(`(normal . ,ver) (>= ver min))
|
||||||
|
(_ (error "pcase-exhaustive is not in Emacs 24.3!"))))
|
||||||
|
|
||||||
|
(defsubst company-clang-version ()
|
||||||
|
"Return the version of `company-clang-executable'."
|
||||||
|
(with-temp-buffer
|
||||||
|
(call-process company-clang-executable nil t nil "--version")
|
||||||
|
(goto-char (point-min))
|
||||||
|
(if (re-search-forward
|
||||||
|
"\\(clang\\|Apple LLVM\\|bcc32x\\|bcc64\\) version \\([0-9.]+\\)" nil t)
|
||||||
|
(cons
|
||||||
|
(if (equal (match-string-no-properties 1) "Apple LLVM")
|
||||||
|
'apple
|
||||||
|
'normal)
|
||||||
|
(string-to-number (match-string-no-properties 2)))
|
||||||
|
0)))
|
||||||
|
|
||||||
|
(defun company-clang (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for Clang.
|
||||||
|
Clang is a parser for C and ObjC. Clang version 1.1 or newer is required.
|
||||||
|
|
||||||
|
Additional command line arguments can be specified in
|
||||||
|
`company-clang-arguments'. Prefix files (-include ...) can be selected
|
||||||
|
with `company-clang-set-prefix' or automatically through a custom
|
||||||
|
`company-clang-prefix-guesser'.
|
||||||
|
|
||||||
|
With Clang versions before 2.9, we have to save the buffer before
|
||||||
|
performing completion. With Clang 2.9 and later, buffer contents are
|
||||||
|
passed via standard input."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-clang))
|
||||||
|
(init (when (memq major-mode company-clang-modes)
|
||||||
|
(unless company-clang-executable
|
||||||
|
(error "Company found no clang executable"))
|
||||||
|
(setq company-clang--version (company-clang-version))
|
||||||
|
(unless (company-clang--check-version
|
||||||
|
company-clang-required-version
|
||||||
|
company-clang-required-version)
|
||||||
|
(error "Company requires clang version %s"
|
||||||
|
company-clang-required-version))))
|
||||||
|
(prefix (and (memq major-mode company-clang-modes)
|
||||||
|
buffer-file-name
|
||||||
|
company-clang-executable
|
||||||
|
(not (company-in-string-or-comment))
|
||||||
|
(or (company-clang--prefix) 'stop)))
|
||||||
|
(candidates (cons :async
|
||||||
|
(lambda (cb) (company-clang--candidates arg cb))))
|
||||||
|
(meta (company-clang--meta arg))
|
||||||
|
(annotation (company-clang--annotation arg))
|
||||||
|
(post-completion (let ((anno (company-clang--annotation arg)))
|
||||||
|
(when (and company-clang-insert-arguments anno)
|
||||||
|
(insert anno)
|
||||||
|
(if (string-match "\\`:[^:]" anno)
|
||||||
|
(company-template-objc-templatify anno)
|
||||||
|
(company-template-c-like-templatify
|
||||||
|
(concat arg anno))))))))
|
||||||
|
|
||||||
|
(provide 'company-clang)
|
||||||
|
;;; company-clang.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-clang.elc
Normal file
BIN
elpa/company-20191029.2116/company-clang.elc
Normal file
Binary file not shown.
206
elpa/company-20191029.2116/company-cmake.el
Normal file
206
elpa/company-20191029.2116/company-cmake.el
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
;;; company-cmake.el --- company-mode completion backend for CMake
|
||||||
|
|
||||||
|
;; Copyright (C) 2013-2014, 2017-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Chen Bin <chenbin DOT sh AT gmail>
|
||||||
|
;; Version: 0.2
|
||||||
|
|
||||||
|
;; This program 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; company-cmake offers completions for module names, variable names and
|
||||||
|
;; commands used by CMake. And their descriptions.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-cmake nil
|
||||||
|
"Completion backend for CMake."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-cmake-executable
|
||||||
|
(executable-find "cmake")
|
||||||
|
"Location of cmake executable."
|
||||||
|
:type 'file)
|
||||||
|
|
||||||
|
(defvar company-cmake-executable-arguments
|
||||||
|
'("--help-command-list"
|
||||||
|
"--help-module-list"
|
||||||
|
"--help-variable-list")
|
||||||
|
"The arguments we pass to cmake, separately.
|
||||||
|
They affect which types of symbols we get completion candidates for.")
|
||||||
|
|
||||||
|
(defvar company-cmake--completion-pattern
|
||||||
|
"^\\(%s[a-zA-Z0-9_<>]%s\\)$"
|
||||||
|
"Regexp to match the candidates.")
|
||||||
|
|
||||||
|
(defvar company-cmake-modes '(cmake-mode)
|
||||||
|
"Major modes in which cmake may complete.")
|
||||||
|
|
||||||
|
(defvar company-cmake--candidates-cache nil
|
||||||
|
"Cache for the raw candidates.")
|
||||||
|
|
||||||
|
(defvar company-cmake--meta-command-cache nil
|
||||||
|
"Cache for command arguments to retrieve descriptions for the candidates.")
|
||||||
|
|
||||||
|
(defun company-cmake--replace-tags (rlt)
|
||||||
|
(setq rlt (replace-regexp-in-string
|
||||||
|
"\\(.*?\\(IS_GNU\\)?\\)<LANG>\\(.*\\)"
|
||||||
|
(lambda (_match)
|
||||||
|
(mapconcat 'identity
|
||||||
|
(if (match-beginning 2)
|
||||||
|
'("\\1CXX\\3" "\\1C\\3" "\\1G77\\3")
|
||||||
|
'("\\1CXX\\3" "\\1C\\3" "\\1Fortran\\3"))
|
||||||
|
"\n"))
|
||||||
|
rlt t))
|
||||||
|
(setq rlt (replace-regexp-in-string
|
||||||
|
"\\(.*\\)<CONFIG>\\(.*\\)"
|
||||||
|
(mapconcat 'identity '("\\1DEBUG\\2" "\\1RELEASE\\2"
|
||||||
|
"\\1RELWITHDEBINFO\\2" "\\1MINSIZEREL\\2")
|
||||||
|
"\n")
|
||||||
|
rlt))
|
||||||
|
rlt)
|
||||||
|
|
||||||
|
(defun company-cmake--fill-candidates-cache (arg)
|
||||||
|
"Fill candidates cache if needed."
|
||||||
|
(let (rlt)
|
||||||
|
(unless company-cmake--candidates-cache
|
||||||
|
(setq company-cmake--candidates-cache (make-hash-table :test 'equal)))
|
||||||
|
|
||||||
|
;; If hash is empty, fill it.
|
||||||
|
(unless (gethash arg company-cmake--candidates-cache)
|
||||||
|
(with-temp-buffer
|
||||||
|
(let ((res (call-process company-cmake-executable nil t nil arg)))
|
||||||
|
(unless (zerop res)
|
||||||
|
(message "cmake executable exited with error=%d" res)))
|
||||||
|
(setq rlt (buffer-string)))
|
||||||
|
(setq rlt (company-cmake--replace-tags rlt))
|
||||||
|
(puthash arg rlt company-cmake--candidates-cache))
|
||||||
|
))
|
||||||
|
|
||||||
|
(defun company-cmake--parse (prefix content cmd)
|
||||||
|
(let ((start 0)
|
||||||
|
(pattern (format company-cmake--completion-pattern
|
||||||
|
(regexp-quote prefix)
|
||||||
|
(if (zerop (length prefix)) "+" "*")))
|
||||||
|
(lines (split-string content "\n"))
|
||||||
|
match
|
||||||
|
rlt)
|
||||||
|
(dolist (line lines)
|
||||||
|
(when (string-match pattern line)
|
||||||
|
(let ((match (match-string 1 line)))
|
||||||
|
(when match
|
||||||
|
(puthash match cmd company-cmake--meta-command-cache)
|
||||||
|
(push match rlt)))))
|
||||||
|
rlt))
|
||||||
|
|
||||||
|
(defun company-cmake--candidates (prefix)
|
||||||
|
(let (results
|
||||||
|
cmd-opts
|
||||||
|
str)
|
||||||
|
|
||||||
|
(unless company-cmake--meta-command-cache
|
||||||
|
(setq company-cmake--meta-command-cache (make-hash-table :test 'equal)))
|
||||||
|
|
||||||
|
(dolist (arg company-cmake-executable-arguments)
|
||||||
|
(company-cmake--fill-candidates-cache arg)
|
||||||
|
(setq cmd-opts (replace-regexp-in-string "-list$" "" arg) )
|
||||||
|
|
||||||
|
(setq str (gethash arg company-cmake--candidates-cache))
|
||||||
|
(when str
|
||||||
|
(setq results (nconc results
|
||||||
|
(company-cmake--parse prefix str cmd-opts)))))
|
||||||
|
results))
|
||||||
|
|
||||||
|
(defun company-cmake--unexpand-candidate (candidate)
|
||||||
|
(cond
|
||||||
|
((string-match "^CMAKE_\\(C\\|CXX\\|Fortran\\)\\(_.*\\)$" candidate)
|
||||||
|
(setq candidate (concat "CMAKE_<LANG>" (match-string 2 candidate))))
|
||||||
|
|
||||||
|
;; C flags
|
||||||
|
((string-match "^\\(.*_\\)IS_GNU\\(C\\|CXX\\|G77\\)$" candidate)
|
||||||
|
(setq candidate (concat (match-string 1 candidate) "IS_GNU<LANG>")))
|
||||||
|
|
||||||
|
;; C flags
|
||||||
|
((string-match "^\\(.*_\\)OVERRIDE_\\(C\\|CXX\\|Fortran\\)$" candidate)
|
||||||
|
(setq candidate (concat (match-string 1 candidate) "OVERRIDE_<LANG>")))
|
||||||
|
|
||||||
|
((string-match "^\\(.*\\)\\(_DEBUG\\|_RELEASE\\|_RELWITHDEBINFO\\|_MINSIZEREL\\)\\(.*\\)$" candidate)
|
||||||
|
(setq candidate (concat (match-string 1 candidate)
|
||||||
|
"_<CONFIG>"
|
||||||
|
(match-string 3 candidate)))))
|
||||||
|
candidate)
|
||||||
|
|
||||||
|
(defun company-cmake--meta (candidate)
|
||||||
|
(let ((cmd-opts (gethash candidate company-cmake--meta-command-cache))
|
||||||
|
result)
|
||||||
|
(setq candidate (company-cmake--unexpand-candidate candidate))
|
||||||
|
|
||||||
|
;; Don't cache the documentation of every candidate (command)
|
||||||
|
;; Cache in this case will cost too much memory.
|
||||||
|
(with-temp-buffer
|
||||||
|
(call-process company-cmake-executable nil t nil cmd-opts candidate)
|
||||||
|
;; Go to the third line, trim it and return the result.
|
||||||
|
;; Tested with cmake 2.8.9.
|
||||||
|
(goto-char (point-min))
|
||||||
|
(forward-line 2)
|
||||||
|
(setq result (buffer-substring-no-properties (line-beginning-position)
|
||||||
|
(line-end-position)))
|
||||||
|
(setq result (replace-regexp-in-string "^[ \t\n\r]+" "" result))
|
||||||
|
result)))
|
||||||
|
|
||||||
|
(defun company-cmake--doc-buffer (candidate)
|
||||||
|
(let ((cmd-opts (gethash candidate company-cmake--meta-command-cache)))
|
||||||
|
|
||||||
|
(setq candidate (company-cmake--unexpand-candidate candidate))
|
||||||
|
(with-temp-buffer
|
||||||
|
(call-process company-cmake-executable nil t nil cmd-opts candidate)
|
||||||
|
;; Go to the third line, trim it and return the doc buffer.
|
||||||
|
;; Tested with cmake 2.8.9.
|
||||||
|
(goto-char (point-min))
|
||||||
|
(forward-line 2)
|
||||||
|
(company-doc-buffer
|
||||||
|
(buffer-substring-no-properties (line-beginning-position)
|
||||||
|
(point-max))))))
|
||||||
|
|
||||||
|
(defun company-cmake-prefix-dollar-brace-p ()
|
||||||
|
"Test if the current symbol follows ${."
|
||||||
|
(save-excursion
|
||||||
|
(skip-syntax-backward "w_")
|
||||||
|
(and (eq (char-before (point)) ?\{)
|
||||||
|
(eq (char-before (1- (point))) ?$))))
|
||||||
|
|
||||||
|
(defun company-cmake (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for CMake.
|
||||||
|
CMake is a cross-platform, open-source make system."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-cmake))
|
||||||
|
(init (when (memq major-mode company-cmake-modes)
|
||||||
|
(unless company-cmake-executable
|
||||||
|
(error "Company found no cmake executable"))))
|
||||||
|
(prefix (and (memq major-mode company-cmake-modes)
|
||||||
|
(or (not (company-in-string-or-comment))
|
||||||
|
(company-cmake-prefix-dollar-brace-p))
|
||||||
|
(company-grab-symbol)))
|
||||||
|
(candidates (company-cmake--candidates arg))
|
||||||
|
(meta (company-cmake--meta arg))
|
||||||
|
(doc-buffer (company-cmake--doc-buffer arg))
|
||||||
|
))
|
||||||
|
|
||||||
|
(provide 'company-cmake)
|
||||||
|
;;; company-cmake.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-cmake.elc
Normal file
BIN
elpa/company-20191029.2116/company-cmake.elc
Normal file
Binary file not shown.
446
elpa/company-20191029.2116/company-css.el
Normal file
446
elpa/company-20191029.2116/company-css.el
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
;;; company-css.el --- company-mode completion backend for css-mode -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2011, 2014, 2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; In Emacs >= 26, company-capf is used instead.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(declare-function web-mode-language-at-pos "web-mode" (&optional pos))
|
||||||
|
|
||||||
|
(defconst company-css-property-alist
|
||||||
|
;; see http://www.w3.org/TR/CSS21/propidx.html
|
||||||
|
'(("azimuth" angle "left-side" "far-left" "left" "center-left" "center"
|
||||||
|
"center-right" "right" "far-right" "right-side" "behind" "leftwards"
|
||||||
|
"rightwards")
|
||||||
|
("background" background-color background-image background-repeat
|
||||||
|
background-attachment background-position
|
||||||
|
background-clip background-origin background-size)
|
||||||
|
("background-attachment" "scroll" "fixed")
|
||||||
|
("background-color" color "transparent")
|
||||||
|
("background-image" uri "none")
|
||||||
|
("background-position" percentage length "left" "center" "right" percentage
|
||||||
|
length "top" "center" "bottom" "left" "center" "right" "top" "center"
|
||||||
|
"bottom")
|
||||||
|
("background-repeat" "repeat" "repeat-x" "repeat-y" "no-repeat")
|
||||||
|
("border" border-width border-style border-color)
|
||||||
|
("border-bottom" border)
|
||||||
|
("border-bottom-color" border-color)
|
||||||
|
("border-bottom-style" border-style)
|
||||||
|
("border-bottom-width" border-width)
|
||||||
|
("border-collapse" "collapse" "separate")
|
||||||
|
("border-color" color "transparent")
|
||||||
|
("border-left" border)
|
||||||
|
("border-left-color" border-color)
|
||||||
|
("border-left-style" border-style)
|
||||||
|
("border-left-width" border-width)
|
||||||
|
("border-right" border)
|
||||||
|
("border-right-color" border-color)
|
||||||
|
("border-right-style" border-style)
|
||||||
|
("border-right-width" border-width)
|
||||||
|
("border-spacing" length length)
|
||||||
|
("border-style" border-style)
|
||||||
|
("border-top" border)
|
||||||
|
("border-top-color" border-color)
|
||||||
|
("border-top-style" border-style)
|
||||||
|
("border-top-width" border-width)
|
||||||
|
("border-width" border-width)
|
||||||
|
("bottom" length percentage "auto")
|
||||||
|
("caption-side" "top" "bottom")
|
||||||
|
("clear" "none" "left" "right" "both")
|
||||||
|
("clip" shape "auto")
|
||||||
|
("color" color)
|
||||||
|
("content" "normal" "none" string uri counter "attr()" "open-quote"
|
||||||
|
"close-quote" "no-open-quote" "no-close-quote")
|
||||||
|
("counter-increment" identifier integer "none")
|
||||||
|
("counter-reset" identifier integer "none")
|
||||||
|
("cue" cue-before cue-after)
|
||||||
|
("cue-after" uri "none")
|
||||||
|
("cue-before" uri "none")
|
||||||
|
("cursor" uri "*" "auto" "crosshair" "default" "pointer" "move" "e-resize"
|
||||||
|
"ne-resize" "nw-resize" "n-resize" "se-resize" "sw-resize" "s-resize"
|
||||||
|
"w-resize" "text" "wait" "help" "progress")
|
||||||
|
("direction" "ltr" "rtl")
|
||||||
|
("display" "inline" "block" "list-item" "run-in" "inline-block" "table"
|
||||||
|
"inline-table" "table-row-group" "table-header-group" "table-footer-group"
|
||||||
|
"table-row" "table-column-group" "table-column" "table-cell"
|
||||||
|
"table-caption" "none")
|
||||||
|
("elevation" angle "below" "level" "above" "higher" "lower")
|
||||||
|
("empty-cells" "show" "hide")
|
||||||
|
("float" "left" "right" "none")
|
||||||
|
("font" font-style font-weight font-size "/" line-height
|
||||||
|
font-family "caption" "icon" "menu" "message-box" "small-caption"
|
||||||
|
"status-bar" "normal" "small-caps"
|
||||||
|
;; CSS3
|
||||||
|
font-stretch)
|
||||||
|
("font-family" family-name generic-family)
|
||||||
|
("font-size" absolute-size relative-size length percentage)
|
||||||
|
("font-style" "normal" "italic" "oblique")
|
||||||
|
("font-weight" "normal" "bold" "bolder" "lighter" "100" "200" "300" "400"
|
||||||
|
"500" "600" "700" "800" "900")
|
||||||
|
("height" length percentage "auto")
|
||||||
|
("left" length percentage "auto")
|
||||||
|
("letter-spacing" "normal" length)
|
||||||
|
("line-height" "normal" number length percentage)
|
||||||
|
("list-style" list-style-type list-style-position list-style-image)
|
||||||
|
("list-style-image" uri "none")
|
||||||
|
("list-style-position" "inside" "outside")
|
||||||
|
("list-style-type" "disc" "circle" "square" "decimal" "decimal-leading-zero"
|
||||||
|
"lower-roman" "upper-roman" "lower-greek" "lower-latin" "upper-latin"
|
||||||
|
"armenian" "georgian" "lower-alpha" "upper-alpha" "none")
|
||||||
|
("margin" margin-width)
|
||||||
|
("margin-bottom" margin-width)
|
||||||
|
("margin-left" margin-width)
|
||||||
|
("margin-right" margin-width)
|
||||||
|
("margin-top" margin-width)
|
||||||
|
("max-height" length percentage "none")
|
||||||
|
("max-width" length percentage "none")
|
||||||
|
("min-height" length percentage)
|
||||||
|
("min-width" length percentage)
|
||||||
|
("orphans" integer)
|
||||||
|
("outline" outline-color outline-style outline-width)
|
||||||
|
("outline-color" color "invert")
|
||||||
|
("outline-style" border-style)
|
||||||
|
("outline-width" border-width)
|
||||||
|
("overflow" "visible" "hidden" "scroll" "auto"
|
||||||
|
;; CSS3:
|
||||||
|
"no-display" "no-content")
|
||||||
|
("padding" padding-width)
|
||||||
|
("padding-bottom" padding-width)
|
||||||
|
("padding-left" padding-width)
|
||||||
|
("padding-right" padding-width)
|
||||||
|
("padding-top" padding-width)
|
||||||
|
("page-break-after" "auto" "always" "avoid" "left" "right")
|
||||||
|
("page-break-before" "auto" "always" "avoid" "left" "right")
|
||||||
|
("page-break-inside" "avoid" "auto")
|
||||||
|
("pause" time percentage)
|
||||||
|
("pause-after" time percentage)
|
||||||
|
("pause-before" time percentage)
|
||||||
|
("pitch" frequency "x-low" "low" "medium" "high" "x-high")
|
||||||
|
("pitch-range" number)
|
||||||
|
("play-during" uri "mix" "repeat" "auto" "none")
|
||||||
|
("position" "static" "relative" "absolute" "fixed")
|
||||||
|
("quotes" string string "none")
|
||||||
|
("richness" number)
|
||||||
|
("right" length percentage "auto")
|
||||||
|
("speak" "normal" "none" "spell-out")
|
||||||
|
("speak-header" "once" "always")
|
||||||
|
("speak-numeral" "digits" "continuous")
|
||||||
|
("speak-punctuation" "code" "none")
|
||||||
|
("speech-rate" number "x-slow" "slow" "medium" "fast" "x-fast" "faster"
|
||||||
|
"slower")
|
||||||
|
("stress" number)
|
||||||
|
("table-layout" "auto" "fixed")
|
||||||
|
("text-align" "left" "right" "center" "justify")
|
||||||
|
("text-indent" length percentage)
|
||||||
|
("text-transform" "capitalize" "uppercase" "lowercase" "none")
|
||||||
|
("top" length percentage "auto")
|
||||||
|
("unicode-bidi" "normal" "embed" "bidi-override")
|
||||||
|
("vertical-align" "baseline" "sub" "super" "top" "text-top" "middle"
|
||||||
|
"bottom" "text-bottom" percentage length)
|
||||||
|
("visibility" "visible" "hidden" "collapse")
|
||||||
|
("voice-family" specific-voice generic-voice "*" specific-voice
|
||||||
|
generic-voice)
|
||||||
|
("volume" number percentage "silent" "x-soft" "soft" "medium" "loud"
|
||||||
|
"x-loud")
|
||||||
|
("white-space" "normal" "pre" "nowrap" "pre-wrap" "pre-line")
|
||||||
|
("widows" integer)
|
||||||
|
("width" length percentage "auto")
|
||||||
|
("word-spacing" "normal" length)
|
||||||
|
("z-index" "auto" integer)
|
||||||
|
;; CSS3
|
||||||
|
("align-content" align-stretch "space-between" "space-around")
|
||||||
|
("align-items" align-stretch "baseline")
|
||||||
|
("align-self" align-items "auto")
|
||||||
|
("animation" animation-name animation-duration animation-timing-function
|
||||||
|
animation-delay animation-iteration-count animation-direction
|
||||||
|
animation-fill-mode)
|
||||||
|
("animation-delay" time)
|
||||||
|
("animation-direction" "normal" "reverse" "alternate" "alternate-reverse")
|
||||||
|
("animation-duration" time)
|
||||||
|
("animation-fill-mode" "none" "forwards" "backwards" "both")
|
||||||
|
("animation-iteration-count" integer "infinite")
|
||||||
|
("animation-name" "none")
|
||||||
|
("animation-play-state" "paused" "running")
|
||||||
|
("animation-timing-function" transition-timing-function
|
||||||
|
"step-start" "step-end" "steps(,)")
|
||||||
|
("backface-visibility" "visible" "hidden")
|
||||||
|
("background-clip" background-origin)
|
||||||
|
("background-origin" "border-box" "padding-box" "content-box")
|
||||||
|
("background-size" length percentage "auto" "cover" "contain")
|
||||||
|
("border-image" border-image-outset border-image-repeat border-image-source
|
||||||
|
border-image-slice border-image-width)
|
||||||
|
("border-image-outset" length)
|
||||||
|
("border-image-repeat" "stretch" "repeat" "round" "space")
|
||||||
|
("border-image-source" uri "none")
|
||||||
|
("border-image-slice" length)
|
||||||
|
("border-image-width" length percentage)
|
||||||
|
("border-radius" length)
|
||||||
|
("border-top-left-radius" length)
|
||||||
|
("border-top-right-radius" length)
|
||||||
|
("border-bottom-left-radius" length)
|
||||||
|
("border-bottom-right-radius" length)
|
||||||
|
("box-decoration-break" "slice" "clone")
|
||||||
|
("box-shadow" length color)
|
||||||
|
("box-sizing" "content-box" "border-box")
|
||||||
|
("break-after" "auto" "always" "avoid" "left" "right" "page" "column"
|
||||||
|
"avoid-page" "avoid-column")
|
||||||
|
("break-before" break-after)
|
||||||
|
("break-inside" "avoid" "auto")
|
||||||
|
("columns" column-width column-count)
|
||||||
|
("column-count" integer)
|
||||||
|
("column-fill" "auto" "balance")
|
||||||
|
("column-gap" length "normal")
|
||||||
|
("column-rule" column-rule-width column-rule-style column-rule-color)
|
||||||
|
("column-rule-color" color)
|
||||||
|
("column-rule-style" border-style)
|
||||||
|
("column-rule-width" border-width)
|
||||||
|
("column-span" "all" "none")
|
||||||
|
("column-width" length "auto")
|
||||||
|
("filter" url "blur()" "brightness()" "contrast()" "drop-shadow()"
|
||||||
|
"grayscale()" "hue-rotate()" "invert()" "opacity()" "saturate()" "sepia()")
|
||||||
|
("flex" flex-grow flex-shrink flex-basis)
|
||||||
|
("flex-basis" percentage length "auto")
|
||||||
|
("flex-direction" "row" "row-reverse" "column" "column-reverse")
|
||||||
|
("flex-flow" flex-direction flex-wrap)
|
||||||
|
("flex-grow" number)
|
||||||
|
("flex-shrink" number)
|
||||||
|
("flex-wrap" "nowrap" "wrap" "wrap-reverse")
|
||||||
|
("font-feature-setting" normal string number)
|
||||||
|
("font-kerning" "auto" "normal" "none")
|
||||||
|
("font-language-override" "normal" string)
|
||||||
|
("font-size-adjust" "none" number)
|
||||||
|
("font-stretch" "normal" "ultra-condensed" "extra-condensed" "condensed"
|
||||||
|
"semi-condensed" "semi-expanded" "expanded" "extra-expanded" "ultra-expanded")
|
||||||
|
("font-synthesis" "none" "weight" "style")
|
||||||
|
("font-variant" font-variant-alternates font-variant-caps
|
||||||
|
font-variant-east-asian font-variant-ligatures font-variant-numeric
|
||||||
|
font-variant-position)
|
||||||
|
("font-variant-alternates" "normal" "historical-forms" "stylistic()"
|
||||||
|
"styleset()" "character-variant()" "swash()" "ornaments()" "annotation()")
|
||||||
|
("font-variant-caps" "normal" "small-caps" "all-small-caps" "petite-caps"
|
||||||
|
"all-petite-caps" "unicase" "titling-caps")
|
||||||
|
("font-variant-east-asian" "jis78" "jis83" "jis90" "jis04" "simplified"
|
||||||
|
"traditional" "full-width" "proportional-width" "ruby")
|
||||||
|
("font-variant-ligatures" "normal" "none" "common-ligatures"
|
||||||
|
"no-common-ligatures" "discretionary-ligatures" "no-discretionary-ligatures"
|
||||||
|
"historical-ligatures" "no-historical-ligatures" "contextual" "no-contextual")
|
||||||
|
("font-variant-numeric" "normal" "ordinal" "slashed-zero"
|
||||||
|
"lining-nums" "oldstyle-nums" "proportional-nums" "tabular-nums"
|
||||||
|
"diagonal-fractions" "stacked-fractions")
|
||||||
|
("font-variant-position" "normal" "sub" "super")
|
||||||
|
("hyphens" "none" "manual" "auto")
|
||||||
|
("justify-content" align-common "space-between" "space-around")
|
||||||
|
("line-break" "auto" "loose" "normal" "strict")
|
||||||
|
("marquee-direction" "forward" "reverse")
|
||||||
|
("marquee-play-count" integer "infinite")
|
||||||
|
("marquee-speed" "slow" "normal" "fast")
|
||||||
|
("marquee-style" "scroll" "slide" "alternate")
|
||||||
|
("opacity" number)
|
||||||
|
("order" number)
|
||||||
|
("outline-offset" length)
|
||||||
|
("overflow-x" overflow)
|
||||||
|
("overflow-y" overflow)
|
||||||
|
("overflow-style" "auto" "marquee-line" "marquee-block")
|
||||||
|
("overflow-wrap" "normal" "break-word")
|
||||||
|
("perspective" "none" length)
|
||||||
|
("perspective-origin" percentage length "left" "center" "right" "top" "bottom")
|
||||||
|
("resize" "none" "both" "horizontal" "vertical")
|
||||||
|
("tab-size" integer length)
|
||||||
|
("text-align-last" "auto" "start" "end" "left" "right" "center" "justify")
|
||||||
|
("text-decoration" text-decoration-color text-decoration-line text-decoration-style)
|
||||||
|
("text-decoration-color" color)
|
||||||
|
("text-decoration-line" "none" "underline" "overline" "line-through" "blink")
|
||||||
|
("text-decoration-style" "solid" "double" "dotted" "dashed" "wavy")
|
||||||
|
("text-overflow" "clip" "ellipsis")
|
||||||
|
("text-shadow" color length)
|
||||||
|
("text-underline-position" "auto" "under" "left" "right")
|
||||||
|
("transform" "matrix(,,,,,)" "translate(,)" "translateX()" "translateY()"
|
||||||
|
"scale()" "scaleX()" "scaleY()" "rotate()" "skewX()" "skewY()" "none")
|
||||||
|
("transform-origin" perspective-origin)
|
||||||
|
("transform-style" "flat" "preserve-3d")
|
||||||
|
("transition" transition-property transition-duration
|
||||||
|
transition-timing-function transition-delay)
|
||||||
|
("transition-delay" time)
|
||||||
|
("transition-duration" time)
|
||||||
|
("transition-timing-function"
|
||||||
|
"ease" "linear" "ease-in" "ease-out" "ease-in-out" "cubic-bezier(,,,)")
|
||||||
|
("transition-property" "none" "all" identifier)
|
||||||
|
("word-wrap" overflow-wrap)
|
||||||
|
("word-break" "normal" "break-all" "keep-all"))
|
||||||
|
"A list of CSS properties and their possible values.")
|
||||||
|
|
||||||
|
(defconst company-css-value-classes
|
||||||
|
'((absolute-size "xx-small" "x-small" "small" "medium" "large" "x-large"
|
||||||
|
"xx-large")
|
||||||
|
(align-common "flex-start" "flex-end" "center")
|
||||||
|
(align-stretch align-common "stretch")
|
||||||
|
(border-style "none" "hidden" "dotted" "dashed" "solid" "double" "groove"
|
||||||
|
"ridge" "inset" "outset")
|
||||||
|
(border-width "thick" "medium" "thin")
|
||||||
|
(color "aqua" "black" "blue" "fuchsia" "gray" "green" "lime" "maroon" "navy"
|
||||||
|
"olive" "orange" "purple" "red" "silver" "teal" "white" "yellow")
|
||||||
|
(counter "counter(,)")
|
||||||
|
(family-name "Courier" "Helvetica" "Times")
|
||||||
|
(generic-family "serif" "sans-serif" "cursive" "fantasy" "monospace")
|
||||||
|
(generic-voice "male" "female" "child")
|
||||||
|
(margin-width "auto") ;; length percentage
|
||||||
|
(relative-size "larger" "smaller")
|
||||||
|
(shape "rect(,,,)")
|
||||||
|
(uri "url()"))
|
||||||
|
"A list of CSS property value classes and their contents.")
|
||||||
|
;; missing, because not completable
|
||||||
|
;; <angle><frequency><identifier><integer><length><number><padding-width>
|
||||||
|
;; <percentage><specific-voice><string><time><uri>
|
||||||
|
|
||||||
|
(defconst company-css-html-tags
|
||||||
|
'("a" "abbr" "acronym" "address" "applet" "area" "b" "base" "basefont" "bdo"
|
||||||
|
"big" "blockquote" "body" "br" "button" "caption" "center" "cite" "code"
|
||||||
|
"col" "colgroup" "dd" "del" "dfn" "dir" "div" "dl" "dt" "em" "fieldset"
|
||||||
|
"font" "form" "frame" "frameset" "h1" "h2" "h3" "h4" "h5" "h6" "head" "hr"
|
||||||
|
"html" "i" "iframe" "img" "input" "ins" "isindex" "kbd" "label" "legend"
|
||||||
|
"li" "link" "map" "menu" "meta" "noframes" "noscript" "object" "ol"
|
||||||
|
"optgroup" "option" "p" "param" "pre" "q" "s" "samp" "script" "select"
|
||||||
|
"small" "span" "strike" "strong" "style" "sub" "sup" "table" "tbody" "td"
|
||||||
|
"textarea" "tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var"
|
||||||
|
;; HTML5
|
||||||
|
"section" "article" "aside" "header" "footer" "nav" "figure" "figcaption"
|
||||||
|
"time" "mark" "main")
|
||||||
|
"A list of HTML tags for use in CSS completion.")
|
||||||
|
|
||||||
|
(defconst company-css-pseudo-classes
|
||||||
|
'("active" "after" "before" "first" "first-child" "first-letter" "first-line"
|
||||||
|
"focus" "hover" "lang" "left" "link" "right" "visited")
|
||||||
|
"Identifiers for CSS pseudo-elements and pseudo-classes.")
|
||||||
|
|
||||||
|
(defconst company-css-property-cache (make-hash-table :size 115 :test 'equal))
|
||||||
|
|
||||||
|
(defun company-css-property-values (attribute)
|
||||||
|
"Access the `company-css-property-alist' cached and flattened."
|
||||||
|
(or (gethash attribute company-css-property-cache)
|
||||||
|
(let (results)
|
||||||
|
(dolist (value (cdr (assoc attribute company-css-property-alist)))
|
||||||
|
(if (symbolp value)
|
||||||
|
(dolist (child (or (cdr (assoc value company-css-value-classes))
|
||||||
|
(company-css-property-values
|
||||||
|
(symbol-name value))))
|
||||||
|
(push child results))
|
||||||
|
(push value results)))
|
||||||
|
(setq results (sort results 'string<))
|
||||||
|
(puthash attribute
|
||||||
|
(if (fboundp 'delete-consecutive-dups)
|
||||||
|
(delete-consecutive-dups results)
|
||||||
|
(delete-dups results))
|
||||||
|
company-css-property-cache)
|
||||||
|
results)))
|
||||||
|
|
||||||
|
;;; bracket detection
|
||||||
|
|
||||||
|
(defconst company-css-braces-syntax-table
|
||||||
|
(let ((table (make-syntax-table)))
|
||||||
|
(setf (aref table ?{) '(4 . 125))
|
||||||
|
(setf (aref table ?}) '(5 . 123))
|
||||||
|
table)
|
||||||
|
"A syntax table giving { and } paren syntax.")
|
||||||
|
|
||||||
|
(defun company-css-inside-braces-p ()
|
||||||
|
"Return non-nil, if point is within matched { and }."
|
||||||
|
(ignore-errors
|
||||||
|
(with-syntax-table company-css-braces-syntax-table
|
||||||
|
(let ((parse-sexp-ignore-comments t))
|
||||||
|
(scan-lists (point) -1 1)))))
|
||||||
|
|
||||||
|
;;; tags
|
||||||
|
(defconst company-css-tag-regexp
|
||||||
|
(concat "\\(?:\\`\\|}\\)[[:space:]]*"
|
||||||
|
;; multiple
|
||||||
|
"\\(?:"
|
||||||
|
;; previous tags:
|
||||||
|
"\\(?:#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\(?:\\[[^]]*\\]\\)?"
|
||||||
|
;; space or selectors
|
||||||
|
"\\(?:[[:space:]]+\\|[[:space:]]*[+,>][[:space:]]*\\)"
|
||||||
|
"\\)*"
|
||||||
|
"\\(\\(?:#\\|\\_<[[:alpha:]]\\)\\(?:[[:alnum:]-#]*\\_>\\)?\\_>\\|\\)"
|
||||||
|
"\\=")
|
||||||
|
"A regular expression matching CSS tags.")
|
||||||
|
|
||||||
|
;;; pseudo id
|
||||||
|
(defconst company-css-pseudo-regexp
|
||||||
|
(concat "\\(?:\\`\\|}\\)[[:space:]]*"
|
||||||
|
;; multiple
|
||||||
|
"\\(?:"
|
||||||
|
;; previous tags:
|
||||||
|
"\\(?:#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\(?:\\[[^]]*\\]\\)?"
|
||||||
|
;; space or delimiters
|
||||||
|
"\\(?:[[:space:]]+\\|[[:space:]]*[+,>][[:space:]]*\\)"
|
||||||
|
"\\)*"
|
||||||
|
"\\(?:\\(?:\\#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\):"
|
||||||
|
"\\([[:alpha:]-]+\\_>\\|\\)\\_>\\=")
|
||||||
|
"A regular expression matching CSS pseudo classes.")
|
||||||
|
|
||||||
|
;;; properties
|
||||||
|
|
||||||
|
(defun company-css-grab-property ()
|
||||||
|
"Return the CSS property before point, if any.
|
||||||
|
Returns \"\" if no property found, but feasible at this position."
|
||||||
|
(when (company-css-inside-braces-p)
|
||||||
|
(company-grab-symbol)))
|
||||||
|
|
||||||
|
;;; values
|
||||||
|
(defconst company-css-property-value-regexp
|
||||||
|
"\\_<\\([[:alpha:]-]+\\):\\(?:[^{};]*[[:space:]]+\\)?\\([^{};]*\\_>\\|\\)\\="
|
||||||
|
"A regular expression matching CSS tags.")
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-css (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for `css-mode'."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-css))
|
||||||
|
(prefix (and (or (derived-mode-p 'css-mode)
|
||||||
|
(and (derived-mode-p 'web-mode)
|
||||||
|
(string= (web-mode-language-at-pos) "css")))
|
||||||
|
(or (company-grab company-css-tag-regexp 1)
|
||||||
|
(company-grab company-css-pseudo-regexp 1)
|
||||||
|
(company-grab company-css-property-value-regexp 2
|
||||||
|
(line-beginning-position))
|
||||||
|
(company-css-grab-property))))
|
||||||
|
(candidates
|
||||||
|
(cond
|
||||||
|
((company-grab company-css-tag-regexp 1)
|
||||||
|
(all-completions arg company-css-html-tags))
|
||||||
|
((company-grab company-css-pseudo-regexp 1)
|
||||||
|
(all-completions arg company-css-pseudo-classes))
|
||||||
|
((company-grab company-css-property-value-regexp 2
|
||||||
|
(line-beginning-position))
|
||||||
|
(all-completions arg
|
||||||
|
(company-css-property-values
|
||||||
|
(company-grab company-css-property-value-regexp 1))))
|
||||||
|
((company-css-grab-property)
|
||||||
|
(all-completions arg company-css-property-alist))))
|
||||||
|
(sorted t)))
|
||||||
|
|
||||||
|
(provide 'company-css)
|
||||||
|
;;; company-css.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-css.elc
Normal file
BIN
elpa/company-20191029.2116/company-css.elc
Normal file
Binary file not shown.
104
elpa/company-20191029.2116/company-dabbrev-code.el
Normal file
104
elpa/company-20191029.2116/company-dabbrev-code.el
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
;;; company-dabbrev-code.el --- dabbrev-like company-mode backend for code -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2011, 2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'company-dabbrev)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-dabbrev-code nil
|
||||||
|
"dabbrev-like completion backend for code."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-code-modes
|
||||||
|
'(prog-mode
|
||||||
|
batch-file-mode csharp-mode css-mode erlang-mode haskell-mode jde-mode
|
||||||
|
lua-mode python-mode)
|
||||||
|
"Modes that use `company-dabbrev-code'.
|
||||||
|
In all these modes (and their derivatives) `company-dabbrev-code' will
|
||||||
|
complete only symbols, not text in comments or strings. In other modes
|
||||||
|
`company-dabbrev-code' will pass control to other backends
|
||||||
|
\(e.g. `company-dabbrev'\). Value t means complete in all modes."
|
||||||
|
:type '(choice (repeat :tag "Some modes" (symbol :tag "Major mode"))
|
||||||
|
(const :tag "All modes" t)))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-code-other-buffers t
|
||||||
|
"Determines whether `company-dabbrev-code' should search other buffers.
|
||||||
|
If `all', search all other buffers, except the ignored ones. If t, search
|
||||||
|
buffers with the same major mode. If `code', search all buffers with major
|
||||||
|
modes in `company-dabbrev-code-modes', or derived from one of them. See
|
||||||
|
also `company-dabbrev-code-time-limit'."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(const :tag "Same major mode" t)
|
||||||
|
(const :tag "Code major modes" code)
|
||||||
|
(const :tag "All" all)))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-code-time-limit .1
|
||||||
|
"Determines how long `company-dabbrev-code' should look for matches."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(number :tag "Seconds")))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-code-everywhere nil
|
||||||
|
"Non-nil to offer completions in comments and strings."
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-code-ignore-case nil
|
||||||
|
"Non-nil to ignore case when collecting completion candidates."
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defun company-dabbrev-code--make-regexp (prefix)
|
||||||
|
(concat "\\_<" (if (equal prefix "")
|
||||||
|
"\\([a-zA-Z]\\|\\s_\\)"
|
||||||
|
(regexp-quote prefix))
|
||||||
|
"\\(\\sw\\|\\s_\\)*\\_>"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-dabbrev-code (command &optional arg &rest ignored)
|
||||||
|
"dabbrev-like `company-mode' backend for code.
|
||||||
|
The backend looks for all symbols in the current buffer that aren't in
|
||||||
|
comments or strings."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-dabbrev-code))
|
||||||
|
(prefix (and (or (eq t company-dabbrev-code-modes)
|
||||||
|
(apply #'derived-mode-p company-dabbrev-code-modes))
|
||||||
|
(or company-dabbrev-code-everywhere
|
||||||
|
(not (company-in-string-or-comment)))
|
||||||
|
(or (company-grab-symbol) 'stop)))
|
||||||
|
(candidates (let ((case-fold-search company-dabbrev-code-ignore-case))
|
||||||
|
(company-dabbrev--search
|
||||||
|
(company-dabbrev-code--make-regexp arg)
|
||||||
|
company-dabbrev-code-time-limit
|
||||||
|
(pcase company-dabbrev-code-other-buffers
|
||||||
|
(`t (list major-mode))
|
||||||
|
(`code company-dabbrev-code-modes)
|
||||||
|
(`all `all))
|
||||||
|
(not company-dabbrev-code-everywhere))))
|
||||||
|
(ignore-case company-dabbrev-code-ignore-case)
|
||||||
|
(duplicates t)))
|
||||||
|
|
||||||
|
(provide 'company-dabbrev-code)
|
||||||
|
;;; company-dabbrev-code.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-dabbrev-code.elc
Normal file
BIN
elpa/company-20191029.2116/company-dabbrev-code.elc
Normal file
Binary file not shown.
206
elpa/company-20191029.2116/company-dabbrev.el
Normal file
206
elpa/company-20191029.2116/company-dabbrev.el
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
;;; company-dabbrev.el --- dabbrev-like company-mode completion backend -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2011, 2014, 2015, 2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-dabbrev nil
|
||||||
|
"dabbrev-like completion backend."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-other-buffers 'all
|
||||||
|
"Determines whether `company-dabbrev' should search other buffers.
|
||||||
|
If `all', search all other buffers, except the ignored ones. If t, search
|
||||||
|
buffers with the same major mode. See also `company-dabbrev-time-limit'."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(const :tag "Same major mode" t)
|
||||||
|
(const :tag "All" all)))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-ignore-buffers "\\`[ *]"
|
||||||
|
"Regexp matching the names of buffers to ignore.
|
||||||
|
Or a function that returns non-nil for such buffers."
|
||||||
|
:type '(choice (regexp :tag "Regexp")
|
||||||
|
(function :tag "Predicate"))
|
||||||
|
:package-version '(company . "0.9.0"))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-time-limit .1
|
||||||
|
"Determines how many seconds `company-dabbrev' should look for matches."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(number :tag "Seconds")))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-char-regexp "\\sw"
|
||||||
|
"A regular expression matching the characters `company-dabbrev' looks for."
|
||||||
|
:type 'regexp)
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-ignore-case 'keep-prefix
|
||||||
|
"Non-nil to ignore case when collecting completion candidates.
|
||||||
|
When it's `keep-prefix', the text before point will remain unchanged after
|
||||||
|
candidate is inserted, even some of its characters have different case."
|
||||||
|
:type '(choice
|
||||||
|
(const :tag "Don't ignore case" nil)
|
||||||
|
(const :tag "Ignore case" t)
|
||||||
|
(const :tag "Keep case before point" keep-prefix)))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-downcase 'case-replace
|
||||||
|
"Whether to downcase the returned candidates.
|
||||||
|
|
||||||
|
The value of nil means keep them as-is.
|
||||||
|
`case-replace' means use the value of `case-replace'.
|
||||||
|
Any other value means downcase.
|
||||||
|
|
||||||
|
If you set this value to nil, you may also want to set
|
||||||
|
`company-dabbrev-ignore-case' to any value other than `keep-prefix'."
|
||||||
|
:type '(choice
|
||||||
|
(const :tag "Keep as-is" nil)
|
||||||
|
(const :tag "Downcase" t)
|
||||||
|
(const :tag "Use case-replace" case-replace)))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-minimum-length 4
|
||||||
|
"The minimum length for the completion candidate to be included.
|
||||||
|
This variable affects both `company-dabbrev' and `company-dabbrev-code'."
|
||||||
|
:type 'integer
|
||||||
|
:package-version '(company . "0.8.3"))
|
||||||
|
|
||||||
|
(defcustom company-dabbrev-ignore-invisible nil
|
||||||
|
"Non-nil to skip invisible text."
|
||||||
|
:type 'boolean
|
||||||
|
:package-version '(company . "0.9.0"))
|
||||||
|
|
||||||
|
(defmacro company-dabbrev--time-limit-while (test start limit freq &rest body)
|
||||||
|
(declare (indent 3) (debug t))
|
||||||
|
`(let ((company-time-limit-while-counter 0))
|
||||||
|
(catch 'done
|
||||||
|
(while ,test
|
||||||
|
,@body
|
||||||
|
(and ,limit
|
||||||
|
(= (cl-incf company-time-limit-while-counter) ,freq)
|
||||||
|
(setq company-time-limit-while-counter 0)
|
||||||
|
(> (float-time (time-since ,start)) ,limit)
|
||||||
|
(throw 'done 'company-time-out))))))
|
||||||
|
|
||||||
|
(defun company-dabbrev--make-regexp ()
|
||||||
|
(concat "\\(?:" company-dabbrev-char-regexp "\\)+"))
|
||||||
|
|
||||||
|
(defun company-dabbrev--search-buffer (regexp pos symbols start limit
|
||||||
|
ignore-comments)
|
||||||
|
(save-excursion
|
||||||
|
(cl-labels ((maybe-collect-match
|
||||||
|
()
|
||||||
|
(let ((match (match-string-no-properties 0)))
|
||||||
|
(when (and (>= (length match) company-dabbrev-minimum-length)
|
||||||
|
(not (and company-dabbrev-ignore-invisible
|
||||||
|
(invisible-p (match-beginning 0)))))
|
||||||
|
(push match symbols)))))
|
||||||
|
(goto-char (if pos (1- pos) (point-min)))
|
||||||
|
;; Search before pos.
|
||||||
|
(let ((tmp-end (point)))
|
||||||
|
(company-dabbrev--time-limit-while (and (not (input-pending-p))
|
||||||
|
(> tmp-end (point-min)))
|
||||||
|
start limit 1
|
||||||
|
(ignore-errors
|
||||||
|
(forward-char -10000))
|
||||||
|
(forward-line 0)
|
||||||
|
(save-excursion
|
||||||
|
;; Before, we used backward search, but it matches non-greedily, and
|
||||||
|
;; that forced us to use the "beginning/end of word" anchors in
|
||||||
|
;; `company-dabbrev--make-regexp'. It's also about 2x slower.
|
||||||
|
(while (and (not (input-pending-p))
|
||||||
|
(re-search-forward regexp tmp-end t))
|
||||||
|
(if (and ignore-comments (save-match-data (company-in-string-or-comment)))
|
||||||
|
(re-search-forward "\\s>\\|\\s!\\|\\s\"" tmp-end t)
|
||||||
|
(maybe-collect-match))))
|
||||||
|
(setq tmp-end (point))))
|
||||||
|
(goto-char (or pos (point-min)))
|
||||||
|
;; Search after pos.
|
||||||
|
(company-dabbrev--time-limit-while (and (not (input-pending-p))
|
||||||
|
(re-search-forward regexp nil t))
|
||||||
|
start limit 25
|
||||||
|
(if (and ignore-comments (save-match-data (company-in-string-or-comment)))
|
||||||
|
(re-search-forward "\\s>\\|\\s!\\|\\s\"" nil t)
|
||||||
|
(maybe-collect-match)))
|
||||||
|
symbols)))
|
||||||
|
|
||||||
|
(defun company-dabbrev--search (regexp &optional limit other-buffer-modes
|
||||||
|
ignore-comments)
|
||||||
|
(let* ((start (current-time))
|
||||||
|
(symbols (company-dabbrev--search-buffer regexp (point) nil start limit
|
||||||
|
ignore-comments)))
|
||||||
|
(when other-buffer-modes
|
||||||
|
(cl-dolist (buffer (delq (current-buffer) (buffer-list)))
|
||||||
|
(unless (if (stringp company-dabbrev-ignore-buffers)
|
||||||
|
(string-match-p company-dabbrev-ignore-buffers
|
||||||
|
(buffer-name buffer))
|
||||||
|
(funcall company-dabbrev-ignore-buffers buffer))
|
||||||
|
(with-current-buffer buffer
|
||||||
|
(when (or (eq other-buffer-modes 'all)
|
||||||
|
(apply #'derived-mode-p other-buffer-modes))
|
||||||
|
(setq symbols
|
||||||
|
(company-dabbrev--search-buffer regexp nil symbols start
|
||||||
|
limit ignore-comments)))))
|
||||||
|
(and limit
|
||||||
|
(> (float-time (time-since start)) limit)
|
||||||
|
(cl-return))))
|
||||||
|
symbols))
|
||||||
|
|
||||||
|
(defun company-dabbrev--prefix ()
|
||||||
|
;; Not in the middle of a word.
|
||||||
|
(unless (looking-at company-dabbrev-char-regexp)
|
||||||
|
;; Emacs can't do greedy backward-search.
|
||||||
|
(company-grab-line (format "\\(?:^\\| \\)[^ ]*?\\(\\(?:%s\\)*\\)"
|
||||||
|
company-dabbrev-char-regexp)
|
||||||
|
1)))
|
||||||
|
|
||||||
|
(defun company-dabbrev--filter (prefix candidates)
|
||||||
|
(let ((completion-ignore-case company-dabbrev-ignore-case))
|
||||||
|
(all-completions prefix candidates)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-dabbrev (command &optional arg &rest ignored)
|
||||||
|
"dabbrev-like `company-mode' completion backend."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-dabbrev))
|
||||||
|
(prefix (company-dabbrev--prefix))
|
||||||
|
(candidates
|
||||||
|
(let* ((case-fold-search company-dabbrev-ignore-case)
|
||||||
|
(words (company-dabbrev--search (company-dabbrev--make-regexp)
|
||||||
|
company-dabbrev-time-limit
|
||||||
|
(pcase company-dabbrev-other-buffers
|
||||||
|
(`t (list major-mode))
|
||||||
|
(`all `all))))
|
||||||
|
(downcase-p (if (eq company-dabbrev-downcase 'case-replace)
|
||||||
|
case-replace
|
||||||
|
company-dabbrev-downcase)))
|
||||||
|
(setq words (company-dabbrev--filter arg words))
|
||||||
|
(if downcase-p
|
||||||
|
(mapcar 'downcase words)
|
||||||
|
words)))
|
||||||
|
(ignore-case company-dabbrev-ignore-case)
|
||||||
|
(duplicates t)))
|
||||||
|
|
||||||
|
(provide 'company-dabbrev)
|
||||||
|
;;; company-dabbrev.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-dabbrev.elc
Normal file
BIN
elpa/company-20191029.2116/company-dabbrev.elc
Normal file
Binary file not shown.
186
elpa/company-20191029.2116/company-eclim.el
Normal file
186
elpa/company-20191029.2116/company-eclim.el
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
;;; company-eclim.el --- company-mode completion backend for Eclim
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2011, 2013, 2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; Using `emacs-eclim' together with (or instead of) this backend is
|
||||||
|
;; recommended, as it allows you to use other Eclim features.
|
||||||
|
;;
|
||||||
|
;; The alternative backend provided by `emacs-eclim' uses `yasnippet'
|
||||||
|
;; instead of `company-template' to expand function calls, and it supports
|
||||||
|
;; some languages other than Java.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'company-template)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-eclim nil
|
||||||
|
"Completion backend for Eclim."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defun company-eclim-executable-find ()
|
||||||
|
(let (file)
|
||||||
|
(cl-dolist (eclipse-root '("/Applications/eclipse" "/usr/lib/eclipse"
|
||||||
|
"/usr/local/lib/eclipse"))
|
||||||
|
(and (file-exists-p (setq file (expand-file-name "plugins" eclipse-root)))
|
||||||
|
(setq file (car (last (directory-files file t "^org.eclim_"))))
|
||||||
|
(file-exists-p (setq file (expand-file-name "bin/eclim" file)))
|
||||||
|
(cl-return file)))))
|
||||||
|
|
||||||
|
(defcustom company-eclim-executable
|
||||||
|
(or (bound-and-true-p eclim-executable)
|
||||||
|
(executable-find "eclim")
|
||||||
|
(company-eclim-executable-find))
|
||||||
|
"Location of eclim executable."
|
||||||
|
:type 'file)
|
||||||
|
|
||||||
|
(defcustom company-eclim-auto-save t
|
||||||
|
"Determines whether to save the buffer when retrieving completions.
|
||||||
|
eclim can only complete correctly when the buffer has been saved."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(const :tag "On" t)))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defvar-local company-eclim--project-dir 'unknown)
|
||||||
|
|
||||||
|
(defvar-local company-eclim--project-name nil)
|
||||||
|
|
||||||
|
(declare-function json-read "json")
|
||||||
|
(defvar json-array-type)
|
||||||
|
|
||||||
|
(defun company-eclim--call-process (&rest args)
|
||||||
|
(let ((coding-system-for-read 'utf-8)
|
||||||
|
res)
|
||||||
|
(require 'json)
|
||||||
|
(with-temp-buffer
|
||||||
|
(if (= 0 (setq res (apply 'call-process company-eclim-executable nil t nil
|
||||||
|
"-command" args)))
|
||||||
|
(let ((json-array-type 'list))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(unless (eobp)
|
||||||
|
(json-read)))
|
||||||
|
(message "Company-eclim command failed with error %d:\n%s" res
|
||||||
|
(buffer-substring (point-min) (point-max)))
|
||||||
|
nil))))
|
||||||
|
|
||||||
|
(defun company-eclim--project-list ()
|
||||||
|
(company-eclim--call-process "project_list"))
|
||||||
|
|
||||||
|
(defun company-eclim--project-dir ()
|
||||||
|
(if (eq company-eclim--project-dir 'unknown)
|
||||||
|
(let ((dir (locate-dominating-file buffer-file-name ".project")))
|
||||||
|
(when dir
|
||||||
|
(setq company-eclim--project-dir
|
||||||
|
(directory-file-name
|
||||||
|
(expand-file-name dir)))))
|
||||||
|
company-eclim--project-dir))
|
||||||
|
|
||||||
|
(defun company-eclim--project-name ()
|
||||||
|
(or company-eclim--project-name
|
||||||
|
(let ((dir (company-eclim--project-dir)))
|
||||||
|
(when dir
|
||||||
|
(setq company-eclim--project-name
|
||||||
|
(cl-loop for project in (company-eclim--project-list)
|
||||||
|
when (equal (cdr (assoc 'path project)) dir)
|
||||||
|
return (cdr (assoc 'name project))))))))
|
||||||
|
|
||||||
|
(defun company-eclim--candidates (prefix)
|
||||||
|
(interactive "d")
|
||||||
|
(let ((project-file (file-relative-name buffer-file-name
|
||||||
|
(company-eclim--project-dir)))
|
||||||
|
completions)
|
||||||
|
(when company-eclim-auto-save
|
||||||
|
(when (buffer-modified-p)
|
||||||
|
(basic-save-buffer))
|
||||||
|
;; FIXME: Sometimes this isn't finished when we complete.
|
||||||
|
(company-eclim--call-process "java_src_update"
|
||||||
|
"-p" (company-eclim--project-name)
|
||||||
|
"-f" project-file))
|
||||||
|
(dolist (item (cdr (assoc 'completions
|
||||||
|
(company-eclim--call-process
|
||||||
|
"java_complete" "-p" (company-eclim--project-name)
|
||||||
|
"-f" project-file
|
||||||
|
"-o" (number-to-string
|
||||||
|
(company-eclim--search-point prefix))
|
||||||
|
"-e" "utf-8"
|
||||||
|
"-l" "standard"))))
|
||||||
|
(let* ((meta (cdr (assoc 'info item)))
|
||||||
|
(completion meta))
|
||||||
|
(when (string-match " ?[(:-]" completion)
|
||||||
|
(setq completion (substring completion 0 (match-beginning 0))))
|
||||||
|
(put-text-property 0 1 'meta meta completion)
|
||||||
|
(push completion completions)))
|
||||||
|
(let ((completion-ignore-case nil))
|
||||||
|
(all-completions prefix completions))))
|
||||||
|
|
||||||
|
(defun company-eclim--search-point (prefix)
|
||||||
|
(if (or (cl-plusp (length prefix)) (eq (char-before) ?.))
|
||||||
|
(1- (point))
|
||||||
|
(point)))
|
||||||
|
|
||||||
|
(defun company-eclim--meta (candidate)
|
||||||
|
(get-text-property 0 'meta candidate))
|
||||||
|
|
||||||
|
(defun company-eclim--annotation (candidate)
|
||||||
|
(let ((meta (company-eclim--meta candidate)))
|
||||||
|
(when (string-match "\\(([^-]*\\) -" meta)
|
||||||
|
(substring meta (match-beginning 1) (match-end 1)))))
|
||||||
|
|
||||||
|
(defun company-eclim--prefix ()
|
||||||
|
(let ((prefix (company-grab-symbol)))
|
||||||
|
(when prefix
|
||||||
|
;; Completion candidates for annotations don't include '@'.
|
||||||
|
(when (eq ?@ (string-to-char prefix))
|
||||||
|
(setq prefix (substring prefix 1)))
|
||||||
|
prefix)))
|
||||||
|
|
||||||
|
(defun company-eclim (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for Eclim.
|
||||||
|
Eclim provides access to Eclipse Java IDE features for other editors.
|
||||||
|
|
||||||
|
Eclim version 1.7.13 or newer (?) is required.
|
||||||
|
|
||||||
|
Completions only work correctly when the buffer has been saved.
|
||||||
|
`company-eclim-auto-save' determines whether to do this automatically."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-eclim))
|
||||||
|
(prefix (and (derived-mode-p 'java-mode 'jde-mode)
|
||||||
|
buffer-file-name
|
||||||
|
company-eclim-executable
|
||||||
|
(company-eclim--project-name)
|
||||||
|
(not (company-in-string-or-comment))
|
||||||
|
(or (company-eclim--prefix) 'stop)))
|
||||||
|
(candidates (company-eclim--candidates arg))
|
||||||
|
(meta (company-eclim--meta arg))
|
||||||
|
;; because "" doesn't return everything
|
||||||
|
(no-cache (equal arg ""))
|
||||||
|
(annotation (company-eclim--annotation arg))
|
||||||
|
(post-completion (let ((anno (company-eclim--annotation arg)))
|
||||||
|
(when anno
|
||||||
|
(insert anno)
|
||||||
|
(company-template-c-like-templatify anno))))))
|
||||||
|
|
||||||
|
(provide 'company-eclim)
|
||||||
|
;;; company-eclim.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-eclim.elc
Normal file
BIN
elpa/company-20191029.2116/company-eclim.elc
Normal file
Binary file not shown.
226
elpa/company-20191029.2116/company-elisp.el
Normal file
226
elpa/company-20191029.2116/company-elisp.el
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
;;; company-elisp.el --- company-mode completion backend for Emacs Lisp -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2011-2013, 2017 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; In newer versions of Emacs, company-capf is used instead.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
(require 'help-mode)
|
||||||
|
(require 'find-func)
|
||||||
|
|
||||||
|
(defgroup company-elisp nil
|
||||||
|
"Completion backend for Emacs Lisp."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-elisp-detect-function-context t
|
||||||
|
"If enabled, offer Lisp functions only in appropriate contexts.
|
||||||
|
Functions are offered for completion only after ' and \(."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(const :tag "On" t)))
|
||||||
|
|
||||||
|
(defcustom company-elisp-show-locals-first t
|
||||||
|
"If enabled, locally bound variables and functions are displayed
|
||||||
|
first in the candidates list."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(const :tag "On" t)))
|
||||||
|
|
||||||
|
(defun company-elisp--prefix ()
|
||||||
|
(let ((prefix (company-grab-symbol)))
|
||||||
|
(if prefix
|
||||||
|
(when (if (company-in-string-or-comment)
|
||||||
|
(= (char-before (- (point) (length prefix))) ?`)
|
||||||
|
(company-elisp--should-complete))
|
||||||
|
prefix)
|
||||||
|
'stop)))
|
||||||
|
|
||||||
|
(defun company-elisp--predicate (symbol)
|
||||||
|
(or (boundp symbol)
|
||||||
|
(fboundp symbol)
|
||||||
|
(facep symbol)
|
||||||
|
(featurep symbol)))
|
||||||
|
|
||||||
|
(defun company-elisp--fns-regexp (&rest names)
|
||||||
|
(concat "\\_<\\(?:cl-\\)?" (regexp-opt names) "\\*?\\_>"))
|
||||||
|
|
||||||
|
(defvar company-elisp-parse-limit 30)
|
||||||
|
(defvar company-elisp-parse-depth 100)
|
||||||
|
|
||||||
|
(defvar company-elisp-defun-names '("defun" "defmacro" "defsubst"))
|
||||||
|
|
||||||
|
(defvar company-elisp-var-binding-regexp
|
||||||
|
(apply #'company-elisp--fns-regexp "let" "lambda" "lexical-let"
|
||||||
|
company-elisp-defun-names)
|
||||||
|
"Regular expression matching head of a multiple variable bindings form.")
|
||||||
|
|
||||||
|
(defvar company-elisp-var-binding-regexp-1
|
||||||
|
(company-elisp--fns-regexp "dolist" "dotimes")
|
||||||
|
"Regular expression matching head of a form with one variable binding.")
|
||||||
|
|
||||||
|
(defvar company-elisp-fun-binding-regexp
|
||||||
|
(company-elisp--fns-regexp "flet" "labels")
|
||||||
|
"Regular expression matching head of a function bindings form.")
|
||||||
|
|
||||||
|
(defvar company-elisp-defuns-regexp
|
||||||
|
(concat "([ \t\n]*"
|
||||||
|
(apply #'company-elisp--fns-regexp company-elisp-defun-names)))
|
||||||
|
|
||||||
|
(defun company-elisp--should-complete ()
|
||||||
|
(let ((start (point))
|
||||||
|
(depth (car (syntax-ppss))))
|
||||||
|
(not
|
||||||
|
(when (> depth 0)
|
||||||
|
(save-excursion
|
||||||
|
(up-list (- depth))
|
||||||
|
(when (looking-at company-elisp-defuns-regexp)
|
||||||
|
(forward-char)
|
||||||
|
(forward-sexp 1)
|
||||||
|
(unless (= (point) start)
|
||||||
|
(condition-case nil
|
||||||
|
(let ((args-end (scan-sexps (point) 2)))
|
||||||
|
(or (null args-end)
|
||||||
|
(> args-end start)))
|
||||||
|
(scan-error
|
||||||
|
t)))))))))
|
||||||
|
|
||||||
|
(defun company-elisp--locals (prefix functions-p)
|
||||||
|
(let ((regexp (concat "[ \t\n]*\\(\\_<" (regexp-quote prefix)
|
||||||
|
"\\(?:\\sw\\|\\s_\\)*\\_>\\)"))
|
||||||
|
(pos (point))
|
||||||
|
res)
|
||||||
|
(condition-case nil
|
||||||
|
(save-excursion
|
||||||
|
(dotimes (_ company-elisp-parse-depth)
|
||||||
|
(up-list -1)
|
||||||
|
(save-excursion
|
||||||
|
(when (eq (char-after) ?\()
|
||||||
|
(forward-char 1)
|
||||||
|
(when (ignore-errors
|
||||||
|
(save-excursion (forward-list)
|
||||||
|
(<= (point) pos)))
|
||||||
|
(skip-chars-forward " \t\n")
|
||||||
|
(cond
|
||||||
|
((looking-at (if functions-p
|
||||||
|
company-elisp-fun-binding-regexp
|
||||||
|
company-elisp-var-binding-regexp))
|
||||||
|
(down-list 1)
|
||||||
|
(condition-case nil
|
||||||
|
(dotimes (_ company-elisp-parse-limit)
|
||||||
|
(save-excursion
|
||||||
|
(when (looking-at "[ \t\n]*(")
|
||||||
|
(down-list 1))
|
||||||
|
(when (looking-at regexp)
|
||||||
|
(cl-pushnew (match-string-no-properties 1) res)))
|
||||||
|
(forward-sexp))
|
||||||
|
(scan-error nil)))
|
||||||
|
((unless functions-p
|
||||||
|
(looking-at company-elisp-var-binding-regexp-1))
|
||||||
|
(down-list 1)
|
||||||
|
(when (looking-at regexp)
|
||||||
|
(cl-pushnew (match-string-no-properties 1) res)))))))))
|
||||||
|
(scan-error nil))
|
||||||
|
res))
|
||||||
|
|
||||||
|
(defun company-elisp-candidates (prefix)
|
||||||
|
(let* ((predicate (company-elisp--candidates-predicate prefix))
|
||||||
|
(locals (company-elisp--locals prefix (eq predicate 'fboundp)))
|
||||||
|
(globals (company-elisp--globals prefix predicate))
|
||||||
|
(locals (cl-loop for local in locals
|
||||||
|
when (not (member local globals))
|
||||||
|
collect local)))
|
||||||
|
(if company-elisp-show-locals-first
|
||||||
|
(append (sort locals 'string<)
|
||||||
|
(sort globals 'string<))
|
||||||
|
(append locals globals))))
|
||||||
|
|
||||||
|
(defun company-elisp--globals (prefix predicate)
|
||||||
|
(all-completions prefix obarray predicate))
|
||||||
|
|
||||||
|
(defun company-elisp--candidates-predicate (prefix)
|
||||||
|
(let* ((completion-ignore-case nil)
|
||||||
|
(beg (- (point) (length prefix)))
|
||||||
|
(before (char-before beg)))
|
||||||
|
(if (and company-elisp-detect-function-context
|
||||||
|
(not (memq before '(?' ?`))))
|
||||||
|
(if (and (eq before ?\()
|
||||||
|
(not
|
||||||
|
(save-excursion
|
||||||
|
(ignore-errors
|
||||||
|
(goto-char (1- beg))
|
||||||
|
(or (company-elisp--before-binding-varlist-p)
|
||||||
|
(progn
|
||||||
|
(up-list -1)
|
||||||
|
(company-elisp--before-binding-varlist-p)))))))
|
||||||
|
'fboundp
|
||||||
|
'boundp)
|
||||||
|
'company-elisp--predicate)))
|
||||||
|
|
||||||
|
(defun company-elisp--before-binding-varlist-p ()
|
||||||
|
(save-excursion
|
||||||
|
(and (prog1 (search-backward "(")
|
||||||
|
(forward-char 1))
|
||||||
|
(looking-at company-elisp-var-binding-regexp))))
|
||||||
|
|
||||||
|
(defun company-elisp--doc (symbol)
|
||||||
|
(let* ((symbol (intern symbol))
|
||||||
|
(doc (if (fboundp symbol)
|
||||||
|
(documentation symbol t)
|
||||||
|
(documentation-property symbol 'variable-documentation t))))
|
||||||
|
(and (stringp doc)
|
||||||
|
(string-match ".*$" doc)
|
||||||
|
(match-string 0 doc))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-elisp (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for Emacs Lisp."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-elisp))
|
||||||
|
(prefix (and (derived-mode-p 'emacs-lisp-mode 'inferior-emacs-lisp-mode)
|
||||||
|
(company-elisp--prefix)))
|
||||||
|
(candidates (company-elisp-candidates arg))
|
||||||
|
(sorted company-elisp-show-locals-first)
|
||||||
|
(meta (company-elisp--doc arg))
|
||||||
|
(doc-buffer (let ((symbol (intern arg)))
|
||||||
|
(save-window-excursion
|
||||||
|
(ignore-errors
|
||||||
|
(cond
|
||||||
|
((fboundp symbol) (describe-function symbol))
|
||||||
|
((boundp symbol) (describe-variable symbol))
|
||||||
|
((featurep symbol) (describe-package symbol))
|
||||||
|
((facep symbol) (describe-face symbol))
|
||||||
|
(t (signal 'user-error nil)))
|
||||||
|
(help-buffer)))))
|
||||||
|
(location (let ((sym (intern arg)))
|
||||||
|
(cond
|
||||||
|
((fboundp sym) (find-definition-noselect sym nil))
|
||||||
|
((boundp sym) (find-definition-noselect sym 'defvar))
|
||||||
|
((featurep sym) (cons (find-file-noselect (find-library-name
|
||||||
|
(symbol-name sym)))
|
||||||
|
0))
|
||||||
|
((facep sym) (find-definition-noselect sym 'defface)))))))
|
||||||
|
|
||||||
|
(provide 'company-elisp)
|
||||||
|
;;; company-elisp.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-elisp.elc
Normal file
BIN
elpa/company-20191029.2116/company-elisp.elc
Normal file
Binary file not shown.
108
elpa/company-20191029.2116/company-etags.el
Normal file
108
elpa/company-20191029.2116/company-etags.el
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
;;; company-etags.el --- company-mode completion backend for etags
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
(require 'etags)
|
||||||
|
|
||||||
|
(defgroup company-etags nil
|
||||||
|
"Completion backend for etags."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-etags-use-main-table-list t
|
||||||
|
"Always search `tags-table-list' if set.
|
||||||
|
If this is disabled, `company-etags' will try to find the one table for each
|
||||||
|
buffer automatically."
|
||||||
|
:type '(choice (const :tag "off" nil)
|
||||||
|
(const :tag "on" t)))
|
||||||
|
|
||||||
|
(defcustom company-etags-ignore-case nil
|
||||||
|
"Non-nil to ignore case in completion candidates."
|
||||||
|
:type 'boolean
|
||||||
|
:package-version '(company . "0.7.3"))
|
||||||
|
|
||||||
|
(defcustom company-etags-everywhere nil
|
||||||
|
"Non-nil to offer completions in comments and strings.
|
||||||
|
Set it to t or to a list of major modes."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(const :tag "Any supported mode" t)
|
||||||
|
(repeat :tag "Some major modes"
|
||||||
|
(symbol :tag "Major mode")))
|
||||||
|
:package-version '(company . "0.9.0"))
|
||||||
|
|
||||||
|
(defvar company-etags-modes '(prog-mode c-mode objc-mode c++-mode java-mode
|
||||||
|
jde-mode pascal-mode perl-mode python-mode))
|
||||||
|
|
||||||
|
(defvar-local company-etags-buffer-table 'unknown)
|
||||||
|
|
||||||
|
(defun company-etags-find-table ()
|
||||||
|
(let ((file (expand-file-name
|
||||||
|
"TAGS"
|
||||||
|
(locate-dominating-file (or buffer-file-name
|
||||||
|
default-directory)
|
||||||
|
"TAGS"))))
|
||||||
|
(when (and file (file-regular-p file))
|
||||||
|
(list file))))
|
||||||
|
|
||||||
|
(defun company-etags-buffer-table ()
|
||||||
|
(or (and company-etags-use-main-table-list tags-table-list)
|
||||||
|
(if (eq company-etags-buffer-table 'unknown)
|
||||||
|
(setq company-etags-buffer-table (company-etags-find-table))
|
||||||
|
company-etags-buffer-table)))
|
||||||
|
|
||||||
|
(defun company-etags--candidates (prefix)
|
||||||
|
(let ((tags-table-list (company-etags-buffer-table))
|
||||||
|
(tags-file-name tags-file-name)
|
||||||
|
(completion-ignore-case company-etags-ignore-case))
|
||||||
|
(and (or tags-file-name tags-table-list)
|
||||||
|
(fboundp 'tags-completion-table)
|
||||||
|
(save-excursion
|
||||||
|
(visit-tags-table-buffer)
|
||||||
|
(all-completions prefix (tags-completion-table))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-etags (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for etags."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-etags))
|
||||||
|
(prefix (and (apply #'derived-mode-p company-etags-modes)
|
||||||
|
(or (eq t company-etags-everywhere)
|
||||||
|
(apply #'derived-mode-p company-etags-everywhere)
|
||||||
|
(not (company-in-string-or-comment)))
|
||||||
|
(company-etags-buffer-table)
|
||||||
|
(or (company-grab-symbol) 'stop)))
|
||||||
|
(candidates (company-etags--candidates arg))
|
||||||
|
(location (let ((tags-table-list (company-etags-buffer-table)))
|
||||||
|
(when (fboundp 'find-tag-noselect)
|
||||||
|
(save-excursion
|
||||||
|
(let ((buffer (find-tag-noselect arg)))
|
||||||
|
(cons buffer (with-current-buffer buffer (point))))))))
|
||||||
|
(ignore-case company-etags-ignore-case)))
|
||||||
|
|
||||||
|
(provide 'company-etags)
|
||||||
|
;;; company-etags.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-etags.elc
Normal file
BIN
elpa/company-20191029.2116/company-etags.elc
Normal file
Binary file not shown.
148
elpa/company-20191029.2116/company-files.el
Normal file
148
elpa/company-20191029.2116/company-files.el
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
;;; company-files.el --- company-mode completion backend for file names
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2014-2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-files nil
|
||||||
|
"Completion backend for file names."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-files-exclusions nil
|
||||||
|
"File name extensions and directory names to ignore.
|
||||||
|
The values should use the same format as `completion-ignored-extensions'."
|
||||||
|
:type '(const string)
|
||||||
|
:package-version '(company . "0.9.1"))
|
||||||
|
|
||||||
|
(defun company-files--directory-files (dir prefix)
|
||||||
|
;; Don't use directory-files. It produces directories without trailing /.
|
||||||
|
(condition-case err
|
||||||
|
(let ((comp (sort (file-name-all-completions prefix dir)
|
||||||
|
(lambda (s1 s2) (string-lessp (downcase s1) (downcase s2))))))
|
||||||
|
(when company-files-exclusions
|
||||||
|
(setq comp (company-files--exclusions-filtered comp)))
|
||||||
|
(if (equal prefix "")
|
||||||
|
(delete "../" (delete "./" comp))
|
||||||
|
comp))
|
||||||
|
(file-error nil)))
|
||||||
|
|
||||||
|
(defun company-files--exclusions-filtered (completions)
|
||||||
|
(let* ((dir-exclusions (cl-delete-if-not #'company-files--trailing-slash-p
|
||||||
|
company-files-exclusions))
|
||||||
|
(file-exclusions (cl-set-difference company-files-exclusions
|
||||||
|
dir-exclusions)))
|
||||||
|
(cl-loop for c in completions
|
||||||
|
unless (if (company-files--trailing-slash-p c)
|
||||||
|
(member c dir-exclusions)
|
||||||
|
(cl-find-if (lambda (exclusion)
|
||||||
|
(string-suffix-p exclusion c))
|
||||||
|
file-exclusions))
|
||||||
|
collect c)))
|
||||||
|
|
||||||
|
(defvar company-files--regexps
|
||||||
|
(let* ((root (if (eq system-type 'windows-nt)
|
||||||
|
"[a-zA-Z]:/"
|
||||||
|
"/"))
|
||||||
|
(begin (concat "\\(?:\\.\\{1,2\\}/\\|~/\\|" root "\\)")))
|
||||||
|
(list (concat "\"\\(" begin "[^\"\n]*\\)")
|
||||||
|
(concat "\'\\(" begin "[^\'\n]*\\)")
|
||||||
|
(concat "\\(?:[ \t=]\\|^\\)\\(" begin "[^ \t\n]*\\)"))))
|
||||||
|
|
||||||
|
(defun company-files--grab-existing-name ()
|
||||||
|
;; Grab the file name.
|
||||||
|
;; When surrounded with quotes, it can include spaces.
|
||||||
|
(let (file dir)
|
||||||
|
(and (cl-dolist (regexp company-files--regexps)
|
||||||
|
(when (setq file (company-grab-line regexp 1))
|
||||||
|
(cl-return file)))
|
||||||
|
(company-files--connected-p file)
|
||||||
|
(setq dir (file-name-directory file))
|
||||||
|
(not (string-match "//" dir))
|
||||||
|
(file-exists-p dir)
|
||||||
|
file)))
|
||||||
|
|
||||||
|
(defun company-files--connected-p (file)
|
||||||
|
(or (not (file-remote-p file))
|
||||||
|
(file-remote-p file nil t)))
|
||||||
|
|
||||||
|
(defun company-files--trailing-slash-p (file)
|
||||||
|
;; `file-directory-p' is very expensive on remotes. We are relying on
|
||||||
|
;; `file-name-all-completions' returning directories with trailing / instead.
|
||||||
|
(let ((len (length file)))
|
||||||
|
(and (> len 0) (eq (aref file (1- len)) ?/))))
|
||||||
|
|
||||||
|
(defvar company-files--completion-cache nil)
|
||||||
|
|
||||||
|
(defun company-files--complete (prefix)
|
||||||
|
(let* ((dir (file-name-directory prefix))
|
||||||
|
(file (file-name-nondirectory prefix))
|
||||||
|
(key (list file
|
||||||
|
(expand-file-name dir)
|
||||||
|
(nth 5 (file-attributes dir))))
|
||||||
|
(completion-ignore-case read-file-name-completion-ignore-case))
|
||||||
|
(unless (company-file--keys-match-p key (car company-files--completion-cache))
|
||||||
|
(let* ((candidates (mapcar (lambda (f) (concat dir f))
|
||||||
|
(company-files--directory-files dir file)))
|
||||||
|
(directories (unless (file-remote-p dir)
|
||||||
|
(cl-remove-if-not (lambda (f)
|
||||||
|
(and (company-files--trailing-slash-p f)
|
||||||
|
(not (file-remote-p f))
|
||||||
|
(company-files--connected-p f)))
|
||||||
|
candidates)))
|
||||||
|
(children (and directories
|
||||||
|
(cl-mapcan (lambda (d)
|
||||||
|
(mapcar (lambda (c) (concat d c))
|
||||||
|
(company-files--directory-files d "")))
|
||||||
|
directories))))
|
||||||
|
(setq company-files--completion-cache
|
||||||
|
(cons key (append candidates children)))))
|
||||||
|
(all-completions prefix
|
||||||
|
(cdr company-files--completion-cache))))
|
||||||
|
|
||||||
|
(defun company-file--keys-match-p (new old)
|
||||||
|
(and (equal (cdr old) (cdr new))
|
||||||
|
(string-prefix-p (car old) (car new))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-files (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend existing file names.
|
||||||
|
Completions works for proper absolute and relative files paths.
|
||||||
|
File paths with spaces are only supported inside strings."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-files))
|
||||||
|
(prefix (company-files--grab-existing-name))
|
||||||
|
(candidates (company-files--complete arg))
|
||||||
|
(location (cons (dired-noselect
|
||||||
|
(file-name-directory (directory-file-name arg))) 1))
|
||||||
|
(post-completion (when (company-files--trailing-slash-p arg)
|
||||||
|
(delete-char -1)))
|
||||||
|
(sorted t)
|
||||||
|
(no-cache t)))
|
||||||
|
|
||||||
|
(provide 'company-files)
|
||||||
|
;;; company-files.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-files.elc
Normal file
BIN
elpa/company-20191029.2116/company-files.elc
Normal file
Binary file not shown.
117
elpa/company-20191029.2116/company-gtags.el
Normal file
117
elpa/company-20191029.2116/company-gtags.el
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
;;; company-gtags.el --- company-mode completion backend for GNU Global
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'company-template)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-gtags nil
|
||||||
|
"Completion backend for GNU Global."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(define-obsolete-variable-alias
|
||||||
|
'company-gtags-gnu-global-program-name
|
||||||
|
'company-gtags-executable "earlier")
|
||||||
|
|
||||||
|
(defcustom company-gtags-executable
|
||||||
|
(executable-find "global")
|
||||||
|
"Location of GNU global executable."
|
||||||
|
:type 'string)
|
||||||
|
|
||||||
|
(defcustom company-gtags-insert-arguments t
|
||||||
|
"When non-nil, insert function arguments as a template after completion."
|
||||||
|
:type 'boolean
|
||||||
|
:package-version '(company . "0.8.1"))
|
||||||
|
|
||||||
|
(defvar-local company-gtags--tags-available-p 'unknown)
|
||||||
|
|
||||||
|
(defcustom company-gtags-modes '(prog-mode jde-mode)
|
||||||
|
"Modes that use `company-gtags'.
|
||||||
|
In all these modes (and their derivatives) `company-gtags' will perform
|
||||||
|
completion."
|
||||||
|
:type '(repeat (symbol :tag "Major mode"))
|
||||||
|
:package-version '(company . "0.8.4"))
|
||||||
|
|
||||||
|
(defun company-gtags--tags-available-p ()
|
||||||
|
(if (eq company-gtags--tags-available-p 'unknown)
|
||||||
|
(setq company-gtags--tags-available-p
|
||||||
|
(locate-dominating-file buffer-file-name "GTAGS"))
|
||||||
|
company-gtags--tags-available-p))
|
||||||
|
|
||||||
|
(defun company-gtags--fetch-tags (prefix)
|
||||||
|
(with-temp-buffer
|
||||||
|
(let (tags)
|
||||||
|
(when (= 0 (process-file company-gtags-executable nil
|
||||||
|
;; "-T" goes through all the tag files listed in GTAGSLIBPATH
|
||||||
|
(list (current-buffer) nil) nil "-xGqT" (concat "^" prefix)))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(cl-loop while
|
||||||
|
(re-search-forward (concat
|
||||||
|
"^"
|
||||||
|
"\\([^ ]*\\)" ;; completion
|
||||||
|
"[ \t]+\\([[:digit:]]+\\)" ;; linum
|
||||||
|
"[ \t]+\\([^ \t]+\\)" ;; file
|
||||||
|
"[ \t]+\\(.*\\)" ;; definition
|
||||||
|
"$"
|
||||||
|
) nil t)
|
||||||
|
collect
|
||||||
|
(propertize (match-string 1)
|
||||||
|
'meta (match-string 4)
|
||||||
|
'location (cons (expand-file-name (match-string 3))
|
||||||
|
(string-to-number (match-string 2)))
|
||||||
|
))))))
|
||||||
|
|
||||||
|
(defun company-gtags--annotation (arg)
|
||||||
|
(let ((meta (get-text-property 0 'meta arg)))
|
||||||
|
(when (string-match (concat arg "\\((.*)\\).*") meta)
|
||||||
|
(match-string 1 meta))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-gtags (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for GNU Global."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-gtags))
|
||||||
|
(prefix (and company-gtags-executable
|
||||||
|
buffer-file-name
|
||||||
|
(apply #'derived-mode-p company-gtags-modes)
|
||||||
|
(not (company-in-string-or-comment))
|
||||||
|
(company-gtags--tags-available-p)
|
||||||
|
(or (company-grab-symbol) 'stop)))
|
||||||
|
(candidates (company-gtags--fetch-tags arg))
|
||||||
|
(sorted t)
|
||||||
|
(duplicates t)
|
||||||
|
(annotation (company-gtags--annotation arg))
|
||||||
|
(meta (get-text-property 0 'meta arg))
|
||||||
|
(location (get-text-property 0 'location arg))
|
||||||
|
(post-completion (let ((anno (company-gtags--annotation arg)))
|
||||||
|
(when (and company-gtags-insert-arguments anno)
|
||||||
|
(insert anno)
|
||||||
|
(company-template-c-like-templatify anno))))))
|
||||||
|
|
||||||
|
(provide 'company-gtags)
|
||||||
|
;;; company-gtags.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-gtags.elc
Normal file
BIN
elpa/company-20191029.2116/company-gtags.elc
Normal file
Binary file not shown.
82
elpa/company-20191029.2116/company-ispell.el
Normal file
82
elpa/company-20191029.2116/company-ispell.el
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
;;; company-ispell.el --- company-mode completion backend using Ispell
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2013-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
(require 'ispell)
|
||||||
|
|
||||||
|
(defgroup company-ispell nil
|
||||||
|
"Completion backend using Ispell."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-ispell-dictionary nil
|
||||||
|
"Dictionary to use for `company-ispell'.
|
||||||
|
If nil, use `ispell-complete-word-dict'."
|
||||||
|
:type '(choice (const :tag "default (nil)" nil)
|
||||||
|
(file :tag "dictionary" t)))
|
||||||
|
|
||||||
|
(defvar company-ispell-available 'unknown)
|
||||||
|
|
||||||
|
(defalias 'company-ispell--lookup-words
|
||||||
|
(if (fboundp 'ispell-lookup-words)
|
||||||
|
'ispell-lookup-words
|
||||||
|
'lookup-words))
|
||||||
|
|
||||||
|
(defun company-ispell-available ()
|
||||||
|
(when (eq company-ispell-available 'unknown)
|
||||||
|
(condition-case err
|
||||||
|
(progn
|
||||||
|
(company-ispell--lookup-words "WHATEVER")
|
||||||
|
(setq company-ispell-available t))
|
||||||
|
(error
|
||||||
|
(message "Company-Ispell: %s" (error-message-string err))
|
||||||
|
(setq company-ispell-available nil))))
|
||||||
|
company-ispell-available)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-ispell (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend using Ispell."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-ispell))
|
||||||
|
(prefix (when (company-ispell-available)
|
||||||
|
(company-grab-word)))
|
||||||
|
(candidates
|
||||||
|
(let ((words (company-ispell--lookup-words
|
||||||
|
arg
|
||||||
|
(or company-ispell-dictionary ispell-complete-word-dict)))
|
||||||
|
(completion-ignore-case t))
|
||||||
|
(if (string= arg "")
|
||||||
|
;; Small optimization.
|
||||||
|
words
|
||||||
|
;; Work around issue #284.
|
||||||
|
(all-completions arg words))))
|
||||||
|
(sorted t)
|
||||||
|
(ignore-case 'keep-prefix)))
|
||||||
|
|
||||||
|
(provide 'company-ispell)
|
||||||
|
;;; company-ispell.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-ispell.elc
Normal file
BIN
elpa/company-20191029.2116/company-ispell.elc
Normal file
Binary file not shown.
306
elpa/company-20191029.2116/company-keywords.el
Normal file
306
elpa/company-20191029.2116/company-keywords.el
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
;;; company-keywords.el --- A company backend for programming language keywords
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defun company-keywords-upper-lower (&rest lst)
|
||||||
|
;; Upcase order is different for _.
|
||||||
|
(nconc (sort (mapcar 'upcase lst) 'string<) lst))
|
||||||
|
|
||||||
|
(defvar company-keywords-alist
|
||||||
|
;; Please contribute corrections or additions.
|
||||||
|
`((c++-mode
|
||||||
|
"alignas" "alignof" "asm" "auto" "bool" "break" "case" "catch" "char"
|
||||||
|
"char16_t" "char32_t" "class" "const" "const_cast" "constexpr" "continue"
|
||||||
|
"decltype" "default" "delete" "do" "double" "dynamic_cast" "else" "enum"
|
||||||
|
"explicit" "export" "extern" "false" "final" "float" "for" "friend"
|
||||||
|
"goto" "if" "inline" "int" "long" "mutable" "namespace" "new" "noexcept"
|
||||||
|
"nullptr" "operator" "override"
|
||||||
|
"private" "protected" "public" "register" "reinterpret_cast"
|
||||||
|
"return" "short" "signed" "sizeof" "static" "static_assert"
|
||||||
|
"static_cast" "struct" "switch" "template" "this" "thread_local"
|
||||||
|
"throw" "true" "try" "typedef" "typeid" "typename"
|
||||||
|
"union" "unsigned" "using" "virtual" "void" "volatile" "wchar_t" "while")
|
||||||
|
(c-mode
|
||||||
|
"auto" "break" "case" "char" "const" "continue" "default" "do"
|
||||||
|
"double" "else" "enum" "extern" "float" "for" "goto" "if" "int" "long"
|
||||||
|
"register" "return" "short" "signed" "sizeof" "static" "struct"
|
||||||
|
"switch" "typedef" "union" "unsigned" "void" "volatile" "while")
|
||||||
|
(csharp-mode
|
||||||
|
"abstract" "add" "alias" "as" "base" "bool" "break" "byte" "case"
|
||||||
|
"catch" "char" "checked" "class" "const" "continue" "decimal" "default"
|
||||||
|
"delegate" "do" "double" "else" "enum" "event" "explicit" "extern"
|
||||||
|
"false" "finally" "fixed" "float" "for" "foreach" "get" "global" "goto"
|
||||||
|
"if" "implicit" "in" "int" "interface" "internal" "is" "lock" "long"
|
||||||
|
"namespace" "new" "null" "object" "operator" "out" "override" "params"
|
||||||
|
"partial" "private" "protected" "public" "readonly" "ref" "remove"
|
||||||
|
"return" "sbyte" "sealed" "set" "short" "sizeof" "stackalloc" "static"
|
||||||
|
"string" "struct" "switch" "this" "throw" "true" "try" "typeof" "uint"
|
||||||
|
"ulong" "unchecked" "unsafe" "ushort" "using" "value" "var" "virtual"
|
||||||
|
"void" "volatile" "where" "while" "yield")
|
||||||
|
(d-mode
|
||||||
|
;; from http://www.digitalmars.com/d/2.0/lex.html
|
||||||
|
"abstract" "alias" "align" "asm"
|
||||||
|
"assert" "auto" "body" "bool" "break" "byte" "case" "cast" "catch"
|
||||||
|
"cdouble" "cent" "cfloat" "char" "class" "const" "continue" "creal"
|
||||||
|
"dchar" "debug" "default" "delegate" "delete" "deprecated" "do"
|
||||||
|
"double" "else" "enum" "export" "extern" "false" "final" "finally"
|
||||||
|
"float" "for" "foreach" "foreach_reverse" "function" "goto" "idouble"
|
||||||
|
"if" "ifloat" "import" "in" "inout" "int" "interface" "invariant"
|
||||||
|
"ireal" "is" "lazy" "long" "macro" "mixin" "module" "new" "nothrow"
|
||||||
|
"null" "out" "override" "package" "pragma" "private" "protected"
|
||||||
|
"public" "pure" "real" "ref" "return" "scope" "short" "static" "struct"
|
||||||
|
"super" "switch" "synchronized" "template" "this" "throw" "true" "try"
|
||||||
|
"typedef" "typeid" "typeof" "ubyte" "ucent" "uint" "ulong" "union"
|
||||||
|
"unittest" "ushort" "version" "void" "volatile" "wchar" "while" "with")
|
||||||
|
(f90-mode .
|
||||||
|
;; from f90.el
|
||||||
|
;; ".AND." ".GE." ".GT." ".LT." ".LE." ".NE." ".OR." ".TRUE." ".FALSE."
|
||||||
|
,(company-keywords-upper-lower
|
||||||
|
"abs" "abstract" "achar" "acos" "adjustl" "adjustr" "aimag" "aint"
|
||||||
|
"align" "all" "all_prefix" "all_scatter" "all_suffix" "allocatable"
|
||||||
|
"allocate" "allocated" "and" "anint" "any" "any_prefix" "any_scatter"
|
||||||
|
"any_suffix" "asin" "assign" "assignment" "associate" "associated"
|
||||||
|
"asynchronous" "atan" "atan2" "backspace" "bind" "bit_size" "block"
|
||||||
|
"btest" "c_alert" "c_associated" "c_backspace" "c_bool"
|
||||||
|
"c_carriage_return" "c_char" "c_double" "c_double_complex" "c_f_pointer"
|
||||||
|
"c_f_procpointer" "c_float" "c_float_complex" "c_form_feed" "c_funloc"
|
||||||
|
"c_funptr" "c_horizontal_tab" "c_int" "c_int16_t" "c_int32_t" "c_int64_t"
|
||||||
|
"c_int8_t" "c_int_fast16_t" "c_int_fast32_t" "c_int_fast64_t"
|
||||||
|
"c_int_fast8_t" "c_int_least16_t" "c_int_least32_t" "c_int_least64_t"
|
||||||
|
"c_int_least8_t" "c_intmax_t" "c_intptr_t" "c_loc" "c_long"
|
||||||
|
"c_long_double" "c_long_double_complex" "c_long_long" "c_new_line"
|
||||||
|
"c_null_char" "c_null_funptr" "c_null_ptr" "c_ptr" "c_short"
|
||||||
|
"c_signed_char" "c_size_t" "c_vertical_tab" "call" "case" "ceiling"
|
||||||
|
"char" "character" "character_storage_size" "class" "close" "cmplx"
|
||||||
|
"command_argument_count" "common" "complex" "conjg" "contains" "continue"
|
||||||
|
"copy_prefix" "copy_scatter" "copy_suffix" "cos" "cosh" "count"
|
||||||
|
"count_prefix" "count_scatter" "count_suffix" "cpu_time" "cshift"
|
||||||
|
"cycle" "cyclic" "data" "date_and_time" "dble" "deallocate" "deferred"
|
||||||
|
"digits" "dim" "dimension" "distribute" "do" "dot_product" "double"
|
||||||
|
"dprod" "dynamic" "elemental" "else" "elseif" "elsewhere" "end" "enddo"
|
||||||
|
"endfile" "endif" "entry" "enum" "enumerator" "eoshift" "epsilon" "eq"
|
||||||
|
"equivalence" "eqv" "error_unit" "exit" "exp" "exponent" "extends"
|
||||||
|
"extends_type_of" "external" "extrinsic" "false" "file_storage_size"
|
||||||
|
"final" "floor" "flush" "forall" "format" "fraction" "function" "ge"
|
||||||
|
"generic" "get_command" "get_command_argument" "get_environment_variable"
|
||||||
|
"goto" "grade_down" "grade_up" "gt" "hpf_alignment" "hpf_distribution"
|
||||||
|
"hpf_template" "huge" "iachar" "iall" "iall_prefix" "iall_scatter"
|
||||||
|
"iall_suffix" "iand" "iany" "iany_prefix" "iany_scatter" "iany_suffix"
|
||||||
|
"ibclr" "ibits" "ibset" "ichar" "ieee_arithmetic" "ieee_exceptions"
|
||||||
|
"ieee_features" "ieee_get_underflow_mode" "ieee_set_underflow_mode"
|
||||||
|
"ieee_support_underflow_control" "ieor" "if" "ilen" "implicit"
|
||||||
|
"import" "include" "independent" "index" "inherit" "input_unit"
|
||||||
|
"inquire" "int" "integer" "intent" "interface" "intrinsic" "ior"
|
||||||
|
"iostat_end" "iostat_eor" "iparity" "iparity_prefix" "iparity_scatter"
|
||||||
|
"iparity_suffix" "ishft" "ishftc" "iso_c_binding" "iso_fortran_env"
|
||||||
|
"kind" "lbound" "le" "leadz" "len" "len_trim" "lge" "lgt" "lle" "llt"
|
||||||
|
"log" "log10" "logical" "lt" "matmul" "max" "maxexponent" "maxloc"
|
||||||
|
"maxval" "maxval_prefix" "maxval_scatter" "maxval_suffix" "merge"
|
||||||
|
"min" "minexponent" "minloc" "minval" "minval_prefix" "minval_scatter"
|
||||||
|
"minval_suffix" "mod" "module" "modulo" "move_alloc" "mvbits" "namelist"
|
||||||
|
"ne" "nearest" "neqv" "new" "new_line" "nint" "non_intrinsic"
|
||||||
|
"non_overridable" "none" "nopass" "not" "null" "nullify"
|
||||||
|
"number_of_processors" "numeric_storage_size" "only" "onto" "open"
|
||||||
|
"operator" "optional" "or" "output_unit" "pack" "parameter" "parity"
|
||||||
|
"parity_prefix" "parity_scatter" "parity_suffix" "pass" "pause"
|
||||||
|
"pointer" "popcnt" "poppar" "precision" "present" "print" "private"
|
||||||
|
"procedure" "processors" "processors_shape" "product" "product_prefix"
|
||||||
|
"product_scatter" "product_suffix" "program" "protected" "public"
|
||||||
|
"pure" "radix" "random_number" "random_seed" "range" "read" "real"
|
||||||
|
"realign" "recursive" "redistribute" "repeat" "reshape" "result"
|
||||||
|
"return" "rewind" "rrspacing" "same_type_as" "save" "scale" "scan"
|
||||||
|
"select" "selected_char_kind" "selected_int_kind" "selected_real_kind"
|
||||||
|
"sequence" "set_exponent" "shape" "sign" "sin" "sinh" "size" "spacing"
|
||||||
|
"spread" "sqrt" "stop" "subroutine" "sum" "sum_prefix" "sum_scatter"
|
||||||
|
"sum_suffix" "system_clock" "tan" "tanh" "target" "template" "then"
|
||||||
|
"tiny" "transfer" "transpose" "trim" "true" "type" "ubound" "unpack"
|
||||||
|
"use" "value" "verify" "volatile" "wait" "where" "while" "with" "write"))
|
||||||
|
(go-mode
|
||||||
|
;; 1. Keywords ref: https://golang.org/ref/spec#Keywords
|
||||||
|
;; 2. Builtin functions and types ref: https://golang.org/pkg/builtin/
|
||||||
|
"append" "bool" "break" "byte" "cap" "case" "chan" "close" "complex" "complex128"
|
||||||
|
"complex64" "const" "continue" "copy" "default" "defer" "delete" "else" "error"
|
||||||
|
"fallthrough" "false" "float32" "float64" "for" "func" "go" "goto" "if" "imag"
|
||||||
|
"import" "int" "int16" "int32" "int64" "int8" "interface" "len" "make"
|
||||||
|
"map" "new" "nil" "package" "panic" "print" "println" "range" "real" "recover"
|
||||||
|
"return" "rune" "select" "string" "struct" "switch" "true" "type" "uint" "uint16"
|
||||||
|
"uint32" "uint64" "uint8" "uintptr" "var")
|
||||||
|
(java-mode
|
||||||
|
"abstract" "assert" "boolean" "break" "byte" "case" "catch" "char" "class"
|
||||||
|
"continue" "default" "do" "double" "else" "enum" "extends" "final"
|
||||||
|
"finally" "float" "for" "if" "implements" "import" "instanceof" "int"
|
||||||
|
"interface" "long" "native" "new" "package" "private" "protected" "public"
|
||||||
|
"return" "short" "static" "strictfp" "super" "switch" "synchronized"
|
||||||
|
"this" "throw" "throws" "transient" "try" "void" "volatile" "while")
|
||||||
|
(javascript-mode
|
||||||
|
;; https://tc39.github.io/ecma262/ + async, static and undefined
|
||||||
|
"async" "await" "break" "case" "catch" "class" "const" "continue"
|
||||||
|
"debugger" "default" "delete" "do" "else" "enum" "export" "extends" "false"
|
||||||
|
"finally" "for" "function" "if" "import" "in" "instanceof" "let" "new"
|
||||||
|
"null" "return" "static" "super" "switch" "this" "throw" "true" "try"
|
||||||
|
"typeof" "undefined" "var" "void" "while" "with" "yield")
|
||||||
|
(kotlin-mode
|
||||||
|
"abstract" "annotation" "as" "break" "by" "catch" "class" "companion"
|
||||||
|
"const" "constructor" "continue" "data" "do" "else" "enum" "false" "final"
|
||||||
|
"finally" "for" "fun" "if" "import" "in" "init" "inner" "interface"
|
||||||
|
"internal" "is" "lateinit" "nested" "null" "object" "open" "out" "override"
|
||||||
|
"package" "private" "protected" "public" "return" "super" "this" "throw"
|
||||||
|
"trait" "true" "try" "typealias" "val" "var" "when" "while")
|
||||||
|
(objc-mode
|
||||||
|
"@catch" "@class" "@encode" "@end" "@finally" "@implementation"
|
||||||
|
"@interface" "@private" "@protected" "@protocol" "@public"
|
||||||
|
"@selector" "@synchronized" "@throw" "@try" "alloc" "autorelease"
|
||||||
|
"bycopy" "byref" "in" "inout" "oneway" "out" "release" "retain")
|
||||||
|
(perl-mode
|
||||||
|
;; from cperl.el
|
||||||
|
"AUTOLOAD" "BEGIN" "CHECK" "CORE" "DESTROY" "END" "INIT" "__END__"
|
||||||
|
"__FILE__" "__LINE__" "abs" "accept" "alarm" "and" "atan2" "bind"
|
||||||
|
"binmode" "bless" "caller" "chdir" "chmod" "chomp" "chop" "chown" "chr"
|
||||||
|
"chroot" "close" "closedir" "cmp" "connect" "continue" "cos"
|
||||||
|
"crypt" "dbmclose" "dbmopen" "defined" "delete" "die" "do" "dump" "each"
|
||||||
|
"else" "elsif" "endgrent" "endhostent" "endnetent" "endprotoent"
|
||||||
|
"endpwent" "endservent" "eof" "eq" "eval" "exec" "exists" "exit" "exp"
|
||||||
|
"fcntl" "fileno" "flock" "for" "foreach" "fork" "format" "formline"
|
||||||
|
"ge" "getc" "getgrent" "getgrgid" "getgrnam" "gethostbyaddr"
|
||||||
|
"gethostbyname" "gethostent" "getlogin" "getnetbyaddr" "getnetbyname"
|
||||||
|
"getnetent" "getpeername" "getpgrp" "getppid" "getpriority"
|
||||||
|
"getprotobyname" "getprotobynumber" "getprotoent" "getpwent" "getpwnam"
|
||||||
|
"getpwuid" "getservbyname" "getservbyport" "getservent" "getsockname"
|
||||||
|
"getsockopt" "glob" "gmtime" "goto" "grep" "gt" "hex" "if" "index" "int"
|
||||||
|
"ioctl" "join" "keys" "kill" "last" "lc" "lcfirst" "le" "length"
|
||||||
|
"link" "listen" "local" "localtime" "lock" "log" "lstat" "lt" "map"
|
||||||
|
"mkdir" "msgctl" "msgget" "msgrcv" "msgsnd" "my" "ne" "next" "no"
|
||||||
|
"not" "oct" "open" "opendir" "or" "ord" "our" "pack" "package" "pipe"
|
||||||
|
"pop" "pos" "print" "printf" "push" "q" "qq" "quotemeta" "qw" "qx"
|
||||||
|
"rand" "read" "readdir" "readline" "readlink" "readpipe" "recv" "redo"
|
||||||
|
"ref" "rename" "require" "reset" "return" "reverse" "rewinddir" "rindex"
|
||||||
|
"rmdir" "scalar" "seek" "seekdir" "select" "semctl" "semget" "semop"
|
||||||
|
"send" "setgrent" "sethostent" "setnetent" "setpgrp" "setpriority"
|
||||||
|
"setprotoent" "setpwent" "setservent" "setsockopt" "shift" "shmctl"
|
||||||
|
"shmget" "shmread" "shmwrite" "shutdown" "sin" "sleep" "socket"
|
||||||
|
"socketpair" "sort" "splice" "split" "sprintf" "sqrt" "srand" "stat"
|
||||||
|
"study" "sub" "substr" "symlink" "syscall" "sysopen" "sysread" "system"
|
||||||
|
"syswrite" "tell" "telldir" "tie" "time" "times" "tr" "truncate" "uc"
|
||||||
|
"ucfirst" "umask" "undef" "unless" "unlink" "unpack" "unshift" "untie"
|
||||||
|
"until" "use" "utime" "values" "vec" "wait" "waitpid"
|
||||||
|
"wantarray" "warn" "while" "write" "x" "xor" "y")
|
||||||
|
(php-mode
|
||||||
|
"__CLASS__" "__DIR__" "__FILE__" "__FUNCTION__" "__LINE__" "__METHOD__"
|
||||||
|
"__NAMESPACE__" "_once" "abstract" "and" "array" "as" "break" "case"
|
||||||
|
"catch" "cfunction" "class" "clone" "const" "continue" "declare"
|
||||||
|
"default" "die" "do" "echo" "else" "elseif" "empty" "enddeclare"
|
||||||
|
"endfor" "endforeach" "endif" "endswitch" "endwhile" "eval" "exception"
|
||||||
|
"exit" "extends" "final" "for" "foreach" "function" "global"
|
||||||
|
"goto" "if" "implements" "include" "instanceof" "interface"
|
||||||
|
"isset" "list" "namespace" "new" "old_function" "or" "php_user_filter"
|
||||||
|
"print" "private" "protected" "public" "require" "require_once" "return"
|
||||||
|
"static" "switch" "this" "throw" "try" "unset" "use" "var" "while" "xor")
|
||||||
|
(python-mode
|
||||||
|
;; https://docs.python.org/3/reference/lexical_analysis.html#keywords
|
||||||
|
"False" "None" "True" "and" "as" "assert" "break" "class" "continue" "def"
|
||||||
|
"del" "elif" "else" "except" "exec" "finally" "for" "from" "global" "if"
|
||||||
|
"import" "in" "is" "lambda" "nonlocal" "not" "or" "pass" "print" "raise"
|
||||||
|
"return" "try" "while" "with" "yield")
|
||||||
|
(ruby-mode
|
||||||
|
"BEGIN" "END" "alias" "and" "begin" "break" "case" "class" "def" "defined?"
|
||||||
|
"do" "else" "elsif" "end" "ensure" "false" "for" "if" "in" "module"
|
||||||
|
"next" "nil" "not" "or" "redo" "rescue" "retry" "return" "self" "super"
|
||||||
|
"then" "true" "undef" "unless" "until" "when" "while" "yield")
|
||||||
|
;; From https://doc.rust-lang.org/grammar.html#keywords
|
||||||
|
;; but excluding unused reserved words: https://www.reddit.com/r/rust/comments/34fq0k/is_there_a_good_list_of_rusts_keywords/cqucvnj
|
||||||
|
(rust-mode
|
||||||
|
"Self"
|
||||||
|
"as" "box" "break" "const" "continue" "crate" "else" "enum" "extern"
|
||||||
|
"false" "fn" "for" "if" "impl" "in" "let" "loop" "macro" "match" "mod"
|
||||||
|
"move" "mut" "pub" "ref" "return" "self" "static" "struct" "super"
|
||||||
|
"trait" "true" "type" "unsafe" "use" "where" "while")
|
||||||
|
(scala-mode
|
||||||
|
"abstract" "case" "catch" "class" "def" "do" "else" "extends" "false"
|
||||||
|
"final" "finally" "for" "forSome" "if" "implicit" "import" "lazy" "match"
|
||||||
|
"new" "null" "object" "override" "package" "private" "protected"
|
||||||
|
"return" "sealed" "super" "this" "throw" "trait" "true" "try" "type" "val"
|
||||||
|
"var" "while" "with" "yield")
|
||||||
|
(swift-mode
|
||||||
|
"Protocol" "Self" "Type" "and" "as" "assignment" "associatedtype"
|
||||||
|
"associativity" "available" "break" "case" "catch" "class" "column" "continue"
|
||||||
|
"convenience" "default" "defer" "deinit" "didSet" "do" "dynamic" "dynamicType"
|
||||||
|
"else" "elseif" "endif" "enum" "extension" "fallthrough" "false" "file"
|
||||||
|
"fileprivate" "final" "for" "func" "function" "get" "guard" "higherThan" "if"
|
||||||
|
"import" "in" "indirect" "infix" "init" "inout" "internal" "is" "lazy" "left"
|
||||||
|
"let" "line" "lowerThan" "mutating" "nil" "none" "nonmutating" "open"
|
||||||
|
"operator" "optional" "override" "postfix" "precedence" "precedencegroup"
|
||||||
|
"prefix" "private" "protocol" "public" "repeat" "required" "rethrows" "return"
|
||||||
|
"right" "selector" "self" "set" "static" "struct" "subscript" "super" "switch"
|
||||||
|
"throw" "throws" "true" "try" "typealias" "unowned" "var" "weak" "where"
|
||||||
|
"while" "willSet")
|
||||||
|
(julia-mode
|
||||||
|
"abstract" "break" "case" "catch" "const" "continue" "do" "else" "elseif"
|
||||||
|
"end" "eval" "export" "false" "finally" "for" "function" "global" "if"
|
||||||
|
"ifelse" "immutable" "import" "importall" "in" "let" "macro" "module"
|
||||||
|
"otherwise" "quote" "return" "switch" "throw" "true" "try" "type"
|
||||||
|
"typealias" "using" "while"
|
||||||
|
)
|
||||||
|
;; From https://github.com/apache/thrift/blob/master/contrib/thrift.el
|
||||||
|
(thrift-mode
|
||||||
|
"binary" "bool" "byte" "const" "double" "enum" "exception" "extends"
|
||||||
|
"i16" "i32" "i64" "include" "list" "map" "oneway" "optional" "required"
|
||||||
|
"service" "set" "string" "struct" "throws" "typedef" "void"
|
||||||
|
)
|
||||||
|
;; aliases
|
||||||
|
(js2-mode . javascript-mode)
|
||||||
|
(js2-jsx-mode . javascript-mode)
|
||||||
|
(espresso-mode . javascript-mode)
|
||||||
|
(js-mode . javascript-mode)
|
||||||
|
(js-jsx-mode . javascript-mode)
|
||||||
|
(rjsx-mode . javascript-mode)
|
||||||
|
(cperl-mode . perl-mode)
|
||||||
|
(jde-mode . java-mode)
|
||||||
|
(ess-julia-mode . julia-mode)
|
||||||
|
(enh-ruby-mode . ruby-mode))
|
||||||
|
"Alist mapping major-modes to sorted keywords for `company-keywords'.")
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-keywords (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' backend for programming language keywords."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-keywords))
|
||||||
|
(prefix (and (assq major-mode company-keywords-alist)
|
||||||
|
(not (company-in-string-or-comment))
|
||||||
|
(or (company-grab-symbol) 'stop)))
|
||||||
|
(candidates
|
||||||
|
(let ((completion-ignore-case nil)
|
||||||
|
(symbols (cdr (assq major-mode company-keywords-alist))))
|
||||||
|
(all-completions arg (if (consp symbols)
|
||||||
|
symbols
|
||||||
|
(cdr (assq symbols company-keywords-alist))))))
|
||||||
|
(sorted t)))
|
||||||
|
|
||||||
|
(provide 'company-keywords)
|
||||||
|
;;; company-keywords.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-keywords.elc
Normal file
BIN
elpa/company-20191029.2116/company-keywords.elc
Normal file
Binary file not shown.
143
elpa/company-20191029.2116/company-nxml.el
Normal file
143
elpa/company-20191029.2116/company-nxml.el
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
;;; company-nxml.el --- company-mode completion backend for nxml-mode
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2013, 2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; In Emacs >= 26, company-capf is used instead.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defvar rng-open-elements)
|
||||||
|
(defvar rng-validate-mode)
|
||||||
|
(defvar rng-in-attribute-regex)
|
||||||
|
(defvar rng-in-attribute-value-regex)
|
||||||
|
(declare-function rng-set-state-after "rng-nxml")
|
||||||
|
(declare-function rng-match-possible-start-tag-names "rng-match")
|
||||||
|
(declare-function rng-adjust-state-for-attribute "rng-nxml")
|
||||||
|
(declare-function rng-match-possible-attribute-names "rng-match")
|
||||||
|
(declare-function rng-adjust-state-for-attribute-value "rng-nxml")
|
||||||
|
(declare-function rng-match-possible-value-strings "rng-match")
|
||||||
|
|
||||||
|
(defconst company-nxml-token-regexp
|
||||||
|
"\\(?:[_[:alpha:]][-._[:alnum:]]*\\_>\\)")
|
||||||
|
|
||||||
|
(defvar company-nxml-in-attribute-value-regexp
|
||||||
|
(replace-regexp-in-string "w" company-nxml-token-regexp
|
||||||
|
"<w\\(?::w\\)?\
|
||||||
|
\\(?:[ \t\r\n]+w\\(?::w\\)?[ \t\r\n]*=\
|
||||||
|
\[ \t\r\n]*\\(?:\"[^\"]*\"\\|'[^']*'\\)\\)*\
|
||||||
|
\[ \t\r\n]+\\(w\\(:w\\)?\\)[ \t\r\n]*=[ \t\r\n]*\
|
||||||
|
\\(\"\\([^\"]*\\>\\)\\|'\\([^']*\\>\\)\\)\\="
|
||||||
|
t t))
|
||||||
|
|
||||||
|
(defvar company-nxml-in-tag-name-regexp
|
||||||
|
(replace-regexp-in-string "w" company-nxml-token-regexp
|
||||||
|
"<\\(/?w\\(?::w?\\)?\\)?\\=" t t))
|
||||||
|
|
||||||
|
(defun company-nxml-all-completions (prefix alist)
|
||||||
|
(let ((candidates (mapcar 'cdr alist))
|
||||||
|
(case-fold-search nil)
|
||||||
|
filtered)
|
||||||
|
(when (cdar rng-open-elements)
|
||||||
|
(push (concat "/" (cdar rng-open-elements)) candidates))
|
||||||
|
(setq candidates (sort (all-completions prefix candidates) 'string<))
|
||||||
|
(while candidates
|
||||||
|
(unless (equal (car candidates) (car filtered))
|
||||||
|
(push (car candidates) filtered))
|
||||||
|
(pop candidates))
|
||||||
|
(nreverse filtered)))
|
||||||
|
|
||||||
|
(defmacro company-nxml-prepared (&rest body)
|
||||||
|
(declare (indent 0) (debug t))
|
||||||
|
`(let ((lt-pos (save-excursion (search-backward "<" nil t)))
|
||||||
|
xmltok-dtd)
|
||||||
|
(when (and lt-pos (= (rng-set-state-after lt-pos) lt-pos))
|
||||||
|
,@body)))
|
||||||
|
|
||||||
|
(defun company-nxml-tag (command &optional arg &rest ignored)
|
||||||
|
(cl-case command
|
||||||
|
(prefix (and (derived-mode-p 'nxml-mode)
|
||||||
|
rng-validate-mode
|
||||||
|
(company-grab company-nxml-in-tag-name-regexp 1)))
|
||||||
|
(candidates (company-nxml-prepared
|
||||||
|
(company-nxml-all-completions
|
||||||
|
arg (rng-match-possible-start-tag-names))))
|
||||||
|
(sorted t)))
|
||||||
|
|
||||||
|
(defun company-nxml-attribute (command &optional arg &rest ignored)
|
||||||
|
(cl-case command
|
||||||
|
(prefix (and (derived-mode-p 'nxml-mode)
|
||||||
|
rng-validate-mode
|
||||||
|
(memq (char-after) '(?\ ?\t ?\n)) ;; outside word
|
||||||
|
(company-grab rng-in-attribute-regex 1)))
|
||||||
|
(candidates (company-nxml-prepared
|
||||||
|
(and (rng-adjust-state-for-attribute
|
||||||
|
lt-pos (- (point) (length arg)))
|
||||||
|
(company-nxml-all-completions
|
||||||
|
arg (rng-match-possible-attribute-names)))))
|
||||||
|
(sorted t)))
|
||||||
|
|
||||||
|
(defun company-nxml-attribute-value (command &optional arg &rest ignored)
|
||||||
|
(cl-case command
|
||||||
|
(prefix (and (derived-mode-p 'nxml-mode)
|
||||||
|
rng-validate-mode
|
||||||
|
(and (memq (char-after) '(?' ?\" ?\ ?\t ?\n)) ;; outside word
|
||||||
|
(looking-back company-nxml-in-attribute-value-regexp nil)
|
||||||
|
(or (match-string-no-properties 4)
|
||||||
|
(match-string-no-properties 5)
|
||||||
|
""))))
|
||||||
|
(candidates (company-nxml-prepared
|
||||||
|
(let (attr-start attr-end colon)
|
||||||
|
(and (looking-back rng-in-attribute-value-regex lt-pos)
|
||||||
|
(setq colon (match-beginning 2)
|
||||||
|
attr-start (match-beginning 1)
|
||||||
|
attr-end (match-end 1))
|
||||||
|
(rng-adjust-state-for-attribute lt-pos attr-start)
|
||||||
|
(rng-adjust-state-for-attribute-value
|
||||||
|
attr-start colon attr-end)
|
||||||
|
(all-completions
|
||||||
|
arg (rng-match-possible-value-strings))))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-nxml (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for `nxml-mode'."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-nxml))
|
||||||
|
(prefix (or (company-nxml-tag 'prefix)
|
||||||
|
(company-nxml-attribute 'prefix)
|
||||||
|
(company-nxml-attribute-value 'prefix)))
|
||||||
|
(candidates (cond
|
||||||
|
((company-nxml-tag 'prefix)
|
||||||
|
(company-nxml-tag 'candidates arg))
|
||||||
|
((company-nxml-attribute 'prefix)
|
||||||
|
(company-nxml-attribute 'candidates arg))
|
||||||
|
((company-nxml-attribute-value 'prefix)
|
||||||
|
(sort (company-nxml-attribute-value 'candidates arg)
|
||||||
|
'string<))))
|
||||||
|
(sorted t)))
|
||||||
|
|
||||||
|
(provide 'company-nxml)
|
||||||
|
;;; company-nxml.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-nxml.elc
Normal file
BIN
elpa/company-20191029.2116/company-nxml.elc
Normal file
Binary file not shown.
57
elpa/company-20191029.2116/company-oddmuse.el
Normal file
57
elpa/company-20191029.2116/company-oddmuse.el
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
;;; company-oddmuse.el --- company-mode completion backend for oddmuse-mode
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
(eval-when-compile (require 'yaoddmuse nil t))
|
||||||
|
(eval-when-compile (require 'oddmuse nil t))
|
||||||
|
|
||||||
|
(defvar company-oddmuse-link-regexp
|
||||||
|
"\\(\\<[A-Z][[:alnum:]]*\\>\\)\\|\\[\\[\\([[:alnum:]]+\\>\\|\\)")
|
||||||
|
|
||||||
|
(defun company-oddmuse-get-page-table ()
|
||||||
|
(cl-case major-mode
|
||||||
|
(yaoddmuse-mode (with-no-warnings
|
||||||
|
(yaoddmuse-get-pagename-table yaoddmuse-wikiname)))
|
||||||
|
(oddmuse-mode (with-no-warnings
|
||||||
|
(oddmuse-make-completion-table oddmuse-wiki)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-oddmuse (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for `oddmuse-mode'."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-oddmuse))
|
||||||
|
(prefix (let ((case-fold-search nil))
|
||||||
|
(and (memq major-mode '(oddmuse-mode yaoddmuse-mode))
|
||||||
|
(looking-back company-oddmuse-link-regexp (point-at-bol))
|
||||||
|
(or (match-string 1)
|
||||||
|
(match-string 2)))))
|
||||||
|
(candidates (all-completions arg (company-oddmuse-get-page-table)))))
|
||||||
|
|
||||||
|
(provide 'company-oddmuse)
|
||||||
|
;;; company-oddmuse.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-oddmuse.elc
Normal file
BIN
elpa/company-20191029.2116/company-oddmuse.elc
Normal file
Binary file not shown.
12
elpa/company-20191029.2116/company-pkg.el
Normal file
12
elpa/company-20191029.2116/company-pkg.el
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
(define-package "company" "20191029.2116" "Modular text completion framework"
|
||||||
|
'((emacs "24.3"))
|
||||||
|
:keywords
|
||||||
|
'("abbrev" "convenience" "matching")
|
||||||
|
:authors
|
||||||
|
'(("Nikolaj Schumacher"))
|
||||||
|
:maintainer
|
||||||
|
'("Dmitry Gutov" . "dgutov@yandex.ru")
|
||||||
|
:url "http://company-mode.github.io/")
|
||||||
|
;; Local Variables:
|
||||||
|
;; no-byte-compile: t
|
||||||
|
;; End:
|
||||||
168
elpa/company-20191029.2116/company-semantic.el
Normal file
168
elpa/company-20191029.2116/company-semantic.el
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
;;; company-semantic.el --- company-mode completion backend using Semantic
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2013-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'company-template)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defvar semantic-idle-summary-function)
|
||||||
|
(declare-function semantic-documentation-for-tag "semantic/doc" )
|
||||||
|
(declare-function semantic-analyze-current-context "semantic/analyze")
|
||||||
|
(declare-function semantic-analyze-possible-completions "semantic/complete")
|
||||||
|
(declare-function semantic-analyze-find-tags-by-prefix "semantic/analyze/fcn")
|
||||||
|
(declare-function semantic-tag-class "semantic/tag")
|
||||||
|
(declare-function semantic-tag-name "semantic/tag")
|
||||||
|
(declare-function semantic-tag-start "semantic/tag")
|
||||||
|
(declare-function semantic-tag-buffer "semantic/tag")
|
||||||
|
(declare-function semantic-active-p "semantic")
|
||||||
|
(declare-function semantic-format-tag-prototype "semantic/format")
|
||||||
|
|
||||||
|
(defgroup company-semantic nil
|
||||||
|
"Completion backend using Semantic."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-semantic-metadata-function 'company-semantic-summary-and-doc
|
||||||
|
"The function turning a semantic tag into doc information."
|
||||||
|
:type 'function)
|
||||||
|
|
||||||
|
(defcustom company-semantic-begin-after-member-access t
|
||||||
|
"When non-nil, automatic completion will start whenever the current
|
||||||
|
symbol is preceded by \".\", \"->\" or \"::\", ignoring
|
||||||
|
`company-minimum-prefix-length'.
|
||||||
|
|
||||||
|
If `company-begin-commands' is a list, it should include `c-electric-lt-gt'
|
||||||
|
and `c-electric-colon', for automatic completion right after \">\" and
|
||||||
|
\":\"."
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom company-semantic-insert-arguments t
|
||||||
|
"When non-nil, insert function arguments as a template after completion."
|
||||||
|
:type 'boolean
|
||||||
|
:package-version '(company . "0.9.0"))
|
||||||
|
|
||||||
|
(defvar company-semantic-modes '(c-mode c++-mode jde-mode java-mode))
|
||||||
|
|
||||||
|
(defvar-local company-semantic--current-tags nil
|
||||||
|
"Tags for the current context.")
|
||||||
|
|
||||||
|
(defun company-semantic-documentation-for-tag (tag)
|
||||||
|
(when (semantic-tag-buffer tag)
|
||||||
|
;; When TAG's buffer is unknown, the function below raises an error.
|
||||||
|
(semantic-documentation-for-tag tag)))
|
||||||
|
|
||||||
|
(defun company-semantic-doc-or-summary (tag)
|
||||||
|
(or (company-semantic-documentation-for-tag tag)
|
||||||
|
(and (require 'semantic-idle nil t)
|
||||||
|
(require 'semantic/idle nil t)
|
||||||
|
(funcall semantic-idle-summary-function tag nil t))))
|
||||||
|
|
||||||
|
(defun company-semantic-summary-and-doc (tag)
|
||||||
|
(let ((doc (company-semantic-documentation-for-tag tag))
|
||||||
|
(summary (funcall semantic-idle-summary-function tag nil t)))
|
||||||
|
(and (stringp doc)
|
||||||
|
(string-match "\n*\\(.*\\)$" doc)
|
||||||
|
(setq doc (match-string 1 doc)))
|
||||||
|
(concat summary
|
||||||
|
(when doc
|
||||||
|
(if (< (+ (length doc) (length summary) 4) (window-width))
|
||||||
|
" -- "
|
||||||
|
"\n"))
|
||||||
|
doc)))
|
||||||
|
|
||||||
|
(defun company-semantic-doc-buffer (tag)
|
||||||
|
(let ((doc (company-semantic-documentation-for-tag tag)))
|
||||||
|
(when doc
|
||||||
|
(company-doc-buffer
|
||||||
|
(concat (funcall semantic-idle-summary-function tag nil t)
|
||||||
|
"\n"
|
||||||
|
doc)))))
|
||||||
|
|
||||||
|
(defsubst company-semantic-completions (prefix)
|
||||||
|
(ignore-errors
|
||||||
|
(let ((completion-ignore-case nil)
|
||||||
|
(context (semantic-analyze-current-context)))
|
||||||
|
(setq company-semantic--current-tags
|
||||||
|
(semantic-analyze-possible-completions context 'no-unique))
|
||||||
|
(all-completions prefix company-semantic--current-tags))))
|
||||||
|
|
||||||
|
(defun company-semantic-completions-raw (prefix)
|
||||||
|
(setq company-semantic--current-tags nil)
|
||||||
|
(dolist (tag (semantic-analyze-find-tags-by-prefix prefix))
|
||||||
|
(unless (eq (semantic-tag-class tag) 'include)
|
||||||
|
(push tag company-semantic--current-tags)))
|
||||||
|
(delete "" (mapcar 'semantic-tag-name company-semantic--current-tags)))
|
||||||
|
|
||||||
|
(defun company-semantic-annotation (argument tags)
|
||||||
|
(let* ((tag (assq argument tags))
|
||||||
|
(kind (when tag (elt tag 1))))
|
||||||
|
(cl-case kind
|
||||||
|
(function (let* ((prototype (semantic-format-tag-prototype tag nil nil))
|
||||||
|
(par-pos (string-match "(" prototype)))
|
||||||
|
(when par-pos (substring prototype par-pos)))))))
|
||||||
|
|
||||||
|
(defun company-semantic--prefix ()
|
||||||
|
(if company-semantic-begin-after-member-access
|
||||||
|
(company-grab-symbol-cons "\\.\\|->\\|::" 2)
|
||||||
|
(company-grab-symbol)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-semantic (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend using CEDET Semantic."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-semantic))
|
||||||
|
(prefix (and (featurep 'semantic)
|
||||||
|
(semantic-active-p)
|
||||||
|
(memq major-mode company-semantic-modes)
|
||||||
|
(not (company-in-string-or-comment))
|
||||||
|
(or (company-semantic--prefix) 'stop)))
|
||||||
|
(candidates (if (and (equal arg "")
|
||||||
|
(not (looking-back "->\\|\\.\\|::" (- (point) 2))))
|
||||||
|
(company-semantic-completions-raw arg)
|
||||||
|
(company-semantic-completions arg)))
|
||||||
|
(meta (funcall company-semantic-metadata-function
|
||||||
|
(assoc arg company-semantic--current-tags)))
|
||||||
|
(annotation (company-semantic-annotation arg
|
||||||
|
company-semantic--current-tags))
|
||||||
|
(doc-buffer (company-semantic-doc-buffer
|
||||||
|
(assoc arg company-semantic--current-tags)))
|
||||||
|
;; Because "" is an empty context and doesn't return local variables.
|
||||||
|
(no-cache (equal arg ""))
|
||||||
|
(duplicates t)
|
||||||
|
(location (let ((tag (assoc arg company-semantic--current-tags)))
|
||||||
|
(when (buffer-live-p (semantic-tag-buffer tag))
|
||||||
|
(cons (semantic-tag-buffer tag)
|
||||||
|
(semantic-tag-start tag)))))
|
||||||
|
(post-completion (let ((anno (company-semantic-annotation
|
||||||
|
arg company-semantic--current-tags)))
|
||||||
|
(when (and company-semantic-insert-arguments anno)
|
||||||
|
(insert anno)
|
||||||
|
(company-template-c-like-templatify (concat arg anno)))
|
||||||
|
))))
|
||||||
|
|
||||||
|
(provide 'company-semantic)
|
||||||
|
;;; company-semantic.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-semantic.elc
Normal file
BIN
elpa/company-20191029.2116/company-semantic.elc
Normal file
Binary file not shown.
272
elpa/company-20191029.2116/company-template.el
Normal file
272
elpa/company-20191029.2116/company-template.el
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
;;; company-template.el --- utility library for template expansion
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2010, 2014-2017 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defface company-template-field
|
||||||
|
'((((background dark)) (:background "yellow" :foreground "black"))
|
||||||
|
(((background light)) (:background "orange" :foreground "black")))
|
||||||
|
"Face used for editable text in template fields."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defvar company-template-forward-field-item
|
||||||
|
'(menu-item "" company-template-forward-field
|
||||||
|
:filter company-template--keymap-filter))
|
||||||
|
|
||||||
|
(defvar company-template-nav-map
|
||||||
|
(let ((keymap (make-sparse-keymap)))
|
||||||
|
(define-key keymap [tab] company-template-forward-field-item)
|
||||||
|
(define-key keymap (kbd "TAB") company-template-forward-field-item)
|
||||||
|
keymap))
|
||||||
|
|
||||||
|
(defvar company-template-clear-field-item
|
||||||
|
'(menu-item "" company-template-clear-field
|
||||||
|
:filter company-template--keymap-filter))
|
||||||
|
|
||||||
|
(defvar company-template-field-map
|
||||||
|
(let ((keymap (make-sparse-keymap)))
|
||||||
|
(set-keymap-parent keymap company-template-nav-map)
|
||||||
|
(define-key keymap (kbd "C-d") company-template-clear-field-item)
|
||||||
|
keymap))
|
||||||
|
|
||||||
|
(defvar-local company-template--buffer-templates nil)
|
||||||
|
|
||||||
|
;; interactive ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-templates-at (pos)
|
||||||
|
(let (os)
|
||||||
|
(dolist (o (overlays-at pos))
|
||||||
|
;; FIXME: Always return the whole list of templates?
|
||||||
|
;; We remove templates not at point after every command.
|
||||||
|
(when (memq o company-template--buffer-templates)
|
||||||
|
(push o os)))
|
||||||
|
os))
|
||||||
|
|
||||||
|
(defun company-template-move-to-first (templ)
|
||||||
|
(interactive)
|
||||||
|
(goto-char (overlay-start templ))
|
||||||
|
(company-template-forward-field))
|
||||||
|
|
||||||
|
(defun company-template-forward-field ()
|
||||||
|
(interactive)
|
||||||
|
(let ((start (point))
|
||||||
|
(next-field-start (company-template-find-next-field)))
|
||||||
|
(push-mark)
|
||||||
|
(goto-char next-field-start)
|
||||||
|
(company-template-remove-field (company-template-field-at start))))
|
||||||
|
|
||||||
|
(defun company-template-clear-field ()
|
||||||
|
"Clear the field at point."
|
||||||
|
(interactive)
|
||||||
|
(let ((ovl (company-template-field-at (point))))
|
||||||
|
(when ovl
|
||||||
|
(company-template-remove-field ovl t)
|
||||||
|
(let ((after-clear-fn
|
||||||
|
(overlay-get ovl 'company-template-after-clear)))
|
||||||
|
(when (functionp after-clear-fn)
|
||||||
|
(funcall after-clear-fn))))))
|
||||||
|
|
||||||
|
(defun company-template--keymap-filter (cmd)
|
||||||
|
(unless (run-hook-with-args-until-success 'yas-keymap-disable-hook)
|
||||||
|
cmd))
|
||||||
|
|
||||||
|
(defun company-template--after-clear-c-like-field ()
|
||||||
|
"Function that can be called after deleting a field of a c-like template.
|
||||||
|
For c-like templates it is set as `after-post-fn' property on fields in
|
||||||
|
`company-template-add-field'. If there is a next field, delete everything
|
||||||
|
from point to it. If there is no field after point, remove preceding comma
|
||||||
|
if present."
|
||||||
|
(let* ((pos (point))
|
||||||
|
(next-field-start (company-template-find-next-field))
|
||||||
|
(last-field-p (not (company-template-field-at next-field-start))))
|
||||||
|
(cond ((and (not last-field-p)
|
||||||
|
(< pos next-field-start)
|
||||||
|
(string-match "^[ ]*,+[ ]*$" (buffer-substring-no-properties
|
||||||
|
pos next-field-start)))
|
||||||
|
(delete-region pos next-field-start))
|
||||||
|
((and last-field-p
|
||||||
|
(looking-back ",+[ ]*" (line-beginning-position)))
|
||||||
|
(delete-region (match-beginning 0) pos)))))
|
||||||
|
|
||||||
|
(defun company-template-find-next-field ()
|
||||||
|
(let* ((start (point))
|
||||||
|
(templates (company-template-templates-at start))
|
||||||
|
(minimum (apply 'max (mapcar 'overlay-end templates)))
|
||||||
|
(fields (cl-loop for templ in templates
|
||||||
|
append (overlay-get templ 'company-template-fields))))
|
||||||
|
(dolist (pos (mapcar 'overlay-start fields) minimum)
|
||||||
|
(and pos
|
||||||
|
(> pos start)
|
||||||
|
(< pos minimum)
|
||||||
|
(setq minimum pos)))))
|
||||||
|
|
||||||
|
(defun company-template-field-at (&optional point)
|
||||||
|
(cl-loop for ovl in (overlays-at (or point (point)))
|
||||||
|
when (overlay-get ovl 'company-template-parent)
|
||||||
|
return ovl))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-declare-template (beg end)
|
||||||
|
(let ((ov (make-overlay beg end)))
|
||||||
|
;; (overlay-put ov 'face 'highlight)
|
||||||
|
(overlay-put ov 'keymap company-template-nav-map)
|
||||||
|
(overlay-put ov 'priority 101)
|
||||||
|
(overlay-put ov 'evaporate t)
|
||||||
|
(push ov company-template--buffer-templates)
|
||||||
|
(add-hook 'post-command-hook 'company-template-post-command nil t)
|
||||||
|
ov))
|
||||||
|
|
||||||
|
(defun company-template-remove-template (templ)
|
||||||
|
(mapc 'company-template-remove-field
|
||||||
|
(overlay-get templ 'company-template-fields))
|
||||||
|
(setq company-template--buffer-templates
|
||||||
|
(delq templ company-template--buffer-templates))
|
||||||
|
(delete-overlay templ))
|
||||||
|
|
||||||
|
(defun company-template-add-field (templ beg end &optional display after-clear-fn)
|
||||||
|
"Add new field to template TEMPL spanning from BEG to END.
|
||||||
|
When DISPLAY is non-nil, set the respective property on the overlay.
|
||||||
|
Leave point at the end of the field.
|
||||||
|
AFTER-CLEAR-FN is a function that can be used to apply custom behavior
|
||||||
|
after deleting a field in `company-template-remove-field'."
|
||||||
|
(cl-assert templ)
|
||||||
|
(when (> end (overlay-end templ))
|
||||||
|
(move-overlay templ (overlay-start templ) end))
|
||||||
|
(let ((ov (make-overlay beg end))
|
||||||
|
(siblings (overlay-get templ 'company-template-fields)))
|
||||||
|
;; (overlay-put ov 'evaporate t)
|
||||||
|
(overlay-put ov 'intangible t)
|
||||||
|
(overlay-put ov 'face 'company-template-field)
|
||||||
|
(when display
|
||||||
|
(overlay-put ov 'display display))
|
||||||
|
(overlay-put ov 'company-template-parent templ)
|
||||||
|
(overlay-put ov 'insert-in-front-hooks '(company-template-insert-hook))
|
||||||
|
(when after-clear-fn
|
||||||
|
(overlay-put ov 'company-template-after-clear after-clear-fn))
|
||||||
|
(overlay-put ov 'keymap company-template-field-map)
|
||||||
|
(overlay-put ov 'priority 101)
|
||||||
|
(push ov siblings)
|
||||||
|
(overlay-put templ 'company-template-fields siblings)))
|
||||||
|
|
||||||
|
(defun company-template-remove-field (ovl &optional clear)
|
||||||
|
(when (overlayp ovl)
|
||||||
|
(when (overlay-buffer ovl)
|
||||||
|
(when clear
|
||||||
|
(delete-region (overlay-start ovl) (overlay-end ovl)))
|
||||||
|
(delete-overlay ovl))
|
||||||
|
(let* ((templ (overlay-get ovl 'company-template-parent))
|
||||||
|
(siblings (overlay-get templ 'company-template-fields)))
|
||||||
|
(setq siblings (delq ovl siblings))
|
||||||
|
(overlay-put templ 'company-template-fields siblings))))
|
||||||
|
|
||||||
|
(defun company-template-clean-up (&optional pos)
|
||||||
|
"Clean up all templates that don't contain POS."
|
||||||
|
(let ((local-ovs (overlays-at (or pos (point)))))
|
||||||
|
(dolist (templ company-template--buffer-templates)
|
||||||
|
(unless (memq templ local-ovs)
|
||||||
|
(company-template-remove-template templ)))))
|
||||||
|
|
||||||
|
;; hooks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-insert-hook (ovl after-p &rest _ignore)
|
||||||
|
"Called when a snippet input prompt is modified."
|
||||||
|
(unless after-p
|
||||||
|
(company-template-remove-field ovl t)))
|
||||||
|
|
||||||
|
(defun company-template-post-command ()
|
||||||
|
(company-template-clean-up)
|
||||||
|
(unless company-template--buffer-templates
|
||||||
|
(remove-hook 'post-command-hook 'company-template-post-command t)))
|
||||||
|
|
||||||
|
;; common ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-c-like-templatify (call)
|
||||||
|
(let* ((end (point-marker))
|
||||||
|
(beg (- (point) (length call)))
|
||||||
|
(templ (company-template-declare-template beg end))
|
||||||
|
paren-open paren-close)
|
||||||
|
(with-syntax-table (make-syntax-table (syntax-table))
|
||||||
|
(modify-syntax-entry ?< "(")
|
||||||
|
(modify-syntax-entry ?> ")")
|
||||||
|
(when (search-backward ")" beg t)
|
||||||
|
(setq paren-close (point-marker))
|
||||||
|
(forward-char 1)
|
||||||
|
(delete-region (point) end)
|
||||||
|
(backward-sexp)
|
||||||
|
(forward-char 1)
|
||||||
|
(setq paren-open (point-marker)))
|
||||||
|
(when (search-backward ">" beg t)
|
||||||
|
(let ((angle-close (point-marker)))
|
||||||
|
(forward-char 1)
|
||||||
|
(backward-sexp)
|
||||||
|
(forward-char)
|
||||||
|
(company-template--c-like-args templ angle-close)))
|
||||||
|
(when (looking-back "\\((\\*)\\)(" (line-beginning-position))
|
||||||
|
(delete-region (match-beginning 1) (match-end 1)))
|
||||||
|
(when paren-open
|
||||||
|
(goto-char paren-open)
|
||||||
|
(company-template--c-like-args templ paren-close)))
|
||||||
|
(if (overlay-get templ 'company-template-fields)
|
||||||
|
(company-template-move-to-first templ)
|
||||||
|
(company-template-remove-template templ)
|
||||||
|
(goto-char end))))
|
||||||
|
|
||||||
|
(defun company-template--c-like-args (templ end)
|
||||||
|
(let ((last-pos (point)))
|
||||||
|
(while (re-search-forward "\\([^,]+\\),?" end 'move)
|
||||||
|
(when (zerop (car (parse-partial-sexp last-pos (point))))
|
||||||
|
(company-template-add-field templ last-pos (match-end 1) nil
|
||||||
|
#'company-template--after-clear-c-like-field)
|
||||||
|
(skip-chars-forward " ")
|
||||||
|
(setq last-pos (point))))))
|
||||||
|
|
||||||
|
;; objc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-objc-templatify (selector)
|
||||||
|
(let* ((end (point-marker))
|
||||||
|
(beg (- (point) (length selector) 1))
|
||||||
|
(templ (company-template-declare-template beg end))
|
||||||
|
(cnt 0))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char beg)
|
||||||
|
(catch 'stop
|
||||||
|
(while (search-forward ":" end t)
|
||||||
|
(if (looking-at "\\(([^)]*)\\) ?")
|
||||||
|
(company-template-add-field templ (point) (match-end 1))
|
||||||
|
;; Not sure which conditions this case manifests under, but
|
||||||
|
;; apparently it did before, when I wrote the first test for this
|
||||||
|
;; function. FIXME: Revisit it.
|
||||||
|
(company-template-add-field templ (point)
|
||||||
|
(progn
|
||||||
|
(insert (format "arg%d" cnt))
|
||||||
|
(point)))
|
||||||
|
(when (< (point) end)
|
||||||
|
(insert " "))
|
||||||
|
(cl-incf cnt))
|
||||||
|
(when (>= (point) end)
|
||||||
|
(throw 'stop t)))))
|
||||||
|
(company-template-move-to-first templ)))
|
||||||
|
|
||||||
|
(provide 'company-template)
|
||||||
|
;;; company-template.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-template.elc
Normal file
BIN
elpa/company-20191029.2116/company-template.elc
Normal file
Binary file not shown.
71
elpa/company-20191029.2116/company-tempo.el
Normal file
71
elpa/company-20191029.2116/company-tempo.el
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
;;; company-tempo.el --- company-mode completion backend for tempo
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
(require 'tempo)
|
||||||
|
|
||||||
|
(defgroup company-tempo nil
|
||||||
|
"Tempo completion backend."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-tempo-expand nil
|
||||||
|
"Whether to expand a tempo tag after completion."
|
||||||
|
:type '(choice (const :tag "Off" nil)
|
||||||
|
(const :tag "On" t)))
|
||||||
|
|
||||||
|
(defsubst company-tempo-lookup (match)
|
||||||
|
(cdr (assoc match (tempo-build-collection))))
|
||||||
|
|
||||||
|
(defun company-tempo-insert (match)
|
||||||
|
"Replace MATCH with the expanded tempo template."
|
||||||
|
(search-backward match)
|
||||||
|
(goto-char (match-beginning 0))
|
||||||
|
(replace-match "")
|
||||||
|
(call-interactively (company-tempo-lookup match)))
|
||||||
|
|
||||||
|
(defsubst company-tempo-meta (match)
|
||||||
|
(let ((templ (company-tempo-lookup match))
|
||||||
|
doc)
|
||||||
|
(and templ
|
||||||
|
(setq doc (documentation templ t))
|
||||||
|
(car (split-string doc "\n" t)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-tempo (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for tempo."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-tempo))
|
||||||
|
(prefix (or (car (tempo-find-match-string tempo-match-finder)) ""))
|
||||||
|
(candidates (all-completions arg (tempo-build-collection)))
|
||||||
|
(meta (company-tempo-meta arg))
|
||||||
|
(post-completion (when company-tempo-expand (company-tempo-insert arg)))
|
||||||
|
(sorted t)))
|
||||||
|
|
||||||
|
(provide 'company-tempo)
|
||||||
|
;;; company-tempo.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-tempo.elc
Normal file
BIN
elpa/company-20191029.2116/company-tempo.elc
Normal file
Binary file not shown.
194
elpa/company-20191029.2116/company-tng.el
Normal file
194
elpa/company-20191029.2116/company-tng.el
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
;;; company-tng.el --- company-mode configuration for single-button interaction
|
||||||
|
|
||||||
|
;; Copyright (C) 2017 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikita Leshenko
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; company-tng (Tab and Go) allows you to perform completion using just TAB.
|
||||||
|
;; Pressing it will both select the next completion candidate in the list and
|
||||||
|
;; insert it into the buffer (or make it look like it's inserted, in fact).
|
||||||
|
;;
|
||||||
|
;; It cycles the candidates like `yank-pop' or `dabbrev-expand' or Vim:
|
||||||
|
;; Pressing TAB selects the first item in the completion menu and inserts it in
|
||||||
|
;; the buffer. Pressing TAB again selects the second item and replaces the
|
||||||
|
;; "inserted" item with the second one. This can continue as long as the user
|
||||||
|
;; wishes to cycle through the menu. You can also press S-TAB to select the
|
||||||
|
;; previous candidate, of course.
|
||||||
|
;;
|
||||||
|
;; The benefits are that you only have to use one shortcut key and there is no
|
||||||
|
;; need to confirm the entry.
|
||||||
|
;;
|
||||||
|
;; Usage:
|
||||||
|
;;
|
||||||
|
;; To apply the default configuration for company-tng call
|
||||||
|
;; `company-tng-configure-default' from your init script.
|
||||||
|
;;
|
||||||
|
;; You can also configure company-tng manually:
|
||||||
|
;;
|
||||||
|
;; Add `company-tng-frontend' to `company-frontends':
|
||||||
|
;;
|
||||||
|
;; (add-to-list 'company-frontends 'company-tng-frontend)
|
||||||
|
;;
|
||||||
|
;; We recommend to bind TAB to `company-select-next', S-TAB to
|
||||||
|
;; `company-select-previous', and unbind RET and other now-unnecessary
|
||||||
|
;; keys from `company-active-map':
|
||||||
|
;;
|
||||||
|
;; (define-key company-active-map (kbd "TAB") 'company-select-next)
|
||||||
|
;; (define-key company-active-map (kbd "<backtab>") 'company-select-previous)
|
||||||
|
;; (define-key company-active-map (kbd "RET") nil)
|
||||||
|
;;
|
||||||
|
;; Note that it's not necessary to rebind keys to use this frontend,
|
||||||
|
;; you can use the arrow keys or M-n/M-p to select and insert
|
||||||
|
;; candidates. You also need to decide which keys to unbind, depending
|
||||||
|
;; on whether you want them to do the Company action or the default
|
||||||
|
;; Emacs action (for example C-s or C-w).
|
||||||
|
;;
|
||||||
|
;; We recommend to disable `company-require-match' to allow free typing at any
|
||||||
|
;; point.
|
||||||
|
;;
|
||||||
|
;; By default, company-tng doesn't work well with backends that use
|
||||||
|
;; `post-completion' (for actions such as expanding snippets in
|
||||||
|
;; company-yasnippet or company-template). In company-tng, completion candidates
|
||||||
|
;; are inserted into the buffer as the user selects them and the completion is
|
||||||
|
;; finished implicitly when the user continues typing after selecting a
|
||||||
|
;; candidate. Modifying the buffer (by expanding a snippet) when the user
|
||||||
|
;; continues typing would be surprising and undesirable, since the candidate was
|
||||||
|
;; already inserted into the buffer. For this reason company-tng disables
|
||||||
|
;; `post-completion' in all backends.
|
||||||
|
;;
|
||||||
|
;; YASnippet and company-tng both use TAB, which causes conflicts. The
|
||||||
|
;; recommended way to use YASnippet with company-tng is to choose a different
|
||||||
|
;; key for expanding a snippet and moving to the next snippet field:
|
||||||
|
;;
|
||||||
|
;; (define-key yas-minor-mode-map "\C-j" 'yas-expand)
|
||||||
|
;; (define-key yas-keymap "\C-j" 'yas-next-field-or-maybe-expand)
|
||||||
|
;; (dolist (keymap (list yas-minor-mode-map yas-keymap))
|
||||||
|
;; (define-key keymap (kbd "TAB") nil)
|
||||||
|
;; (define-key keymap [(tab)] nil))
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defvar-local company-tng--overlay nil)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-tng-frontend (command)
|
||||||
|
"When the user changes the selection at least once, this
|
||||||
|
frontend will display the candidate in the buffer as if it's
|
||||||
|
already there and any key outside of `company-active-map' will
|
||||||
|
confirm the selection and finish the completion."
|
||||||
|
(cl-case command
|
||||||
|
(show
|
||||||
|
(let ((ov (make-overlay (point) (point))))
|
||||||
|
(setq company-tng--overlay ov)
|
||||||
|
(overlay-put ov 'priority 2))
|
||||||
|
(advice-add 'company-select-next :before-until 'company-tng--allow-unselected)
|
||||||
|
(advice-add 'company-fill-propertize :filter-args 'company-tng--adjust-tooltip-highlight))
|
||||||
|
(update
|
||||||
|
(let ((ov company-tng--overlay)
|
||||||
|
(selected (nth company-selection company-candidates))
|
||||||
|
(prefix (length company-prefix)))
|
||||||
|
(move-overlay ov (- (point) prefix) (point))
|
||||||
|
(overlay-put ov
|
||||||
|
(if (= prefix 0) 'after-string 'display)
|
||||||
|
(and company-selection-changed selected))))
|
||||||
|
(hide
|
||||||
|
(when company-tng--overlay
|
||||||
|
(delete-overlay company-tng--overlay)
|
||||||
|
(kill-local-variable 'company-tng--overlay))
|
||||||
|
(advice-remove 'company-select-next 'company-tng--allow-unselected)
|
||||||
|
(advice-remove 'company-fill-propertize 'company-tng--adjust-tooltip-highlight))
|
||||||
|
(pre-command
|
||||||
|
(when (and company-selection-changed
|
||||||
|
(not (company--company-command-p (this-command-keys))))
|
||||||
|
(company--unread-this-command-keys)
|
||||||
|
(setq this-command 'company-complete-selection)
|
||||||
|
(advice-add 'company-call-backend :before-until 'company-tng--supress-post-completion)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-tng-configure-default ()
|
||||||
|
"Applies the default configuration to enable company-tng."
|
||||||
|
(setq company-require-match nil)
|
||||||
|
(setq company-frontends '(company-tng-frontend
|
||||||
|
company-pseudo-tooltip-frontend
|
||||||
|
company-echo-metadata-frontend))
|
||||||
|
(let ((keymap company-active-map))
|
||||||
|
(define-key keymap [return] nil)
|
||||||
|
(define-key keymap (kbd "RET") nil)
|
||||||
|
(define-key keymap [tab] 'company-select-next)
|
||||||
|
(define-key keymap (kbd "TAB") 'company-select-next)
|
||||||
|
(define-key keymap [backtab] 'company-select-previous)
|
||||||
|
(define-key keymap (kbd "S-TAB") 'company-select-previous)))
|
||||||
|
|
||||||
|
(defun company-tng--allow-unselected (&optional arg)
|
||||||
|
"Advice `company-select-next' to allow for an 'unselected'
|
||||||
|
state. Unselected means that no user interaction took place on the
|
||||||
|
completion candidates and it's marked by setting
|
||||||
|
`company-selection-changed' to nil. This advice will call the underlying
|
||||||
|
`company-select-next' unless we need to transition to or from an unselected
|
||||||
|
state.
|
||||||
|
|
||||||
|
Possible state transitions:
|
||||||
|
- (arg > 0) unselected -> first candidate selected
|
||||||
|
- (arg < 0) first candidate selected -> unselected
|
||||||
|
- (arg < 0 wrap-round) unselected -> last candidate selected
|
||||||
|
- (arg < 0 no wrap-round) unselected -> unselected
|
||||||
|
|
||||||
|
There is no need to advice `company-select-previous' because it calls
|
||||||
|
`company-select-next' internally."
|
||||||
|
(cond
|
||||||
|
;; Selecting next
|
||||||
|
((or (not arg) (> arg 0))
|
||||||
|
(unless company-selection-changed
|
||||||
|
(company-set-selection (1- (or arg 1)) 'force-update)
|
||||||
|
t))
|
||||||
|
;; Selecting previous
|
||||||
|
((< arg 0)
|
||||||
|
(when (and company-selection-changed
|
||||||
|
(< (+ company-selection arg) 0))
|
||||||
|
(company-set-selection 0)
|
||||||
|
(setq company-selection-changed nil)
|
||||||
|
(company-call-frontends 'update)
|
||||||
|
t)
|
||||||
|
)))
|
||||||
|
|
||||||
|
(defun company-tng--adjust-tooltip-highlight (args)
|
||||||
|
"Prevent the tooltip from highlighting the current selection if it wasn't
|
||||||
|
made explicitly (i.e. `company-selection-changed' is true)"
|
||||||
|
(unless company-selection-changed
|
||||||
|
;; The 4th arg of `company-fill-propertize' is selected
|
||||||
|
(setf (nth 3 args) nil))
|
||||||
|
args)
|
||||||
|
|
||||||
|
(defun company-tng--supress-post-completion (command &rest args)
|
||||||
|
"Installed as a :before-until advice on `company-call-backend' and
|
||||||
|
prevents the 'post-completion command from being delivered to the backend
|
||||||
|
for the next iteration. post-completion do things like expand snippets
|
||||||
|
which are undesirable because completions are implicit in company-tng and
|
||||||
|
visible side-effects after the completion are surprising."
|
||||||
|
(when (eq command 'post-completion)
|
||||||
|
(advice-remove 'company-call-backend 'company-tng--supress-post-completion)
|
||||||
|
t))
|
||||||
|
|
||||||
|
(provide 'company-tng)
|
||||||
|
;;; company-tng.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-tng.elc
Normal file
BIN
elpa/company-20191029.2116/company-tng.elc
Normal file
Binary file not shown.
123
elpa/company-20191029.2116/company-xcode.el
Normal file
123
elpa/company-20191029.2116/company-xcode.el
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
;;; company-xcode.el --- company-mode completion backend for Xcode projects
|
||||||
|
|
||||||
|
;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-xcode nil
|
||||||
|
"Completion backend for Xcode projects."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-xcode-xcodeindex-executable (executable-find "xcodeindex")
|
||||||
|
"Location of xcodeindex executable."
|
||||||
|
:type 'file)
|
||||||
|
|
||||||
|
(defvar company-xcode-tags nil)
|
||||||
|
|
||||||
|
(defun company-xcode-reset ()
|
||||||
|
"Reset the cached tags."
|
||||||
|
(interactive)
|
||||||
|
(setq company-xcode-tags nil))
|
||||||
|
|
||||||
|
(defcustom company-xcode-types
|
||||||
|
'("Class" "Constant" "Enum" "Macro" "Modeled Class" "Structure"
|
||||||
|
"Type" "Union" "Function")
|
||||||
|
"The types of symbols offered by `company-xcode'.
|
||||||
|
No context-enabled completion is available. Types like methods will be
|
||||||
|
offered regardless of whether the class supports them. The defaults should be
|
||||||
|
valid in most contexts."
|
||||||
|
:set (lambda (variable value)
|
||||||
|
(set variable value)
|
||||||
|
(company-xcode-reset))
|
||||||
|
:type '(set (const "Category") (const "Class") (const "Class Method")
|
||||||
|
(const "Class Variable") (const "Constant") (const "Enum")
|
||||||
|
(const "Field") (const "Instance Method")
|
||||||
|
(const "Instance Variable") (const "Macro")
|
||||||
|
(const "Modeled Class") (const "Modeled Method")
|
||||||
|
(const "Modeled Property") (const "Property") (const "Protocol")
|
||||||
|
(const "Structure") (const "Type") (const "Union")
|
||||||
|
(const "Variable") (const "Function")))
|
||||||
|
|
||||||
|
(defvar-local company-xcode-project 'unknown)
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-xcode-fetch (project-bundle)
|
||||||
|
(setq project-bundle (directory-file-name project-bundle))
|
||||||
|
(message "Retrieving dump from %s..." project-bundle)
|
||||||
|
(with-temp-buffer
|
||||||
|
(let ((default-directory (file-name-directory project-bundle)))
|
||||||
|
(call-process company-xcode-xcodeindex-executable nil (current-buffer)
|
||||||
|
nil "dump" "-project"
|
||||||
|
(file-name-nondirectory project-bundle) "-quiet")
|
||||||
|
(goto-char (point-min))
|
||||||
|
(let ((regexp (concat "^\\([^\t\n]*\\)\t[^\t\n]*\t"
|
||||||
|
(regexp-opt company-xcode-types)
|
||||||
|
"\t[^\t\n]*\t[^\t\n]*"))
|
||||||
|
candidates)
|
||||||
|
(while (re-search-forward regexp nil t)
|
||||||
|
(cl-pushnew (match-string 1) candidates :test #'equal))
|
||||||
|
(message "Retrieving dump from %s...done" project-bundle)
|
||||||
|
candidates))))
|
||||||
|
|
||||||
|
(defun company-xcode-find-project ()
|
||||||
|
(let ((dir (if buffer-file-name
|
||||||
|
(file-name-directory buffer-file-name)
|
||||||
|
(expand-file-name default-directory)))
|
||||||
|
(prev-dir nil)
|
||||||
|
file)
|
||||||
|
(while (not (or file (equal dir prev-dir)))
|
||||||
|
(setq file (car (directory-files dir t ".xcodeproj\\'" t))
|
||||||
|
prev-dir dir
|
||||||
|
dir (file-name-directory (directory-file-name dir))))
|
||||||
|
file))
|
||||||
|
|
||||||
|
(defun company-xcode-tags ()
|
||||||
|
(when (eq company-xcode-project 'unknown)
|
||||||
|
(setq company-xcode-project (company-xcode-find-project)))
|
||||||
|
(when company-xcode-project
|
||||||
|
(cdr (or (assoc company-xcode-project company-xcode-tags)
|
||||||
|
(car (push (cons company-xcode-project
|
||||||
|
(company-xcode-fetch company-xcode-project))
|
||||||
|
company-xcode-tags))))))
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-xcode (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for Xcode projects."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-xcode))
|
||||||
|
(prefix (and company-xcode-xcodeindex-executable
|
||||||
|
(company-xcode-tags)
|
||||||
|
(not (company-in-string-or-comment))
|
||||||
|
(or (company-grab-symbol) 'stop)))
|
||||||
|
(candidates (let ((completion-ignore-case nil))
|
||||||
|
(company-xcode-tags)
|
||||||
|
(all-completions arg (company-xcode-tags))))))
|
||||||
|
|
||||||
|
|
||||||
|
(provide 'company-xcode)
|
||||||
|
;;; company-xcode.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-xcode.elc
Normal file
BIN
elpa/company-20191029.2116/company-xcode.elc
Normal file
Binary file not shown.
147
elpa/company-20191029.2116/company-yasnippet.el
Normal file
147
elpa/company-20191029.2116/company-yasnippet.el
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
;;; company-yasnippet.el --- company-mode completion backend for Yasnippet
|
||||||
|
|
||||||
|
;; Copyright (C) 2014, 2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Dmitry Gutov
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(declare-function yas--table-hash "yasnippet")
|
||||||
|
(declare-function yas--get-snippet-tables "yasnippet")
|
||||||
|
(declare-function yas-expand-snippet "yasnippet")
|
||||||
|
(declare-function yas--template-content "yasnippet")
|
||||||
|
(declare-function yas--template-expand-env "yasnippet")
|
||||||
|
(declare-function yas--warning "yasnippet")
|
||||||
|
|
||||||
|
(defun company-yasnippet--key-prefixes ()
|
||||||
|
;; Mostly copied from `yas--templates-for-key-at-point'.
|
||||||
|
(defvar yas-key-syntaxes)
|
||||||
|
(save-excursion
|
||||||
|
(let ((original (point))
|
||||||
|
(methods yas-key-syntaxes)
|
||||||
|
prefixes
|
||||||
|
method)
|
||||||
|
(while methods
|
||||||
|
(unless (eq method (car methods))
|
||||||
|
(goto-char original))
|
||||||
|
(setq method (car methods))
|
||||||
|
(cond ((stringp method)
|
||||||
|
(skip-syntax-backward method)
|
||||||
|
(setq methods (cdr methods)))
|
||||||
|
((functionp method)
|
||||||
|
(unless (eq (funcall method original)
|
||||||
|
'again)
|
||||||
|
(setq methods (cdr methods))))
|
||||||
|
(t
|
||||||
|
(setq methods (cdr methods))
|
||||||
|
(yas--warning "Invalid element `%s' in `yas-key-syntaxes'" method)))
|
||||||
|
(let ((prefix (buffer-substring-no-properties (point) original)))
|
||||||
|
(unless (equal prefix (car prefixes))
|
||||||
|
(push prefix prefixes))))
|
||||||
|
prefixes)))
|
||||||
|
|
||||||
|
(defun company-yasnippet--candidates (prefix)
|
||||||
|
;; Process the prefixes in reverse: unlike Yasnippet, we look for prefix
|
||||||
|
;; matches, so the longest prefix with any matches should be the most useful.
|
||||||
|
(cl-loop with tables = (yas--get-snippet-tables)
|
||||||
|
for key-prefix in (company-yasnippet--key-prefixes)
|
||||||
|
;; Only consider keys at least as long as the symbol at point.
|
||||||
|
when (>= (length key-prefix) (length prefix))
|
||||||
|
thereis (company-yasnippet--completions-for-prefix prefix
|
||||||
|
key-prefix
|
||||||
|
tables)))
|
||||||
|
|
||||||
|
(defun company-yasnippet--completions-for-prefix (prefix key-prefix tables)
|
||||||
|
(cl-mapcan
|
||||||
|
(lambda (table)
|
||||||
|
(let ((keyhash (yas--table-hash table))
|
||||||
|
res)
|
||||||
|
(when keyhash
|
||||||
|
(maphash
|
||||||
|
(lambda (key value)
|
||||||
|
(when (and (stringp key)
|
||||||
|
(string-prefix-p key-prefix key))
|
||||||
|
(maphash
|
||||||
|
(lambda (name template)
|
||||||
|
(push
|
||||||
|
(propertize key
|
||||||
|
'yas-annotation name
|
||||||
|
'yas-template template
|
||||||
|
'yas-prefix-offset (- (length key-prefix)
|
||||||
|
(length prefix)))
|
||||||
|
res))
|
||||||
|
value)))
|
||||||
|
keyhash))
|
||||||
|
res))
|
||||||
|
tables))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun company-yasnippet (command &optional arg &rest ignore)
|
||||||
|
"`company-mode' backend for `yasnippet'.
|
||||||
|
|
||||||
|
This backend should be used with care, because as long as there are
|
||||||
|
snippets defined for the current major mode, this backend will always
|
||||||
|
shadow backends that come after it. Recommended usages:
|
||||||
|
|
||||||
|
* In a buffer-local value of `company-backends', grouped with a backend or
|
||||||
|
several that provide actual text completions.
|
||||||
|
|
||||||
|
(add-hook 'js-mode-hook
|
||||||
|
(lambda ()
|
||||||
|
(set (make-local-variable 'company-backends)
|
||||||
|
'((company-dabbrev-code company-yasnippet)))))
|
||||||
|
|
||||||
|
* After keyword `:with', grouped with other backends.
|
||||||
|
|
||||||
|
(push '(company-semantic :with company-yasnippet) company-backends)
|
||||||
|
|
||||||
|
* Not in `company-backends', just bound to a key.
|
||||||
|
|
||||||
|
(global-set-key (kbd \"C-c y\") 'company-yasnippet)
|
||||||
|
"
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-yasnippet))
|
||||||
|
(prefix
|
||||||
|
;; Should probably use `yas--current-key', but that's bound to be slower.
|
||||||
|
;; How many trigger keys start with non-symbol characters anyway?
|
||||||
|
(and (bound-and-true-p yas-minor-mode)
|
||||||
|
(company-grab-symbol)))
|
||||||
|
(annotation
|
||||||
|
(concat
|
||||||
|
(unless company-tooltip-align-annotations " -> ")
|
||||||
|
(get-text-property 0 'yas-annotation arg)))
|
||||||
|
(candidates (company-yasnippet--candidates arg))
|
||||||
|
(no-cache t)
|
||||||
|
(post-completion
|
||||||
|
(let ((template (get-text-property 0 'yas-template arg))
|
||||||
|
(prefix-offset (get-text-property 0 'yas-prefix-offset arg)))
|
||||||
|
(yas-expand-snippet (yas--template-content template)
|
||||||
|
(- (point) (length arg) prefix-offset)
|
||||||
|
(point)
|
||||||
|
(yas--template-expand-env template))))))
|
||||||
|
|
||||||
|
(provide 'company-yasnippet)
|
||||||
|
;;; company-yasnippet.el ends here
|
||||||
BIN
elpa/company-20191029.2116/company-yasnippet.elc
Normal file
BIN
elpa/company-20191029.2116/company-yasnippet.elc
Normal file
Binary file not shown.
3217
elpa/company-20191029.2116/company.el
Normal file
3217
elpa/company-20191029.2116/company.el
Normal file
File diff suppressed because it is too large
Load Diff
BIN
elpa/company-20191029.2116/company.elc
Normal file
BIN
elpa/company-20191029.2116/company.elc
Normal file
Binary file not shown.
79
elpa/dumb-jump-20190928.1758/dumb-jump-autoloads.el
Normal file
79
elpa/dumb-jump-20190928.1758/dumb-jump-autoloads.el
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
;;; dumb-jump-autoloads.el --- automatically extracted autoloads
|
||||||
|
;;
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(add-to-list 'load-path (directory-file-name
|
||||||
|
(or (file-name-directory #$) (car load-path))))
|
||||||
|
|
||||||
|
|
||||||
|
;;;### (autoloads nil "dumb-jump" "dumb-jump.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from dumb-jump.el
|
||||||
|
|
||||||
|
(defvar dumb-jump-mode-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-M-g") 'dumb-jump-go) (define-key map (kbd "C-M-p") 'dumb-jump-back) (define-key map (kbd "C-M-q") 'dumb-jump-quick-look) map))
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-back "dumb-jump" "\
|
||||||
|
Jump back to where the last jump was done.
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-quick-look "dumb-jump" "\
|
||||||
|
Run dumb-jump-go in quick look mode. That is, show a tooltip of where it would jump instead.
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-go-other-window "dumb-jump" "\
|
||||||
|
Like 'dumb-jump-go' but use 'find-file-other-window' instead of 'find-file'.
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-go-current-window "dumb-jump" "\
|
||||||
|
Like dumb-jump-go but always use 'find-file'.
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-go-prefer-external "dumb-jump" "\
|
||||||
|
Like dumb-jump-go but prefer external matches from the current file.
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-go-prompt "dumb-jump" "\
|
||||||
|
Like dumb-jump-go but prompts for function instead of using under point
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-go-prefer-external-other-window "dumb-jump" "\
|
||||||
|
Like dumb-jump-go-prefer-external but use 'find-file-other-window' instead of 'find-file'.
|
||||||
|
|
||||||
|
\(fn)" t nil)
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-go "dumb-jump" "\
|
||||||
|
Go to the function/variable declaration for thing at point.
|
||||||
|
When USE-TOOLTIP is t a tooltip jump preview will show instead.
|
||||||
|
When PREFER-EXTERNAL is t it will sort external matches before
|
||||||
|
current file.
|
||||||
|
|
||||||
|
\(fn &optional USE-TOOLTIP PREFER-EXTERNAL PROMPT)" t nil)
|
||||||
|
|
||||||
|
(defvar dumb-jump-mode nil "\
|
||||||
|
Non-nil if Dumb-Jump mode is enabled.
|
||||||
|
See the `dumb-jump-mode' command
|
||||||
|
for a description of this minor mode.")
|
||||||
|
|
||||||
|
(custom-autoload 'dumb-jump-mode "dumb-jump" nil)
|
||||||
|
|
||||||
|
(autoload 'dumb-jump-mode "dumb-jump" "\
|
||||||
|
Minor mode for jumping to variable and function definitions
|
||||||
|
|
||||||
|
\(fn &optional ARG)" t nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dumb-jump" '("dumb-jump-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;; Local Variables:
|
||||||
|
;; version-control: never
|
||||||
|
;; no-byte-compile: t
|
||||||
|
;; no-update-autoloads: t
|
||||||
|
;; coding: utf-8
|
||||||
|
;; End:
|
||||||
|
;;; dumb-jump-autoloads.el ends here
|
||||||
2
elpa/dumb-jump-20190928.1758/dumb-jump-pkg.el
Normal file
2
elpa/dumb-jump-20190928.1758/dumb-jump-pkg.el
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
;;; -*- no-byte-compile: t -*-
|
||||||
|
(define-package "dumb-jump" "20190928.1758" "jump to definition for 40+ languages without configuration." '((emacs "24.3") (f "0.20.0") (s "1.11.0") (dash "2.9.0") (popup "0.5.3")) :commit "34fb76982dafc62f8105c520aece4c3ceccb7307" :keywords '("programming") :authors '(("jack angers and contributors")) :maintainer '("jack angers and contributors"))
|
||||||
2803
elpa/dumb-jump-20190928.1758/dumb-jump.el
Normal file
2803
elpa/dumb-jump-20190928.1758/dumb-jump.el
Normal file
File diff suppressed because it is too large
Load Diff
BIN
elpa/dumb-jump-20190928.1758/dumb-jump.elc
Normal file
BIN
elpa/dumb-jump-20190928.1758/dumb-jump.elc
Normal file
Binary file not shown.
53
elpa/git-commit-20190928.1746/git-commit-autoloads.el
Normal file
53
elpa/git-commit-20190928.1746/git-commit-autoloads.el
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
;;; git-commit-autoloads.el --- automatically extracted autoloads
|
||||||
|
;;
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(add-to-list 'load-path (directory-file-name
|
||||||
|
(or (file-name-directory #$) (car load-path))))
|
||||||
|
|
||||||
|
|
||||||
|
;;;### (autoloads nil "git-commit" "git-commit.el" (0 0 0 0))
|
||||||
|
;;; Generated autoloads from git-commit.el
|
||||||
|
|
||||||
|
(defvar global-git-commit-mode t "\
|
||||||
|
Non-nil if Global Git-Commit mode is enabled.
|
||||||
|
See the `global-git-commit-mode' command
|
||||||
|
for a description of this minor mode.
|
||||||
|
Setting this variable directly does not take effect;
|
||||||
|
either customize it (see the info node `Easy Customization')
|
||||||
|
or call the function `global-git-commit-mode'.")
|
||||||
|
|
||||||
|
(custom-autoload 'global-git-commit-mode "git-commit" nil)
|
||||||
|
|
||||||
|
(autoload 'global-git-commit-mode "git-commit" "\
|
||||||
|
Edit Git commit messages.
|
||||||
|
This global mode arranges for `git-commit-setup' to be called
|
||||||
|
when a Git commit message file is opened. That usually happens
|
||||||
|
when Git uses the Emacsclient as $GIT_EDITOR to have the user
|
||||||
|
provide such a commit message.
|
||||||
|
|
||||||
|
\(fn &optional ARG)" t nil)
|
||||||
|
|
||||||
|
(defconst git-commit-filename-regexp "/\\(\\(\\(COMMIT\\|NOTES\\|PULLREQ\\|MERGEREQ\\|TAG\\)_EDIT\\|MERGE_\\|\\)MSG\\|\\(BRANCH\\|EDIT\\)_DESCRIPTION\\)\\'")
|
||||||
|
|
||||||
|
(autoload 'git-commit-setup-check-buffer "git-commit" "\
|
||||||
|
|
||||||
|
|
||||||
|
\(fn)" nil nil)
|
||||||
|
|
||||||
|
(autoload 'git-commit-setup "git-commit" "\
|
||||||
|
|
||||||
|
|
||||||
|
\(fn)" nil nil)
|
||||||
|
|
||||||
|
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "git-commit" '("git-commit-")))
|
||||||
|
|
||||||
|
;;;***
|
||||||
|
|
||||||
|
;; Local Variables:
|
||||||
|
;; version-control: never
|
||||||
|
;; no-byte-compile: t
|
||||||
|
;; no-update-autoloads: t
|
||||||
|
;; coding: utf-8
|
||||||
|
;; End:
|
||||||
|
;;; git-commit-autoloads.el ends here
|
||||||
2
elpa/git-commit-20190928.1746/git-commit-pkg.el
Normal file
2
elpa/git-commit-20190928.1746/git-commit-pkg.el
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
;;; -*- no-byte-compile: t -*-
|
||||||
|
(define-package "git-commit" "20190928.1746" "Edit Git commit messages" '((emacs "25.1") (dash "20180910") (with-editor "20181103")) :commit "7118a9af4f002d6cdc8762b16c45e1ba307dcc8a" :keywords '("git" "tools" "vc") :maintainer '("Jonas Bernoulli" . "jonas@bernoul.li") :url "https://github.com/magit/magit")
|
||||||
990
elpa/git-commit-20190928.1746/git-commit.el
Normal file
990
elpa/git-commit-20190928.1746/git-commit.el
Normal file
@@ -0,0 +1,990 @@
|
|||||||
|
;;; git-commit.el --- Edit Git commit messages -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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.
|
||||||
|
|
||||||
|
;; Authors: Jonas Bernoulli <jonas@bernoul.li>
|
||||||
|
;; Sebastian Wiesner <lunaryorn@gmail.com>
|
||||||
|
;; Florian Ragwitz <rafl@debian.org>
|
||||||
|
;; Marius Vollmer <marius.vollmer@gmail.com>
|
||||||
|
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
|
||||||
|
|
||||||
|
;; Package-Requires: ((emacs "25.1") (dash "20180910") (with-editor "20181103"))
|
||||||
|
;; Package-Version: 20190928.1746
|
||||||
|
;; Keywords: git tools vc
|
||||||
|
;; Homepage: https://github.com/magit/magit
|
||||||
|
|
||||||
|
;; This file is not part of GNU Emacs.
|
||||||
|
|
||||||
|
;; This file 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.
|
||||||
|
|
||||||
|
;; This file 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 this file. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; This package assists the user in writing good Git commit messages.
|
||||||
|
|
||||||
|
;; While Git allows for the message to be provided on the command
|
||||||
|
;; line, it is preferable to tell Git to create the commit without
|
||||||
|
;; actually passing it a message. Git then invokes the `$GIT_EDITOR'
|
||||||
|
;; (or if that is undefined `$EDITOR') asking the user to provide the
|
||||||
|
;; message by editing the file ".git/COMMIT_EDITMSG" (or another file
|
||||||
|
;; in that directory, e.g. ".git/MERGE_MSG" for merge commits).
|
||||||
|
|
||||||
|
;; When `global-git-commit-mode' is enabled, which it is by default,
|
||||||
|
;; then opening such a file causes the features described below, to
|
||||||
|
;; be enabled in that buffer. Normally this would be done using a
|
||||||
|
;; major-mode but to allow the use of any major-mode, as the user sees
|
||||||
|
;; fit, it is done here by running a setup function, which among other
|
||||||
|
;; things turns on the preferred major-mode, by default `text-mode'.
|
||||||
|
|
||||||
|
;; Git waits for the `$EDITOR' to finish and then either creates the
|
||||||
|
;; commit using the contents of the file as commit message, or, if the
|
||||||
|
;; editor process exited with a non-zero exit status, aborts without
|
||||||
|
;; creating a commit. Unfortunately Emacsclient (which is what Emacs
|
||||||
|
;; users should be using as `$EDITOR' or at least as `$GIT_EDITOR')
|
||||||
|
;; does not differentiate between "successfully" editing a file and
|
||||||
|
;; aborting; not out of the box that is.
|
||||||
|
|
||||||
|
;; By making use of the `with-editor' package this package provides
|
||||||
|
;; both ways of finish an editing session. In either case the file
|
||||||
|
;; is saved, but Emacseditor's exit code differs.
|
||||||
|
;;
|
||||||
|
;; C-c C-c Finish the editing session successfully by returning
|
||||||
|
;; with exit code 0. Git then creates the commit using
|
||||||
|
;; the message it finds in the file.
|
||||||
|
;;
|
||||||
|
;; C-c C-k Aborts the edit editing session by returning with exit
|
||||||
|
;; code 1. Git then aborts the commit.
|
||||||
|
|
||||||
|
;; Aborting the commit does not cause the message to be lost, but
|
||||||
|
;; relying solely on the file not being tampered with is risky. This
|
||||||
|
;; package additionally stores all aborted messages for the duration
|
||||||
|
;; of the current session (i.e. until you close Emacs). To get back
|
||||||
|
;; an aborted message use M-p and M-n while editing a message.
|
||||||
|
;;
|
||||||
|
;; M-p Replace the buffer contents with the previous message
|
||||||
|
;; from the message ring. Of course only after storing
|
||||||
|
;; the current content there too.
|
||||||
|
;;
|
||||||
|
;; M-n Replace the buffer contents with the next message from
|
||||||
|
;; the message ring, after storing the current content.
|
||||||
|
|
||||||
|
;; Some support for pseudo headers as used in some projects is
|
||||||
|
;; provided by these commands:
|
||||||
|
;;
|
||||||
|
;; C-c C-s Insert a Signed-off-by header.
|
||||||
|
;; C-c C-a Insert a Acked-by header.
|
||||||
|
;; C-c C-m Insert a Modified-by header.
|
||||||
|
;; C-c C-t Insert a Tested-by header.
|
||||||
|
;; C-c C-r Insert a Reviewed-by header.
|
||||||
|
;; C-c C-o Insert a Cc header.
|
||||||
|
;; C-c C-p Insert a Reported-by header.
|
||||||
|
;; C-c C-i Insert a Suggested-by header.
|
||||||
|
|
||||||
|
;; When Git requests a commit message from the user, it does so by
|
||||||
|
;; having her edit a file which initially contains some comments,
|
||||||
|
;; instructing her what to do, and providing useful information, such
|
||||||
|
;; as which files were modified. These comments, even when left
|
||||||
|
;; intact by the user, do not become part of the commit message. This
|
||||||
|
;; package ensures these comments are propertizes as such and further
|
||||||
|
;; prettifies them by using different faces for various parts, such as
|
||||||
|
;; files.
|
||||||
|
|
||||||
|
;; Finally this package highlights style errors, like lines that are
|
||||||
|
;; too long, or when the second line is not empty. It may even nag
|
||||||
|
;; you when you attempt to finish the commit without having fixed
|
||||||
|
;; these issues. The style checks and many other settings can easily
|
||||||
|
;; be configured:
|
||||||
|
;;
|
||||||
|
;; M-x customize-group RET git-commit RET
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
;;;; Dependencies
|
||||||
|
|
||||||
|
(require 'dash)
|
||||||
|
(require 'log-edit)
|
||||||
|
(require 'magit-git nil t)
|
||||||
|
(require 'magit-utils nil t)
|
||||||
|
(require 'ring)
|
||||||
|
(require 'server)
|
||||||
|
(require 'with-editor)
|
||||||
|
|
||||||
|
(eval-when-compile (require 'recentf))
|
||||||
|
|
||||||
|
;;;; Declarations
|
||||||
|
|
||||||
|
(defvar diff-default-read-only)
|
||||||
|
(defvar flyspell-generic-check-word-predicate)
|
||||||
|
(defvar font-lock-beg)
|
||||||
|
(defvar font-lock-end)
|
||||||
|
|
||||||
|
(declare-function magit-expand-git-file-name "magit-git" (filename))
|
||||||
|
(declare-function magit-list-local-branch-names "magit-git" ())
|
||||||
|
(declare-function magit-list-remote-branch-names "magit-git"
|
||||||
|
(&optional remote relative))
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
;;;; Variables
|
||||||
|
|
||||||
|
(defgroup git-commit nil
|
||||||
|
"Edit Git commit messages."
|
||||||
|
:prefix "git-commit-"
|
||||||
|
:link '(info-link "(magit)Editing Commit Messages")
|
||||||
|
:group 'tools)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(define-minor-mode global-git-commit-mode
|
||||||
|
"Edit Git commit messages.
|
||||||
|
This global mode arranges for `git-commit-setup' to be called
|
||||||
|
when a Git commit message file is opened. That usually happens
|
||||||
|
when Git uses the Emacsclient as $GIT_EDITOR to have the user
|
||||||
|
provide such a commit message."
|
||||||
|
:group 'git-commit
|
||||||
|
:type 'boolean
|
||||||
|
:global t
|
||||||
|
:init-value t
|
||||||
|
:initialize (lambda (symbol exp)
|
||||||
|
(custom-initialize-default symbol exp)
|
||||||
|
(when global-git-commit-mode
|
||||||
|
(add-hook 'find-file-hook 'git-commit-setup-check-buffer)))
|
||||||
|
(if global-git-commit-mode
|
||||||
|
(add-hook 'find-file-hook 'git-commit-setup-check-buffer)
|
||||||
|
(remove-hook 'find-file-hook 'git-commit-setup-check-buffer)))
|
||||||
|
|
||||||
|
(defcustom git-commit-major-mode 'text-mode
|
||||||
|
"Major mode used to edit Git commit messages.
|
||||||
|
The major mode configured here is turned on by the minor mode
|
||||||
|
`git-commit-mode'."
|
||||||
|
:group 'git-commit
|
||||||
|
:type '(choice (function-item text-mode)
|
||||||
|
(const :tag "No major mode")))
|
||||||
|
|
||||||
|
(defcustom git-commit-setup-hook
|
||||||
|
'(git-commit-save-message
|
||||||
|
git-commit-setup-changelog-support
|
||||||
|
git-commit-turn-on-auto-fill
|
||||||
|
git-commit-propertize-diff
|
||||||
|
bug-reference-mode
|
||||||
|
with-editor-usage-message)
|
||||||
|
"Hook run at the end of `git-commit-setup'."
|
||||||
|
:group 'git-commit
|
||||||
|
:type 'hook
|
||||||
|
:get (and (featurep 'magit-utils) 'magit-hook-custom-get)
|
||||||
|
:options '(git-commit-save-message
|
||||||
|
git-commit-setup-changelog-support
|
||||||
|
git-commit-turn-on-auto-fill
|
||||||
|
git-commit-turn-on-flyspell
|
||||||
|
git-commit-propertize-diff
|
||||||
|
bug-reference-mode
|
||||||
|
with-editor-usage-message))
|
||||||
|
|
||||||
|
(defcustom git-commit-post-finish-hook nil
|
||||||
|
"Hook run after the user finished writing a commit message.
|
||||||
|
|
||||||
|
\\<with-editor-mode-map>\
|
||||||
|
This hook is only run after pressing \\[with-editor-finish] in a buffer used
|
||||||
|
to edit a commit message. If a commit is created without the
|
||||||
|
user typing a message into a buffer, then this hook is not run.
|
||||||
|
|
||||||
|
This hook is not run until the new commit has been created. If
|
||||||
|
doing so takes Git longer than one second, then this hook isn't
|
||||||
|
run at all. For certain commands such as `magit-rebase-continue'
|
||||||
|
this hook is never run because doing so would lead to a race
|
||||||
|
condition.
|
||||||
|
|
||||||
|
This hook is only run if `magit' is available.
|
||||||
|
|
||||||
|
Also see `magit-post-commit-hook'."
|
||||||
|
:group 'git-commit
|
||||||
|
:type 'hook
|
||||||
|
:get (and (featurep 'magit-utils) 'magit-hook-custom-get))
|
||||||
|
|
||||||
|
(defcustom git-commit-finish-query-functions
|
||||||
|
'(git-commit-check-style-conventions)
|
||||||
|
"List of functions called to query before performing commit.
|
||||||
|
|
||||||
|
The commit message buffer is current while the functions are
|
||||||
|
called. If any of them returns nil, then the commit is not
|
||||||
|
performed and the buffer is not killed. The user should then
|
||||||
|
fix the issue and try again.
|
||||||
|
|
||||||
|
The functions are called with one argument. If it is non-nil,
|
||||||
|
then that indicates that the user used a prefix argument to
|
||||||
|
force finishing the session despite issues. Functions should
|
||||||
|
usually honor this wish and return non-nil."
|
||||||
|
:options '(git-commit-check-style-conventions)
|
||||||
|
:type 'hook
|
||||||
|
:group 'git-commit)
|
||||||
|
|
||||||
|
(defcustom git-commit-style-convention-checks '(non-empty-second-line)
|
||||||
|
"List of checks performed by `git-commit-check-style-conventions'.
|
||||||
|
Valid members are `non-empty-second-line' and `overlong-summary-line'.
|
||||||
|
That function is a member of `git-commit-finish-query-functions'."
|
||||||
|
:options '(non-empty-second-line overlong-summary-line)
|
||||||
|
:type '(list :convert-widget custom-hook-convert-widget)
|
||||||
|
:group 'git-commit)
|
||||||
|
|
||||||
|
(defcustom git-commit-summary-max-length 68
|
||||||
|
"Column beyond which characters in the summary lines are highlighted.
|
||||||
|
|
||||||
|
The highlighting indicates that the summary is getting too long
|
||||||
|
by some standards. It does in no way imply that going over the
|
||||||
|
limit a few characters or in some cases even many characters is
|
||||||
|
anything that deserves shaming. It's just a friendly reminder
|
||||||
|
that if you can make the summary shorter, then you might want
|
||||||
|
to consider doing so."
|
||||||
|
:group 'git-commit
|
||||||
|
:safe 'numberp
|
||||||
|
:type 'number)
|
||||||
|
|
||||||
|
(defcustom git-commit-fill-column nil
|
||||||
|
"Override `fill-column' in commit message buffers.
|
||||||
|
|
||||||
|
If this is non-nil, then it should be an integer. If that is the
|
||||||
|
case and the buffer-local value of `fill-column' is not already
|
||||||
|
set by the time `git-commit-turn-on-auto-fill' is called as a
|
||||||
|
member of `git-commit-setup-hook', then that function sets the
|
||||||
|
buffer-local value of `fill-column' to the value of this option.
|
||||||
|
|
||||||
|
This option exists mostly for historic reasons. If you are not
|
||||||
|
already using it, then you probably shouldn't start doing so."
|
||||||
|
:group 'git-commit
|
||||||
|
:safe 'numberp
|
||||||
|
:type '(choice (const :tag "use regular fill-column")
|
||||||
|
number))
|
||||||
|
|
||||||
|
(make-obsolete-variable 'git-commit-fill-column 'fill-column
|
||||||
|
"Magit 2.11.0" 'set)
|
||||||
|
|
||||||
|
(defcustom git-commit-known-pseudo-headers
|
||||||
|
'("Signed-off-by" "Acked-by" "Modified-by" "Cc"
|
||||||
|
"Suggested-by" "Reported-by" "Tested-by" "Reviewed-by"
|
||||||
|
"Co-authored-by")
|
||||||
|
"A list of Git pseudo headers to be highlighted."
|
||||||
|
:group 'git-commit
|
||||||
|
:safe (lambda (val) (and (listp val) (-all-p 'stringp val)))
|
||||||
|
:type '(repeat string))
|
||||||
|
|
||||||
|
;;;; Faces
|
||||||
|
|
||||||
|
(defgroup git-commit-faces nil
|
||||||
|
"Faces used for highlighting Git commit messages."
|
||||||
|
:prefix "git-commit-"
|
||||||
|
:group 'git-commit
|
||||||
|
:group 'faces)
|
||||||
|
|
||||||
|
(defface git-commit-summary
|
||||||
|
'((t :inherit font-lock-type-face))
|
||||||
|
"Face used for the summary in commit messages."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-overlong-summary
|
||||||
|
'((t :inherit font-lock-warning-face))
|
||||||
|
"Face used for the tail of overlong commit message summaries."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-nonempty-second-line
|
||||||
|
'((t :inherit font-lock-warning-face))
|
||||||
|
"Face used for non-whitespace on the second line of commit messages."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-keyword
|
||||||
|
'((t :inherit font-lock-string-face))
|
||||||
|
"Face used for keywords in commit messages.
|
||||||
|
In this context a \"keyword\" is text surrounded be brackets."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(define-obsolete-face-alias 'git-commit-note
|
||||||
|
'git-commit-keyword "Git-Commit 2.91.0")
|
||||||
|
|
||||||
|
(defface git-commit-pseudo-header
|
||||||
|
'((t :inherit font-lock-string-face))
|
||||||
|
"Face used for pseudo headers in commit messages."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-known-pseudo-header
|
||||||
|
'((t :inherit font-lock-keyword-face))
|
||||||
|
"Face used for the keywords of known pseudo headers in commit messages."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-comment-branch-local
|
||||||
|
(if (featurep 'magit)
|
||||||
|
'((t :inherit magit-branch-local))
|
||||||
|
'((t :inherit font-lock-variable-name-face)))
|
||||||
|
"Face used for names of local branches in commit message comments."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(define-obsolete-face-alias 'git-commit-comment-branch
|
||||||
|
'git-commit-comment-branch-local "Git-Commit 2.12.0")
|
||||||
|
|
||||||
|
(defface git-commit-comment-branch-remote
|
||||||
|
(if (featurep 'magit)
|
||||||
|
'((t :inherit magit-branch-remote))
|
||||||
|
'((t :inherit font-lock-variable-name-face)))
|
||||||
|
"Face used for names of remote branches in commit message comments.
|
||||||
|
This is only used if Magit is available."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-comment-detached
|
||||||
|
'((t :inherit git-commit-comment-branch-local))
|
||||||
|
"Face used for detached `HEAD' in commit message comments."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-comment-heading
|
||||||
|
'((t :inherit git-commit-known-pseudo-header))
|
||||||
|
"Face used for headings in commit message comments."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-comment-file
|
||||||
|
'((t :inherit git-commit-pseudo-header))
|
||||||
|
"Face used for file names in commit message comments."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
(defface git-commit-comment-action
|
||||||
|
'((t :inherit bold))
|
||||||
|
"Face used for actions in commit message comments."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
;;; Keymap
|
||||||
|
|
||||||
|
(defvar git-commit-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(cond ((featurep 'jkl)
|
||||||
|
(define-key map (kbd "C-M-i") 'git-commit-prev-message)
|
||||||
|
(define-key map (kbd "C-M-k") 'git-commit-next-message))
|
||||||
|
(t
|
||||||
|
(define-key map (kbd "M-p") 'git-commit-prev-message)
|
||||||
|
(define-key map (kbd "M-n") 'git-commit-next-message)
|
||||||
|
;; Old bindings to avoid confusion
|
||||||
|
(define-key map (kbd "C-c C-x a") 'git-commit-ack)
|
||||||
|
(define-key map (kbd "C-c C-x i") 'git-commit-suggested)
|
||||||
|
(define-key map (kbd "C-c C-x m") 'git-commit-modified)
|
||||||
|
(define-key map (kbd "C-c C-x o") 'git-commit-cc)
|
||||||
|
(define-key map (kbd "C-c C-x p") 'git-commit-reported)
|
||||||
|
(define-key map (kbd "C-c C-x r") 'git-commit-review)
|
||||||
|
(define-key map (kbd "C-c C-x s") 'git-commit-signoff)
|
||||||
|
(define-key map (kbd "C-c C-x t") 'git-commit-test)))
|
||||||
|
(define-key map (kbd "C-c C-a") 'git-commit-ack)
|
||||||
|
(define-key map (kbd "C-c C-i") 'git-commit-suggested)
|
||||||
|
(define-key map (kbd "C-c C-m") 'git-commit-modified)
|
||||||
|
(define-key map (kbd "C-c C-o") 'git-commit-cc)
|
||||||
|
(define-key map (kbd "C-c C-p") 'git-commit-reported)
|
||||||
|
(define-key map (kbd "C-c C-r") 'git-commit-review)
|
||||||
|
(define-key map (kbd "C-c C-s") 'git-commit-signoff)
|
||||||
|
(define-key map (kbd "C-c C-t") 'git-commit-test)
|
||||||
|
(define-key map (kbd "C-c M-s") 'git-commit-save-message)
|
||||||
|
map)
|
||||||
|
"Key map used by `git-commit-mode'.")
|
||||||
|
|
||||||
|
;;; Menu
|
||||||
|
|
||||||
|
(require 'easymenu)
|
||||||
|
(easy-menu-define git-commit-mode-menu git-commit-mode-map
|
||||||
|
"Git Commit Mode Menu"
|
||||||
|
'("Commit"
|
||||||
|
["Previous" git-commit-prev-message t]
|
||||||
|
["Next" git-commit-next-message t]
|
||||||
|
"-"
|
||||||
|
["Ack" git-commit-ack :active t
|
||||||
|
:help "Insert an 'Acked-by' header"]
|
||||||
|
["Sign-Off" git-commit-signoff :active t
|
||||||
|
:help "Insert a 'Signed-off-by' header"]
|
||||||
|
["Modified-by" git-commit-modified :active t
|
||||||
|
:help "Insert a 'Modified-by' header"]
|
||||||
|
["Tested-by" git-commit-test :active t
|
||||||
|
:help "Insert a 'Tested-by' header"]
|
||||||
|
["Reviewed-by" git-commit-review :active t
|
||||||
|
:help "Insert a 'Reviewed-by' header"]
|
||||||
|
["CC" git-commit-cc t
|
||||||
|
:help "Insert a 'Cc' header"]
|
||||||
|
["Reported" git-commit-reported :active t
|
||||||
|
:help "Insert a 'Reported-by' header"]
|
||||||
|
["Suggested" git-commit-suggested t
|
||||||
|
:help "Insert a 'Suggested-by' header"]
|
||||||
|
["Co-authored-by" git-commit-co-authored t
|
||||||
|
:help "Insert a 'Co-authored-by' header"]
|
||||||
|
"-"
|
||||||
|
["Save" git-commit-save-message t]
|
||||||
|
["Cancel" with-editor-cancel t]
|
||||||
|
["Commit" with-editor-finish t]))
|
||||||
|
|
||||||
|
;;; Hooks
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defconst git-commit-filename-regexp "/\\(\
|
||||||
|
\\(\\(COMMIT\\|NOTES\\|PULLREQ\\|MERGEREQ\\|TAG\\)_EDIT\\|MERGE_\\|\\)MSG\
|
||||||
|
\\|\\(BRANCH\\|EDIT\\)_DESCRIPTION\\)\\'")
|
||||||
|
|
||||||
|
(eval-after-load 'recentf
|
||||||
|
'(add-to-list 'recentf-exclude git-commit-filename-regexp))
|
||||||
|
|
||||||
|
(add-to-list 'with-editor-file-name-history-exclude git-commit-filename-regexp)
|
||||||
|
|
||||||
|
(defun git-commit-setup-font-lock-in-buffer ()
|
||||||
|
(and buffer-file-name
|
||||||
|
(string-match-p git-commit-filename-regexp buffer-file-name)
|
||||||
|
(git-commit-setup-font-lock)))
|
||||||
|
|
||||||
|
(add-hook 'after-change-major-mode-hook 'git-commit-setup-font-lock-in-buffer)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun git-commit-setup-check-buffer ()
|
||||||
|
(and buffer-file-name
|
||||||
|
(string-match-p git-commit-filename-regexp buffer-file-name)
|
||||||
|
(git-commit-setup)))
|
||||||
|
|
||||||
|
(defvar git-commit-mode)
|
||||||
|
|
||||||
|
(defun git-commit-file-not-found ()
|
||||||
|
;; cygwin git will pass a cygwin path (/cygdrive/c/foo/.git/...),
|
||||||
|
;; try to handle this in window-nt Emacs.
|
||||||
|
(--when-let
|
||||||
|
(and (or (string-match-p git-commit-filename-regexp buffer-file-name)
|
||||||
|
(and (boundp 'git-rebase-filename-regexp)
|
||||||
|
(string-match-p git-rebase-filename-regexp
|
||||||
|
buffer-file-name)))
|
||||||
|
(not (file-accessible-directory-p
|
||||||
|
(file-name-directory buffer-file-name)))
|
||||||
|
(if (require 'magit-git nil t)
|
||||||
|
;; Emacs prepends a "c:".
|
||||||
|
(magit-expand-git-file-name (substring buffer-file-name 2))
|
||||||
|
;; Fallback if we can't load `magit-git'.
|
||||||
|
(and (string-match "\\`[a-z]:/\\(cygdrive/\\)?\\([a-z]\\)/\\(.*\\)"
|
||||||
|
buffer-file-name)
|
||||||
|
(concat (match-string 2 buffer-file-name) ":/"
|
||||||
|
(match-string 3 buffer-file-name)))))
|
||||||
|
(when (file-accessible-directory-p (file-name-directory it))
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(insert-file-contents it t)
|
||||||
|
t))))
|
||||||
|
|
||||||
|
(when (eq system-type 'windows-nt)
|
||||||
|
(add-hook 'find-file-not-found-functions #'git-commit-file-not-found))
|
||||||
|
|
||||||
|
(defconst git-commit-usage-message "\
|
||||||
|
Type \\[with-editor-finish] to finish, \
|
||||||
|
\\[with-editor-cancel] to cancel, and \
|
||||||
|
\\[git-commit-prev-message] and \\[git-commit-next-message] \
|
||||||
|
to recover older messages")
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun git-commit-setup ()
|
||||||
|
(when (fboundp 'magit-toplevel)
|
||||||
|
;; `magit-toplevel' is autoloaded and defined in magit-git.el,
|
||||||
|
;; That library declares this functions without loading
|
||||||
|
;; magit-process.el, which defines it.
|
||||||
|
(require 'magit-process nil t))
|
||||||
|
;; Pretend that git-commit-mode is a major-mode,
|
||||||
|
;; so that directory-local settings can be used.
|
||||||
|
(let ((default-directory
|
||||||
|
(or (and (not (file-exists-p ".dir-locals.el"))
|
||||||
|
;; When $GIT_DIR/.dir-locals.el doesn't exist,
|
||||||
|
;; fallback to $GIT_WORK_TREE/.dir-locals.el,
|
||||||
|
;; because the maintainer can use the latter
|
||||||
|
;; to enforce conventions, while s/he has no
|
||||||
|
;; control over the former.
|
||||||
|
(fboundp 'magit-toplevel) ; silence byte-compiler
|
||||||
|
(magit-toplevel))
|
||||||
|
default-directory)))
|
||||||
|
(let ((buffer-file-name nil) ; trick hack-dir-local-variables
|
||||||
|
(major-mode 'git-commit-mode)) ; trick dir-locals-collect-variables
|
||||||
|
(hack-dir-local-variables)
|
||||||
|
(hack-local-variables-apply)))
|
||||||
|
(when git-commit-major-mode
|
||||||
|
(let ((auto-mode-alist (list (cons (concat "\\`"
|
||||||
|
(regexp-quote buffer-file-name)
|
||||||
|
"\\'")
|
||||||
|
git-commit-major-mode)))
|
||||||
|
;; The major-mode hook might want to consult these minor
|
||||||
|
;; modes, while the minor-mode hooks might want to consider
|
||||||
|
;; the major mode.
|
||||||
|
(git-commit-mode t)
|
||||||
|
(with-editor-mode t))
|
||||||
|
(normal-mode t)))
|
||||||
|
;; Show our own message using our hook.
|
||||||
|
(setq with-editor-show-usage nil)
|
||||||
|
(setq with-editor-usage-message git-commit-usage-message)
|
||||||
|
(unless with-editor-mode
|
||||||
|
;; Maybe already enabled when using `shell-command' or an Emacs shell.
|
||||||
|
(with-editor-mode 1))
|
||||||
|
(add-hook 'with-editor-finish-query-functions
|
||||||
|
'git-commit-finish-query-functions nil t)
|
||||||
|
(add-hook 'with-editor-pre-finish-hook
|
||||||
|
'git-commit-save-message nil t)
|
||||||
|
(add-hook 'with-editor-pre-cancel-hook
|
||||||
|
'git-commit-save-message nil t)
|
||||||
|
(when (and (fboundp 'magit-rev-parse)
|
||||||
|
(not (memq last-command
|
||||||
|
'(magit-sequencer-continue
|
||||||
|
magit-sequencer-skip
|
||||||
|
magit-am-continue
|
||||||
|
magit-am-skip
|
||||||
|
magit-rebase-continue
|
||||||
|
magit-rebase-skip))))
|
||||||
|
(add-hook 'with-editor-post-finish-hook
|
||||||
|
(apply-partially 'git-commit-run-post-finish-hook
|
||||||
|
(magit-rev-parse "HEAD"))
|
||||||
|
nil t)
|
||||||
|
(when (fboundp 'magit-wip-maybe-add-commit-hook)
|
||||||
|
(magit-wip-maybe-add-commit-hook)))
|
||||||
|
(setq with-editor-cancel-message
|
||||||
|
'git-commit-cancel-message)
|
||||||
|
(make-local-variable 'log-edit-comment-ring-index)
|
||||||
|
(git-commit-mode 1)
|
||||||
|
(git-commit-setup-font-lock)
|
||||||
|
(when (boundp 'save-place)
|
||||||
|
(setq save-place nil))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(when (looking-at "\\`\\(\\'\\|\n[^\n]\\)")
|
||||||
|
(open-line 1)))
|
||||||
|
(with-demoted-errors "Error running git-commit-setup-hook: %S"
|
||||||
|
(run-hooks 'git-commit-setup-hook))
|
||||||
|
(set-buffer-modified-p nil))
|
||||||
|
|
||||||
|
(defun git-commit-run-post-finish-hook (previous)
|
||||||
|
(when (and git-commit-post-finish-hook
|
||||||
|
(require 'magit nil t)
|
||||||
|
(fboundp 'magit-rev-parse))
|
||||||
|
(cl-block nil
|
||||||
|
(let ((break (time-add (current-time)
|
||||||
|
(seconds-to-time 1))))
|
||||||
|
(while (equal (magit-rev-parse "HEAD") previous)
|
||||||
|
(if (time-less-p (current-time) break)
|
||||||
|
(sit-for 0.01)
|
||||||
|
(message "No commit created after 1 second. Not running %s."
|
||||||
|
'git-commit-post-finish-hook)
|
||||||
|
(cl-return))))
|
||||||
|
(run-hooks 'git-commit-post-finish-hook))))
|
||||||
|
|
||||||
|
(define-minor-mode git-commit-mode
|
||||||
|
"Auxiliary minor mode used when editing Git commit messages.
|
||||||
|
This mode is only responsible for setting up some key bindings.
|
||||||
|
Don't use it directly, instead enable `global-git-commit-mode'."
|
||||||
|
:lighter "")
|
||||||
|
|
||||||
|
(put 'git-commit-mode 'permanent-local t)
|
||||||
|
|
||||||
|
(defun git-commit-setup-changelog-support ()
|
||||||
|
"Treat ChangeLog entries as unindented paragraphs."
|
||||||
|
(setq-local fill-indent-according-to-mode t)
|
||||||
|
(setq-local paragraph-start (concat paragraph-start "\\|\\*\\|(")))
|
||||||
|
|
||||||
|
(defun git-commit-turn-on-auto-fill ()
|
||||||
|
"Unconditionally turn on Auto Fill mode.
|
||||||
|
If `git-commit-fill-column' is non-nil, and `fill-column'
|
||||||
|
doesn't already have a buffer-local value, then set that
|
||||||
|
to `git-commit-fill-column'."
|
||||||
|
(when (and (numberp git-commit-fill-column)
|
||||||
|
(not (local-variable-p 'fill-column)))
|
||||||
|
(setq fill-column git-commit-fill-column))
|
||||||
|
(setq-local comment-auto-fill-only-comments nil)
|
||||||
|
(turn-on-auto-fill))
|
||||||
|
|
||||||
|
(defun git-commit-turn-on-flyspell ()
|
||||||
|
"Unconditionally turn on Flyspell mode.
|
||||||
|
Also prevent comments from being checked and
|
||||||
|
finally check current non-comment text."
|
||||||
|
(require 'flyspell)
|
||||||
|
(turn-on-flyspell)
|
||||||
|
(setq flyspell-generic-check-word-predicate
|
||||||
|
'git-commit-flyspell-verify)
|
||||||
|
(let ((end)
|
||||||
|
(comment-start-regex (format "^\\(%s\\|$\\)" comment-start)))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-max))
|
||||||
|
(while (and (not (bobp)) (looking-at comment-start-regex))
|
||||||
|
(forward-line -1))
|
||||||
|
(unless (looking-at comment-start-regex)
|
||||||
|
(forward-line))
|
||||||
|
(setq end (point)))
|
||||||
|
(flyspell-region (point-min) end)))
|
||||||
|
|
||||||
|
(defun git-commit-flyspell-verify ()
|
||||||
|
(not (= (char-after (line-beginning-position))
|
||||||
|
(aref comment-start 0))))
|
||||||
|
|
||||||
|
(defun git-commit-finish-query-functions (force)
|
||||||
|
(run-hook-with-args-until-failure
|
||||||
|
'git-commit-finish-query-functions force))
|
||||||
|
|
||||||
|
(defun git-commit-check-style-conventions (force)
|
||||||
|
"Check for violations of certain basic style conventions.
|
||||||
|
|
||||||
|
For each violation ask the user if she wants to proceed anyway.
|
||||||
|
Option `git-commit-check-style-conventions' controls which
|
||||||
|
conventions are checked."
|
||||||
|
(or force
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(re-search-forward (git-commit-summary-regexp) nil t)
|
||||||
|
(if (equal (match-string 1) "")
|
||||||
|
t ; Just try; we don't know whether --allow-empty-message was used.
|
||||||
|
(and (or (not (memq 'overlong-summary-line
|
||||||
|
git-commit-style-convention-checks))
|
||||||
|
(equal (match-string 2) "")
|
||||||
|
(y-or-n-p "Summary line is too long. Commit anyway? "))
|
||||||
|
(or (not (memq 'non-empty-second-line
|
||||||
|
git-commit-style-convention-checks))
|
||||||
|
(not (match-string 3))
|
||||||
|
(y-or-n-p "Second line is not empty. Commit anyway? ")))))))
|
||||||
|
|
||||||
|
(defun git-commit-cancel-message ()
|
||||||
|
(message
|
||||||
|
(concat "Commit canceled"
|
||||||
|
(and (memq 'git-commit-save-message with-editor-pre-cancel-hook)
|
||||||
|
". Message saved to `log-edit-comment-ring'"))))
|
||||||
|
|
||||||
|
;;; History
|
||||||
|
|
||||||
|
(defun git-commit-prev-message (arg)
|
||||||
|
"Cycle backward through message history, after saving current message.
|
||||||
|
With a numeric prefix ARG, go back ARG comments."
|
||||||
|
(interactive "*p")
|
||||||
|
(when (and (git-commit-save-message) (> arg 0))
|
||||||
|
(setq log-edit-comment-ring-index
|
||||||
|
(log-edit-new-comment-index
|
||||||
|
arg (ring-length log-edit-comment-ring))))
|
||||||
|
(save-restriction
|
||||||
|
(goto-char (point-min))
|
||||||
|
(narrow-to-region (point)
|
||||||
|
(if (re-search-forward (concat "^" comment-start) nil t)
|
||||||
|
(max 1 (- (point) 2))
|
||||||
|
(point-max)))
|
||||||
|
(log-edit-previous-comment arg)))
|
||||||
|
|
||||||
|
(defun git-commit-next-message (arg)
|
||||||
|
"Cycle forward through message history, after saving current message.
|
||||||
|
With a numeric prefix ARG, go forward ARG comments."
|
||||||
|
(interactive "*p")
|
||||||
|
(git-commit-prev-message (- arg)))
|
||||||
|
|
||||||
|
(defun git-commit-save-message ()
|
||||||
|
"Save current message to `log-edit-comment-ring'."
|
||||||
|
(interactive)
|
||||||
|
(--when-let (git-commit-buffer-message)
|
||||||
|
(unless (ring-member log-edit-comment-ring it)
|
||||||
|
(ring-insert log-edit-comment-ring it))))
|
||||||
|
|
||||||
|
(defun git-commit-buffer-message ()
|
||||||
|
(let ((flush (concat "^" comment-start))
|
||||||
|
(str (buffer-substring-no-properties (point-min) (point-max))))
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert str)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(when (re-search-forward (concat flush " -+ >8 -+$") nil t)
|
||||||
|
(delete-region (point-at-bol) (point-max)))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(flush-lines flush)
|
||||||
|
(goto-char (point-max))
|
||||||
|
(unless (eq (char-before) ?\n)
|
||||||
|
(insert ?\n))
|
||||||
|
(setq str (buffer-string)))
|
||||||
|
(unless (string-match "\\`[ \t\n\r]*\\'" str)
|
||||||
|
(when (string-match "\\`\n\\{2,\\}" str)
|
||||||
|
(setq str (replace-match "\n" t t str)))
|
||||||
|
(when (string-match "\n\\{2,\\}\\'" str)
|
||||||
|
(setq str (replace-match "\n" t t str)))
|
||||||
|
str)))
|
||||||
|
|
||||||
|
;;; Headers
|
||||||
|
|
||||||
|
(defun git-commit-ack (name mail)
|
||||||
|
"Insert a header acknowledging that you have looked at the commit."
|
||||||
|
(interactive (git-commit-self-ident))
|
||||||
|
(git-commit-insert-header "Acked-by" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-modified (name mail)
|
||||||
|
"Insert a header to signal that you have modified the commit."
|
||||||
|
(interactive (git-commit-self-ident))
|
||||||
|
(git-commit-insert-header "Modified-by" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-review (name mail)
|
||||||
|
"Insert a header acknowledging that you have reviewed the commit."
|
||||||
|
(interactive (git-commit-self-ident))
|
||||||
|
(git-commit-insert-header "Reviewed-by" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-signoff (name mail)
|
||||||
|
"Insert a header to sign off the commit."
|
||||||
|
(interactive (git-commit-self-ident))
|
||||||
|
(git-commit-insert-header "Signed-off-by" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-test (name mail)
|
||||||
|
"Insert a header acknowledging that you have tested the commit."
|
||||||
|
(interactive (git-commit-self-ident))
|
||||||
|
(git-commit-insert-header "Tested-by" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-cc (name mail)
|
||||||
|
"Insert a header mentioning someone who might be interested."
|
||||||
|
(interactive (git-commit-read-ident))
|
||||||
|
(git-commit-insert-header "Cc" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-reported (name mail)
|
||||||
|
"Insert a header mentioning the person who reported the issue."
|
||||||
|
(interactive (git-commit-read-ident))
|
||||||
|
(git-commit-insert-header "Reported-by" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-suggested (name mail)
|
||||||
|
"Insert a header mentioning the person who suggested the change."
|
||||||
|
(interactive (git-commit-read-ident))
|
||||||
|
(git-commit-insert-header "Suggested-by" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-co-authored-by (name mail)
|
||||||
|
"Insert a header mentioning the person who co-authored the commit."
|
||||||
|
(interactive (git-commit-read-ident))
|
||||||
|
(git-commit-insert-header "Co-authored-by" name mail))
|
||||||
|
|
||||||
|
(defun git-commit-self-ident ()
|
||||||
|
(list (or (getenv "GIT_AUTHOR_NAME")
|
||||||
|
(getenv "GIT_COMMITTER_NAME")
|
||||||
|
(ignore-errors (car (process-lines "git" "config" "user.name")))
|
||||||
|
user-full-name
|
||||||
|
(read-string "Name: "))
|
||||||
|
(or (getenv "GIT_AUTHOR_EMAIL")
|
||||||
|
(getenv "GIT_COMMITTER_EMAIL")
|
||||||
|
(getenv "EMAIL")
|
||||||
|
(ignore-errors (car (process-lines "git" "config" "user.email")))
|
||||||
|
(read-string "Email: "))))
|
||||||
|
|
||||||
|
(defun git-commit-read-ident ()
|
||||||
|
(list (read-string "Name: ")
|
||||||
|
(read-string "Email: ")))
|
||||||
|
|
||||||
|
(defun git-commit-insert-header (header name email)
|
||||||
|
(setq header (format "%s: %s <%s>" header name email))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-max))
|
||||||
|
(cond ((re-search-backward "^[-a-zA-Z]+: [^<]+? <[^>]+>" nil t)
|
||||||
|
(end-of-line)
|
||||||
|
(insert ?\n header)
|
||||||
|
(unless (= (char-after) ?\n)
|
||||||
|
(insert ?\n)))
|
||||||
|
(t
|
||||||
|
(while (re-search-backward (concat "^" comment-start) nil t))
|
||||||
|
(unless (looking-back "\n\n" nil)
|
||||||
|
(insert ?\n))
|
||||||
|
(insert header ?\n)))
|
||||||
|
(unless (or (eobp) (= (char-after) ?\n))
|
||||||
|
(insert ?\n))))
|
||||||
|
|
||||||
|
;;; Font-Lock
|
||||||
|
|
||||||
|
(defvar-local git-commit-need-summary-line t
|
||||||
|
"Whether the text should have a heading that is separated from the body.
|
||||||
|
|
||||||
|
For commit messages that is a convention that should not
|
||||||
|
be violated. For notes it is up to the user. If you do
|
||||||
|
not want to insist on an empty second line here, then use
|
||||||
|
something like:
|
||||||
|
|
||||||
|
(add-hook \\='git-commit-setup-hook
|
||||||
|
(lambda ()
|
||||||
|
(when (equal (file-name-nondirectory (buffer-file-name))
|
||||||
|
\"NOTES_EDITMSG\")
|
||||||
|
(setq git-commit-need-summary-line nil))))")
|
||||||
|
|
||||||
|
(defun git-commit-summary-regexp ()
|
||||||
|
(if git-commit-need-summary-line
|
||||||
|
(concat
|
||||||
|
;; Leading empty lines and comments
|
||||||
|
(format "\\`\\(?:^\\(?:\\s-*\\|%s.*\\)\n\\)*" comment-start)
|
||||||
|
;; Summary line
|
||||||
|
(format "\\(.\\{0,%d\\}\\)\\(.*\\)" git-commit-summary-max-length)
|
||||||
|
;; Non-empty non-comment second line
|
||||||
|
(format "\\(?:\n%s\\|\n\\(.+\\)\\)?" comment-start))
|
||||||
|
"\\(EASTER\\) \\(EGG\\)"))
|
||||||
|
|
||||||
|
(defun git-commit-extend-region-summary-line ()
|
||||||
|
"Identify the multiline summary-regexp construct.
|
||||||
|
Added to `font-lock-extend-region-functions'."
|
||||||
|
(save-excursion
|
||||||
|
(save-match-data
|
||||||
|
(goto-char (point-min))
|
||||||
|
(when (looking-at (git-commit-summary-regexp))
|
||||||
|
(let ((summary-beg (match-beginning 0))
|
||||||
|
(summary-end (match-end 0)))
|
||||||
|
(when (or (< summary-beg font-lock-beg summary-end)
|
||||||
|
(< summary-beg font-lock-end summary-end))
|
||||||
|
(setq font-lock-beg (min font-lock-beg summary-beg))
|
||||||
|
(setq font-lock-end (max font-lock-end summary-end))))))))
|
||||||
|
|
||||||
|
(defvar-local git-commit--branch-name-regexp nil)
|
||||||
|
|
||||||
|
(defconst git-commit-comment-headings
|
||||||
|
'("Changes to be committed:"
|
||||||
|
"Untracked files:"
|
||||||
|
"Changed but not updated:"
|
||||||
|
"Changes not staged for commit:"
|
||||||
|
"Unmerged paths:"
|
||||||
|
"Author:"
|
||||||
|
"Date:"))
|
||||||
|
|
||||||
|
(defconst git-commit-font-lock-keywords-1
|
||||||
|
'(;; Pseudo headers
|
||||||
|
(eval . `(,(format "^\\(%s:\\)\\( .*\\)"
|
||||||
|
(regexp-opt git-commit-known-pseudo-headers))
|
||||||
|
(1 'git-commit-known-pseudo-header)
|
||||||
|
(2 'git-commit-pseudo-header)))
|
||||||
|
("^[-a-zA-Z]+: [^<]+? <[^>]+>"
|
||||||
|
(0 'git-commit-pseudo-header))
|
||||||
|
;; Summary
|
||||||
|
(eval . `(,(git-commit-summary-regexp)
|
||||||
|
(1 'git-commit-summary)))
|
||||||
|
;; - Keyword [aka "text in brackets"] (overrides summary)
|
||||||
|
("\\[.+?\\]"
|
||||||
|
(0 'git-commit-keyword t))
|
||||||
|
;; - Non-empty second line (overrides summary and note)
|
||||||
|
(eval . `(,(git-commit-summary-regexp)
|
||||||
|
(2 'git-commit-overlong-summary t t)
|
||||||
|
(3 'git-commit-nonempty-second-line t t)))))
|
||||||
|
|
||||||
|
(defconst git-commit-font-lock-keywords-2
|
||||||
|
`(,@git-commit-font-lock-keywords-1
|
||||||
|
;; Comments
|
||||||
|
(eval . `(,(format "^%s.*" comment-start)
|
||||||
|
(0 'font-lock-comment-face)))
|
||||||
|
(eval . `(,(format "^%s On branch \\(.*\\)" comment-start)
|
||||||
|
(1 'git-commit-comment-branch-local t)))
|
||||||
|
(eval . `(,(format "^%s \\(HEAD\\) detached at" comment-start)
|
||||||
|
(1 'git-commit-comment-detached t)))
|
||||||
|
(eval . `(,(format "^%s %s" comment-start
|
||||||
|
(regexp-opt git-commit-comment-headings t))
|
||||||
|
(1 'git-commit-comment-heading t)))
|
||||||
|
(eval . `(,(format "^%s\t\\(?:\\([^:\n]+\\):\\s-+\\)?\\(.*\\)" comment-start)
|
||||||
|
(1 'git-commit-comment-action t t)
|
||||||
|
(2 'git-commit-comment-file t)))))
|
||||||
|
|
||||||
|
(defconst git-commit-font-lock-keywords-3
|
||||||
|
`(,@git-commit-font-lock-keywords-2
|
||||||
|
;; More comments
|
||||||
|
(eval
|
||||||
|
;; Your branch is ahead of 'master' by 3 commits.
|
||||||
|
;; Your branch is behind 'master' by 2 commits, and can be fast-forwarded.
|
||||||
|
. `(,(format
|
||||||
|
"^%s Your branch is \\(?:ahead\\|behind\\) of '%s' by \\([0-9]*\\)"
|
||||||
|
comment-start git-commit--branch-name-regexp)
|
||||||
|
(1 'git-commit-comment-branch-local t)
|
||||||
|
(2 'git-commit-comment-branch-remote t)
|
||||||
|
(3 'bold t)))
|
||||||
|
(eval
|
||||||
|
;; Your branch is up to date with 'master'.
|
||||||
|
;; Your branch and 'master' have diverged,
|
||||||
|
. `(,(format
|
||||||
|
"^%s Your branch \\(?:is up-to-date with\\|and\\) '%s'"
|
||||||
|
comment-start git-commit--branch-name-regexp)
|
||||||
|
(1 'git-commit-comment-branch-local t)
|
||||||
|
(2 'git-commit-comment-branch-remote t)))
|
||||||
|
(eval
|
||||||
|
;; and have 1 and 2 different commits each, respectively.
|
||||||
|
. `(,(format
|
||||||
|
"^%s and have \\([0-9]*\\) and \\([0-9]*\\) commits each"
|
||||||
|
comment-start)
|
||||||
|
(1 'bold t)
|
||||||
|
(2 'bold t)))))
|
||||||
|
|
||||||
|
(defvar git-commit-font-lock-keywords git-commit-font-lock-keywords-2
|
||||||
|
"Font-Lock keywords for Git-Commit mode.")
|
||||||
|
|
||||||
|
(defun git-commit-setup-font-lock ()
|
||||||
|
(let ((table (make-syntax-table (syntax-table))))
|
||||||
|
(when comment-start
|
||||||
|
(modify-syntax-entry (string-to-char comment-start) "." table))
|
||||||
|
(modify-syntax-entry ?# "." table)
|
||||||
|
(modify-syntax-entry ?\" "." table)
|
||||||
|
(modify-syntax-entry ?\' "." table)
|
||||||
|
(modify-syntax-entry ?` "." table)
|
||||||
|
(set-syntax-table table))
|
||||||
|
(setq-local comment-start
|
||||||
|
(or (ignore-errors
|
||||||
|
(car (process-lines "git" "config" "core.commentchar")))
|
||||||
|
"#"))
|
||||||
|
(setq-local comment-start-skip (format "^%s+[\s\t]*" comment-start))
|
||||||
|
(setq-local comment-end-skip "\n")
|
||||||
|
(setq-local comment-use-syntax nil)
|
||||||
|
(setq-local git-commit--branch-name-regexp
|
||||||
|
(if (and (featurep 'magit-git)
|
||||||
|
;; When using cygwin git, we may end up in a
|
||||||
|
;; non-existing directory, which would cause
|
||||||
|
;; any git calls to signal an error.
|
||||||
|
(file-accessible-directory-p default-directory))
|
||||||
|
(progn
|
||||||
|
;; Make sure the below functions are available.
|
||||||
|
(require 'magit)
|
||||||
|
;; Font-Lock wants every submatch to succeed,
|
||||||
|
;; so also match the empty string. Do not use
|
||||||
|
;; `regexp-quote' because that is slow if there
|
||||||
|
;; are thousands of branches outweighing the
|
||||||
|
;; benefit of an efficient regep.
|
||||||
|
(format "\\(\\(?:%s\\)\\|\\)\\(\\(?:%s\\)\\|\\)"
|
||||||
|
(mapconcat #'identity
|
||||||
|
(magit-list-local-branch-names)
|
||||||
|
"\\|")
|
||||||
|
(mapconcat #'identity
|
||||||
|
(magit-list-remote-branch-names)
|
||||||
|
"\\|")))
|
||||||
|
"\\([^']*\\)"))
|
||||||
|
(setq-local font-lock-multiline t)
|
||||||
|
(add-hook 'font-lock-extend-region-functions
|
||||||
|
#'git-commit-extend-region-summary-line
|
||||||
|
t t)
|
||||||
|
(font-lock-add-keywords nil git-commit-font-lock-keywords))
|
||||||
|
|
||||||
|
(defun git-commit-propertize-diff ()
|
||||||
|
(require 'diff-mode)
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(when (re-search-forward "^diff --git" nil t)
|
||||||
|
(beginning-of-line)
|
||||||
|
(let ((buffer (current-buffer)))
|
||||||
|
(insert
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert
|
||||||
|
(with-current-buffer buffer
|
||||||
|
(prog1 (buffer-substring-no-properties (point) (point-max))
|
||||||
|
(delete-region (point) (point-max)))))
|
||||||
|
(let ((diff-default-read-only nil))
|
||||||
|
(diff-mode))
|
||||||
|
(let (font-lock-verbose font-lock-support-mode)
|
||||||
|
(if (fboundp 'font-lock-ensure)
|
||||||
|
(font-lock-ensure)
|
||||||
|
(with-no-warnings
|
||||||
|
(font-lock-fontify-buffer))))
|
||||||
|
(let (next (pos (point-min)))
|
||||||
|
(while (setq next (next-single-property-change pos 'face))
|
||||||
|
(put-text-property pos next 'font-lock-face
|
||||||
|
(get-text-property pos 'face))
|
||||||
|
(setq pos next))
|
||||||
|
(put-text-property pos (point-max) 'font-lock-face
|
||||||
|
(get-text-property pos 'face)))
|
||||||
|
(buffer-string)))))))
|
||||||
|
|
||||||
|
;;; Elisp Text Mode
|
||||||
|
|
||||||
|
(define-derived-mode git-commit-elisp-text-mode text-mode "ElText"
|
||||||
|
"Major mode for editing commit messages of elisp projects.
|
||||||
|
This is intended for use as `git-commit-major-mode' for projects
|
||||||
|
that expect `symbols' to look like this. I.e. like they look in
|
||||||
|
Elisp doc-strings, including this one. Unlike in doc-strings,
|
||||||
|
\"strings\" also look different than the other text."
|
||||||
|
(setq font-lock-defaults '(git-commit-elisp-text-mode-keywords)))
|
||||||
|
|
||||||
|
(defvar git-commit-elisp-text-mode-keywords
|
||||||
|
`((,(concat "[`‘]\\(" lisp-mode-symbol-regexp "\\)['’]")
|
||||||
|
(1 font-lock-constant-face prepend))
|
||||||
|
("\"[^\"]*\"" (0 font-lock-string-face prepend))))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'git-commit)
|
||||||
|
;;; git-commit.el ends here
|
||||||
BIN
elpa/git-commit-20190928.1746/git-commit.elc
Normal file
BIN
elpa/git-commit-20190928.1746/git-commit.elc
Normal file
Binary file not shown.
341
elpa/magit-20191030.1315/AUTHORS.md
Normal file
341
elpa/magit-20191030.1315/AUTHORS.md
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
Authors
|
||||||
|
=======
|
||||||
|
|
||||||
|
The following people have contributed to Magit, including the
|
||||||
|
libraries `git-commit.el`, `magit-popup.el`, and `with-editor.el`
|
||||||
|
which are distributed as separate Elpa packages.
|
||||||
|
|
||||||
|
For statistics see https://magit.vc/stats/authors.html.
|
||||||
|
|
||||||
|
Names below are sorted alphabetically.
|
||||||
|
|
||||||
|
Author
|
||||||
|
------
|
||||||
|
|
||||||
|
- Marius Vollmer <marius.vollmer@gmail.com>
|
||||||
|
|
||||||
|
Maintainer
|
||||||
|
----------
|
||||||
|
|
||||||
|
- Jonas Bernoulli <jonas@bernoul.li>
|
||||||
|
|
||||||
|
Developers
|
||||||
|
----------
|
||||||
|
|
||||||
|
- Kyle Meyer <kyle@kyleam.com>
|
||||||
|
- Noam Postavsky <npostavs@users.sourceforge.net>
|
||||||
|
|
||||||
|
Retired Maintainers and Developers
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
- Nicolas Dudebout <nicolas.dudebout@gatech.edu>
|
||||||
|
- Peter J. Weisberg <pj@irregularexpressions.net>
|
||||||
|
- Pieter Praet <pieter@praet.org>
|
||||||
|
- Phil Jackson <phil@shellarchive.co.uk>
|
||||||
|
- Rémi Vanicat <vanicat@debian.org>
|
||||||
|
- Yann Hodique <yann.hodique@gmail.com>
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
------------
|
||||||
|
|
||||||
|
- Aaron Culich <aculich@gmail.com>
|
||||||
|
- Aaron Madlon-Kay <aaron@madlon-kay.com>
|
||||||
|
- Abdo Roig-Maranges <abdo.roig@gmail.com>
|
||||||
|
- Adam Benanti <0entropy@protonmail.com>
|
||||||
|
- Adam Porter <adam@alphapapa.net>
|
||||||
|
- Adam Spiers <emacs@adamspiers.org>
|
||||||
|
- Adeodato Simó <dato@net.com.org.es>
|
||||||
|
- Ævar Arnfjörð Bjarmason <avarab@gmail.com>
|
||||||
|
- Alan Falloon <alan.falloon@gmail.com>
|
||||||
|
- Alban Gruin <alban@pa1ch.fr>
|
||||||
|
- Aleksey Uimanov <s9gf4ult@gmail.com>
|
||||||
|
- Alexander Gramiak <fice-t@protonmail.com>
|
||||||
|
- Alexander Miller <alexanderm@web.de>
|
||||||
|
- Alex Branham <alex.branham@gmail.com>
|
||||||
|
- Alex Dunn <adunn@ucsb.edu>
|
||||||
|
- Alexey Voinov <alexey.v.voinov@gmail.com>
|
||||||
|
- Alex Kost <alezost@gmail.com>
|
||||||
|
- Alex Ott <alexott@gmail.com>
|
||||||
|
- Allen <darkfeline@felesatra.moe>
|
||||||
|
- Allen Li <darkfeline@felesatra.moe>
|
||||||
|
- Andreas Fuchs <asf@boinkor.net>
|
||||||
|
- Andreas Liljeqvist <andreas.liljeqvist@robacks.se>
|
||||||
|
- Andreas Rottmann <a.rottmann@gmx.at>
|
||||||
|
- Andrei Chițu <andrei.chitu1@gmail.com>
|
||||||
|
- Andrew Eggenberger <andrew.eggenberger@gmail.com>
|
||||||
|
- Andrew Kirkpatrick <andrew.kirkpatrick@adelaide.edu.au>
|
||||||
|
- Andrew Schwartzmeyer <andrew@schwartzmeyer.com>
|
||||||
|
- Andrey Smirnov <andrew.smirnov@gmail.com>
|
||||||
|
- Andriy Kmit' <dev@madand.net>
|
||||||
|
- Andy Sawyer <git@pureabstract.org>
|
||||||
|
- Aria Edmonds <aria@ar1as.space>
|
||||||
|
- Arialdo Martini <arialdomartini@gmail.com>
|
||||||
|
- Barak A. Pearlmutter <barak+git@pearlmutter.net>
|
||||||
|
- Bar Magal <bmagamb@gmail.com>
|
||||||
|
- Bart Bakker <bart@thesoftwarecraft.com>
|
||||||
|
- Basil L. Contovounesios <contovob@tcd.ie>
|
||||||
|
- Bastian Beischer <beischer@physik.rwth-aachen.de>
|
||||||
|
- Benjamin Motz <benjamin.motz@mailbox.org>
|
||||||
|
- Ben North <ben@redfrontdoor.org>
|
||||||
|
- Ben Walton <bwalton@artsci.utoronto.ca>
|
||||||
|
- Bob Uhl <buhl@zvelo.com>
|
||||||
|
- Bradley Wright <brad@intranation.com>
|
||||||
|
- Brandon W Maister <quodlibetor@gmail.com>
|
||||||
|
- Brian Warner <warner@lothar.com>
|
||||||
|
- Bryan Shell <bryan.shell@orbitz.com>
|
||||||
|
- Buster Copley <buster@buster.me.uk>
|
||||||
|
- Carl Lieberman <liebermancarl@gmail.com>
|
||||||
|
- Chillar Anand <anand21nanda@gmail.com>
|
||||||
|
- Chris Bernard <cebernard@gmail.com>
|
||||||
|
- Chris Done <chrisdone@gmail.com>
|
||||||
|
- Chris LaRose <cjlarose@gmail.com>
|
||||||
|
- Chris Moore <dooglus@gmail.com>
|
||||||
|
- Chris Ring <chris@ringthis.com>
|
||||||
|
- Chris Shoemaker <chris@mojotech.com>
|
||||||
|
- Christian Dietrich <christian.dietrich@informatik.uni-erlangen.de>
|
||||||
|
- Christian Kluge <ckfrakturfreak@web.de>
|
||||||
|
- Christophe Junke <junke.christophe@gmail.com>
|
||||||
|
- Christopher Monsanto <chris@monsan.to>
|
||||||
|
- Cornelius Mika <cornelius.mika@gmail.com>
|
||||||
|
- Craig Andera <candera@wangdera.com>
|
||||||
|
- Dale Hagglund <dale.hagglund@gmail.com>
|
||||||
|
- Damien Cassou <damien@cassou.me>
|
||||||
|
- Dan Erikson <derikson3@gmail.com>
|
||||||
|
- Daniel Brockman <daniel@gointeractive.se>
|
||||||
|
- Daniel Farina <drfarina@acm.org>
|
||||||
|
- Daniel Gröber <daniel@dps.uibk.ac.at>
|
||||||
|
- Daniel Hackney <dan@haxney.org>
|
||||||
|
- Daniel Kraus <daniel@kraus.my>
|
||||||
|
- Daniel Mai <daniel@danielmai.net>
|
||||||
|
- Daniel Martín <mardani29@yahoo.es>
|
||||||
|
- Dan LaManna <dan.lamanna@gmail.com>
|
||||||
|
- Danny Zhu <dzhu@dzhu.us>
|
||||||
|
- Dato Simó <dato@net.com.org.es>
|
||||||
|
- David Abrahams <dave@boostpro.com>
|
||||||
|
- David Ellison <davidehellison@gmail.com>
|
||||||
|
- David Ellison <davide@voicebox.com>
|
||||||
|
- David Hull <david.hull@openx.com>
|
||||||
|
- David L. Rager <ragerdl@gmail.com>
|
||||||
|
- David Wallin <david.wallin@gmail.com>
|
||||||
|
- Dean Kariniemi <8913263+d3k4r@users.noreply.github.com>
|
||||||
|
- Dennis Paskorz <dennis@walltowall.com>
|
||||||
|
- Divye Kapoor <divye@google.com>
|
||||||
|
- Dominique Quatravaux <dominique.quatravaux@epfl.ch>
|
||||||
|
- Dominique Quatravaux <domq@google.com>
|
||||||
|
- Duianto Vebotci <vebotci@openmailbox.org>
|
||||||
|
- Eli Barzilay <eli@barzilay.org>
|
||||||
|
- Eric Davis <ed@npri.org>
|
||||||
|
- Eric Prud'hommeaux <eric@w3.org>
|
||||||
|
- Eric Schulte <schulte.eric@gmail.com>
|
||||||
|
- Erik Anderson <erikbpanderson@gmail.com>
|
||||||
|
- Evan Torrie <etorrie@gmail.com>
|
||||||
|
- Evgkeni Sampelnikof <esabof@gmail.com>
|
||||||
|
- Eyal Lotem <eyal.lotem@gmail.com>
|
||||||
|
- Fabian Wiget <fabacino@gmail.com>
|
||||||
|
- Felix Geller <fgeller@gmail.com>
|
||||||
|
- Felix Yan <felixonmars@archlinux.org>
|
||||||
|
- Feng Li <fengli@blackmagicdesign.com>
|
||||||
|
- Florian Ragwitz <rafl@debian.org>
|
||||||
|
- Fritz Grabo <fritz.grabo@gmail.com>
|
||||||
|
- Fritz Stelzer <brotzeitmacher@gmail.com>
|
||||||
|
- Geoff Shannon <geoffpshannon@gmail.com>
|
||||||
|
- George Kadianakis <desnacked@gmail.com>
|
||||||
|
- Graham Clark <grclark@gmail.com>
|
||||||
|
- Graham Dobbins <gdobbins@protonmail.com>
|
||||||
|
- Greg A. Woods <woods@planix.com>
|
||||||
|
- Greg Lucas <greg@glucas.net>
|
||||||
|
- Greg Sexton <gregsexton@gmail.com>
|
||||||
|
- Guillaume Martres <smarter@ubuntu.com>
|
||||||
|
- Hannu Koivisto <azure@iki.fi>
|
||||||
|
- Hans-Peter Deifel <hpdeifel@gmx.de>
|
||||||
|
- Hussein Ait-Lahcen <hussein.ait-lahcen@fretlink.com>
|
||||||
|
- Ian Eure <ian.eure@gmail.com>
|
||||||
|
- Ingo Lohmar <i.lohmar@gmail.com>
|
||||||
|
- Ioan-Adrian Ratiu <adi@adirat.com>
|
||||||
|
- Ivan Brennan <ivan.brennan@gmail.com>
|
||||||
|
- Jan Tatarik <jan.tatarik@xing.com>
|
||||||
|
- Jasper St. Pierre <jstpierre@mecheye.net>
|
||||||
|
- Jeff Bellegarde <jbellegarde@whitepages.com>
|
||||||
|
- Jeff Dairiki <dairiki@dairiki.org>
|
||||||
|
- Jeremy Meng <yumeng@microsoft.com>
|
||||||
|
- Jesse Alama <jesse.alama@gmail.com>
|
||||||
|
- Jim Blandy <jimb@red-bean.com>
|
||||||
|
- Joakim Jalap <JOJA@stoneridge.com>
|
||||||
|
- Johannes Altmanninger <aclopte@gmail.com>
|
||||||
|
- Johann Klähn <kljohann@gmail.com>
|
||||||
|
- John Mastro <john.b.mastro@gmail.com>
|
||||||
|
- John Morris <john@zultron.com>
|
||||||
|
- John Wiegley <johnw@newartisans.com>
|
||||||
|
- Jonas Bernoulli <jonas@bernoul.li>
|
||||||
|
- Jonathan Arnett <jonathan@scriptdrop.co>
|
||||||
|
- Jonathan Leech-Pepin <jonathan.leechpepin@gmail.com>
|
||||||
|
- Jonathan Roes <jroes@jroes.net>
|
||||||
|
- Jon Vanderwijk <jonathn@github.com>
|
||||||
|
- Jordan Galby <gravemind2a@gmail.com>
|
||||||
|
- Jordan Greenberg <jordan@softwareslave.com>
|
||||||
|
- Josh Elsasser <jelsasser@appneta.com>
|
||||||
|
- Josiah Schwab <jschwab@gmail.com>
|
||||||
|
- Julien Danjou <julien@danjou.info>
|
||||||
|
- Justin Burkett <justin@burkett.cc>
|
||||||
|
- Justin Caratzas <justin.caratzas@gmail.com>
|
||||||
|
- Justin Guenther <jguenther@gmail.com>
|
||||||
|
- Justin Thomas <justin.thomas1@gmail.com>
|
||||||
|
- Kan-Ru Chen <kanru@kanru.info>
|
||||||
|
- Kenny Ballou <kballou@devnulllabs.io>
|
||||||
|
- Keshav Kini <keshav.kini@gmail.com>
|
||||||
|
- Kevin Brubeck Unhammer <unhammer@fsfe.org>
|
||||||
|
- Kevin J. Foley <kfoley15@gmail.com>
|
||||||
|
- Kévin Le Gouguec <kevin.legouguec@gmail.com>
|
||||||
|
- Kimberly Wolk <kimwolk@hotmail.com>
|
||||||
|
- Knut Olav Bøhmer <bohmer@gmail.com>
|
||||||
|
- Kyle Meyer <kyle@kyleam.com>
|
||||||
|
- Laurent Laffont <laurent.laffont@gmail.com>
|
||||||
|
- Laverne Schrock <laverne@schrock.email>
|
||||||
|
- Leandro Facchinetti <me@leafac.com>
|
||||||
|
- Lele Gaifax <lele@metapensiero.it>
|
||||||
|
- Leo Liu <sdl.web@gmail.com>
|
||||||
|
- Leonardo Etcheverry <leo@kalio.net>
|
||||||
|
- Lingchao Xin <douglarek@users.noreply.github.com>
|
||||||
|
- Li-Yun Chang <michael142536@gmail.com>
|
||||||
|
- Lluís Vilanova <vilanova@ac.upc.edu>
|
||||||
|
- Loic Dachary <loic@dachary.org>
|
||||||
|
- Louis Roché <louis@louisroche.net>
|
||||||
|
- Luís Oliveira <luismbo@gmail.com>
|
||||||
|
- Luke Amdor <luke.amdor@gmail.com>
|
||||||
|
- Mak Kolybabi <mak@kolybabi.com>
|
||||||
|
- Manuel Vázquez Acosta <mva.led@gmail.com>
|
||||||
|
- Marcel Wolf <mwolf@ml1.net>
|
||||||
|
- Marc Herbert <marc.herbert@gmail.com>
|
||||||
|
- Marcin Bachry <hegel666@gmail.com>
|
||||||
|
- Marco Craveiro <marco.craveiro@gmail.com>
|
||||||
|
- Marco Wahl <marcowahlsoft@gmail.com>
|
||||||
|
- Marc Sherry <msherry@gmail.com>
|
||||||
|
- Marian Schubert <marian.schubert@gmail.com>
|
||||||
|
- Mario Rodas <marsam@users.noreply.github.com>
|
||||||
|
- Marius Vollmer <marius.vollmer@gmail.com>
|
||||||
|
- Mark Hepburn <Mark.Hepburn@csiro.au>
|
||||||
|
- Mark Karpov <markkarpov@opmbx.org>
|
||||||
|
- Mark Oteiza <mvoteiza@udel.edu>
|
||||||
|
- Matthew Fluet <matthew.fluet@gmail.com>
|
||||||
|
- Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
|
||||||
|
- Matus Goljer <dota.keys@gmail.com>
|
||||||
|
- Michael Fogleman <michaelwfogleman@gmail.com>
|
||||||
|
- Michael Griffiths <mikey@cich.li>
|
||||||
|
- Michael Heerdegen <michael_heerdegen@web.de>
|
||||||
|
- Michal Sojka <sojkam1@fel.cvut.cz>
|
||||||
|
- Miciah Masters <miciah.masters@gmail.com>
|
||||||
|
- Miles Bader <miles@gnu.org>
|
||||||
|
- Miloš Mošić <mosic.milos@gmail.com>
|
||||||
|
- Mitchel Humpherys <mitch.special@gmail.com>
|
||||||
|
- Moritz Bunkus <moritz@bunkus.org>
|
||||||
|
- Naoya Yamashita <conao3@gmail.com>
|
||||||
|
- Natalie Weizenbaum <nex342@gmail.com>
|
||||||
|
- Nguyễn Tuấn Anh <ubolonton@gmail.com>
|
||||||
|
- Nic Ferier <nic@ferrier.me.uk>
|
||||||
|
- Nick Alcock <nick.alcock@oracle.com>
|
||||||
|
- Nick Alexander <nalexander@mozilla.com>
|
||||||
|
- Nick Dimiduk <ndimiduk@gmail.com>
|
||||||
|
- Nicklas Lindgren <nili@gulmohar.se>
|
||||||
|
- Nicolas Dudebout <nicolas.dudebout@gatech.edu>
|
||||||
|
- Nicolas Petton <nicolas@petton.fr>
|
||||||
|
- Nicolas Richard <theonewiththeevillook@yahoo.fr>
|
||||||
|
- Nikolay Martynov <mar.kolya@gmail.com>
|
||||||
|
- Noam Postavsky <npostavs@users.sourceforge.net>
|
||||||
|
- N. Troy de Freitas <me@ntdef.com>
|
||||||
|
- Ole Arndt <oliver.arndt@cegedim.com>
|
||||||
|
- Oleh Krehel <ohwoeowho@gmail.com>
|
||||||
|
- Orivej Desh <orivej@gmx.fr>
|
||||||
|
- Óscar Fuentes <ofv@wanadoo.es>
|
||||||
|
- Paul Stadig <paul@stadig.name>
|
||||||
|
- Pavel Holejsovsky <pavel.holejsovsky@upek.com>
|
||||||
|
- Pekka Pessi <nospam@pessi.fi>
|
||||||
|
- Peter Eisentraut <peter@eisentraut.org>
|
||||||
|
- Peter Jaros <peter.a.jaros@gmail.com>
|
||||||
|
- Peter J. Weisberg <pj@irregularexpressions.net>
|
||||||
|
- Peter Vasil <mail@petervasil.net>
|
||||||
|
- Philippe Vaucher <philippe.vaucher@gmail.com>
|
||||||
|
- Philipp Haselwarter <philipp@haselwarter.org>
|
||||||
|
- Philipp Stephani <phst@google.com>
|
||||||
|
- Philip Weaver <philip.weaver@gmail.com>
|
||||||
|
- Phil Jackson <phil@shellarchive.co.uk>
|
||||||
|
- Phil Sainty <phil@catalyst.net.nz>
|
||||||
|
- Pierre Neidhardt <ambrevar@gmail.com>
|
||||||
|
- Pieter Praet <pieter@praet.org>
|
||||||
|
- Prathamesh Sonpatki <csonpatki@gmail.com>
|
||||||
|
- rabio <rabiodev@o2.pl>
|
||||||
|
- Radon Rosborough <radon.neon@gmail.com>
|
||||||
|
- Rafael Laboissiere <rafael@laboissiere.net>
|
||||||
|
- Raimon Grau <raimon@3scale.net>
|
||||||
|
- Ramkumar Ramachandra <artagnon@gmail.com>
|
||||||
|
- Remco van 't Veer <rwvtveer@xs4all.nl>
|
||||||
|
- Rémi Vanicat <vanicat@debian.org>
|
||||||
|
- René Stadler <mail@renestadler.de>
|
||||||
|
- Richard Kim <emacs18@gmail.com>
|
||||||
|
- Robert Boone <robo4288@gmail.com>
|
||||||
|
- Robin Green <greenrd@greenrd.org>
|
||||||
|
- Roger Crew <crew@cs.stanford.edu>
|
||||||
|
- Romain Francoise <romain@orebokech.com>
|
||||||
|
- Ron Parker <rparker@a123systems.com>
|
||||||
|
- Roy Crihfield <rscrihf@gmail.com>
|
||||||
|
- Rüdiger Sonderfeld <ruediger@c-plusplus.net>
|
||||||
|
- Russell Black <black.russell@gmail.com>
|
||||||
|
- Ryan C. Thompson <rct@thompsonclan.org>
|
||||||
|
- Samuel Bronson <naesten@gmail.com>
|
||||||
|
- Samuel W. Flint <swflint@flintfam.org>
|
||||||
|
- Sanjoy Das <sanjoy@playingwithpointers.com>
|
||||||
|
- Sean Allred <code@seanallred.com>
|
||||||
|
- Sean Bryant <sbryant@hackinggibsons.com>
|
||||||
|
- Sean Whitton <spwhitton@spwhitton.name>
|
||||||
|
- Sebastian Wiesner <lunaryorn@gmail.com>
|
||||||
|
- Sébastien Gross <seb@chezwam.org>
|
||||||
|
- Seong-Kook Shin <cinsky@gmail.com>
|
||||||
|
- Sergey Pashinin <sergey@pashinin.com>
|
||||||
|
- Sergey Vinokurov <serg.foo@gmail.com>
|
||||||
|
- Servilio Afre Puentes <afrepues@mcmaster.ca>
|
||||||
|
- Silent Sphere <silentsphere110@gmail.com>
|
||||||
|
- Štěpán Němec <stepnem@gmail.com>
|
||||||
|
- Steven Chow <steve@myfreestuffapp.com>
|
||||||
|
- Steven E. Harris <seh@panix.com>
|
||||||
|
- Steven Thomas <sthomas314@gmail.com>
|
||||||
|
- Steven Vancoillie <steven.vancoillie@runbox.com>
|
||||||
|
- Steve Purcell <steve@sanityinc.com>
|
||||||
|
- Suhail Shergill <suhailshergill@gmail.com>
|
||||||
|
- Sylvain Rousseau <thisirs@gmail.com>
|
||||||
|
- Syohei Yoshida <syohex@gmail.com>
|
||||||
|
- Takafumi Arakaki <aka.tkf@gmail.com>
|
||||||
|
- Tassilo Horn <tsdh@gnu.org>
|
||||||
|
- Teemu Likonen <tlikonen@iki.fi>
|
||||||
|
- Teruki Shigitani <teruki.shigitani@gmail.com>
|
||||||
|
- Thierry Volpiatto <thierry.volpiatto@gmail.com>
|
||||||
|
- Thomas A Caswell <tcaswell@gmail.com>
|
||||||
|
- Thomas Fini Hansen <xen@xen.dk>
|
||||||
|
- Thomas Frössman <thomasf@jossystem.se>
|
||||||
|
- Thomas Jost <thomas.jost@gmail.com>
|
||||||
|
- Thomas Riccardi <riccardi.thomas@gmail.com>
|
||||||
|
- Tibor Simko <tibor.simko@cern.ch>
|
||||||
|
- Timo Juhani Lindfors <timo.lindfors@iki.fi>
|
||||||
|
- Tim Perkins <tprk77@gmail.com>
|
||||||
|
- Tim Wraight <tim@wraight.net>
|
||||||
|
- Ting-Yu Lin <aethanyc@gmail.com>
|
||||||
|
- Tom Feist <shabble@metavore.org>
|
||||||
|
- Topi Miettinen <toiwoton@gmail.com>
|
||||||
|
- Troy Hinckley <t.macman@gmail.com>
|
||||||
|
- Tunc Uzlu <bb2020@users.noreply.github.com>
|
||||||
|
- Vineet Naik <vineet@helpshift.com>
|
||||||
|
- Vitaly Ostashov <hotosho@yandex-team.ru>
|
||||||
|
- Vladimir Panteleev <git@thecybershadow.net>
|
||||||
|
- Wei Huang <weih@opera.com>
|
||||||
|
- Wilfred Hughes <me@wilfred.me.uk>
|
||||||
|
- Win Treese <treese@acm.org>
|
||||||
|
- Wouter Bolsterlee <wouter@bolsterl.ee>
|
||||||
|
- Xavier Noria <fxn@hashref.com>
|
||||||
|
- Xu Chunyang <mail@xuchunyang.me>
|
||||||
|
- Yann Hodique <yann.hodique@gmail.com>
|
||||||
|
- Ynilu <ynilu.chang@gmail.com>
|
||||||
|
- York Zhao <gtdplatform@gmail.com>
|
||||||
|
- Yuichi Higashi <aaa707b@gmail.com>
|
||||||
|
- Yuri Khan <yurivkhan@gmail.com>
|
||||||
|
- Zach Latta <zach@zachlatta.com>
|
||||||
|
- zakora <zakora@users.noreply.github.com>
|
||||||
|
- Zhu Zihao <all_but_last@163.com>
|
||||||
|
- zilongshanren <guanghui8827@126.com>
|
||||||
676
elpa/magit-20191030.1315/LICENSE
Normal file
676
elpa/magit-20191030.1315/LICENSE
Normal file
@@ -0,0 +1,676 @@
|
|||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program 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 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|
||||||
18
elpa/magit-20191030.1315/dir
Normal file
18
elpa/magit-20191030.1315/dir
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
This is the file .../info/dir, which contains the
|
||||||
|
topmost node of the Info hierarchy, called (dir)Top.
|
||||||
|
The first time you invoke Info you start off looking at this node.
|
||||||
|
|
||||||
|
File: dir, Node: Top This is the top of the INFO tree
|
||||||
|
|
||||||
|
This (the Directory node) gives a menu of major topics.
|
||||||
|
Typing "q" exits, "H" lists all Info commands, "d" returns here,
|
||||||
|
"h" gives a primer for first-timers,
|
||||||
|
"mEmacs<Return>" visits the Emacs manual, etc.
|
||||||
|
|
||||||
|
In Emacs, you can click mouse button 2 on a menu item or cross reference
|
||||||
|
to select it.
|
||||||
|
|
||||||
|
* Menu:
|
||||||
|
|
||||||
|
Emacs
|
||||||
|
* Magit: (magit). Using Git from Emacs with Magit.
|
||||||
818
elpa/magit-20191030.1315/git-rebase.el
Normal file
818
elpa/magit-20191030.1315/git-rebase.el
Normal file
@@ -0,0 +1,818 @@
|
|||||||
|
;;; git-rebase.el --- Edit Git rebase files -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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: Phil Jackson <phil@shellarchive.co.uk>
|
||||||
|
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
|
||||||
|
|
||||||
|
;; This file is not part of GNU Emacs.
|
||||||
|
|
||||||
|
;; This file 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.
|
||||||
|
|
||||||
|
;; This file 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 this file. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; This package assists the user in editing the list of commits to be
|
||||||
|
;; rewritten during an interactive rebase.
|
||||||
|
|
||||||
|
;; When the user initiates an interactive rebase, e.g. using "r e" in
|
||||||
|
;; a Magit buffer or on the command line using "git rebase -i REV",
|
||||||
|
;; Git invokes the `$GIT_SEQUENCE_EDITOR' (or if that is undefined
|
||||||
|
;; `$GIT_EDITOR' or even `$EDITOR') letting the user rearrange, drop,
|
||||||
|
;; reword, edit, and squash commits.
|
||||||
|
|
||||||
|
;; This package provides the major-mode `git-rebase-mode' which makes
|
||||||
|
;; doing so much more fun, by making the buffer more colorful and
|
||||||
|
;; providing the following commands:
|
||||||
|
;;
|
||||||
|
;; C-c C-c Tell Git to make it happen.
|
||||||
|
;; C-c C-k Tell Git that you changed your mind, i.e. abort.
|
||||||
|
;;
|
||||||
|
;; p Move point to previous line.
|
||||||
|
;; n Move point to next line.
|
||||||
|
;;
|
||||||
|
;; M-p Move the commit at point up.
|
||||||
|
;; M-n Move the commit at point down.
|
||||||
|
;;
|
||||||
|
;; k Drop the commit at point.
|
||||||
|
;; c Don't drop the commit at point.
|
||||||
|
;; r Change the message of the commit at point.
|
||||||
|
;; e Edit the commit at point.
|
||||||
|
;; s Squash the commit at point, into the one above.
|
||||||
|
;; f Like "s" but don't also edit the commit message.
|
||||||
|
;; b Break for editing at this point in the sequence.
|
||||||
|
;; x Add a script to be run with the commit at point
|
||||||
|
;; being checked out.
|
||||||
|
;; z Add noop action at point.
|
||||||
|
;;
|
||||||
|
;; SPC Show the commit at point in another buffer.
|
||||||
|
;; RET Show the commit at point in another buffer and
|
||||||
|
;; select its window.
|
||||||
|
;; C-/ Undo last change.
|
||||||
|
;;
|
||||||
|
;; Commands for --rebase-merges:
|
||||||
|
;; l Associate label with current HEAD in sequence.
|
||||||
|
;; MM Merge specified revisions into HEAD.
|
||||||
|
;; Mt Toggle whether the merge will invoke an editor
|
||||||
|
;; before committing.
|
||||||
|
;; t Reset HEAD to the specified label.
|
||||||
|
|
||||||
|
;; You should probably also read the `git-rebase' manpage.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'dash)
|
||||||
|
(require 'easymenu)
|
||||||
|
(require 'server)
|
||||||
|
(require 'with-editor)
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
(and (require 'async-bytecomp nil t)
|
||||||
|
(let ((pkgs (bound-and-true-p async-bytecomp-allowed-packages)))
|
||||||
|
(if (consp pkgs)
|
||||||
|
(cl-intersection '(all magit) pkgs)
|
||||||
|
(memq pkgs '(all t))))
|
||||||
|
(fboundp 'async-bytecomp-package-mode)
|
||||||
|
(async-bytecomp-package-mode 1))
|
||||||
|
|
||||||
|
(eval-when-compile (require 'recentf))
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
;;;; Variables
|
||||||
|
|
||||||
|
(defgroup git-rebase nil
|
||||||
|
"Edit Git rebase sequences."
|
||||||
|
:link '(info-link "(magit)Editing Rebase Sequences")
|
||||||
|
:group 'tools)
|
||||||
|
|
||||||
|
(defcustom git-rebase-auto-advance t
|
||||||
|
"Whether to move to next line after changing a line."
|
||||||
|
:group 'git-rebase
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom git-rebase-show-instructions t
|
||||||
|
"Whether to show usage instructions inside the rebase buffer."
|
||||||
|
:group 'git-rebase
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom git-rebase-confirm-cancel t
|
||||||
|
"Whether confirmation is required to cancel."
|
||||||
|
:group 'git-rebase
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
;;;; Faces
|
||||||
|
|
||||||
|
(defgroup git-rebase-faces nil
|
||||||
|
"Faces used by Git-Rebase mode."
|
||||||
|
:group 'faces
|
||||||
|
:group 'git-rebase)
|
||||||
|
|
||||||
|
(defface git-rebase-hash '((t (:inherit magit-hash)))
|
||||||
|
"Face for commit hashes."
|
||||||
|
:group 'git-rebase-faces)
|
||||||
|
|
||||||
|
(defface git-rebase-label '((t (:inherit magit-refname)))
|
||||||
|
"Face for labels in label, merge, and reset lines."
|
||||||
|
:group 'git-rebase-faces)
|
||||||
|
|
||||||
|
(defface git-rebase-description nil
|
||||||
|
"Face for commit descriptions."
|
||||||
|
:group 'git-rebase-faces)
|
||||||
|
|
||||||
|
(defface git-rebase-killed-action
|
||||||
|
'((t (:inherit font-lock-comment-face :strike-through t)))
|
||||||
|
"Face for commented commit action lines."
|
||||||
|
:group 'git-rebase-faces)
|
||||||
|
|
||||||
|
(defface git-rebase-comment-hash
|
||||||
|
'((t (:inherit git-rebase-hash :weight bold)))
|
||||||
|
"Face for commit hashes in commit message comments."
|
||||||
|
:group 'git-rebase-faces)
|
||||||
|
|
||||||
|
(defface git-rebase-comment-heading
|
||||||
|
'((t :inherit font-lock-keyword-face))
|
||||||
|
"Face for headings in rebase message comments."
|
||||||
|
:group 'git-commit-faces)
|
||||||
|
|
||||||
|
;;; Keymaps
|
||||||
|
|
||||||
|
(defvar git-rebase-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(set-keymap-parent map special-mode-map)
|
||||||
|
(cond ((featurep 'jkl)
|
||||||
|
(define-key map [return] 'git-rebase-show-commit)
|
||||||
|
(define-key map (kbd "i") 'git-rebase-backward-line)
|
||||||
|
(define-key map (kbd "k") 'forward-line)
|
||||||
|
(define-key map (kbd "M-i") 'git-rebase-move-line-up)
|
||||||
|
(define-key map (kbd "M-k") 'git-rebase-move-line-down)
|
||||||
|
(define-key map (kbd "p") 'git-rebase-pick)
|
||||||
|
(define-key map (kbd ",") 'git-rebase-kill-line))
|
||||||
|
(t
|
||||||
|
(define-key map (kbd "C-m") 'git-rebase-show-commit)
|
||||||
|
(define-key map (kbd "p") 'git-rebase-backward-line)
|
||||||
|
(define-key map (kbd "n") 'forward-line)
|
||||||
|
(define-key map (kbd "M-p") 'git-rebase-move-line-up)
|
||||||
|
(define-key map (kbd "M-n") 'git-rebase-move-line-down)
|
||||||
|
(define-key map (kbd "c") 'git-rebase-pick)
|
||||||
|
(define-key map (kbd "k") 'git-rebase-kill-line)
|
||||||
|
(define-key map (kbd "C-k") 'git-rebase-kill-line)))
|
||||||
|
(define-key map (kbd "b") 'git-rebase-break)
|
||||||
|
(define-key map (kbd "e") 'git-rebase-edit)
|
||||||
|
(define-key map (kbd "l") 'git-rebase-label)
|
||||||
|
(define-key map (kbd "MM") 'git-rebase-merge)
|
||||||
|
(define-key map (kbd "Mt") 'git-rebase-merge-toggle-editmsg)
|
||||||
|
(define-key map (kbd "m") 'git-rebase-edit)
|
||||||
|
(define-key map (kbd "f") 'git-rebase-fixup)
|
||||||
|
(define-key map (kbd "q") 'undefined)
|
||||||
|
(define-key map (kbd "r") 'git-rebase-reword)
|
||||||
|
(define-key map (kbd "w") 'git-rebase-reword)
|
||||||
|
(define-key map (kbd "s") 'git-rebase-squash)
|
||||||
|
(define-key map (kbd "t") 'git-rebase-reset)
|
||||||
|
(define-key map (kbd "x") 'git-rebase-exec)
|
||||||
|
(define-key map (kbd "y") 'git-rebase-insert)
|
||||||
|
(define-key map (kbd "z") 'git-rebase-noop)
|
||||||
|
(define-key map (kbd "SPC") 'git-rebase-show-or-scroll-up)
|
||||||
|
(define-key map (kbd "DEL") 'git-rebase-show-or-scroll-down)
|
||||||
|
(define-key map (kbd "C-x C-t") 'git-rebase-move-line-up)
|
||||||
|
(define-key map [M-up] 'git-rebase-move-line-up)
|
||||||
|
(define-key map [M-down] 'git-rebase-move-line-down)
|
||||||
|
(define-key map [remap undo] 'git-rebase-undo)
|
||||||
|
map)
|
||||||
|
"Keymap for Git-Rebase mode.")
|
||||||
|
|
||||||
|
(cond ((featurep 'jkl)
|
||||||
|
(put 'git-rebase-reword :advertised-binding "r")
|
||||||
|
(put 'git-rebase-move-line-up :advertised-binding (kbd "M-i"))
|
||||||
|
(put 'git-rebase-kill-line :advertised-binding ","))
|
||||||
|
(t
|
||||||
|
(put 'git-rebase-reword :advertised-binding "r")
|
||||||
|
(put 'git-rebase-move-line-up :advertised-binding (kbd "M-p"))
|
||||||
|
(put 'git-rebase-kill-line :advertised-binding "k")))
|
||||||
|
|
||||||
|
(easy-menu-define git-rebase-mode-menu git-rebase-mode-map
|
||||||
|
"Git-Rebase mode menu"
|
||||||
|
'("Rebase"
|
||||||
|
["Pick" git-rebase-pick t]
|
||||||
|
["Reword" git-rebase-reword t]
|
||||||
|
["Edit" git-rebase-edit t]
|
||||||
|
["Squash" git-rebase-squash t]
|
||||||
|
["Fixup" git-rebase-fixup t]
|
||||||
|
["Kill" git-rebase-kill-line t]
|
||||||
|
["Noop" git-rebase-noop t]
|
||||||
|
["Execute" git-rebase-exec t]
|
||||||
|
["Move Down" git-rebase-move-line-down t]
|
||||||
|
["Move Up" git-rebase-move-line-up t]
|
||||||
|
"---"
|
||||||
|
["Cancel" with-editor-cancel t]
|
||||||
|
["Finish" with-editor-finish t]))
|
||||||
|
|
||||||
|
(defvar git-rebase-command-descriptions
|
||||||
|
'((with-editor-finish . "tell Git to make it happen")
|
||||||
|
(with-editor-cancel . "tell Git that you changed your mind, i.e. abort")
|
||||||
|
(git-rebase-backward-line . "move point to previous line")
|
||||||
|
(forward-line . "move point to next line")
|
||||||
|
(git-rebase-move-line-up . "move the commit at point up")
|
||||||
|
(git-rebase-move-line-down . "move the commit at point down")
|
||||||
|
(git-rebase-show-or-scroll-up . "show the commit at point in another buffer")
|
||||||
|
(git-rebase-show-commit
|
||||||
|
. "show the commit at point in another buffer and select its window")
|
||||||
|
(undo . "undo last change")
|
||||||
|
(git-rebase-kill-line . "drop the commit at point")
|
||||||
|
(git-rebase-insert . "insert a line for an arbitrary commit")
|
||||||
|
(git-rebase-noop . "add noop action at point")))
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
|
||||||
|
(defun git-rebase-pick ()
|
||||||
|
"Use commit on current line."
|
||||||
|
(interactive)
|
||||||
|
(git-rebase-set-action "pick"))
|
||||||
|
|
||||||
|
(defun git-rebase-reword ()
|
||||||
|
"Edit message of commit on current line."
|
||||||
|
(interactive)
|
||||||
|
(git-rebase-set-action "reword"))
|
||||||
|
|
||||||
|
(defun git-rebase-edit ()
|
||||||
|
"Stop at the commit on the current line."
|
||||||
|
(interactive)
|
||||||
|
(git-rebase-set-action "edit"))
|
||||||
|
|
||||||
|
(defun git-rebase-squash ()
|
||||||
|
"Meld commit on current line into previous commit, edit message."
|
||||||
|
(interactive)
|
||||||
|
(git-rebase-set-action "squash"))
|
||||||
|
|
||||||
|
(defun git-rebase-fixup ()
|
||||||
|
"Meld commit on current line into previous commit, discard its message."
|
||||||
|
(interactive)
|
||||||
|
(git-rebase-set-action "fixup"))
|
||||||
|
|
||||||
|
(defvar-local git-rebase-comment-re nil)
|
||||||
|
|
||||||
|
(defvar git-rebase-short-options
|
||||||
|
'((?b . "break")
|
||||||
|
(?e . "edit")
|
||||||
|
(?f . "fixup")
|
||||||
|
(?l . "label")
|
||||||
|
(?m . "merge")
|
||||||
|
(?p . "pick")
|
||||||
|
(?r . "reword")
|
||||||
|
(?s . "squash")
|
||||||
|
(?t . "reset")
|
||||||
|
(?x . "exec"))
|
||||||
|
"Alist mapping single key of an action to the full name.")
|
||||||
|
|
||||||
|
(defclass git-rebase-action ()
|
||||||
|
(;; action-type: commit, exec, bare, label, merge
|
||||||
|
(action-type :initarg :action-type :initform nil)
|
||||||
|
;; Examples for each action type:
|
||||||
|
;; | action | action options | target | trailer |
|
||||||
|
;; |--------+----------------+---------+---------|
|
||||||
|
;; | pick | | hash | subject |
|
||||||
|
;; | exec | | command | |
|
||||||
|
;; | noop | | | |
|
||||||
|
;; | reset | | name | subject |
|
||||||
|
;; | merge | -C hash | name | subject |
|
||||||
|
(action :initarg :action :initform nil)
|
||||||
|
(action-options :initarg :action-options :initform nil)
|
||||||
|
(target :initarg :target :initform nil)
|
||||||
|
(trailer :initarg :trailer :initform nil)
|
||||||
|
(comment-p :initarg :comment-p :initform nil)))
|
||||||
|
|
||||||
|
(defvar git-rebase-line-regexps
|
||||||
|
`((commit . ,(concat
|
||||||
|
(regexp-opt '("e" "edit"
|
||||||
|
"f" "fixup"
|
||||||
|
"p" "pick"
|
||||||
|
"r" "reword"
|
||||||
|
"s" "squash")
|
||||||
|
"\\(?1:")
|
||||||
|
" \\(?3:[^ \n]+\\) \\(?4:.*\\)"))
|
||||||
|
(exec . "\\(?1:x\\|exec\\) \\(?3:.*\\)")
|
||||||
|
(bare . ,(concat (regexp-opt '("b" "break" "noop") "\\(?1:")
|
||||||
|
" *$"))
|
||||||
|
(label . ,(concat (regexp-opt '("l" "label"
|
||||||
|
"t" "reset")
|
||||||
|
"\\(?1:")
|
||||||
|
" \\(?3:[^ \n]+\\) ?\\(?4:.*\\)"))
|
||||||
|
(merge . ,(concat "\\(?1:m\\|merge\\) "
|
||||||
|
"\\(?:\\(?2:-[cC] [^ \n]+\\) \\)?"
|
||||||
|
"\\(?3:[^ \n]+\\)"
|
||||||
|
" ?\\(?4:.*\\)"))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun git-rebase-current-line ()
|
||||||
|
"Parse current line into a `git-rebase-action' instance.
|
||||||
|
If the current line isn't recognized as a rebase line, an
|
||||||
|
instance with all nil values is returned."
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (line-beginning-position))
|
||||||
|
(if-let ((re-start (concat "^\\(?5:" (regexp-quote comment-start)
|
||||||
|
"\\)? *"))
|
||||||
|
(type (-some (lambda (arg)
|
||||||
|
(let ((case-fold-search nil))
|
||||||
|
(and (looking-at (concat re-start (cdr arg)))
|
||||||
|
(car arg))))
|
||||||
|
git-rebase-line-regexps)))
|
||||||
|
(git-rebase-action
|
||||||
|
:action-type type
|
||||||
|
:action (when-let ((action (match-string-no-properties 1)))
|
||||||
|
(or (cdr (assoc action git-rebase-short-options))
|
||||||
|
action))
|
||||||
|
:action-options (match-string-no-properties 2)
|
||||||
|
:target (match-string-no-properties 3)
|
||||||
|
:trailer (match-string-no-properties 4)
|
||||||
|
:comment-p (and (match-string 5) t))
|
||||||
|
;; Use default empty class rather than nil to ease handling.
|
||||||
|
(git-rebase-action))))
|
||||||
|
|
||||||
|
(defun git-rebase-set-action (action)
|
||||||
|
(goto-char (line-beginning-position))
|
||||||
|
(with-slots (action-type target trailer)
|
||||||
|
(git-rebase-current-line)
|
||||||
|
(if (eq action-type 'commit)
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(magit-delete-line)
|
||||||
|
(insert (concat action " " target " " trailer "\n"))
|
||||||
|
(unless git-rebase-auto-advance
|
||||||
|
(forward-line -1)))
|
||||||
|
(ding))))
|
||||||
|
|
||||||
|
(defun git-rebase-line-p (&optional pos)
|
||||||
|
(save-excursion
|
||||||
|
(when pos (goto-char pos))
|
||||||
|
(and (oref (git-rebase-current-line) action-type)
|
||||||
|
t)))
|
||||||
|
|
||||||
|
(defun git-rebase-region-bounds ()
|
||||||
|
(when (use-region-p)
|
||||||
|
(let ((beg (save-excursion (goto-char (region-beginning))
|
||||||
|
(line-beginning-position)))
|
||||||
|
(end (save-excursion (goto-char (region-end))
|
||||||
|
(line-end-position))))
|
||||||
|
(when (and (git-rebase-line-p beg)
|
||||||
|
(git-rebase-line-p end))
|
||||||
|
(list beg (1+ end))))))
|
||||||
|
|
||||||
|
(defun git-rebase-move-line-down (n)
|
||||||
|
"Move the current commit (or command) N lines down.
|
||||||
|
If N is negative, move the commit up instead. With an active
|
||||||
|
region, move all the lines that the region touches, not just the
|
||||||
|
current line."
|
||||||
|
(interactive "p")
|
||||||
|
(pcase-let* ((`(,beg ,end)
|
||||||
|
(or (git-rebase-region-bounds)
|
||||||
|
(list (line-beginning-position)
|
||||||
|
(1+ (line-end-position)))))
|
||||||
|
(pt-offset (- (point) beg))
|
||||||
|
(mark-offset (and mark-active (- (mark) beg))))
|
||||||
|
(save-restriction
|
||||||
|
(narrow-to-region
|
||||||
|
(point-min)
|
||||||
|
(1-
|
||||||
|
(if git-rebase-show-instructions
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(while (or (git-rebase-line-p)
|
||||||
|
;; The output for --rebase-merges has empty
|
||||||
|
;; lines and "Branch" comments interspersed.
|
||||||
|
(looking-at-p "^$")
|
||||||
|
(looking-at-p (concat git-rebase-comment-re
|
||||||
|
" Branch")))
|
||||||
|
(forward-line))
|
||||||
|
(line-beginning-position))
|
||||||
|
(point-max))))
|
||||||
|
(if (or (and (< n 0) (= beg (point-min)))
|
||||||
|
(and (> n 0) (= end (point-max)))
|
||||||
|
(> end (point-max)))
|
||||||
|
(ding)
|
||||||
|
(goto-char (if (< n 0) beg end))
|
||||||
|
(forward-line n)
|
||||||
|
(atomic-change-group
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(insert (delete-and-extract-region beg end)))
|
||||||
|
(let ((new-beg (- (point) (- end beg))))
|
||||||
|
(when (use-region-p)
|
||||||
|
(setq deactivate-mark nil)
|
||||||
|
(set-mark (+ new-beg mark-offset)))
|
||||||
|
(goto-char (+ new-beg pt-offset))))))))
|
||||||
|
|
||||||
|
(defun git-rebase-move-line-up (n)
|
||||||
|
"Move the current commit (or command) N lines up.
|
||||||
|
If N is negative, move the commit down instead. With an active
|
||||||
|
region, move all the lines that the region touches, not just the
|
||||||
|
current line."
|
||||||
|
(interactive "p")
|
||||||
|
(git-rebase-move-line-down (- n)))
|
||||||
|
|
||||||
|
(defun git-rebase-highlight-region (start end window rol)
|
||||||
|
(let ((inhibit-read-only t)
|
||||||
|
(deactivate-mark nil)
|
||||||
|
(bounds (git-rebase-region-bounds)))
|
||||||
|
(mapc #'delete-overlay magit-section-highlight-overlays)
|
||||||
|
(when bounds
|
||||||
|
(magit-section-make-overlay (car bounds) (cadr bounds)
|
||||||
|
'magit-section-heading-selection))
|
||||||
|
(if (and bounds (not magit-keep-region-overlay))
|
||||||
|
(funcall (default-value 'redisplay-unhighlight-region-function) rol)
|
||||||
|
(funcall (default-value 'redisplay-highlight-region-function)
|
||||||
|
start end window rol))))
|
||||||
|
|
||||||
|
(defun git-rebase-unhighlight-region (rol)
|
||||||
|
(mapc #'delete-overlay magit-section-highlight-overlays)
|
||||||
|
(funcall (default-value 'redisplay-unhighlight-region-function) rol))
|
||||||
|
|
||||||
|
(defun git-rebase-kill-line ()
|
||||||
|
"Kill the current action line."
|
||||||
|
(interactive)
|
||||||
|
(goto-char (line-beginning-position))
|
||||||
|
(unless (oref (git-rebase-current-line) comment-p)
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(insert comment-start)
|
||||||
|
(insert " "))
|
||||||
|
(goto-char (line-beginning-position))
|
||||||
|
(when git-rebase-auto-advance
|
||||||
|
(forward-line))))
|
||||||
|
|
||||||
|
(defun git-rebase-insert (rev)
|
||||||
|
"Read an arbitrary commit and insert it below current line."
|
||||||
|
(interactive (list (magit-read-branch-or-commit "Insert revision")))
|
||||||
|
(forward-line)
|
||||||
|
(--if-let (magit-rev-format "%h %s" rev)
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(insert "pick " it ?\n))
|
||||||
|
(user-error "Unknown revision")))
|
||||||
|
|
||||||
|
(defun git-rebase-set-noncommit-action (action value-fn arg)
|
||||||
|
(goto-char (line-beginning-position))
|
||||||
|
(pcase-let* ((inhibit-read-only t)
|
||||||
|
(`(,initial ,trailer ,comment-p)
|
||||||
|
(and (not arg)
|
||||||
|
(with-slots ((ln-action action)
|
||||||
|
target trailer comment-p)
|
||||||
|
(git-rebase-current-line)
|
||||||
|
(and (equal ln-action action)
|
||||||
|
(list target trailer comment-p)))))
|
||||||
|
(value (funcall value-fn initial)))
|
||||||
|
(pcase (list value initial comment-p)
|
||||||
|
(`("" nil ,_)
|
||||||
|
(ding))
|
||||||
|
(`("" ,_ ,_)
|
||||||
|
(magit-delete-line))
|
||||||
|
(_
|
||||||
|
(if initial
|
||||||
|
(magit-delete-line)
|
||||||
|
(forward-line))
|
||||||
|
(insert (concat action " " value
|
||||||
|
(and (equal value initial)
|
||||||
|
trailer
|
||||||
|
(concat " " trailer))
|
||||||
|
"\n"))
|
||||||
|
(unless git-rebase-auto-advance
|
||||||
|
(forward-line -1))))))
|
||||||
|
|
||||||
|
(defun git-rebase-exec (arg)
|
||||||
|
"Insert a shell command to be run after the current commit.
|
||||||
|
|
||||||
|
If there already is such a command on the current line, then edit
|
||||||
|
that instead. With a prefix argument insert a new command even
|
||||||
|
when there already is one on the current line. With empty input
|
||||||
|
remove the command on the current line, if any."
|
||||||
|
(interactive "P")
|
||||||
|
(git-rebase-set-noncommit-action
|
||||||
|
"exec"
|
||||||
|
(lambda (initial) (read-shell-command "Execute: " initial))
|
||||||
|
arg))
|
||||||
|
|
||||||
|
(defun git-rebase-label (arg)
|
||||||
|
"Add a label after the current commit.
|
||||||
|
If there already is a label on the current line, then edit that
|
||||||
|
instead. With a prefix argument, insert a new label even when
|
||||||
|
there is already a label on the current line. With empty input,
|
||||||
|
remove the label on the current line, if any."
|
||||||
|
(interactive "P")
|
||||||
|
(git-rebase-set-noncommit-action
|
||||||
|
"label"
|
||||||
|
(lambda (initial)
|
||||||
|
(read-from-minibuffer
|
||||||
|
"Label: " initial magit-minibuffer-local-ns-map))
|
||||||
|
arg))
|
||||||
|
|
||||||
|
(defun git-rebase-buffer-labels ()
|
||||||
|
(let (labels)
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(while (re-search-forward "^\\(?:l\\|label\\) \\([^ \n]+\\)" nil t)
|
||||||
|
(push (match-string-no-properties 1) labels)))
|
||||||
|
(nreverse labels)))
|
||||||
|
|
||||||
|
(defun git-rebase-reset (arg)
|
||||||
|
"Reset the current HEAD to a label.
|
||||||
|
If there already is a reset command on the current line, then
|
||||||
|
edit that instead. With a prefix argument, insert a new reset
|
||||||
|
line even when point is already on a reset line. With empty
|
||||||
|
input, remove the reset command on the current line, if any."
|
||||||
|
(interactive "P")
|
||||||
|
(git-rebase-set-noncommit-action
|
||||||
|
"reset"
|
||||||
|
(lambda (initial)
|
||||||
|
(or (magit-completing-read "Label" (git-rebase-buffer-labels)
|
||||||
|
nil t initial)
|
||||||
|
""))
|
||||||
|
arg))
|
||||||
|
|
||||||
|
(defun git-rebase-merge (arg)
|
||||||
|
"Add a merge command after the current commit.
|
||||||
|
If there is already a merge command on the current line, then
|
||||||
|
replace that command instead. With a prefix argument, insert a
|
||||||
|
new merge command even when there is already one on the current
|
||||||
|
line. With empty input, remove the merge command on the current
|
||||||
|
line, if any."
|
||||||
|
(interactive "P")
|
||||||
|
(git-rebase-set-noncommit-action
|
||||||
|
"merge"
|
||||||
|
(lambda (_)
|
||||||
|
(or (magit-completing-read "Merge" (git-rebase-buffer-labels))
|
||||||
|
""))
|
||||||
|
arg))
|
||||||
|
|
||||||
|
(defun git-rebase-merge-toggle-editmsg ()
|
||||||
|
"Toggle whether an editor is invoked when performing the merge at point.
|
||||||
|
When a merge command uses a lower-case -c, the message for the
|
||||||
|
specified commit will be opened in an editor before creating the
|
||||||
|
commit. For an upper-case -C, the message will be used as is."
|
||||||
|
(interactive)
|
||||||
|
(with-slots (action-type target action-options trailer)
|
||||||
|
(git-rebase-current-line)
|
||||||
|
(if (eq action-type 'merge)
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(magit-delete-line)
|
||||||
|
(insert
|
||||||
|
(format "merge %s %s %s\n"
|
||||||
|
(replace-regexp-in-string
|
||||||
|
"-[cC]" (lambda (c)
|
||||||
|
(if (equal c "-c") "-C" "-c"))
|
||||||
|
action-options t t)
|
||||||
|
target
|
||||||
|
trailer)))
|
||||||
|
(ding))))
|
||||||
|
|
||||||
|
(defun git-rebase-set-bare-action (action arg)
|
||||||
|
(goto-char (line-beginning-position))
|
||||||
|
(with-slots ((ln-action action) comment-p)
|
||||||
|
(git-rebase-current-line)
|
||||||
|
(let ((same-action-p (equal action ln-action))
|
||||||
|
(inhibit-read-only t))
|
||||||
|
(when (or arg
|
||||||
|
(not ln-action)
|
||||||
|
(not same-action-p)
|
||||||
|
(and same-action-p comment-p))
|
||||||
|
(unless (or arg (not same-action-p))
|
||||||
|
(magit-delete-line))
|
||||||
|
(insert action ?\n)
|
||||||
|
(unless git-rebase-auto-advance
|
||||||
|
(forward-line -1))))))
|
||||||
|
|
||||||
|
(defun git-rebase-noop (&optional arg)
|
||||||
|
"Add noop action at point.
|
||||||
|
|
||||||
|
If the current line already contains a noop action, leave it
|
||||||
|
unchanged. If there is a commented noop action present, remove
|
||||||
|
the comment. Otherwise add a new noop action. With a prefix
|
||||||
|
argument insert a new noop action regardless of what is already
|
||||||
|
present on the current line.
|
||||||
|
|
||||||
|
A noop action can be used to make git perform a rebase even if
|
||||||
|
no commits are selected. Without the noop action present, git
|
||||||
|
would see an empty file and therefore do nothing."
|
||||||
|
(interactive "P")
|
||||||
|
(git-rebase-set-bare-action "noop" arg))
|
||||||
|
|
||||||
|
(defun git-rebase-break (&optional arg)
|
||||||
|
"Add break action at point.
|
||||||
|
|
||||||
|
If there is a commented break action present, remove the comment.
|
||||||
|
If the current line already contains a break action, add another
|
||||||
|
break action only if a prefix argument is given.
|
||||||
|
|
||||||
|
A break action can be used to interrupt the rebase at the
|
||||||
|
specified point. It is particularly useful for pausing before
|
||||||
|
the first commit in the sequence. For other cases, the
|
||||||
|
equivalent behavior can be achieved with `git-rebase-edit'."
|
||||||
|
(interactive "P")
|
||||||
|
(git-rebase-set-bare-action "break" arg))
|
||||||
|
|
||||||
|
(defun git-rebase-undo (&optional arg)
|
||||||
|
"Undo some previous changes.
|
||||||
|
Like `undo' but works in read-only buffers."
|
||||||
|
(interactive "P")
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(undo arg)))
|
||||||
|
|
||||||
|
(defun git-rebase--show-commit (&optional scroll)
|
||||||
|
(let ((disable-magit-save-buffers t))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (line-beginning-position))
|
||||||
|
(--if-let (with-slots (action-type target) (git-rebase-current-line)
|
||||||
|
(and (eq action-type 'commit)
|
||||||
|
target))
|
||||||
|
(pcase scroll
|
||||||
|
(`up (magit-diff-show-or-scroll-up))
|
||||||
|
(`down (magit-diff-show-or-scroll-down))
|
||||||
|
(_ (apply #'magit-show-commit it
|
||||||
|
(magit-diff-arguments 'magit-revision-mode))))
|
||||||
|
(ding)))))
|
||||||
|
|
||||||
|
(defun git-rebase-show-commit ()
|
||||||
|
"Show the commit on the current line if any."
|
||||||
|
(interactive)
|
||||||
|
(git-rebase--show-commit))
|
||||||
|
|
||||||
|
(defun git-rebase-show-or-scroll-up ()
|
||||||
|
"Update the commit buffer for commit on current line.
|
||||||
|
|
||||||
|
Either show the commit at point in the appropriate buffer, or if
|
||||||
|
that buffer is already being displayed in the current frame and
|
||||||
|
contains information about that commit, then instead scroll the
|
||||||
|
buffer up."
|
||||||
|
(interactive)
|
||||||
|
(git-rebase--show-commit 'up))
|
||||||
|
|
||||||
|
(defun git-rebase-show-or-scroll-down ()
|
||||||
|
"Update the commit buffer for commit on current line.
|
||||||
|
|
||||||
|
Either show the commit at point in the appropriate buffer, or if
|
||||||
|
that buffer is already being displayed in the current frame and
|
||||||
|
contains information about that commit, then instead scroll the
|
||||||
|
buffer down."
|
||||||
|
(interactive)
|
||||||
|
(git-rebase--show-commit 'down))
|
||||||
|
|
||||||
|
(defun git-rebase-backward-line (&optional n)
|
||||||
|
"Move N lines backward (forward if N is negative).
|
||||||
|
Like `forward-line' but go into the opposite direction."
|
||||||
|
(interactive "p")
|
||||||
|
(forward-line (- (or n 1))))
|
||||||
|
|
||||||
|
;;; Mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(define-derived-mode git-rebase-mode special-mode "Git Rebase"
|
||||||
|
"Major mode for editing of a Git rebase file.
|
||||||
|
|
||||||
|
Rebase files are generated when you run 'git rebase -i' or run
|
||||||
|
`magit-interactive-rebase'. They describe how Git should perform
|
||||||
|
the rebase. See the documentation for git-rebase (e.g., by
|
||||||
|
running 'man git-rebase' at the command line) for details."
|
||||||
|
:group 'git-rebase
|
||||||
|
(setq comment-start (or (magit-get "core.commentChar") "#"))
|
||||||
|
(setq git-rebase-comment-re (concat "^" (regexp-quote comment-start)))
|
||||||
|
(setq font-lock-defaults (list (git-rebase-mode-font-lock-keywords) t t))
|
||||||
|
(unless git-rebase-show-instructions
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(flush-lines git-rebase-comment-re)))
|
||||||
|
(unless with-editor-mode
|
||||||
|
;; Maybe already enabled when using `shell-command' or an Emacs shell.
|
||||||
|
(with-editor-mode 1))
|
||||||
|
(when git-rebase-confirm-cancel
|
||||||
|
(add-hook 'with-editor-cancel-query-functions
|
||||||
|
'git-rebase-cancel-confirm nil t))
|
||||||
|
(setq-local redisplay-highlight-region-function 'git-rebase-highlight-region)
|
||||||
|
(setq-local redisplay-unhighlight-region-function 'git-rebase-unhighlight-region)
|
||||||
|
(add-hook 'with-editor-pre-cancel-hook 'git-rebase-autostash-save nil t)
|
||||||
|
(add-hook 'with-editor-post-cancel-hook 'git-rebase-autostash-apply nil t)
|
||||||
|
(setq imenu-prev-index-position-function
|
||||||
|
#'magit-imenu--rebase-prev-index-position-function)
|
||||||
|
(setq imenu-extract-index-name-function
|
||||||
|
#'magit-imenu--rebase-extract-index-name-function)
|
||||||
|
(when (boundp 'save-place)
|
||||||
|
(setq save-place nil)))
|
||||||
|
|
||||||
|
(defun git-rebase-cancel-confirm (force)
|
||||||
|
(or (not (buffer-modified-p))
|
||||||
|
force
|
||||||
|
(magit-confirm 'abort-rebase "Abort this rebase" nil 'noabort)))
|
||||||
|
|
||||||
|
(defun git-rebase-autostash-save ()
|
||||||
|
(--when-let (magit-file-line (magit-git-dir "rebase-merge/autostash"))
|
||||||
|
(push (cons 'stash it) with-editor-cancel-alist)))
|
||||||
|
|
||||||
|
(defun git-rebase-autostash-apply ()
|
||||||
|
(--when-let (cdr (assq 'stash with-editor-cancel-alist))
|
||||||
|
(magit-stash-apply it)))
|
||||||
|
|
||||||
|
(defun git-rebase-match-comment-line (limit)
|
||||||
|
(re-search-forward (concat git-rebase-comment-re ".*") limit t))
|
||||||
|
|
||||||
|
(defun git-rebase-mode-font-lock-keywords ()
|
||||||
|
"Font lock keywords for Git-Rebase mode."
|
||||||
|
`((,(concat "^" (cdr (assq 'commit git-rebase-line-regexps)))
|
||||||
|
(1 'font-lock-keyword-face)
|
||||||
|
(3 'git-rebase-hash)
|
||||||
|
(4 'git-rebase-description))
|
||||||
|
(,(concat "^" (cdr (assq 'exec git-rebase-line-regexps)))
|
||||||
|
(1 'font-lock-keyword-face)
|
||||||
|
(3 'git-rebase-description))
|
||||||
|
(,(concat "^" (cdr (assq 'bare git-rebase-line-regexps)))
|
||||||
|
(1 'font-lock-keyword-face))
|
||||||
|
(,(concat "^" (cdr (assq 'label git-rebase-line-regexps)))
|
||||||
|
(1 'font-lock-keyword-face)
|
||||||
|
(3 'git-rebase-label)
|
||||||
|
(4 'font-lock-comment-face))
|
||||||
|
("^\\(m\\(?:erge\\)?\\) -[Cc] \\([^ \n]+\\) \\([^ \n]+\\)\\( #.*\\)?"
|
||||||
|
(1 'font-lock-keyword-face)
|
||||||
|
(2 'git-rebase-hash)
|
||||||
|
(3 'git-rebase-label)
|
||||||
|
(4 'font-lock-comment-face))
|
||||||
|
("^\\(m\\(?:erge\\)?\\) \\([^ \n]+\\)"
|
||||||
|
(1 'font-lock-keyword-face)
|
||||||
|
(2 'git-rebase-label))
|
||||||
|
(,(concat git-rebase-comment-re " *"
|
||||||
|
(cdr (assq 'commit git-rebase-line-regexps)))
|
||||||
|
0 'git-rebase-killed-action t)
|
||||||
|
(git-rebase-match-comment-line 0 'font-lock-comment-face)
|
||||||
|
("\\[[^[]*\\]"
|
||||||
|
0 'magit-keyword t)
|
||||||
|
("\\(?:fixup!\\|squash!\\)"
|
||||||
|
0 'magit-keyword-squash t)
|
||||||
|
(,(format "^%s Rebase \\([^ ]*\\) onto \\([^ ]*\\)" comment-start)
|
||||||
|
(1 'git-rebase-comment-hash t)
|
||||||
|
(2 'git-rebase-comment-hash t))
|
||||||
|
(,(format "^%s \\(Commands:\\)" comment-start)
|
||||||
|
(1 'git-rebase-comment-heading t))
|
||||||
|
(,(format "^%s Branch \\(.*\\)" comment-start)
|
||||||
|
(1 'git-rebase-label t))))
|
||||||
|
|
||||||
|
(defun git-rebase-mode-show-keybindings ()
|
||||||
|
"Modify the \"Commands:\" section of the comment Git generates
|
||||||
|
at the bottom of the file so that in place of the one-letter
|
||||||
|
abbreviation for the command, it shows the command's keybinding.
|
||||||
|
By default, this is the same except for the \"pick\" command."
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(when (and git-rebase-show-instructions
|
||||||
|
(re-search-forward
|
||||||
|
(concat git-rebase-comment-re "\\s-+p, pick")
|
||||||
|
nil t))
|
||||||
|
(goto-char (line-beginning-position))
|
||||||
|
(pcase-dolist (`(,cmd . ,desc) git-rebase-command-descriptions)
|
||||||
|
(insert (format "%s %-8s %s\n"
|
||||||
|
comment-start
|
||||||
|
(substitute-command-keys (format "\\[%s]" cmd))
|
||||||
|
desc)))
|
||||||
|
(while (re-search-forward (concat git-rebase-comment-re
|
||||||
|
"\\( ?\\)\\([^\n,],\\) "
|
||||||
|
"\\([^\n ]+\\) ")
|
||||||
|
nil t)
|
||||||
|
(let ((cmd (intern (concat "git-rebase-" (match-string 3)))))
|
||||||
|
(if (not (fboundp cmd))
|
||||||
|
(delete-region (line-beginning-position) (1+ (line-end-position)))
|
||||||
|
(replace-match " " t t nil 1)
|
||||||
|
(replace-match
|
||||||
|
(format "%-8s"
|
||||||
|
(mapconcat #'key-description
|
||||||
|
(--remove (eq (elt it 0) 'menu-bar)
|
||||||
|
(reverse (where-is-internal
|
||||||
|
cmd git-rebase-mode-map)))
|
||||||
|
", "))
|
||||||
|
t t nil 2))))))))
|
||||||
|
|
||||||
|
(add-hook 'git-rebase-mode-hook 'git-rebase-mode-show-keybindings t)
|
||||||
|
|
||||||
|
(defun git-rebase-mode-disable-before-save-hook ()
|
||||||
|
(set (make-local-variable 'before-save-hook) nil))
|
||||||
|
|
||||||
|
(add-hook 'git-rebase-mode-hook 'git-rebase-mode-disable-before-save-hook)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defconst git-rebase-filename-regexp "/git-rebase-todo\\'")
|
||||||
|
;;;###autoload
|
||||||
|
(add-to-list 'auto-mode-alist
|
||||||
|
(cons git-rebase-filename-regexp 'git-rebase-mode))
|
||||||
|
|
||||||
|
(add-to-list 'with-editor-server-window-alist
|
||||||
|
(cons git-rebase-filename-regexp 'switch-to-buffer))
|
||||||
|
|
||||||
|
(eval-after-load 'recentf
|
||||||
|
'(add-to-list 'recentf-exclude git-rebase-filename-regexp))
|
||||||
|
|
||||||
|
(add-to-list 'with-editor-file-name-history-exclude git-rebase-filename-regexp)
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'git-rebase)
|
||||||
|
;;; git-rebase.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/git-rebase.elc
Normal file
BIN
elpa/magit-20191030.1315/git-rebase.elc
Normal file
Binary file not shown.
739
elpa/magit-20191030.1315/magit-apply.el
Normal file
739
elpa/magit-20191030.1315/magit-apply.el
Normal file
@@ -0,0 +1,739 @@
|
|||||||
|
;;; magit-apply.el --- apply Git diffs -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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 commands for applying Git diffs or parts
|
||||||
|
;; of such a diff. The supported "apply variants" are apply, stage,
|
||||||
|
;; unstage, discard, and reverse - more than Git itself knows about,
|
||||||
|
;; at least at the porcelain level.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'subr-x))
|
||||||
|
|
||||||
|
(require 'magit-core)
|
||||||
|
(require 'magit-diff)
|
||||||
|
(require 'magit-wip)
|
||||||
|
|
||||||
|
(require 'transient) ; See #3732.
|
||||||
|
|
||||||
|
;; For `magit-apply'
|
||||||
|
(declare-function magit-am "magit-sequence" ())
|
||||||
|
(declare-function magit-patch-apply "magit-files" ())
|
||||||
|
;; For `magit-discard-files'
|
||||||
|
(declare-function magit-checkout-stage "magit-merge" (file arg))
|
||||||
|
(declare-function magit-checkout-read-stage "magit-merge" (file))
|
||||||
|
(defvar auto-revert-verbose)
|
||||||
|
;; For `magit-stage-untracked'
|
||||||
|
(declare-function magit-submodule-add-1 "magit-submodule"
|
||||||
|
(url &optional path name args))
|
||||||
|
(declare-function magit-submodule-read-name-for-path "magit-submodule"
|
||||||
|
(path &optional prefer-short))
|
||||||
|
(declare-function borg--maybe-absorb-gitdir "borg" (pkg))
|
||||||
|
(declare-function borg--sort-submodule-sections "borg" (file))
|
||||||
|
(defvar borg-user-emacs-directory)
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defcustom magit-delete-by-moving-to-trash t
|
||||||
|
"Whether Magit uses the system's trash can.
|
||||||
|
|
||||||
|
You should absolutely not disable this and also remove `discard'
|
||||||
|
from `magit-no-confirm'. You shouldn't do that even if you have
|
||||||
|
all of the Magit-Wip modes enabled, because those modes do not
|
||||||
|
track any files that are not tracked in the proper branch."
|
||||||
|
:package-version '(magit . "2.1.0")
|
||||||
|
:group 'magit-essentials
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-unstage-committed t
|
||||||
|
"Whether unstaging a committed change reverts it instead.
|
||||||
|
|
||||||
|
A committed change cannot be unstaged, because staging and
|
||||||
|
unstaging are actions that are concerned with the differences
|
||||||
|
between the index and the working tree, not with committed
|
||||||
|
changes.
|
||||||
|
|
||||||
|
If this option is non-nil (the default), then typing \"u\"
|
||||||
|
\(`magit-unstage') on a committed change, causes it to be
|
||||||
|
reversed in the index but not the working tree. For more
|
||||||
|
information see command `magit-reverse-in-index'."
|
||||||
|
:package-version '(magit . "2.4.1")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-reverse-atomically nil
|
||||||
|
"Whether to reverse changes atomically.
|
||||||
|
|
||||||
|
If some changes can be reversed while others cannot, then nothing
|
||||||
|
is reversed if the value of this option is non-nil. But when it
|
||||||
|
is nil, then the changes that can be reversed are reversed and
|
||||||
|
for the other changes diff files are created that contain the
|
||||||
|
rejected reversals."
|
||||||
|
:package-version '(magit . "2.7.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-post-stage-hook nil
|
||||||
|
"Hook run after staging changes.
|
||||||
|
This hook is run by `magit-refresh' if `this-command'
|
||||||
|
is a member of `magit-post-stage-hook-commands'."
|
||||||
|
:package-version '(magit . "2.90.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'hook)
|
||||||
|
|
||||||
|
(defvar magit-post-stage-hook-commands
|
||||||
|
'(magit-stage magit-stage-file magit-stage-modified))
|
||||||
|
|
||||||
|
(defcustom magit-post-unstage-hook nil
|
||||||
|
"Hook run after unstaging changes.
|
||||||
|
This hook is run by `magit-refresh' if `this-command'
|
||||||
|
is a member of `magit-post-unstage-hook-commands'."
|
||||||
|
:package-version '(magit . "2.90.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'hook)
|
||||||
|
|
||||||
|
(defvar magit-post-unstage-hook-commands
|
||||||
|
'(magit-unstage magit-unstage-file magit-unstage-all))
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
;;;; Apply
|
||||||
|
|
||||||
|
(defun magit-apply (&rest args)
|
||||||
|
"Apply the change at point to the working tree.
|
||||||
|
With a prefix argument fallback to a 3-way merge. Doing
|
||||||
|
so causes the change to be applied to the index as well."
|
||||||
|
(interactive (and current-prefix-arg (list "--3way")))
|
||||||
|
(--when-let (magit-apply--get-selection)
|
||||||
|
(pcase (list (magit-diff-type) (magit-diff-scope))
|
||||||
|
(`(,(or `unstaged `staged) ,_)
|
||||||
|
(user-error "Change is already in the working tree"))
|
||||||
|
(`(untracked ,(or `file `files))
|
||||||
|
(call-interactively 'magit-am))
|
||||||
|
(`(,_ region) (magit-apply-region it args))
|
||||||
|
(`(,_ hunk) (magit-apply-hunk it args))
|
||||||
|
(`(,_ hunks) (magit-apply-hunks it args))
|
||||||
|
(`(rebase-sequence file)
|
||||||
|
(call-interactively 'magit-patch-apply))
|
||||||
|
(`(,_ file) (magit-apply-diff it args))
|
||||||
|
(`(,_ files) (magit-apply-diffs it args)))))
|
||||||
|
|
||||||
|
(defun magit-apply--section-content (section)
|
||||||
|
(buffer-substring-no-properties (if (magit-hunk-section-p section)
|
||||||
|
(oref section start)
|
||||||
|
(oref section content))
|
||||||
|
(oref section end)))
|
||||||
|
|
||||||
|
(defun magit-apply-diffs (sections &rest args)
|
||||||
|
(setq sections (magit-apply--get-diffs sections))
|
||||||
|
(magit-apply-patch sections args
|
||||||
|
(mapconcat
|
||||||
|
(lambda (s)
|
||||||
|
(concat (magit-diff-file-header s)
|
||||||
|
(magit-apply--section-content s)))
|
||||||
|
sections "")))
|
||||||
|
|
||||||
|
(defun magit-apply-diff (section &rest args)
|
||||||
|
(setq section (car (magit-apply--get-diffs (list section))))
|
||||||
|
(magit-apply-patch section args
|
||||||
|
(concat (magit-diff-file-header section)
|
||||||
|
(magit-apply--section-content section))))
|
||||||
|
|
||||||
|
(defun magit-apply--adjust-hunk-new-starts (hunks)
|
||||||
|
"Adjust new line numbers in headers of HUNKS for partial application.
|
||||||
|
HUNKS should be a list of ordered, contiguous hunks to be applied
|
||||||
|
from a file. For example, if there is a sequence of hunks with
|
||||||
|
the headers
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@
|
||||||
|
@@ -10,6 +11,7 @@
|
||||||
|
@@ -18,6 +20,7 @@
|
||||||
|
|
||||||
|
and only the second and third are to be applied, they would be
|
||||||
|
adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
|
||||||
|
(let* ((first-hunk (car hunks))
|
||||||
|
(offset (if (string-match diff-hunk-header-re-unified first-hunk)
|
||||||
|
(- (string-to-number (match-string 3 first-hunk))
|
||||||
|
(string-to-number (match-string 1 first-hunk)))
|
||||||
|
(error "Hunk does not have expected header"))))
|
||||||
|
(if (= offset 0)
|
||||||
|
hunks
|
||||||
|
(mapcar (lambda (hunk)
|
||||||
|
(if (string-match diff-hunk-header-re-unified hunk)
|
||||||
|
(replace-match (number-to-string
|
||||||
|
(- (string-to-number (match-string 3 hunk))
|
||||||
|
offset))
|
||||||
|
t t hunk 3)
|
||||||
|
(error "Hunk does not have expected header")))
|
||||||
|
hunks))))
|
||||||
|
|
||||||
|
(defun magit-apply--adjust-hunk-new-start (hunk)
|
||||||
|
(car (magit-apply--adjust-hunk-new-starts (list hunk))))
|
||||||
|
|
||||||
|
(defun magit-apply-hunks (sections &rest args)
|
||||||
|
(let ((section (oref (car sections) parent)))
|
||||||
|
(when (string-match "^diff --cc" (oref section value))
|
||||||
|
(user-error "Cannot un-/stage resolution hunks. Stage the whole file"))
|
||||||
|
(magit-apply-patch
|
||||||
|
section args
|
||||||
|
(concat (oref section header)
|
||||||
|
(mapconcat #'identity
|
||||||
|
(magit-apply--adjust-hunk-new-starts
|
||||||
|
(mapcar #'magit-apply--section-content sections))
|
||||||
|
"")))))
|
||||||
|
|
||||||
|
(defun magit-apply-hunk (section &rest args)
|
||||||
|
(when (string-match "^diff --cc" (magit-section-parent-value section))
|
||||||
|
(user-error "Cannot un-/stage resolution hunks. Stage the whole file"))
|
||||||
|
(magit-apply-patch (oref section parent) args
|
||||||
|
(concat (magit-diff-file-header section)
|
||||||
|
(magit-apply--adjust-hunk-new-start
|
||||||
|
(magit-apply--section-content section)))))
|
||||||
|
|
||||||
|
(defun magit-apply-region (section &rest args)
|
||||||
|
(when (string-match "^diff --cc" (magit-section-parent-value section))
|
||||||
|
(user-error "Cannot un-/stage resolution hunks. Stage the whole file"))
|
||||||
|
(magit-apply-patch (oref section parent) args
|
||||||
|
(concat (magit-diff-file-header section)
|
||||||
|
(magit-apply--adjust-hunk-new-start
|
||||||
|
(magit-diff-hunk-region-patch section args)))))
|
||||||
|
|
||||||
|
(defun magit-apply-patch (section:s args patch)
|
||||||
|
(let* ((files (if (atom section:s)
|
||||||
|
(list (oref section:s value))
|
||||||
|
(--map (oref it value) section:s)))
|
||||||
|
(command (symbol-name this-command))
|
||||||
|
(command (if (and command (string-match "^magit-\\([^-]+\\)" command))
|
||||||
|
(match-string 1 command)
|
||||||
|
"apply"))
|
||||||
|
(ignore-context (magit-diff-ignore-any-space-p)))
|
||||||
|
(unless (magit-diff-context-p)
|
||||||
|
(user-error "Not enough context to apply patch. Increase the context"))
|
||||||
|
(when (and magit-wip-before-change-mode (not inhibit-magit-refresh))
|
||||||
|
(magit-wip-commit-before-change files (concat " before " command)))
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert patch)
|
||||||
|
(magit-run-git-with-input
|
||||||
|
"apply" args "-p0"
|
||||||
|
(and ignore-context "-C0")
|
||||||
|
"--ignore-space-change" "-"))
|
||||||
|
(unless inhibit-magit-refresh
|
||||||
|
(when magit-wip-after-apply-mode
|
||||||
|
(magit-wip-commit-after-apply files (concat " after " command)))
|
||||||
|
(magit-refresh))))
|
||||||
|
|
||||||
|
(defun magit-apply--get-selection ()
|
||||||
|
(or (magit-region-sections '(hunk file module) t)
|
||||||
|
(let ((section (magit-current-section)))
|
||||||
|
(pcase (oref section type)
|
||||||
|
((or `hunk `file `module) section)
|
||||||
|
((or `staged `unstaged `untracked
|
||||||
|
`stashed-index `stashed-worktree `stashed-untracked)
|
||||||
|
(oref section children))
|
||||||
|
(_ (user-error "Cannot apply this, it's not a change"))))))
|
||||||
|
|
||||||
|
(defun magit-apply--get-diffs (sections)
|
||||||
|
(magit-section-case
|
||||||
|
([file diffstat]
|
||||||
|
(--map (or (magit-get-section
|
||||||
|
(append `((file . ,(oref it value)))
|
||||||
|
(magit-section-ident magit-root-section)))
|
||||||
|
(error "Cannot get required diff headers"))
|
||||||
|
sections))
|
||||||
|
(t sections)))
|
||||||
|
|
||||||
|
(defun magit-apply--diff-ignores-whitespace-p ()
|
||||||
|
(and (cl-intersection magit-buffer-diff-args
|
||||||
|
'("--ignore-space-at-eol"
|
||||||
|
"--ignore-space-change"
|
||||||
|
"--ignore-all-space"
|
||||||
|
"--ignore-blank-lines")
|
||||||
|
:test #'equal)
|
||||||
|
t))
|
||||||
|
|
||||||
|
;;;; Stage
|
||||||
|
|
||||||
|
(defun magit-stage (&optional intent)
|
||||||
|
"Add the change at point to the staging area.
|
||||||
|
With a prefix argument, INTENT, and an untracked file (or files)
|
||||||
|
at point, stage the file but not its content."
|
||||||
|
(interactive "P")
|
||||||
|
(--if-let (and (derived-mode-p 'magit-mode) (magit-apply--get-selection))
|
||||||
|
(pcase (list (magit-diff-type)
|
||||||
|
(magit-diff-scope)
|
||||||
|
(magit-apply--diff-ignores-whitespace-p))
|
||||||
|
(`(untracked ,_ ,_) (magit-stage-untracked intent))
|
||||||
|
(`(unstaged region ,_) (magit-apply-region it "--cached"))
|
||||||
|
(`(unstaged hunk ,_) (magit-apply-hunk it "--cached"))
|
||||||
|
(`(unstaged hunks ,_) (magit-apply-hunks it "--cached"))
|
||||||
|
(`(unstaged file t) (magit-apply-diff it "--cached"))
|
||||||
|
(`(unstaged files t) (magit-apply-diffs it "--cached"))
|
||||||
|
(`(unstaged list t) (magit-apply-diffs it "--cached"))
|
||||||
|
(`(unstaged file nil) (magit-stage-1 "-u" (list (oref it value))))
|
||||||
|
(`(unstaged files nil) (magit-stage-1 "-u" (magit-region-values nil t)))
|
||||||
|
(`(unstaged list nil) (magit-stage-modified))
|
||||||
|
(`(staged ,_ ,_) (user-error "Already staged"))
|
||||||
|
(`(committed ,_ ,_) (user-error "Cannot stage committed changes"))
|
||||||
|
(`(undefined ,_ ,_) (user-error "Cannot stage this change")))
|
||||||
|
(call-interactively 'magit-stage-file)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-stage-file (file)
|
||||||
|
"Stage all changes to FILE.
|
||||||
|
With a prefix argument or when there is no file at point ask for
|
||||||
|
the file to be staged. Otherwise stage the file at point without
|
||||||
|
requiring confirmation."
|
||||||
|
(interactive
|
||||||
|
(let* ((atpoint (magit-section-value-if 'file))
|
||||||
|
(current (magit-file-relative-name))
|
||||||
|
(choices (nconc (magit-unstaged-files)
|
||||||
|
(magit-untracked-files)))
|
||||||
|
(default (car (member (or atpoint current) choices))))
|
||||||
|
(list (if (or current-prefix-arg (not default))
|
||||||
|
(magit-completing-read "Stage file" choices
|
||||||
|
nil t nil nil default)
|
||||||
|
default))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-stage-1 nil (list file))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-stage-modified (&optional all)
|
||||||
|
"Stage all changes to files modified in the worktree.
|
||||||
|
Stage all new content of tracked files and remove tracked files
|
||||||
|
that no longer exist in the working tree from the index also.
|
||||||
|
With a prefix argument also stage previously untracked (but not
|
||||||
|
ignored) files."
|
||||||
|
(interactive "P")
|
||||||
|
(when (magit-anything-staged-p)
|
||||||
|
(magit-confirm 'stage-all-changes))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-stage-1 (if all "--all" "-u") magit-buffer-diff-files)))
|
||||||
|
|
||||||
|
(defun magit-stage-1 (arg &optional files)
|
||||||
|
(magit-wip-commit-before-change files " before stage")
|
||||||
|
(magit-run-git "add" arg (if files (cons "--" files) "."))
|
||||||
|
(when magit-auto-revert-mode
|
||||||
|
(mapc #'magit-turn-on-auto-revert-mode-if-desired files))
|
||||||
|
(magit-wip-commit-after-apply files " after stage"))
|
||||||
|
|
||||||
|
(defun magit-stage-untracked (&optional intent)
|
||||||
|
(let* ((section (magit-current-section))
|
||||||
|
(files (pcase (magit-diff-scope)
|
||||||
|
(`file (list (oref section value)))
|
||||||
|
(`files (magit-region-values nil t))
|
||||||
|
(`list (magit-untracked-files))))
|
||||||
|
plain repos)
|
||||||
|
(dolist (file files)
|
||||||
|
(if (and (not (file-symlink-p file))
|
||||||
|
(magit-git-repo-p file t))
|
||||||
|
(push file repos)
|
||||||
|
(push file plain)))
|
||||||
|
(magit-wip-commit-before-change files " before stage")
|
||||||
|
(when plain
|
||||||
|
(magit-run-git "add" (and intent "--intent-to-add")
|
||||||
|
"--" plain)
|
||||||
|
(when magit-auto-revert-mode
|
||||||
|
(mapc #'magit-turn-on-auto-revert-mode-if-desired plain)))
|
||||||
|
(dolist (repo repos)
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (oref (magit-get-section
|
||||||
|
`((file . ,repo) (untracked) (status)))
|
||||||
|
start))
|
||||||
|
(let* ((topdir (magit-toplevel))
|
||||||
|
(package
|
||||||
|
(and (equal (bound-and-true-p borg-user-emacs-directory)
|
||||||
|
topdir)
|
||||||
|
(file-name-nondirectory (directory-file-name repo)))))
|
||||||
|
(magit-submodule-add-1
|
||||||
|
(let ((default-directory
|
||||||
|
(file-name-as-directory (expand-file-name repo))))
|
||||||
|
(or (magit-get "remote" (magit-get-some-remote) "url")
|
||||||
|
(concat (file-name-as-directory ".") repo)))
|
||||||
|
repo
|
||||||
|
(magit-submodule-read-name-for-path repo package))
|
||||||
|
(when package
|
||||||
|
(borg--sort-submodule-sections
|
||||||
|
(expand-file-name ".gitmodules" topdir))
|
||||||
|
(let ((default-directory borg-user-emacs-directory))
|
||||||
|
(borg--maybe-absorb-gitdir package))
|
||||||
|
(when (and (y-or-n-p
|
||||||
|
(format "Also build and activate `%s' drone?" package))
|
||||||
|
(fboundp 'borg-build)
|
||||||
|
(fboundp 'borg-activate))
|
||||||
|
(borg-build package)
|
||||||
|
(borg-activate package))))))
|
||||||
|
(magit-wip-commit-after-apply files " after stage")))
|
||||||
|
|
||||||
|
;;;; Unstage
|
||||||
|
|
||||||
|
(defun magit-unstage ()
|
||||||
|
"Remove the change at point from the staging area."
|
||||||
|
(interactive)
|
||||||
|
(--when-let (magit-apply--get-selection)
|
||||||
|
(pcase (list (magit-diff-type)
|
||||||
|
(magit-diff-scope)
|
||||||
|
(magit-apply--diff-ignores-whitespace-p))
|
||||||
|
(`(untracked ,_ ,_) (user-error "Cannot unstage untracked changes"))
|
||||||
|
(`(unstaged file ,_) (magit-unstage-intent (list (oref it value))))
|
||||||
|
(`(unstaged files ,_) (magit-unstage-intent (magit-region-values nil t)))
|
||||||
|
(`(unstaged ,_ ,_) (user-error "Already unstaged"))
|
||||||
|
(`(staged region ,_) (magit-apply-region it "--reverse" "--cached"))
|
||||||
|
(`(staged hunk ,_) (magit-apply-hunk it "--reverse" "--cached"))
|
||||||
|
(`(staged hunks ,_) (magit-apply-hunks it "--reverse" "--cached"))
|
||||||
|
(`(staged file t) (magit-apply-diff it "--reverse" "--cached"))
|
||||||
|
(`(staged files t) (magit-apply-diffs it "--reverse" "--cached"))
|
||||||
|
(`(staged list t) (magit-apply-diffs it "--reverse" "--cached"))
|
||||||
|
(`(staged file nil) (magit-unstage-1 (list (oref it value))))
|
||||||
|
(`(staged files nil) (magit-unstage-1 (magit-region-values nil t)))
|
||||||
|
(`(staged list nil) (magit-unstage-all))
|
||||||
|
(`(committed ,_ ,_) (if magit-unstage-committed
|
||||||
|
(magit-reverse-in-index)
|
||||||
|
(user-error "Cannot unstage committed changes")))
|
||||||
|
(`(undefined ,_ ,_) (user-error "Cannot unstage this change")))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-unstage-file (file)
|
||||||
|
"Unstage all changes to FILE.
|
||||||
|
With a prefix argument or when there is no file at point ask for
|
||||||
|
the file to be unstaged. Otherwise unstage the file at point
|
||||||
|
without requiring confirmation."
|
||||||
|
(interactive
|
||||||
|
(let* ((atpoint (magit-section-value-if 'file))
|
||||||
|
(current (magit-file-relative-name))
|
||||||
|
(choices (magit-staged-files))
|
||||||
|
(default (car (member (or atpoint current) choices))))
|
||||||
|
(list (if (or current-prefix-arg (not default))
|
||||||
|
(magit-completing-read "Unstage file" choices
|
||||||
|
nil t nil nil default)
|
||||||
|
default))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-unstage-1 (list file))))
|
||||||
|
|
||||||
|
(defun magit-unstage-1 (files)
|
||||||
|
(magit-wip-commit-before-change files " before unstage")
|
||||||
|
(if (magit-no-commit-p)
|
||||||
|
(magit-run-git "rm" "--cached" "--" files)
|
||||||
|
(magit-run-git "reset" "HEAD" "--" files))
|
||||||
|
(magit-wip-commit-after-apply files " after unstage"))
|
||||||
|
|
||||||
|
(defun magit-unstage-intent (files)
|
||||||
|
(if-let ((staged (magit-staged-files))
|
||||||
|
(intent (--filter (member it staged) files)))
|
||||||
|
(magit-unstage-1 intent)
|
||||||
|
(user-error "Already unstaged")))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-unstage-all ()
|
||||||
|
"Remove all changes from the staging area."
|
||||||
|
(interactive)
|
||||||
|
(when (or (magit-anything-unstaged-p)
|
||||||
|
(magit-untracked-files))
|
||||||
|
(magit-confirm 'unstage-all-changes))
|
||||||
|
(magit-wip-commit-before-change nil " before unstage")
|
||||||
|
(magit-run-git "reset" "HEAD" "--" magit-buffer-diff-files)
|
||||||
|
(magit-wip-commit-after-apply nil " after unstage"))
|
||||||
|
|
||||||
|
;;;; Discard
|
||||||
|
|
||||||
|
(defun magit-discard ()
|
||||||
|
"Remove the change at point."
|
||||||
|
(interactive)
|
||||||
|
(--when-let (magit-apply--get-selection)
|
||||||
|
(pcase (list (magit-diff-type) (magit-diff-scope))
|
||||||
|
(`(committed ,_) (user-error "Cannot discard committed changes"))
|
||||||
|
(`(undefined ,_) (user-error "Cannot discard this change"))
|
||||||
|
(`(,_ region) (magit-discard-region it))
|
||||||
|
(`(,_ hunk) (magit-discard-hunk it))
|
||||||
|
(`(,_ hunks) (magit-discard-hunks it))
|
||||||
|
(`(,_ file) (magit-discard-file it))
|
||||||
|
(`(,_ files) (magit-discard-files it))
|
||||||
|
(`(,_ list) (magit-discard-files it)))))
|
||||||
|
|
||||||
|
(defun magit-discard-region (section)
|
||||||
|
(magit-confirm 'discard "Discard region")
|
||||||
|
(magit-discard-apply section 'magit-apply-region))
|
||||||
|
|
||||||
|
(defun magit-discard-hunk (section)
|
||||||
|
(magit-confirm 'discard "Discard hunk")
|
||||||
|
(magit-discard-apply section 'magit-apply-hunk))
|
||||||
|
|
||||||
|
(defun magit-discard-apply (section apply)
|
||||||
|
(if (eq (magit-diff-type section) 'unstaged)
|
||||||
|
(funcall apply section "--reverse")
|
||||||
|
(if (magit-anything-unstaged-p
|
||||||
|
nil (if (magit-file-section-p section)
|
||||||
|
(oref section value)
|
||||||
|
(magit-section-parent-value section)))
|
||||||
|
(progn (let ((inhibit-magit-refresh t))
|
||||||
|
(funcall apply section "--reverse" "--cached")
|
||||||
|
(funcall apply section "--reverse" "--reject"))
|
||||||
|
(magit-refresh))
|
||||||
|
(funcall apply section "--reverse" "--index"))))
|
||||||
|
|
||||||
|
(defun magit-discard-hunks (sections)
|
||||||
|
(magit-confirm 'discard (format "Discard %s hunks from %s"
|
||||||
|
(length sections)
|
||||||
|
(magit-section-parent-value (car sections))))
|
||||||
|
(magit-discard-apply-n sections 'magit-apply-hunks))
|
||||||
|
|
||||||
|
(defun magit-discard-apply-n (sections apply)
|
||||||
|
(let ((section (car sections)))
|
||||||
|
(if (eq (magit-diff-type section) 'unstaged)
|
||||||
|
(funcall apply sections "--reverse")
|
||||||
|
(if (magit-anything-unstaged-p
|
||||||
|
nil (if (magit-file-section-p section)
|
||||||
|
(oref section value)
|
||||||
|
(magit-section-parent-value section)))
|
||||||
|
(progn (let ((inhibit-magit-refresh t))
|
||||||
|
(funcall apply sections "--reverse" "--cached")
|
||||||
|
(funcall apply sections "--reverse" "--reject"))
|
||||||
|
(magit-refresh))
|
||||||
|
(funcall apply sections "--reverse" "--index")))))
|
||||||
|
|
||||||
|
(defun magit-discard-file (section)
|
||||||
|
(magit-discard-files (list section)))
|
||||||
|
|
||||||
|
(defun magit-discard-files (sections)
|
||||||
|
(let ((auto-revert-verbose nil)
|
||||||
|
(type (magit-diff-type (car sections)))
|
||||||
|
(status (magit-file-status))
|
||||||
|
files delete resurrect rename discard discard-new resolve)
|
||||||
|
(dolist (section sections)
|
||||||
|
(let ((file (oref section value)))
|
||||||
|
(push file files)
|
||||||
|
(pcase (cons (pcase type
|
||||||
|
(`staged ?X)
|
||||||
|
(`unstaged ?Y)
|
||||||
|
(`untracked ?Z))
|
||||||
|
(cddr (assoc file status)))
|
||||||
|
(`(?Z) (dolist (f (magit-untracked-files nil file))
|
||||||
|
(push f delete)))
|
||||||
|
((or `(?Z ?? ??) `(?Z ?! ?!)) (push file delete))
|
||||||
|
((or `(?Z ?D ? ) `(,_ ?D ?D)) (push file delete))
|
||||||
|
((or `(,_ ?U ,_) `(,_ ,_ ?U)) (push file resolve))
|
||||||
|
(`(,_ ?A ?A) (push file resolve))
|
||||||
|
(`(?X ?M ,(or ? ?M ?D)) (push section discard))
|
||||||
|
(`(?Y ,_ ?M ) (push section discard))
|
||||||
|
(`(?X ?A ?M ) (push file discard-new))
|
||||||
|
(`(?X ?C ?M ) (push file discard-new))
|
||||||
|
(`(?X ?A ,(or ? ?D)) (push file delete))
|
||||||
|
(`(?X ?C ,(or ? ?D)) (push file delete))
|
||||||
|
(`(?X ?D ,(or ? ?M )) (push file resurrect))
|
||||||
|
(`(?Y ,_ ?D ) (push file resurrect))
|
||||||
|
(`(?X ?R ,(or ? ?M ?D)) (push file rename)))))
|
||||||
|
(unwind-protect
|
||||||
|
(let ((inhibit-magit-refresh t))
|
||||||
|
(magit-wip-commit-before-change files " before discard")
|
||||||
|
(when resolve
|
||||||
|
(magit-discard-files--resolve (nreverse resolve)))
|
||||||
|
(when resurrect
|
||||||
|
(magit-discard-files--resurrect (nreverse resurrect)))
|
||||||
|
(when delete
|
||||||
|
(magit-discard-files--delete (nreverse delete) status))
|
||||||
|
(when rename
|
||||||
|
(magit-discard-files--rename (nreverse rename) status))
|
||||||
|
(when (or discard discard-new)
|
||||||
|
(magit-discard-files--discard (nreverse discard)
|
||||||
|
(nreverse discard-new)))
|
||||||
|
(magit-wip-commit-after-apply files " after discard"))
|
||||||
|
(magit-refresh))))
|
||||||
|
|
||||||
|
(defun magit-discard-files--resolve (files)
|
||||||
|
(if-let ((arg (and (cdr files)
|
||||||
|
(magit-read-char-case
|
||||||
|
(format "For these %i files\n%s\ncheckout:\n"
|
||||||
|
(length files)
|
||||||
|
(mapconcat (lambda (file)
|
||||||
|
(concat " " file))
|
||||||
|
files "\n"))
|
||||||
|
t
|
||||||
|
(?o "[o]ur stage" "--ours")
|
||||||
|
(?t "[t]heir stage" "--theirs")
|
||||||
|
(?c "[c]onflict" "--merge")
|
||||||
|
(?i "decide [i]ndividually" nil)))))
|
||||||
|
(dolist (file files)
|
||||||
|
(magit-checkout-stage file arg))
|
||||||
|
(dolist (file files)
|
||||||
|
(magit-checkout-stage file (magit-checkout-read-stage file)))))
|
||||||
|
|
||||||
|
(defun magit-discard-files--resurrect (files)
|
||||||
|
(magit-confirm-files 'resurrect files)
|
||||||
|
(if (eq (magit-diff-type) 'staged)
|
||||||
|
(magit-call-git "reset" "--" files)
|
||||||
|
(magit-call-git "checkout" "--" files)))
|
||||||
|
|
||||||
|
(defun magit-discard-files--delete (files status)
|
||||||
|
(magit-confirm-files (if magit-delete-by-moving-to-trash 'trash 'delete)
|
||||||
|
files)
|
||||||
|
(let ((delete-by-moving-to-trash magit-delete-by-moving-to-trash))
|
||||||
|
(dolist (file files)
|
||||||
|
(when (string-match-p "\\`\\\\?~" file)
|
||||||
|
(error "Refusing to delete %S, too dangerous" file))
|
||||||
|
(pcase (nth 3 (assoc file status))
|
||||||
|
((guard (memq (magit-diff-type) '(unstaged untracked)))
|
||||||
|
(dired-delete-file file dired-recursive-deletes
|
||||||
|
magit-delete-by-moving-to-trash)
|
||||||
|
(dired-clean-up-after-deletion file))
|
||||||
|
(?\s (delete-file file t)
|
||||||
|
(magit-call-git "rm" "--cached" "--" file))
|
||||||
|
(?M (let ((temp (magit-git-string "checkout-index" "--temp" file)))
|
||||||
|
(string-match
|
||||||
|
(format "\\(.+?\\)\t%s" (regexp-quote file)) temp)
|
||||||
|
(rename-file (match-string 1 temp)
|
||||||
|
(setq temp (concat file ".~{index}~")))
|
||||||
|
(delete-file temp t))
|
||||||
|
(magit-call-git "rm" "--cached" "--force" "--" file))
|
||||||
|
(?D (magit-call-git "checkout" "--" file)
|
||||||
|
(delete-file file t)
|
||||||
|
(magit-call-git "rm" "--cached" "--force" "--" file))))))
|
||||||
|
|
||||||
|
(defun magit-discard-files--rename (files status)
|
||||||
|
(magit-confirm 'rename "Undo rename %s" "Undo %i renames" nil
|
||||||
|
(mapcar (lambda (file)
|
||||||
|
(setq file (assoc file status))
|
||||||
|
(format "%s -> %s" (cadr file) (car file)))
|
||||||
|
files))
|
||||||
|
(dolist (file files)
|
||||||
|
(let ((orig (cadr (assoc file status))))
|
||||||
|
(if (file-exists-p file)
|
||||||
|
(progn
|
||||||
|
(--when-let (file-name-directory orig)
|
||||||
|
(make-directory it t))
|
||||||
|
(magit-call-git "mv" file orig))
|
||||||
|
(magit-call-git "rm" "--cached" "--" file)
|
||||||
|
(magit-call-git "reset" "--" orig)))))
|
||||||
|
|
||||||
|
(defun magit-discard-files--discard (sections new-files)
|
||||||
|
(let ((files (--map (oref it value) sections)))
|
||||||
|
(magit-confirm-files 'discard (append files new-files)
|
||||||
|
(format "Discard %s changes in" (magit-diff-type)))
|
||||||
|
(if (eq (magit-diff-type (car sections)) 'unstaged)
|
||||||
|
(magit-call-git "checkout" "--" files)
|
||||||
|
(when new-files
|
||||||
|
(magit-call-git "add" "--" new-files)
|
||||||
|
(magit-call-git "reset" "--" new-files))
|
||||||
|
(let ((binaries (magit-binary-files "--cached")))
|
||||||
|
(when binaries
|
||||||
|
(setq sections
|
||||||
|
(--remove (member (oref it value) binaries)
|
||||||
|
sections)))
|
||||||
|
(cond ((= (length sections) 1)
|
||||||
|
(magit-discard-apply (car sections) 'magit-apply-diff))
|
||||||
|
(sections
|
||||||
|
(magit-discard-apply-n sections 'magit-apply-diffs)))
|
||||||
|
(when binaries
|
||||||
|
(let ((modified (magit-unstaged-files t)))
|
||||||
|
(setq binaries (--separate (member it modified) binaries)))
|
||||||
|
(when (cadr binaries)
|
||||||
|
(magit-call-git "reset" "--" (cadr binaries)))
|
||||||
|
(when (car binaries)
|
||||||
|
(user-error
|
||||||
|
(concat
|
||||||
|
"Cannot discard staged changes to binary files, "
|
||||||
|
"which also have unstaged changes. Unstage instead."))))))))
|
||||||
|
|
||||||
|
;;;; Reverse
|
||||||
|
|
||||||
|
(defun magit-reverse (&rest args)
|
||||||
|
"Reverse the change at point in the working tree.
|
||||||
|
With a prefix argument fallback to a 3-way merge. Doing
|
||||||
|
so causes the change to be applied to the index as well."
|
||||||
|
(interactive (and current-prefix-arg (list "--3way")))
|
||||||
|
(--when-let (magit-apply--get-selection)
|
||||||
|
(pcase (list (magit-diff-type) (magit-diff-scope))
|
||||||
|
(`(untracked ,_) (user-error "Cannot reverse untracked changes"))
|
||||||
|
(`(unstaged ,_) (user-error "Cannot reverse unstaged changes"))
|
||||||
|
(`(,_ region) (magit-reverse-region it args))
|
||||||
|
(`(,_ hunk) (magit-reverse-hunk it args))
|
||||||
|
(`(,_ hunks) (magit-reverse-hunks it args))
|
||||||
|
(`(,_ file) (magit-reverse-file it args))
|
||||||
|
(`(,_ files) (magit-reverse-files it args))
|
||||||
|
(`(,_ list) (magit-reverse-files it args)))))
|
||||||
|
|
||||||
|
(defun magit-reverse-region (section args)
|
||||||
|
(magit-confirm 'reverse "Reverse region")
|
||||||
|
(magit-reverse-apply section 'magit-apply-region args))
|
||||||
|
|
||||||
|
(defun magit-reverse-hunk (section args)
|
||||||
|
(magit-confirm 'reverse "Reverse hunk")
|
||||||
|
(magit-reverse-apply section 'magit-apply-hunk args))
|
||||||
|
|
||||||
|
(defun magit-reverse-hunks (sections args)
|
||||||
|
(magit-confirm 'reverse
|
||||||
|
(format "Reverse %s hunks from %s"
|
||||||
|
(length sections)
|
||||||
|
(magit-section-parent-value (car sections))))
|
||||||
|
(magit-reverse-apply sections 'magit-apply-hunks args))
|
||||||
|
|
||||||
|
(defun magit-reverse-file (section args)
|
||||||
|
(magit-reverse-files (list section) args))
|
||||||
|
|
||||||
|
(defun magit-reverse-files (sections args)
|
||||||
|
(pcase-let ((`(,binaries ,sections)
|
||||||
|
(let ((bs (magit-binary-files
|
||||||
|
(cond ((derived-mode-p 'magit-revision-mode)
|
||||||
|
magit-buffer-range)
|
||||||
|
((derived-mode-p 'magit-diff-mode)
|
||||||
|
magit-buffer-range)
|
||||||
|
(t
|
||||||
|
"--cached")))))
|
||||||
|
(--separate (member (oref it value) bs)
|
||||||
|
sections))))
|
||||||
|
(magit-confirm-files 'reverse (--map (oref it value) sections))
|
||||||
|
(cond ((= (length sections) 1)
|
||||||
|
(magit-reverse-apply (car sections) 'magit-apply-diff args))
|
||||||
|
(sections
|
||||||
|
(magit-reverse-apply sections 'magit-apply-diffs args)))
|
||||||
|
(when binaries
|
||||||
|
(user-error "Cannot reverse binary files"))))
|
||||||
|
|
||||||
|
(defun magit-reverse-apply (section:s apply args)
|
||||||
|
(funcall apply section:s "--reverse" args
|
||||||
|
(and (not magit-reverse-atomically)
|
||||||
|
(not (member "--3way" args))
|
||||||
|
"--reject")))
|
||||||
|
|
||||||
|
(defun magit-reverse-in-index (&rest args)
|
||||||
|
"Reverse the change at point in the index but not the working tree.
|
||||||
|
|
||||||
|
Use this command to extract a change from `HEAD', while leaving
|
||||||
|
it in the working tree, so that it can later be committed using
|
||||||
|
a separate commit. A typical workflow would be:
|
||||||
|
|
||||||
|
0. Optionally make sure that there are no uncommitted changes.
|
||||||
|
1. Visit the `HEAD' commit and navigate to the change that should
|
||||||
|
not have been included in that commit.
|
||||||
|
2. Type \"u\" (`magit-unstage') to reverse it in the index.
|
||||||
|
This assumes that `magit-unstage-committed-changes' is non-nil.
|
||||||
|
3. Type \"c e\" to extend `HEAD' with the staged changes,
|
||||||
|
including those that were already staged before.
|
||||||
|
4. Optionally stage the remaining changes using \"s\" or \"S\"
|
||||||
|
and then type \"c c\" to create a new commit."
|
||||||
|
(interactive)
|
||||||
|
(magit-reverse (cons "--cached" args)))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-apply)
|
||||||
|
;;; magit-apply.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-apply.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-apply.elc
Normal file
Binary file not shown.
2510
elpa/magit-20191030.1315/magit-autoloads.el
Normal file
2510
elpa/magit-20191030.1315/magit-autoloads.el
Normal file
File diff suppressed because it is too large
Load Diff
258
elpa/magit-20191030.1315/magit-autorevert.el
Normal file
258
elpa/magit-20191030.1315/magit-autorevert.el
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
;;; magit-autorevert.el --- revert buffers when files in repository change -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'cl-lib)
|
||||||
|
(require 'dash)
|
||||||
|
|
||||||
|
(require 'magit-git)
|
||||||
|
|
||||||
|
(require 'autorevert)
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defgroup magit-auto-revert nil
|
||||||
|
"Revert buffers when files in repository change."
|
||||||
|
:link '(custom-group-link auto-revert)
|
||||||
|
:link '(info-link "(magit)Automatic Reverting of File-Visiting Buffers")
|
||||||
|
:group 'auto-revert
|
||||||
|
:group 'magit-essentials
|
||||||
|
:group 'magit-modes)
|
||||||
|
|
||||||
|
(defcustom auto-revert-buffer-list-filter nil
|
||||||
|
"Filter that determines which buffers `auto-revert-buffers' reverts.
|
||||||
|
|
||||||
|
This option is provided by Magit, which also advises
|
||||||
|
`auto-revert-buffers' to respect it. Magit users who do not turn
|
||||||
|
on the local mode `auto-revert-mode' themselves, are best served
|
||||||
|
by setting the value to `magit-auto-revert-repository-buffer-p'.
|
||||||
|
|
||||||
|
However the default is nil, so as not to disturb users who do use
|
||||||
|
the local mode directly. If you experience delays when running
|
||||||
|
Magit commands, then you should consider using one of the
|
||||||
|
predicates provided by Magit - especially if you also use Tramp.
|
||||||
|
|
||||||
|
Users who do turn on `auto-revert-mode' in buffers in which Magit
|
||||||
|
doesn't do that for them, should likely not use any filter.
|
||||||
|
Users who turn on `global-auto-revert-mode', do not have to worry
|
||||||
|
about this option, because it is disregarded if the global mode
|
||||||
|
is enabled."
|
||||||
|
:package-version '(magit . "2.4.2")
|
||||||
|
:group 'auto-revert
|
||||||
|
:group 'magit-auto-revert
|
||||||
|
:group 'magit-related
|
||||||
|
:type '(radio (const :tag "No filter" nil)
|
||||||
|
(function-item magit-auto-revert-buffer-p)
|
||||||
|
(function-item magit-auto-revert-repository-buffer-p)
|
||||||
|
function))
|
||||||
|
|
||||||
|
(defcustom magit-auto-revert-tracked-only t
|
||||||
|
"Whether `magit-auto-revert-mode' only reverts tracked files."
|
||||||
|
:package-version '(magit . "2.4.0")
|
||||||
|
:group 'magit-auto-revert
|
||||||
|
:type 'boolean
|
||||||
|
:set (lambda (var val)
|
||||||
|
(set var val)
|
||||||
|
(when (and (bound-and-true-p magit-auto-revert-mode)
|
||||||
|
(featurep 'magit-autorevert))
|
||||||
|
(magit-auto-revert-mode -1)
|
||||||
|
(magit-auto-revert-mode))))
|
||||||
|
|
||||||
|
(defcustom magit-auto-revert-immediately t
|
||||||
|
"Whether Magit reverts buffers immediately.
|
||||||
|
|
||||||
|
If this is non-nil and either `global-auto-revert-mode' or
|
||||||
|
`magit-auto-revert-mode' is enabled, then Magit immediately
|
||||||
|
reverts buffers by explicitly calling `auto-revert-buffers'
|
||||||
|
after running Git for side-effects.
|
||||||
|
|
||||||
|
If `auto-revert-use-notify' is non-nil (and file notifications
|
||||||
|
are actually supported), then `magit-auto-revert-immediately'
|
||||||
|
does not have to be non-nil, because the reverts happen
|
||||||
|
immediately anyway.
|
||||||
|
|
||||||
|
If `magit-auto-revert-immediately' and `auto-revert-use-notify'
|
||||||
|
are both nil, then reverts happen after `auto-revert-interval'
|
||||||
|
seconds of user inactivity. That is not desirable."
|
||||||
|
:package-version '(magit . "2.4.0")
|
||||||
|
:group 'magit-auto-revert
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
;;; Mode
|
||||||
|
|
||||||
|
(defun magit-turn-on-auto-revert-mode-if-desired (&optional file)
|
||||||
|
(if file
|
||||||
|
(--when-let (find-buffer-visiting file)
|
||||||
|
(with-current-buffer it
|
||||||
|
(magit-turn-on-auto-revert-mode-if-desired)))
|
||||||
|
(when (and buffer-file-name
|
||||||
|
(file-readable-p buffer-file-name)
|
||||||
|
(magit-toplevel)
|
||||||
|
(or (not magit-auto-revert-tracked-only)
|
||||||
|
(magit-file-tracked-p buffer-file-name))
|
||||||
|
(not auto-revert-mode) ; see #3014
|
||||||
|
(not global-auto-revert-mode)) ; see #3460
|
||||||
|
(auto-revert-mode 1))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(define-globalized-minor-mode magit-auto-revert-mode auto-revert-mode
|
||||||
|
magit-turn-on-auto-revert-mode-if-desired
|
||||||
|
:package-version '(magit . "2.4.0")
|
||||||
|
:link '(info-link "(magit)Automatic Reverting of File-Visiting Buffers")
|
||||||
|
:group 'magit-auto-revert
|
||||||
|
:group 'magit-essentials
|
||||||
|
;; - When `global-auto-revert-mode' is enabled, then this mode is
|
||||||
|
;; redundant.
|
||||||
|
;; - In all other cases enable the mode because if buffers are not
|
||||||
|
;; automatically reverted that would make many very common tasks
|
||||||
|
;; much more cumbersome.
|
||||||
|
:init-value (not (or global-auto-revert-mode
|
||||||
|
noninteractive)))
|
||||||
|
;; - Unfortunately `:init-value t' only sets the value of the mode
|
||||||
|
;; variable but does not cause the mode function to be called.
|
||||||
|
;; - I don't think it works like this on purpose, but since one usually
|
||||||
|
;; should not enable global modes by default, it is understandable.
|
||||||
|
;; - If the user has set the variable `magit-auto-revert-mode' to nil
|
||||||
|
;; after loading magit (instead of doing so before loading magit or
|
||||||
|
;; by using the function), then we should still respect that setting.
|
||||||
|
;; - If the user sets one of these variables after loading magit and
|
||||||
|
;; after `after-init-hook' has run, then that won't have an effect
|
||||||
|
;; and there is nothing we can do about it.
|
||||||
|
(defun magit-auto-revert-mode--init-kludge ()
|
||||||
|
"This is an internal kludge to be used on `after-init-hook'.
|
||||||
|
Do not use this function elsewhere, and don't remove it from
|
||||||
|
the `after-init-hook'. For more information see the comments
|
||||||
|
and code surrounding the definition of this function."
|
||||||
|
(if magit-auto-revert-mode
|
||||||
|
(let ((start (current-time)))
|
||||||
|
(magit-message "Turning on magit-auto-revert-mode...")
|
||||||
|
(magit-auto-revert-mode 1)
|
||||||
|
(magit-message
|
||||||
|
"Turning on magit-auto-revert-mode...done%s"
|
||||||
|
(let ((elapsed (float-time (time-subtract nil start))))
|
||||||
|
(if (> elapsed 0.2)
|
||||||
|
(format " (%.3fs, %s buffers checked)" elapsed
|
||||||
|
(length (buffer-list)))
|
||||||
|
""))))
|
||||||
|
(magit-auto-revert-mode -1)))
|
||||||
|
(if after-init-time
|
||||||
|
;; Since `after-init-hook' has already been
|
||||||
|
;; run, turn the mode on or off right now.
|
||||||
|
(magit-auto-revert-mode--init-kludge)
|
||||||
|
;; By the time the init file has been fully loaded the
|
||||||
|
;; values of the relevant variables might have changed.
|
||||||
|
(add-hook 'after-init-hook #'magit-auto-revert-mode--init-kludge t))
|
||||||
|
|
||||||
|
(put 'magit-auto-revert-mode 'function-documentation
|
||||||
|
"Toggle Magit Auto Revert mode.
|
||||||
|
If called interactively, enable Magit Auto Revert mode if ARG is
|
||||||
|
positive, and disable it if ARG is zero or negative. If called
|
||||||
|
from Lisp, also enable the mode if ARG is omitted or nil, and
|
||||||
|
toggle it if ARG is `toggle'; disable the mode otherwise.
|
||||||
|
|
||||||
|
Magit Auto Revert mode is a global minor mode that reverts
|
||||||
|
buffers associated with a file that is located inside a Git
|
||||||
|
repository when the file changes on disk. Use `auto-revert-mode'
|
||||||
|
to revert a particular buffer. Or use `global-auto-revert-mode'
|
||||||
|
to revert all file-visiting buffers, not just those that visit
|
||||||
|
a file located inside a Git repository.
|
||||||
|
|
||||||
|
This global mode works by turning on the buffer-local mode
|
||||||
|
`auto-revert-mode' at the time a buffer is first created. The
|
||||||
|
local mode is turned on if the visited file is being tracked in
|
||||||
|
a Git repository at the time when the buffer is created.
|
||||||
|
|
||||||
|
If `magit-auto-revert-tracked-only' is non-nil (the default),
|
||||||
|
then only tracked files are reverted. But if you stage a
|
||||||
|
previously untracked file using `magit-stage', then this mode
|
||||||
|
notices that.
|
||||||
|
|
||||||
|
Unlike `global-auto-revert-mode', this mode never reverts any
|
||||||
|
buffers that are not visiting files.
|
||||||
|
|
||||||
|
The behavior of this mode can be customized using the options
|
||||||
|
in the `autorevert' and `magit-autorevert' groups.
|
||||||
|
|
||||||
|
This function calls the hook `magit-auto-revert-mode-hook'.")
|
||||||
|
|
||||||
|
(defun magit-auto-revert-buffers ()
|
||||||
|
(when (and magit-auto-revert-immediately
|
||||||
|
(or global-auto-revert-mode
|
||||||
|
(and magit-auto-revert-mode auto-revert-buffer-list)))
|
||||||
|
(let ((auto-revert-buffer-list-filter
|
||||||
|
(or auto-revert-buffer-list-filter
|
||||||
|
#'magit-auto-revert-repository-buffer-p)))
|
||||||
|
(auto-revert-buffers))))
|
||||||
|
|
||||||
|
(defvar magit-auto-revert-toplevel nil)
|
||||||
|
|
||||||
|
(defvar magit-auto-revert-counter 1
|
||||||
|
"Incremented each time `auto-revert-buffers' is called.")
|
||||||
|
|
||||||
|
(defun magit-auto-revert-buffer-p (buffer)
|
||||||
|
"Return non-nil if BUFFER visits a file inside the current repository.
|
||||||
|
The current repository is the one containing `default-directory'.
|
||||||
|
If there is no current repository, then return t for any BUFFER."
|
||||||
|
(magit-auto-revert-repository-buffer-p buffer t))
|
||||||
|
|
||||||
|
(defun magit-auto-revert-repository-buffer-p (buffer &optional fallback)
|
||||||
|
"Return non-nil if BUFFER visits a file inside the current repository.
|
||||||
|
The current repository is the one containing `default-directory'.
|
||||||
|
If there is no current repository, then return FALLBACK (which
|
||||||
|
defaults to nil) for any BUFFER."
|
||||||
|
;; Call `magit-toplevel' just once per cycle.
|
||||||
|
(unless (and magit-auto-revert-toplevel
|
||||||
|
(= (cdr magit-auto-revert-toplevel)
|
||||||
|
magit-auto-revert-counter))
|
||||||
|
(setq magit-auto-revert-toplevel
|
||||||
|
(cons (or (magit-toplevel) 'no-repo)
|
||||||
|
magit-auto-revert-counter)))
|
||||||
|
(let ((top (car magit-auto-revert-toplevel)))
|
||||||
|
(if (eq top 'no-repo)
|
||||||
|
fallback
|
||||||
|
(let ((dir (buffer-local-value 'default-directory buffer)))
|
||||||
|
(and (equal (file-remote-p dir)
|
||||||
|
(file-remote-p top))
|
||||||
|
;; ^ `tramp-handle-file-in-directory-p' lacks this optimization.
|
||||||
|
(file-in-directory-p dir top))))))
|
||||||
|
|
||||||
|
(defun auto-revert-buffers--buffer-list-filter (fn)
|
||||||
|
(cl-incf magit-auto-revert-counter)
|
||||||
|
(if (or global-auto-revert-mode
|
||||||
|
(not auto-revert-buffer-list)
|
||||||
|
(not auto-revert-buffer-list-filter))
|
||||||
|
(funcall fn)
|
||||||
|
(let ((auto-revert-buffer-list
|
||||||
|
(-filter auto-revert-buffer-list-filter
|
||||||
|
auto-revert-buffer-list)))
|
||||||
|
(funcall fn))
|
||||||
|
(unless auto-revert-timer
|
||||||
|
(auto-revert-set-timer))))
|
||||||
|
|
||||||
|
(advice-add 'auto-revert-buffers :around
|
||||||
|
'auto-revert-buffers--buffer-list-filter)
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-autorevert)
|
||||||
|
;;; magit-autorevert.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-autorevert.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-autorevert.elc
Normal file
Binary file not shown.
239
elpa/magit-20191030.1315/magit-bisect.el
Normal file
239
elpa/magit-20191030.1315/magit-bisect.el
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
;;; magit-bisect.el --- bisect support for Magit -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2011-2019 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:
|
||||||
|
|
||||||
|
;; Use a binary search to find the commit that introduced a bug.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defcustom magit-bisect-show-graph t
|
||||||
|
"Whether to use `--graph' in the log showing commits yet to be bisected."
|
||||||
|
:package-version '(magit . "2.8.0")
|
||||||
|
:group 'magit-status
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defface magit-bisect-good
|
||||||
|
'((t :foreground "DarkOliveGreen"))
|
||||||
|
"Face for good bisect revisions."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-bisect-skip
|
||||||
|
'((t :foreground "DarkGoldenrod"))
|
||||||
|
"Face for skipped bisect revisions."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-bisect-bad
|
||||||
|
'((t :foreground "IndianRed4"))
|
||||||
|
"Face for bad bisect revisions."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-bisect "magit-bisect" nil t)
|
||||||
|
(define-transient-command magit-bisect ()
|
||||||
|
"Narrow in on the commit that introduced a bug."
|
||||||
|
:man-page "git-bisect"
|
||||||
|
["Actions"
|
||||||
|
:if-not magit-bisect-in-progress-p
|
||||||
|
("B" "Start" magit-bisect-start)
|
||||||
|
("s" "Start script" magit-bisect-run)]
|
||||||
|
["Actions"
|
||||||
|
:if magit-bisect-in-progress-p
|
||||||
|
("B" "Bad" magit-bisect-bad)
|
||||||
|
("g" "Good" magit-bisect-good)
|
||||||
|
("k" "Skip" magit-bisect-skip)
|
||||||
|
("r" "Reset" magit-bisect-reset)
|
||||||
|
("s" "Run script" magit-bisect-run)])
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-bisect-start (bad good)
|
||||||
|
"Start a bisect session.
|
||||||
|
|
||||||
|
Bisecting a bug means to find the commit that introduced it.
|
||||||
|
This command starts such a bisect session by asking for a know
|
||||||
|
good and a bad commit. To move the session forward use the
|
||||||
|
other actions from the bisect transient command (\
|
||||||
|
\\<magit-status-mode-map>\\[magit-bisect])."
|
||||||
|
(interactive (if (magit-bisect-in-progress-p)
|
||||||
|
(user-error "Already bisecting")
|
||||||
|
(magit-bisect-start-read-args)))
|
||||||
|
(unless (magit-rev-ancestor-p good bad)
|
||||||
|
(user-error
|
||||||
|
"The good revision (%s) has to be an ancestor of the bad one (%s)"
|
||||||
|
good bad))
|
||||||
|
(when (magit-anything-modified-p)
|
||||||
|
(user-error "Cannot bisect with uncommitted changes"))
|
||||||
|
(magit-git-bisect "start" (list bad good) t))
|
||||||
|
|
||||||
|
(defun magit-bisect-start-read-args ()
|
||||||
|
(let ((b (magit-read-branch-or-commit "Start bisect with bad revision")))
|
||||||
|
(list b (magit-read-other-branch-or-commit "Good revision" b))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-bisect-reset ()
|
||||||
|
"After bisecting, cleanup bisection state and return to original `HEAD'."
|
||||||
|
(interactive)
|
||||||
|
(magit-confirm 'reset-bisect)
|
||||||
|
(magit-run-git "bisect" "reset")
|
||||||
|
(ignore-errors (delete-file (magit-git-dir "BISECT_CMD_OUTPUT"))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-bisect-good ()
|
||||||
|
"While bisecting, mark the current commit as good.
|
||||||
|
Use this after you have asserted that the commit does not contain
|
||||||
|
the bug in question."
|
||||||
|
(interactive)
|
||||||
|
(magit-git-bisect "good"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-bisect-bad ()
|
||||||
|
"While bisecting, mark the current commit as bad.
|
||||||
|
Use this after you have asserted that the commit does contain the
|
||||||
|
bug in question."
|
||||||
|
(interactive)
|
||||||
|
(magit-git-bisect "bad"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-bisect-skip ()
|
||||||
|
"While bisecting, skip the current commit.
|
||||||
|
Use this if for some reason the current commit is not a good one
|
||||||
|
to test. This command lets Git choose a different one."
|
||||||
|
(interactive)
|
||||||
|
(magit-git-bisect "skip"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-bisect-run (cmdline &optional bad good)
|
||||||
|
"Bisect automatically by running commands after each step.
|
||||||
|
|
||||||
|
Unlike `git bisect run' this can be used before bisecting has
|
||||||
|
begun. In that case it behaves like `git bisect start; git
|
||||||
|
bisect run'."
|
||||||
|
(interactive (let ((args (and (not (magit-bisect-in-progress-p))
|
||||||
|
(magit-bisect-start-read-args))))
|
||||||
|
(cons (read-shell-command "Bisect shell command: ") args)))
|
||||||
|
(when (and bad good)
|
||||||
|
(magit-bisect-start bad good))
|
||||||
|
(magit-git-bisect "run" (list shell-file-name shell-command-switch cmdline)))
|
||||||
|
|
||||||
|
(defun magit-git-bisect (subcommand &optional args no-assert)
|
||||||
|
(unless (or no-assert (magit-bisect-in-progress-p))
|
||||||
|
(user-error "Not bisecting"))
|
||||||
|
(message "Bisecting...")
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git-async "bisect" subcommand args))
|
||||||
|
(set-process-sentinel
|
||||||
|
magit-this-process
|
||||||
|
(lambda (process event)
|
||||||
|
(when (memq (process-status process) '(exit signal))
|
||||||
|
(if (> (process-exit-status process) 0)
|
||||||
|
(magit-process-sentinel process event)
|
||||||
|
(process-put process 'inhibit-refresh t)
|
||||||
|
(magit-process-sentinel process event)
|
||||||
|
(when (buffer-live-p (process-buffer process))
|
||||||
|
(with-current-buffer (process-buffer process)
|
||||||
|
(when-let ((section (get-text-property (point) 'magit-section))
|
||||||
|
(output (buffer-substring-no-properties
|
||||||
|
(oref section content)
|
||||||
|
(oref section end))))
|
||||||
|
(with-temp-file (magit-git-dir "BISECT_CMD_OUTPUT")
|
||||||
|
(insert output)))))
|
||||||
|
(magit-refresh))
|
||||||
|
(message "Bisecting...done")))))
|
||||||
|
|
||||||
|
;;; Sections
|
||||||
|
|
||||||
|
(defun magit-bisect-in-progress-p ()
|
||||||
|
(file-exists-p (magit-git-dir "BISECT_LOG")))
|
||||||
|
|
||||||
|
(defun magit-insert-bisect-output ()
|
||||||
|
"While bisecting, insert section with output from `git bisect'."
|
||||||
|
(when (magit-bisect-in-progress-p)
|
||||||
|
(let* ((lines
|
||||||
|
(or (magit-file-lines (magit-git-dir "BISECT_CMD_OUTPUT"))
|
||||||
|
(list "Bisecting: (no saved bisect output)"
|
||||||
|
"It appears you have invoked `git bisect' from a shell."
|
||||||
|
"There is nothing wrong with that, we just cannot display"
|
||||||
|
"anything useful here. Consult the shell output instead.")))
|
||||||
|
(done-re "^\\([a-z0-9]\\{40\\}\\) is the first bad commit$")
|
||||||
|
(bad-line (or (and (string-match done-re (car lines))
|
||||||
|
(pop lines))
|
||||||
|
(--first (string-match done-re it) lines))))
|
||||||
|
(magit-insert-section ((eval (if bad-line 'commit 'bisect-output))
|
||||||
|
(and bad-line (match-string 1 bad-line)))
|
||||||
|
(magit-insert-heading
|
||||||
|
(propertize (or bad-line (pop lines))
|
||||||
|
'font-lock-face 'magit-section-heading))
|
||||||
|
(dolist (line lines)
|
||||||
|
(insert line "\n"))))
|
||||||
|
(insert "\n")))
|
||||||
|
|
||||||
|
(defun magit-insert-bisect-rest ()
|
||||||
|
"While bisecting, insert section visualizing the bisect state."
|
||||||
|
(when (magit-bisect-in-progress-p)
|
||||||
|
(magit-insert-section (bisect-view)
|
||||||
|
(magit-insert-heading "Bisect Rest:")
|
||||||
|
(magit-git-wash (apply-partially 'magit-log-wash-log 'bisect-vis)
|
||||||
|
"bisect" "visualize" "git" "log"
|
||||||
|
"--format=%h%x00%D%x00%s" "--decorate=full"
|
||||||
|
(and magit-bisect-show-graph "--graph")))))
|
||||||
|
|
||||||
|
(defun magit-insert-bisect-log ()
|
||||||
|
"While bisecting, insert section logging bisect progress."
|
||||||
|
(when (magit-bisect-in-progress-p)
|
||||||
|
(magit-insert-section (bisect-log)
|
||||||
|
(magit-insert-heading "Bisect Log:")
|
||||||
|
(magit-git-wash #'magit-wash-bisect-log "bisect" "log")
|
||||||
|
(insert ?\n))))
|
||||||
|
|
||||||
|
(defun magit-wash-bisect-log (_args)
|
||||||
|
(let (beg)
|
||||||
|
(while (progn (setq beg (point-marker))
|
||||||
|
(re-search-forward "^\\(git bisect [^\n]+\n\\)" nil t))
|
||||||
|
(magit-bind-match-strings (heading) nil
|
||||||
|
(magit-delete-match)
|
||||||
|
(save-restriction
|
||||||
|
(narrow-to-region beg (point))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(magit-insert-section (bisect-item heading t)
|
||||||
|
(insert (propertize heading 'font-lock-face
|
||||||
|
'magit-section-secondary-heading))
|
||||||
|
(magit-insert-heading)
|
||||||
|
(magit-wash-sequence
|
||||||
|
(apply-partially 'magit-log-wash-rev 'bisect-log
|
||||||
|
(magit-abbrev-length)))
|
||||||
|
(insert ?\n)))))
|
||||||
|
(when (re-search-forward
|
||||||
|
"# first bad commit: \\[\\([a-z0-9]\\{40\\}\\)\\] [^\n]+\n" nil t)
|
||||||
|
(magit-bind-match-strings (hash) nil
|
||||||
|
(magit-delete-match)
|
||||||
|
(magit-insert-section (bisect-item)
|
||||||
|
(insert hash " is the first bad commit\n"))))))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-bisect)
|
||||||
|
;;; magit-bisect.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-bisect.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-bisect.elc
Normal file
Binary file not shown.
948
elpa/magit-20191030.1315/magit-blame.el
Normal file
948
elpa/magit-20191030.1315/magit-blame.el
Normal file
@@ -0,0 +1,948 @@
|
|||||||
|
;;; magit-blame.el --- blame support for Magit -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2012-2019 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:
|
||||||
|
|
||||||
|
;; Annotates each line in file-visiting buffer with information from
|
||||||
|
;; the revision which last modified the line.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'subr-x))
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defgroup magit-blame nil
|
||||||
|
"Blame support for Magit."
|
||||||
|
:link '(info-link "(magit)Blaming")
|
||||||
|
:group 'magit-modes)
|
||||||
|
|
||||||
|
(defcustom magit-blame-styles
|
||||||
|
'((headings
|
||||||
|
(heading-format . "%-20a %C %s\n"))
|
||||||
|
(margin
|
||||||
|
(margin-format . (" %s%f" " %C %a" " %H"))
|
||||||
|
(margin-width . 42)
|
||||||
|
(margin-face . magit-blame-margin)
|
||||||
|
(margin-body-face . (magit-blame-dimmed)))
|
||||||
|
(highlight
|
||||||
|
(highlight-face . magit-blame-highlight))
|
||||||
|
(lines
|
||||||
|
(show-lines . t)
|
||||||
|
(show-message . t)))
|
||||||
|
"List of styles used to visualize blame information.
|
||||||
|
|
||||||
|
Each entry has the form (IDENT (KEY . VALUE)...). IDENT has
|
||||||
|
to be a symbol uniquely identifing the style. The following
|
||||||
|
KEYs are recognized:
|
||||||
|
|
||||||
|
`show-lines'
|
||||||
|
Whether to prefix each chunk of lines with a thin line.
|
||||||
|
This has no effect if `heading-format' is non-nil.
|
||||||
|
`show-message'
|
||||||
|
Whether to display a commit's summary line in the echo area
|
||||||
|
when crossing chunks.
|
||||||
|
`highlight-face'
|
||||||
|
Face used to highlight the first line of each chunk.
|
||||||
|
If this is nil, then those lines are not highlighted.
|
||||||
|
`heading-format'
|
||||||
|
String specifying the information to be shown above each
|
||||||
|
chunk of lines. It must end with a newline character.
|
||||||
|
`margin-format'
|
||||||
|
String specifying the information to be shown in the left
|
||||||
|
buffer margin. It must NOT end with a newline character.
|
||||||
|
This can also be a list of formats used for the lines at
|
||||||
|
the same positions within the chunk. If the chunk has
|
||||||
|
more lines than formats are specified, then the last is
|
||||||
|
repeated.
|
||||||
|
`margin-width'
|
||||||
|
Width of the margin, provided `margin-format' is non-nil.
|
||||||
|
`margin-face'
|
||||||
|
Face used in the margin, provided `margin-format' is
|
||||||
|
non-nil. This face is used in combination with the faces
|
||||||
|
that are specific to the used %-specs. If this is nil,
|
||||||
|
then `magit-blame-margin' is used.
|
||||||
|
`margin-body-face'
|
||||||
|
Face used in the margin for all but first line of a chunk.
|
||||||
|
This face is used in combination with the faces that are
|
||||||
|
specific to the used %-specs. This can also be a list of
|
||||||
|
faces (usually one face), in which case only these faces
|
||||||
|
are used and the %-spec faces are ignored. A good value
|
||||||
|
might be `(magit-blame-dimmed)'. If this is nil, then
|
||||||
|
the same face as for the first line is used.
|
||||||
|
|
||||||
|
The following %-specs can be used in `heading-format' and
|
||||||
|
`margin-format':
|
||||||
|
|
||||||
|
%H hash using face `magit-blame-hash'
|
||||||
|
%s summary using face `magit-blame-summary'
|
||||||
|
%a author using face `magit-blame-name'
|
||||||
|
%A author time using face `magit-blame-date'
|
||||||
|
%c committer using face `magit-blame-name'
|
||||||
|
%C committer time using face `magit-blame-date'
|
||||||
|
|
||||||
|
Additionally if `margin-format' ends with %f, then the string
|
||||||
|
that is displayed in the margin is made at least `margin-width'
|
||||||
|
characters wide, which may be desirable if the used face sets
|
||||||
|
the background color.
|
||||||
|
|
||||||
|
The style used in the current buffer can be cycled from the blame
|
||||||
|
popup. Blame commands (except `magit-blame-echo') use the first
|
||||||
|
style as the initial style when beginning to blame in a buffer."
|
||||||
|
:package-version '(magit . "2.13.0")
|
||||||
|
:group 'magit-blame
|
||||||
|
:type 'string)
|
||||||
|
|
||||||
|
(defcustom magit-blame-echo-style 'lines
|
||||||
|
"The blame visualization style used by `magit-blame-echo'.
|
||||||
|
A symbol that has to be used as the identifier for one of the
|
||||||
|
styles defined in `magit-blame-styles'."
|
||||||
|
:package-version '(magit . "2.13.0")
|
||||||
|
:group 'magit-blame
|
||||||
|
:type 'symbol)
|
||||||
|
|
||||||
|
(defcustom magit-blame-time-format "%F %H:%M"
|
||||||
|
"Format for time strings in blame headings."
|
||||||
|
:group 'magit-blame
|
||||||
|
:type 'string)
|
||||||
|
|
||||||
|
(defcustom magit-blame-read-only t
|
||||||
|
"Whether to initially make the blamed buffer read-only."
|
||||||
|
:package-version '(magit . "2.13.0")
|
||||||
|
:group 'magit-blame
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-blame-disable-modes '(fci-mode yascroll-bar-mode)
|
||||||
|
"List of modes not compatible with Magit-Blame mode.
|
||||||
|
This modes are turned off when Magit-Blame mode is turned on,
|
||||||
|
and then turned on again when turning off the latter."
|
||||||
|
:group 'magit-blame
|
||||||
|
:type '(repeat (symbol :tag "Mode")))
|
||||||
|
|
||||||
|
(defcustom magit-blame-mode-lighter " Blame"
|
||||||
|
"The mode-line lighter of the Magit-Blame mode."
|
||||||
|
:group 'magit-blame
|
||||||
|
:type '(choice (const :tag "No lighter" "") string))
|
||||||
|
|
||||||
|
(defcustom magit-blame-goto-chunk-hook
|
||||||
|
'(magit-blame-maybe-update-revision-buffer
|
||||||
|
magit-blame-maybe-show-message)
|
||||||
|
"Hook run after point entered another chunk."
|
||||||
|
:package-version '(magit . "2.13.0")
|
||||||
|
:group 'magit-blame
|
||||||
|
:type 'hook
|
||||||
|
:get 'magit-hook-custom-get
|
||||||
|
:options '(magit-blame-maybe-update-revision-buffer
|
||||||
|
magit-blame-maybe-show-message))
|
||||||
|
|
||||||
|
;;; Faces
|
||||||
|
|
||||||
|
(defface magit-blame-highlight
|
||||||
|
'((((class color) (background light))
|
||||||
|
:background "grey80"
|
||||||
|
:foreground "black")
|
||||||
|
(((class color) (background dark))
|
||||||
|
:background "grey25"
|
||||||
|
:foreground "white"))
|
||||||
|
"Face used for highlighting when blaming.
|
||||||
|
Also see option `magit-blame-styles'."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-blame-margin
|
||||||
|
'((t :inherit magit-blame-highlight
|
||||||
|
:weight normal
|
||||||
|
:slant normal))
|
||||||
|
"Face used for the blame margin by default when blaming.
|
||||||
|
Also see option `magit-blame-styles'."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-blame-dimmed
|
||||||
|
'((t :inherit magit-dimmed
|
||||||
|
:weight normal
|
||||||
|
:slant normal))
|
||||||
|
"Face used for the blame margin in some cases when blaming.
|
||||||
|
Also see option `magit-blame-styles'."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-blame-heading
|
||||||
|
'((t :inherit magit-blame-highlight
|
||||||
|
:weight normal
|
||||||
|
:slant normal))
|
||||||
|
"Face used for blame headings by default when blaming.
|
||||||
|
Also see option `magit-blame-styles'."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-blame-summary nil
|
||||||
|
"Face used for commit summaries when blaming."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-blame-hash nil
|
||||||
|
"Face used for commit hashes when blaming."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-blame-name nil
|
||||||
|
"Face used for author and committer names when blaming."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
(defface magit-blame-date nil
|
||||||
|
"Face used for dates when blaming."
|
||||||
|
:group 'magit-faces)
|
||||||
|
|
||||||
|
;;; Chunks
|
||||||
|
|
||||||
|
(defclass magit-blame-chunk ()
|
||||||
|
(;; <orig-rev> <orig-line> <final-line> <num-lines>
|
||||||
|
(orig-rev :initarg :orig-rev)
|
||||||
|
(orig-line :initarg :orig-line)
|
||||||
|
(final-line :initarg :final-line)
|
||||||
|
(num-lines :initarg :num-lines)
|
||||||
|
;; previous <prev-rev> <prev-file>
|
||||||
|
(prev-rev :initform nil)
|
||||||
|
(prev-file :initform nil)
|
||||||
|
;; filename <orig-file>
|
||||||
|
(orig-file)))
|
||||||
|
|
||||||
|
(defun magit-current-blame-chunk (&optional type)
|
||||||
|
(or (and (not (and type (not (eq type magit-blame-type))))
|
||||||
|
(magit-blame-chunk-at (point)))
|
||||||
|
(and type
|
||||||
|
(let ((rev (or magit-buffer-refname magit-buffer-revision))
|
||||||
|
(file (magit-file-relative-name nil (not magit-buffer-file-name)))
|
||||||
|
(line (format "%i,+1" (line-number-at-pos))))
|
||||||
|
(unless file
|
||||||
|
(error "Buffer does not visit a tracked file"))
|
||||||
|
(with-temp-buffer
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-git-insert
|
||||||
|
"blame" "--porcelain"
|
||||||
|
(if (memq magit-blame-type '(final removal))
|
||||||
|
(cons "--reverse" (magit-blame-arguments))
|
||||||
|
(magit-blame-arguments))
|
||||||
|
"-L" line rev "--" file)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(car (magit-blame--parse-chunk type))))))))
|
||||||
|
|
||||||
|
(defun magit-blame-chunk-at (pos)
|
||||||
|
(--some (overlay-get it 'magit-blame-chunk)
|
||||||
|
(overlays-at pos)))
|
||||||
|
|
||||||
|
(defun magit-blame--overlay-at (&optional pos key)
|
||||||
|
(unless pos
|
||||||
|
(setq pos (point)))
|
||||||
|
(--first (overlay-get it (or key 'magit-blame-chunk))
|
||||||
|
(nconc (overlays-at pos)
|
||||||
|
(overlays-in pos pos))))
|
||||||
|
|
||||||
|
;;; Keymaps
|
||||||
|
|
||||||
|
(defvar magit-blame-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(define-key map (kbd "C-c C-q") 'magit-blame-quit)
|
||||||
|
map)
|
||||||
|
"Keymap for `magit-blame-mode'.
|
||||||
|
Note that most blaming key bindings are defined
|
||||||
|
in `magit-blame-read-only-mode-map' instead.")
|
||||||
|
|
||||||
|
(defvar magit-blame-read-only-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(cond ((featurep 'jkl)
|
||||||
|
(define-key map [return] 'magit-show-commit)
|
||||||
|
(define-key map (kbd "i") 'magit-blame-previous-chunk)
|
||||||
|
(define-key map (kbd "I") 'magit-blame-previous-chunk-same-commit)
|
||||||
|
(define-key map (kbd "k") 'magit-blame-next-chunk)
|
||||||
|
(define-key map (kbd "K") 'magit-blame-next-chunk-same-commit)
|
||||||
|
(define-key map (kbd "j") 'magit-blame-addition)
|
||||||
|
(define-key map (kbd "l") 'magit-blame-removal)
|
||||||
|
(define-key map (kbd "f") 'magit-blame-reverse)
|
||||||
|
(define-key map (kbd "b") 'magit-blame))
|
||||||
|
(t
|
||||||
|
(define-key map (kbd "C-m") 'magit-show-commit)
|
||||||
|
(define-key map (kbd "p") 'magit-blame-previous-chunk)
|
||||||
|
(define-key map (kbd "P") 'magit-blame-previous-chunk-same-commit)
|
||||||
|
(define-key map (kbd "n") 'magit-blame-next-chunk)
|
||||||
|
(define-key map (kbd "N") 'magit-blame-next-chunk-same-commit)
|
||||||
|
(define-key map (kbd "b") 'magit-blame-addition)
|
||||||
|
(define-key map (kbd "r") 'magit-blame-removal)
|
||||||
|
(define-key map (kbd "f") 'magit-blame-reverse)
|
||||||
|
(define-key map (kbd "B") 'magit-blame)))
|
||||||
|
(define-key map (kbd "c") 'magit-blame-cycle-style)
|
||||||
|
(define-key map (kbd "q") 'magit-blame-quit)
|
||||||
|
(define-key map (kbd "M-w") 'magit-blame-copy-hash)
|
||||||
|
(define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up)
|
||||||
|
(define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down)
|
||||||
|
map)
|
||||||
|
"Keymap for `magit-blame-read-only-mode'.")
|
||||||
|
|
||||||
|
;;; Modes
|
||||||
|
;;;; Variables
|
||||||
|
|
||||||
|
(defvar-local magit-blame-buffer-read-only nil)
|
||||||
|
(defvar-local magit-blame-cache nil)
|
||||||
|
(defvar-local magit-blame-disabled-modes nil)
|
||||||
|
(defvar-local magit-blame-process nil)
|
||||||
|
(defvar-local magit-blame-recursive-p nil)
|
||||||
|
(defvar-local magit-blame-type nil)
|
||||||
|
(defvar-local magit-blame-separator nil)
|
||||||
|
(defvar-local magit-blame-previous-chunk nil)
|
||||||
|
|
||||||
|
(defvar-local magit-blame--style nil)
|
||||||
|
|
||||||
|
(defsubst magit-blame--style-get (key)
|
||||||
|
(cdr (assoc key (cdr magit-blame--style))))
|
||||||
|
|
||||||
|
;;;; Base Mode
|
||||||
|
|
||||||
|
(define-minor-mode magit-blame-mode
|
||||||
|
"Display blame information inline."
|
||||||
|
:lighter magit-blame-mode-lighter
|
||||||
|
(cond (magit-blame-mode
|
||||||
|
(when (called-interactively-p 'any)
|
||||||
|
(setq magit-blame-mode nil)
|
||||||
|
(user-error
|
||||||
|
(concat "Don't call `magit-blame-mode' directly; "
|
||||||
|
"instead use `magit-blame'")))
|
||||||
|
(add-hook 'after-save-hook 'magit-blame--run t t)
|
||||||
|
(add-hook 'post-command-hook 'magit-blame-goto-chunk-hook t t)
|
||||||
|
(add-hook 'before-revert-hook 'magit-blame--remove-overlays t t)
|
||||||
|
(add-hook 'after-revert-hook 'magit-blame--run t t)
|
||||||
|
(add-hook 'read-only-mode-hook 'magit-blame-toggle-read-only t t)
|
||||||
|
(setq magit-blame-buffer-read-only buffer-read-only)
|
||||||
|
(when (or magit-blame-read-only magit-buffer-file-name)
|
||||||
|
(read-only-mode 1))
|
||||||
|
(dolist (mode magit-blame-disable-modes)
|
||||||
|
(when (and (boundp mode) (symbol-value mode))
|
||||||
|
(funcall mode -1)
|
||||||
|
(push mode magit-blame-disabled-modes)))
|
||||||
|
(setq magit-blame-separator (magit-blame--format-separator))
|
||||||
|
(unless magit-blame--style
|
||||||
|
(setq magit-blame--style (car magit-blame-styles)))
|
||||||
|
(magit-blame--update-margin))
|
||||||
|
(t
|
||||||
|
(when (process-live-p magit-blame-process)
|
||||||
|
(kill-process magit-blame-process)
|
||||||
|
(while magit-blame-process
|
||||||
|
(sit-for 0.01))) ; avoid racing the sentinal
|
||||||
|
(remove-hook 'after-save-hook 'magit-blame--run t)
|
||||||
|
(remove-hook 'post-command-hook 'magit-blame-goto-chunk-hook t)
|
||||||
|
(remove-hook 'before-revert-hook 'magit-blame--remove-overlays t)
|
||||||
|
(remove-hook 'after-revert-hook 'magit-blame--run t)
|
||||||
|
(remove-hook 'read-only-mode-hook 'magit-blame-toggle-read-only t)
|
||||||
|
(unless magit-blame-buffer-read-only
|
||||||
|
(read-only-mode -1))
|
||||||
|
(magit-blame-read-only-mode -1)
|
||||||
|
(dolist (mode magit-blame-disabled-modes)
|
||||||
|
(funcall mode 1))
|
||||||
|
(kill-local-variable 'magit-blame-disabled-modes)
|
||||||
|
(kill-local-variable 'magit-blame-type)
|
||||||
|
(kill-local-variable 'magit-blame--style)
|
||||||
|
(magit-blame--update-margin)
|
||||||
|
(magit-blame--remove-overlays))))
|
||||||
|
|
||||||
|
(defun magit-blame-goto-chunk-hook ()
|
||||||
|
(let ((chunk (magit-blame-chunk-at (point))))
|
||||||
|
(when (cl-typep chunk 'magit-blame-chunk)
|
||||||
|
(unless (eq chunk magit-blame-previous-chunk)
|
||||||
|
(run-hooks 'magit-blame-goto-chunk-hook))
|
||||||
|
(setq magit-blame-previous-chunk chunk))))
|
||||||
|
|
||||||
|
(defun magit-blame-toggle-read-only ()
|
||||||
|
(magit-blame-read-only-mode (if buffer-read-only 1 -1)))
|
||||||
|
|
||||||
|
;;;; Read-Only Mode
|
||||||
|
|
||||||
|
(define-minor-mode magit-blame-read-only-mode
|
||||||
|
"Provide keybindings for Magit-Blame mode.
|
||||||
|
|
||||||
|
This minor-mode provides the key bindings for Magit-Blame mode,
|
||||||
|
but only when Read-Only mode is also enabled because these key
|
||||||
|
bindings would otherwise conflict badly with regular bindings.
|
||||||
|
|
||||||
|
When both Magit-Blame mode and Read-Only mode are enabled, then
|
||||||
|
this mode gets automatically enabled too and when one of these
|
||||||
|
modes is toggled, then this mode also gets toggled automatically.
|
||||||
|
|
||||||
|
\\{magit-blame-read-only-mode-map}")
|
||||||
|
|
||||||
|
;;;; Kludges
|
||||||
|
|
||||||
|
(defun magit-blame-put-keymap-before-view-mode ()
|
||||||
|
"Put `magit-blame-read-only-mode' ahead of `view-mode' in `minor-mode-map-alist'."
|
||||||
|
(--when-let (assq 'magit-blame-read-only-mode
|
||||||
|
(cl-member 'view-mode minor-mode-map-alist :key #'car))
|
||||||
|
(setq minor-mode-map-alist
|
||||||
|
(cons it (delq it minor-mode-map-alist))))
|
||||||
|
(remove-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode))
|
||||||
|
|
||||||
|
(add-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode)
|
||||||
|
|
||||||
|
;;; Process
|
||||||
|
|
||||||
|
(defun magit-blame--run (args)
|
||||||
|
(magit-with-toplevel
|
||||||
|
(unless magit-blame-mode
|
||||||
|
(magit-blame-mode 1))
|
||||||
|
(message "Blaming...")
|
||||||
|
(magit-blame-run-process
|
||||||
|
(or magit-buffer-refname magit-buffer-revision)
|
||||||
|
(magit-file-relative-name nil (not magit-buffer-file-name))
|
||||||
|
(if (memq magit-blame-type '(final removal))
|
||||||
|
(cons "--reverse" args)
|
||||||
|
args)
|
||||||
|
(list (line-number-at-pos (window-start))
|
||||||
|
(line-number-at-pos (1- (window-end nil t)))))
|
||||||
|
(set-process-sentinel magit-this-process
|
||||||
|
'magit-blame-process-quickstart-sentinel)))
|
||||||
|
|
||||||
|
(defun magit-blame-run-process (revision file args &optional lines)
|
||||||
|
(let ((process (magit-parse-git-async
|
||||||
|
"blame" "--incremental" args
|
||||||
|
(and lines (list "-L" (apply #'format "%s,%s" lines)))
|
||||||
|
revision "--" file)))
|
||||||
|
(set-process-filter process 'magit-blame-process-filter)
|
||||||
|
(set-process-sentinel process 'magit-blame-process-sentinel)
|
||||||
|
(process-put process 'arguments (list revision file args))
|
||||||
|
(setq magit-blame-cache (make-hash-table :test 'equal))
|
||||||
|
(setq magit-blame-process process)))
|
||||||
|
|
||||||
|
(defun magit-blame-process-quickstart-sentinel (process event)
|
||||||
|
(when (memq (process-status process) '(exit signal))
|
||||||
|
(magit-blame-process-sentinel process event t)
|
||||||
|
(magit-blame-assert-buffer process)
|
||||||
|
(with-current-buffer (process-get process 'command-buf)
|
||||||
|
(when magit-blame-mode
|
||||||
|
(let ((default-directory (magit-toplevel)))
|
||||||
|
(apply #'magit-blame-run-process
|
||||||
|
(process-get process 'arguments)))))))
|
||||||
|
|
||||||
|
(defun magit-blame-process-sentinel (process _event &optional quiet)
|
||||||
|
(let ((status (process-status process)))
|
||||||
|
(when (memq status '(exit signal))
|
||||||
|
(kill-buffer (process-buffer process))
|
||||||
|
(if (and (eq status 'exit)
|
||||||
|
(zerop (process-exit-status process)))
|
||||||
|
(unless quiet
|
||||||
|
(message "Blaming...done"))
|
||||||
|
(magit-blame-assert-buffer process)
|
||||||
|
(with-current-buffer (process-get process 'command-buf)
|
||||||
|
(if magit-blame-mode
|
||||||
|
(progn (magit-blame-mode -1)
|
||||||
|
(message "Blaming...failed"))
|
||||||
|
(message "Blaming...aborted"))))
|
||||||
|
(kill-local-variable 'magit-blame-process))))
|
||||||
|
|
||||||
|
(defun magit-blame-process-filter (process string)
|
||||||
|
(internal-default-process-filter process string)
|
||||||
|
(let ((buf (process-get process 'command-buf))
|
||||||
|
(pos (process-get process 'parsed))
|
||||||
|
(mark (process-mark process))
|
||||||
|
type cache)
|
||||||
|
(with-current-buffer buf
|
||||||
|
(setq type magit-blame-type)
|
||||||
|
(setq cache magit-blame-cache))
|
||||||
|
(with-current-buffer (process-buffer process)
|
||||||
|
(goto-char pos)
|
||||||
|
(while (and (< (point) mark)
|
||||||
|
(save-excursion (re-search-forward "^filename .+\n" nil t)))
|
||||||
|
(pcase-let* ((`(,chunk ,revinfo)
|
||||||
|
(magit-blame--parse-chunk type))
|
||||||
|
(rev (oref chunk orig-rev)))
|
||||||
|
(if revinfo
|
||||||
|
(puthash rev revinfo cache)
|
||||||
|
(setq revinfo
|
||||||
|
(or (gethash rev cache)
|
||||||
|
(puthash rev (magit-blame--commit-alist rev) cache))))
|
||||||
|
(magit-blame--make-overlays buf chunk revinfo))
|
||||||
|
(process-put process 'parsed (point))))))
|
||||||
|
|
||||||
|
(defun magit-blame--parse-chunk (type)
|
||||||
|
(let (chunk revinfo)
|
||||||
|
(looking-at "^\\(.\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)")
|
||||||
|
(with-slots (orig-rev orig-file prev-rev prev-file)
|
||||||
|
(setq chunk (magit-blame-chunk
|
||||||
|
:orig-rev (match-string 1)
|
||||||
|
:orig-line (string-to-number (match-string 2))
|
||||||
|
:final-line (string-to-number (match-string 3))
|
||||||
|
:num-lines (string-to-number (match-string 4))))
|
||||||
|
(forward-line)
|
||||||
|
(let (done)
|
||||||
|
(while (not done)
|
||||||
|
(cond ((looking-at "^filename \\(.+\\)")
|
||||||
|
(setq done t)
|
||||||
|
(setf orig-file (match-string 1)))
|
||||||
|
((looking-at "^previous \\(.\\{40\\}\\) \\(.+\\)")
|
||||||
|
(setf prev-rev (match-string 1))
|
||||||
|
(setf prev-file (match-string 2)))
|
||||||
|
((looking-at "^\\([^ ]+\\) \\(.+\\)")
|
||||||
|
(push (cons (match-string 1)
|
||||||
|
(match-string 2)) revinfo)))
|
||||||
|
(forward-line)))
|
||||||
|
(when (and (eq type 'removal) prev-rev)
|
||||||
|
(cl-rotatef orig-rev prev-rev)
|
||||||
|
(cl-rotatef orig-file prev-file)
|
||||||
|
(setq revinfo nil)))
|
||||||
|
(list chunk revinfo)))
|
||||||
|
|
||||||
|
(defun magit-blame--commit-alist (rev)
|
||||||
|
(cl-mapcar 'cons
|
||||||
|
'("summary"
|
||||||
|
"author" "author-time" "author-tz"
|
||||||
|
"committer" "committer-time" "committer-tz")
|
||||||
|
(split-string (magit-rev-format "%s\v%an\v%ad\v%cn\v%cd" rev
|
||||||
|
"--date=format:%s\v%z")
|
||||||
|
"\v")))
|
||||||
|
|
||||||
|
(defun magit-blame-assert-buffer (process)
|
||||||
|
(unless (buffer-live-p (process-get process 'command-buf))
|
||||||
|
(kill-process process)
|
||||||
|
(user-error "Buffer being blamed has been killed")))
|
||||||
|
|
||||||
|
;;; Display
|
||||||
|
|
||||||
|
(defun magit-blame--make-overlays (buf chunk revinfo)
|
||||||
|
(with-current-buffer buf
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(forward-line (1- (oref chunk final-line)))
|
||||||
|
(let ((beg (point))
|
||||||
|
(end (save-excursion
|
||||||
|
(forward-line (oref chunk num-lines))
|
||||||
|
(point))))
|
||||||
|
(magit-blame--remove-overlays beg end)
|
||||||
|
(magit-blame--make-margin-overlays chunk revinfo beg end)
|
||||||
|
(magit-blame--make-heading-overlay chunk revinfo beg end)
|
||||||
|
(magit-blame--make-highlight-overlay chunk beg))))))
|
||||||
|
|
||||||
|
(defun magit-blame--make-margin-overlays (chunk revinfo _beg end)
|
||||||
|
(save-excursion
|
||||||
|
(let ((line 0))
|
||||||
|
(while (< (point) end)
|
||||||
|
(magit-blame--make-margin-overlay chunk revinfo line)
|
||||||
|
(forward-line)
|
||||||
|
(cl-incf line)))))
|
||||||
|
|
||||||
|
(defun magit-blame--make-margin-overlay (chunk revinfo line)
|
||||||
|
(let* ((end (line-end-position))
|
||||||
|
;; If possible avoid putting this on the first character
|
||||||
|
;; of the line to avoid a conflict with the line overlay.
|
||||||
|
(beg (min (1+ (line-beginning-position)) end))
|
||||||
|
(ov (make-overlay beg end)))
|
||||||
|
(overlay-put ov 'magit-blame-chunk chunk)
|
||||||
|
(overlay-put ov 'magit-blame-revinfo revinfo)
|
||||||
|
(overlay-put ov 'magit-blame-margin line)
|
||||||
|
(magit-blame--update-margin-overlay ov)))
|
||||||
|
|
||||||
|
(defun magit-blame--make-heading-overlay (chunk revinfo beg end)
|
||||||
|
(let ((ov (make-overlay beg end)))
|
||||||
|
(overlay-put ov 'magit-blame-chunk chunk)
|
||||||
|
(overlay-put ov 'magit-blame-revinfo revinfo)
|
||||||
|
(overlay-put ov 'magit-blame-heading t)
|
||||||
|
(magit-blame--update-heading-overlay ov)))
|
||||||
|
|
||||||
|
(defun magit-blame--make-highlight-overlay (chunk beg)
|
||||||
|
(let ((ov (make-overlay beg (1+ (line-end-position)))))
|
||||||
|
(overlay-put ov 'magit-blame-chunk chunk)
|
||||||
|
(overlay-put ov 'magit-blame-highlight t)
|
||||||
|
(magit-blame--update-highlight-overlay ov)))
|
||||||
|
|
||||||
|
(defun magit-blame--update-margin ()
|
||||||
|
(setq left-margin-width (or (magit-blame--style-get 'margin-width) 0))
|
||||||
|
(set-window-buffer (selected-window) (current-buffer)))
|
||||||
|
|
||||||
|
(defun magit-blame--update-overlays ()
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(dolist (ov (overlays-in (point-min) (point-max)))
|
||||||
|
(cond ((overlay-get ov 'magit-blame-heading)
|
||||||
|
(magit-blame--update-heading-overlay ov))
|
||||||
|
((overlay-get ov 'magit-blame-margin)
|
||||||
|
(magit-blame--update-margin-overlay ov))
|
||||||
|
((overlay-get ov 'magit-blame-highlight)
|
||||||
|
(magit-blame--update-highlight-overlay ov))))))
|
||||||
|
|
||||||
|
(defun magit-blame--update-margin-overlay (ov)
|
||||||
|
(overlay-put
|
||||||
|
ov 'before-string
|
||||||
|
(and (magit-blame--style-get 'margin-width)
|
||||||
|
(propertize
|
||||||
|
"o" 'display
|
||||||
|
(list (list 'margin 'left-margin)
|
||||||
|
(let ((line (overlay-get ov 'magit-blame-margin))
|
||||||
|
(format (magit-blame--style-get 'margin-format))
|
||||||
|
(face (magit-blame--style-get 'margin-face)))
|
||||||
|
(magit-blame--format-string
|
||||||
|
ov
|
||||||
|
(or (and (atom format)
|
||||||
|
format)
|
||||||
|
(nth line format)
|
||||||
|
(car (last format)))
|
||||||
|
(or (and (not (zerop line))
|
||||||
|
(magit-blame--style-get 'margin-body-face))
|
||||||
|
face
|
||||||
|
'magit-blame-margin))))))))
|
||||||
|
|
||||||
|
(defun magit-blame--update-heading-overlay (ov)
|
||||||
|
(overlay-put
|
||||||
|
ov 'before-string
|
||||||
|
(--if-let (magit-blame--style-get 'heading-format)
|
||||||
|
(magit-blame--format-string ov it 'magit-blame-heading)
|
||||||
|
(and (magit-blame--style-get 'show-lines)
|
||||||
|
(or (not (magit-blame--style-get 'margin-format))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (overlay-start ov))
|
||||||
|
;; Special case of the special case described in
|
||||||
|
;; `magit-blame--make-margin-overlay'. For empty
|
||||||
|
;; lines it is not possible to show both overlays
|
||||||
|
;; without the line being to high.
|
||||||
|
(not (= (point) (line-end-position)))))
|
||||||
|
magit-blame-separator))))
|
||||||
|
|
||||||
|
(defun magit-blame--update-highlight-overlay (ov)
|
||||||
|
(overlay-put ov 'font-lock-face (magit-blame--style-get 'highlight-face)))
|
||||||
|
|
||||||
|
(defun magit-blame--format-string (ov format face)
|
||||||
|
(let* ((chunk (overlay-get ov 'magit-blame-chunk))
|
||||||
|
(revinfo (overlay-get ov 'magit-blame-revinfo))
|
||||||
|
(key (list format face))
|
||||||
|
(string (cdr (assoc key revinfo))))
|
||||||
|
(unless string
|
||||||
|
(setq string
|
||||||
|
(and format
|
||||||
|
(magit-blame--format-string-1 (oref chunk orig-rev)
|
||||||
|
revinfo format face)))
|
||||||
|
(nconc revinfo (list (cons key string))))
|
||||||
|
string))
|
||||||
|
|
||||||
|
(defun magit-blame--format-string-1 (rev revinfo format face)
|
||||||
|
(let ((str
|
||||||
|
(if (equal rev "0000000000000000000000000000000000000000")
|
||||||
|
(propertize (concat (if (string-prefix-p "\s" format) "\s" "")
|
||||||
|
"Not Yet Committed"
|
||||||
|
(if (string-suffix-p "\n" format) "\n" ""))
|
||||||
|
'font-lock-face face)
|
||||||
|
(magit--format-spec
|
||||||
|
(propertize format 'font-lock-face face)
|
||||||
|
(cl-flet* ((p0 (s f)
|
||||||
|
(propertize s 'font-lock-face
|
||||||
|
(if face
|
||||||
|
(if (listp face)
|
||||||
|
face
|
||||||
|
(list f face))
|
||||||
|
f)))
|
||||||
|
(p1 (k f)
|
||||||
|
(p0 (cdr (assoc k revinfo)) f))
|
||||||
|
(p2 (k1 k2 f)
|
||||||
|
(p0 (magit-blame--format-time-string
|
||||||
|
(cdr (assoc k1 revinfo))
|
||||||
|
(cdr (assoc k2 revinfo)))
|
||||||
|
f)))
|
||||||
|
`((?H . ,(p0 rev 'magit-blame-hash))
|
||||||
|
(?s . ,(p1 "summary" 'magit-blame-summary))
|
||||||
|
(?a . ,(p1 "author" 'magit-blame-name))
|
||||||
|
(?c . ,(p1 "committer" 'magit-blame-name))
|
||||||
|
(?A . ,(p2 "author-time" "author-tz" 'magit-blame-date))
|
||||||
|
(?C . ,(p2 "committer-time" "committer-tz" 'magit-blame-date))
|
||||||
|
(?f . "")))))))
|
||||||
|
(if-let ((width (and (string-suffix-p "%f" format)
|
||||||
|
(magit-blame--style-get 'margin-width))))
|
||||||
|
(concat str
|
||||||
|
(propertize (make-string (max 0 (- width (length str))) ?\s)
|
||||||
|
'font-lock-face face))
|
||||||
|
str)))
|
||||||
|
|
||||||
|
(defun magit-blame--format-separator ()
|
||||||
|
(propertize
|
||||||
|
(concat (propertize "\s" 'display '(space :height (2)))
|
||||||
|
(propertize "\n" 'line-height t))
|
||||||
|
'font-lock-face (list :background
|
||||||
|
(face-attribute 'magit-blame-heading
|
||||||
|
:background nil t))))
|
||||||
|
|
||||||
|
(defun magit-blame--format-time-string (time tz)
|
||||||
|
(let* ((time-format (or (magit-blame--style-get 'time-format)
|
||||||
|
magit-blame-time-format))
|
||||||
|
(tz-in-second (and (string-match "%z" time-format)
|
||||||
|
(car (last (parse-time-string tz))))))
|
||||||
|
(format-time-string time-format
|
||||||
|
(seconds-to-time (string-to-number time))
|
||||||
|
tz-in-second)))
|
||||||
|
|
||||||
|
(defun magit-blame--remove-overlays (&optional beg end)
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(dolist (ov (overlays-in (or beg (point-min))
|
||||||
|
(or end (point-max))))
|
||||||
|
(when (overlay-get ov 'magit-blame-chunk)
|
||||||
|
(delete-overlay ov)))))
|
||||||
|
|
||||||
|
(defun magit-blame-maybe-show-message ()
|
||||||
|
(when (magit-blame--style-get 'show-message)
|
||||||
|
(let ((message-log-max 0))
|
||||||
|
(if-let ((msg (cdr (assoc "summary"
|
||||||
|
(gethash (oref (magit-current-blame-chunk)
|
||||||
|
orig-rev)
|
||||||
|
magit-blame-cache)))))
|
||||||
|
(progn (set-text-properties 0 (length msg) nil msg)
|
||||||
|
(message msg))
|
||||||
|
(message "Commit data not available yet. Still blaming.")))))
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-blame-echo "magit-blame" nil t)
|
||||||
|
(define-suffix-command magit-blame-echo (args)
|
||||||
|
"For each line show the revision in which it was added.
|
||||||
|
Show the information about the chunk at point in the echo area
|
||||||
|
when moving between chunks. Unlike other blaming commands, do
|
||||||
|
not turn on `read-only-mode'."
|
||||||
|
:if (lambda ()
|
||||||
|
(and buffer-file-name
|
||||||
|
(or (not magit-blame-mode)
|
||||||
|
buffer-read-only)))
|
||||||
|
(interactive (list (magit-blame-arguments)))
|
||||||
|
(when magit-buffer-file-name
|
||||||
|
(user-error "Blob buffers aren't supported"))
|
||||||
|
(setq-local magit-blame--style
|
||||||
|
(assq magit-blame-echo-style magit-blame-styles))
|
||||||
|
(setq-local magit-blame-disable-modes
|
||||||
|
(cons 'eldoc-mode magit-blame-disable-modes))
|
||||||
|
(if (not magit-blame-mode)
|
||||||
|
(let ((magit-blame-read-only nil))
|
||||||
|
(magit-blame--pre-blame-assert 'addition)
|
||||||
|
(magit-blame--pre-blame-setup 'addition)
|
||||||
|
(magit-blame--run args))
|
||||||
|
(read-only-mode -1)
|
||||||
|
(magit-blame--update-overlays)))
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-blame-addition "magit-blame" nil t)
|
||||||
|
(define-suffix-command magit-blame-addition (args)
|
||||||
|
"For each line show the revision in which it was added."
|
||||||
|
(interactive (list (magit-blame-arguments)))
|
||||||
|
(magit-blame--pre-blame-assert 'addition)
|
||||||
|
(magit-blame--pre-blame-setup 'addition)
|
||||||
|
(magit-blame--run args))
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-blame-removal "magit-blame" nil t)
|
||||||
|
(define-suffix-command magit-blame-removal (args)
|
||||||
|
"For each line show the revision in which it was removed."
|
||||||
|
:if-nil 'buffer-file-name
|
||||||
|
(interactive (list (magit-blame-arguments)))
|
||||||
|
(unless magit-buffer-file-name
|
||||||
|
(user-error "Only blob buffers can be blamed in reverse"))
|
||||||
|
(magit-blame--pre-blame-assert 'removal)
|
||||||
|
(magit-blame--pre-blame-setup 'removal)
|
||||||
|
(magit-blame--run args))
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-blame-reverse "magit-blame" nil t)
|
||||||
|
(define-suffix-command magit-blame-reverse (args)
|
||||||
|
"For each line show the last revision in which it still exists."
|
||||||
|
:if-nil 'buffer-file-name
|
||||||
|
(interactive (list (magit-blame-arguments)))
|
||||||
|
(unless magit-buffer-file-name
|
||||||
|
(user-error "Only blob buffers can be blamed in reverse"))
|
||||||
|
(magit-blame--pre-blame-assert 'final)
|
||||||
|
(magit-blame--pre-blame-setup 'final)
|
||||||
|
(magit-blame--run args))
|
||||||
|
|
||||||
|
(defun magit-blame--pre-blame-assert (type)
|
||||||
|
(unless (magit-toplevel)
|
||||||
|
(magit--not-inside-repository-error))
|
||||||
|
(if (and magit-blame-mode
|
||||||
|
(eq type magit-blame-type))
|
||||||
|
(if-let ((chunk (magit-current-blame-chunk)))
|
||||||
|
(unless (oref chunk prev-rev)
|
||||||
|
(user-error "Chunk has no further history"))
|
||||||
|
(user-error "Commit data not available yet. Still blaming."))
|
||||||
|
(unless (magit-file-relative-name nil (not magit-buffer-file-name))
|
||||||
|
(if buffer-file-name
|
||||||
|
(user-error "Buffer isn't visiting a tracked file")
|
||||||
|
(user-error "Buffer isn't visiting a file")))))
|
||||||
|
|
||||||
|
(defun magit-blame--pre-blame-setup (type)
|
||||||
|
(when magit-blame-mode
|
||||||
|
(if (eq type magit-blame-type)
|
||||||
|
(let ((style magit-blame--style))
|
||||||
|
(magit-blame-visit-other-file)
|
||||||
|
(setq-local magit-blame--style style)
|
||||||
|
(setq-local magit-blame-recursive-p t)
|
||||||
|
;; Set window-start for the benefit of quickstart.
|
||||||
|
(redisplay))
|
||||||
|
(magit-blame--remove-overlays)))
|
||||||
|
(setq magit-blame-type type))
|
||||||
|
|
||||||
|
(defun magit-blame-visit-other-file ()
|
||||||
|
"Visit another blob related to the current chunk."
|
||||||
|
(interactive)
|
||||||
|
(with-slots (prev-rev prev-file orig-line)
|
||||||
|
(magit-current-blame-chunk)
|
||||||
|
(unless prev-rev
|
||||||
|
(user-error "Chunk has no further history"))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-find-file prev-rev prev-file))
|
||||||
|
;; TODO Adjust line like magit-diff-visit-file.
|
||||||
|
(goto-char (point-min))
|
||||||
|
(forward-line (1- orig-line))))
|
||||||
|
|
||||||
|
(defun magit-blame-visit-file ()
|
||||||
|
"Visit the blob related to the current chunk."
|
||||||
|
(interactive)
|
||||||
|
(with-slots (orig-rev orig-file orig-line)
|
||||||
|
(magit-current-blame-chunk)
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-find-file orig-rev orig-file))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(forward-line (1- orig-line))))
|
||||||
|
|
||||||
|
(define-suffix-command magit-blame-quit ()
|
||||||
|
"Turn off Magit-Blame mode.
|
||||||
|
If the buffer was created during a recursive blame,
|
||||||
|
then also kill the buffer."
|
||||||
|
:if-non-nil 'magit-blame-mode
|
||||||
|
(interactive)
|
||||||
|
(magit-blame-mode -1)
|
||||||
|
(when magit-blame-recursive-p
|
||||||
|
(kill-buffer)))
|
||||||
|
|
||||||
|
(defun magit-blame-next-chunk ()
|
||||||
|
"Move to the next chunk."
|
||||||
|
(interactive)
|
||||||
|
(--if-let (next-single-char-property-change (point) 'magit-blame-chunk)
|
||||||
|
(goto-char it)
|
||||||
|
(user-error "No more chunks")))
|
||||||
|
|
||||||
|
(defun magit-blame-previous-chunk ()
|
||||||
|
"Move to the previous chunk."
|
||||||
|
(interactive)
|
||||||
|
(--if-let (previous-single-char-property-change (point) 'magit-blame-chunk)
|
||||||
|
(goto-char it)
|
||||||
|
(user-error "No more chunks")))
|
||||||
|
|
||||||
|
(defun magit-blame-next-chunk-same-commit (&optional previous)
|
||||||
|
"Move to the next chunk from the same commit.\n\n(fn)"
|
||||||
|
(interactive)
|
||||||
|
(if-let ((rev (oref (magit-current-blame-chunk) orig-rev)))
|
||||||
|
(let ((pos (point)) ov)
|
||||||
|
(save-excursion
|
||||||
|
(while (and (not ov)
|
||||||
|
(not (= pos (if previous (point-min) (point-max))))
|
||||||
|
(setq pos (funcall
|
||||||
|
(if previous
|
||||||
|
'previous-single-char-property-change
|
||||||
|
'next-single-char-property-change)
|
||||||
|
pos 'magit-blame-chunk)))
|
||||||
|
(--when-let (magit-blame--overlay-at pos)
|
||||||
|
(when (equal (oref (magit-blame-chunk-at pos) orig-rev) rev)
|
||||||
|
(setq ov it)))))
|
||||||
|
(if ov
|
||||||
|
(goto-char (overlay-start ov))
|
||||||
|
(user-error "No more chunks from same commit")))
|
||||||
|
(user-error "This chunk hasn't been blamed yet")))
|
||||||
|
|
||||||
|
(defun magit-blame-previous-chunk-same-commit ()
|
||||||
|
"Move to the previous chunk from the same commit."
|
||||||
|
(interactive)
|
||||||
|
(magit-blame-next-chunk-same-commit 'previous-single-char-property-change))
|
||||||
|
|
||||||
|
(defun magit-blame-cycle-style ()
|
||||||
|
"Change how blame information is visualized.
|
||||||
|
Cycle through the elements of option `magit-blame-styles'."
|
||||||
|
(interactive)
|
||||||
|
(setq magit-blame--style
|
||||||
|
(or (cadr (cl-member (car magit-blame--style)
|
||||||
|
magit-blame-styles :key #'car))
|
||||||
|
(car magit-blame-styles)))
|
||||||
|
(magit-blame--update-margin)
|
||||||
|
(magit-blame--update-overlays))
|
||||||
|
|
||||||
|
(defun magit-blame-copy-hash ()
|
||||||
|
"Save hash of the current chunk's commit to the kill ring.
|
||||||
|
|
||||||
|
When the region is active, then save the region's content
|
||||||
|
instead of the hash, like `kill-ring-save' would."
|
||||||
|
(interactive)
|
||||||
|
(if (use-region-p)
|
||||||
|
(copy-region-as-kill nil nil 'region)
|
||||||
|
(kill-new (message "%s" (oref (magit-current-blame-chunk) orig-rev)))))
|
||||||
|
|
||||||
|
;;; Popup
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-blame "magit-blame" nil t)
|
||||||
|
(define-transient-command magit-blame ()
|
||||||
|
"Show the commits that added or removed lines in the visited file."
|
||||||
|
:man-page "git-blame"
|
||||||
|
:value '("-w")
|
||||||
|
["Arguments"
|
||||||
|
("-w" "Ignore whitespace" "-w")
|
||||||
|
("-r" "Do not treat root commits as boundaries" "--root")
|
||||||
|
(magit-blame:-M)
|
||||||
|
(magit-blame:-C)]
|
||||||
|
["Actions"
|
||||||
|
("b" "Show commits adding lines" magit-blame-addition)
|
||||||
|
("r" "Show commits removing lines" magit-blame-removal)
|
||||||
|
("f" "Show last commits that still have lines" magit-blame-reverse)
|
||||||
|
("m" "Blame echo" magit-blame-echo)
|
||||||
|
("q" "Quit blaming" magit-blame-quit)]
|
||||||
|
["Refresh"
|
||||||
|
:if-non-nil magit-blame-mode
|
||||||
|
("c" "Cycle style" magit-blame-cycle-style)])
|
||||||
|
|
||||||
|
(defun magit-blame-arguments ()
|
||||||
|
(transient-args 'magit-blame))
|
||||||
|
|
||||||
|
(define-infix-argument magit-blame:-M ()
|
||||||
|
:description "Detect lines moved or copied within a file"
|
||||||
|
:class 'transient-option
|
||||||
|
:argument "-M"
|
||||||
|
:reader 'transient-read-number-N+)
|
||||||
|
|
||||||
|
(define-infix-argument magit-blame:-C ()
|
||||||
|
:description "Detect lines moved or copied between files"
|
||||||
|
:class 'transient-option
|
||||||
|
:argument "-C"
|
||||||
|
:reader 'transient-read-number-N+)
|
||||||
|
|
||||||
|
;;; Utilities
|
||||||
|
|
||||||
|
(defun magit-blame-maybe-update-revision-buffer ()
|
||||||
|
(when-let ((chunk (magit-current-blame-chunk))
|
||||||
|
(commit (oref chunk orig-rev))
|
||||||
|
(buffer (magit-get-mode-buffer 'magit-revision-mode nil t)))
|
||||||
|
(if magit--update-revision-buffer
|
||||||
|
(setq magit--update-revision-buffer (list commit buffer))
|
||||||
|
(setq magit--update-revision-buffer (list commit buffer))
|
||||||
|
(run-with-idle-timer
|
||||||
|
magit-update-other-window-delay nil
|
||||||
|
(lambda ()
|
||||||
|
(pcase-let ((`(,rev ,buf) magit--update-revision-buffer))
|
||||||
|
(setq magit--update-revision-buffer nil)
|
||||||
|
(when (buffer-live-p buf)
|
||||||
|
(let ((magit-display-buffer-noselect t))
|
||||||
|
(apply #'magit-show-commit rev
|
||||||
|
(magit-diff-arguments 'magit-revision-mode))))))))))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-blame)
|
||||||
|
;;; magit-blame.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-blame.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-blame.elc
Normal file
Binary file not shown.
203
elpa/magit-20191030.1315/magit-bookmark.el
Normal file
203
elpa/magit-20191030.1315/magit-bookmark.el
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
;;; magit-bookmark.el --- bookmark support for Magit -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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>
|
||||||
|
|
||||||
|
;; Inspired by an earlier implementation by Yuri Khan.
|
||||||
|
|
||||||
|
;; 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:
|
||||||
|
|
||||||
|
;; Support for bookmarks for most Magit buffers.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'subr-x))
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
(require 'bookmark)
|
||||||
|
|
||||||
|
;;; Core
|
||||||
|
|
||||||
|
(defun magit--make-bookmark ()
|
||||||
|
"Create a bookmark for the current Magit buffer.
|
||||||
|
Input values are the major-mode's `magit-bookmark-name' method,
|
||||||
|
and the buffer-local values of the variables referenced in its
|
||||||
|
`magit-bookmark-variables' property."
|
||||||
|
(if (plist-member (symbol-plist major-mode) 'magit-bookmark-variables)
|
||||||
|
(let ((bookmark (bookmark-make-record-default 'no-file)))
|
||||||
|
(bookmark-prop-set bookmark 'handler 'magit--handle-bookmark)
|
||||||
|
(bookmark-prop-set bookmark 'mode major-mode)
|
||||||
|
(bookmark-prop-set bookmark 'filename (magit-toplevel))
|
||||||
|
(bookmark-prop-set bookmark 'defaults (list (magit-bookmark-name)))
|
||||||
|
(dolist (var (get major-mode 'magit-bookmark-variables))
|
||||||
|
(bookmark-prop-set bookmark var (symbol-value var)))
|
||||||
|
(bookmark-prop-set
|
||||||
|
bookmark 'magit-hidden-sections
|
||||||
|
(--keep (and (oref it hidden)
|
||||||
|
(cons (oref it type)
|
||||||
|
(if (derived-mode-p 'magit-stash-mode)
|
||||||
|
(replace-regexp-in-string
|
||||||
|
(regexp-quote magit-buffer-revision)
|
||||||
|
magit-buffer-revision-hash
|
||||||
|
(oref it value))
|
||||||
|
(oref it value))))
|
||||||
|
(oref magit-root-section children)))
|
||||||
|
bookmark)
|
||||||
|
(user-error "Bookmarking is not implemented for %s buffers" major-mode)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit--handle-bookmark (bookmark)
|
||||||
|
"Open a bookmark created by `magit--make-bookmark'.
|
||||||
|
Call the `magit-*-setup-buffer' function of the the major-mode
|
||||||
|
with the variables' values as arguments, which were recorded by
|
||||||
|
`magit--make-bookmark'. Ignore `magit-display-buffer-function'."
|
||||||
|
(let ((buffer (let ((default-directory (bookmark-get-filename bookmark))
|
||||||
|
(mode (bookmark-prop-get bookmark 'mode))
|
||||||
|
(magit-display-buffer-function #'identity)
|
||||||
|
(magit-display-buffer-noselect t))
|
||||||
|
(apply (intern (format "%s-setup-buffer"
|
||||||
|
(substring (symbol-name mode) 0 -5)))
|
||||||
|
(--map (bookmark-prop-get bookmark it)
|
||||||
|
(get mode 'magit-bookmark-variables))))))
|
||||||
|
(set-buffer buffer) ; That is the interface we have to adhere to.
|
||||||
|
(when-let ((hidden (bookmark-prop-get bookmark 'magit-hidden-sections)))
|
||||||
|
(with-current-buffer buffer
|
||||||
|
(dolist (child (oref magit-root-section children))
|
||||||
|
(if (member (cons (oref child type)
|
||||||
|
(oref child value))
|
||||||
|
hidden)
|
||||||
|
(magit-section-hide child)
|
||||||
|
(magit-section-show child)))))
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(cl-defgeneric magit-bookmark-name ()
|
||||||
|
"Return name for bookmark to current buffer."
|
||||||
|
(format "%s%s"
|
||||||
|
(substring (symbol-name major-mode) 0 -5)
|
||||||
|
(if-let ((vars (get major-mode 'magit-bookmark-variables)))
|
||||||
|
(cl-mapcan (lambda (var)
|
||||||
|
(let ((val (symbol-value var)))
|
||||||
|
(if (and val (atom val))
|
||||||
|
(list val)
|
||||||
|
val)))
|
||||||
|
vars)
|
||||||
|
"")))
|
||||||
|
|
||||||
|
;;; Diff
|
||||||
|
;;;; Diff
|
||||||
|
|
||||||
|
(put 'magit-diff-mode 'magit-bookmark-variables
|
||||||
|
'(magit-buffer-range-hashed
|
||||||
|
magit-buffer-typearg
|
||||||
|
magit-buffer-diff-args
|
||||||
|
magit-buffer-diff-files))
|
||||||
|
|
||||||
|
(cl-defmethod magit-bookmark-name (&context (major-mode magit-diff-mode))
|
||||||
|
(format "magit-diff(%s%s)"
|
||||||
|
(pcase (magit-diff-type)
|
||||||
|
(`staged "staged")
|
||||||
|
(`unstaged "unstaged")
|
||||||
|
(`committed magit-buffer-range)
|
||||||
|
(`undefined
|
||||||
|
(delq nil (list magit-buffer-typearg magit-buffer-range-hashed))))
|
||||||
|
(if magit-buffer-diff-files
|
||||||
|
(concat " -- " (mapconcat #'identity magit-buffer-diff-files " "))
|
||||||
|
"")))
|
||||||
|
|
||||||
|
;;;; Revision
|
||||||
|
|
||||||
|
(put 'magit-revision-mode 'magit-bookmark-variables
|
||||||
|
'(magit-buffer-revision-hash
|
||||||
|
magit-buffer-diff-args
|
||||||
|
magit-buffer-diff-files))
|
||||||
|
|
||||||
|
(cl-defmethod magit-bookmark-name (&context (major-mode magit-revision-mode))
|
||||||
|
(format "magit-revision(%s %s)"
|
||||||
|
(magit-rev-abbrev magit-buffer-revision)
|
||||||
|
(if magit-buffer-diff-files
|
||||||
|
(mapconcat #'identity magit-buffer-diff-files " ")
|
||||||
|
(magit-rev-format "%s" magit-buffer-revision))))
|
||||||
|
|
||||||
|
;;;; Stash
|
||||||
|
|
||||||
|
(put 'magit-stash-mode 'magit-bookmark-variables
|
||||||
|
'(magit-buffer-revision-hash
|
||||||
|
magit-buffer-diff-args
|
||||||
|
magit-buffer-diff-files))
|
||||||
|
|
||||||
|
(cl-defmethod magit-bookmark-name (&context (major-mode magit-stash-mode))
|
||||||
|
(format "magit-stash(%s %s)"
|
||||||
|
(magit-rev-abbrev magit-buffer-revision)
|
||||||
|
(if magit-buffer-diff-files
|
||||||
|
(mapconcat #'identity magit-buffer-diff-files " ")
|
||||||
|
(magit-rev-format "%s" magit-buffer-revision))))
|
||||||
|
|
||||||
|
;;; Log
|
||||||
|
;;;; Log
|
||||||
|
|
||||||
|
(put 'magit-log-mode 'magit-bookmark-variables
|
||||||
|
'(magit-buffer-revisions
|
||||||
|
magit-buffer-log-args
|
||||||
|
magit-buffer-log-files))
|
||||||
|
|
||||||
|
(cl-defmethod magit-bookmark-name (&context (major-mode magit-log-mode))
|
||||||
|
(format "magit-log(%s%s)"
|
||||||
|
(mapconcat #'identity magit-buffer-revisions " ")
|
||||||
|
(if magit-buffer-log-files
|
||||||
|
(concat " -- " (mapconcat #'identity magit-buffer-log-files " "))
|
||||||
|
"")))
|
||||||
|
|
||||||
|
;;;; Cherry
|
||||||
|
|
||||||
|
(put 'magit-cherry-mode 'magit-bookmark-variables
|
||||||
|
'(magit-buffer-refname
|
||||||
|
magit-buffer-upstream))
|
||||||
|
|
||||||
|
(cl-defmethod magit-bookmark-name (&context (major-mode magit-cherry-mode))
|
||||||
|
(format "magit-cherry(%s > %s)"
|
||||||
|
magit-buffer-refname
|
||||||
|
magit-buffer-upstream))
|
||||||
|
|
||||||
|
;;;; Reflog
|
||||||
|
|
||||||
|
(put 'magit-reflog-mode 'magit-bookmark-variables
|
||||||
|
'(magit-buffer-refname))
|
||||||
|
|
||||||
|
(cl-defmethod magit-bookmark-name (&context (major-mode magit-reflog-mode))
|
||||||
|
(format "magit-reflog(%s)" magit-buffer-refname))
|
||||||
|
|
||||||
|
;;; Misc
|
||||||
|
|
||||||
|
(put 'magit-status-mode 'magit-bookmark-variables nil)
|
||||||
|
|
||||||
|
(put 'magit-refs-mode 'magit-bookmark-variables
|
||||||
|
'(magit-buffer-upstream
|
||||||
|
magit-buffer-arguments))
|
||||||
|
|
||||||
|
(put 'magit-stashes-mode 'magit-bookmark-variables nil)
|
||||||
|
|
||||||
|
(cl-defmethod magit-bookmark-name (&context (major-mode magit-stashes-mode))
|
||||||
|
(format "magit-states(%s)" magit-buffer-refname))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-bookmark)
|
||||||
|
;;; magit-bookmark.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-bookmark.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-bookmark.elc
Normal file
Binary file not shown.
887
elpa/magit-20191030.1315/magit-branch.el
Normal file
887
elpa/magit-20191030.1315/magit-branch.el
Normal file
@@ -0,0 +1,887 @@
|
|||||||
|
;;; magit-branch.el --- branch support -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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 support for branches. It defines commands
|
||||||
|
;; for creating, checking out, manipulating, and configuring branches.
|
||||||
|
;; Commands defined here are mainly concerned with branches as
|
||||||
|
;; pointers, commands that deal with what a branch points at, are
|
||||||
|
;; defined elsewhere.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'subr-x))
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
(require 'magit-reset)
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defcustom magit-branch-read-upstream-first t
|
||||||
|
"Whether to read upstream before name of new branch when creating a branch.
|
||||||
|
|
||||||
|
`nil' Read the branch name first.
|
||||||
|
`t' Read the upstream first.
|
||||||
|
`fallback' Read the upstream first, but if it turns out that the chosen
|
||||||
|
value is not a valid upstream (because it cannot be resolved
|
||||||
|
as an existing revision), then treat it as the name of the
|
||||||
|
new branch and continue by reading the upstream next."
|
||||||
|
:package-version '(magit . "2.2.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(choice (const :tag "read branch name first" nil)
|
||||||
|
(const :tag "read upstream first" t)
|
||||||
|
(const :tag "read upstream first, with fallback" fallback)))
|
||||||
|
|
||||||
|
(defcustom magit-branch-prefer-remote-upstream nil
|
||||||
|
"Whether to favor remote upstreams when creating new branches.
|
||||||
|
|
||||||
|
When a new branch is created, then the branch, commit, or stash
|
||||||
|
at point is suggested as the default starting point of the new
|
||||||
|
branch, or if there is no such revision at point the current
|
||||||
|
branch. In either case the user may choose another starting
|
||||||
|
point.
|
||||||
|
|
||||||
|
If the chosen starting point is a branch, then it may also be set
|
||||||
|
as the upstream of the new branch, depending on the value of the
|
||||||
|
Git variable `branch.autoSetupMerge'. By default this is done
|
||||||
|
for remote branches, but not for local branches.
|
||||||
|
|
||||||
|
You might prefer to always use some remote branch as upstream.
|
||||||
|
If the chosen starting point is (1) a local branch, (2) whose
|
||||||
|
name matches a member of the value of this option, (3) the
|
||||||
|
upstream of that local branch is a remote branch with the same
|
||||||
|
name, and (4) that remote branch can be fast-forwarded to the
|
||||||
|
local branch, then the chosen branch is used as starting point,
|
||||||
|
but its own upstream is used as the upstream of the new branch.
|
||||||
|
|
||||||
|
Members of this option's value are treated as branch names that
|
||||||
|
have to match exactly unless they contain a character that makes
|
||||||
|
them invalid as a branch name. Recommended characters to use
|
||||||
|
to trigger interpretation as a regexp are \"*\" and \"^\". Some
|
||||||
|
other characters which you might expect to be invalid, actually
|
||||||
|
are not, e.g. \".+$\" are all perfectly valid. More precisely,
|
||||||
|
if `git check-ref-format --branch STRING' exits with a non-zero
|
||||||
|
status, then treat STRING as a regexp.
|
||||||
|
|
||||||
|
Assuming the chosen branch matches these conditions you would end
|
||||||
|
up with with e.g.:
|
||||||
|
|
||||||
|
feature --upstream--> origin/master
|
||||||
|
|
||||||
|
instead of
|
||||||
|
|
||||||
|
feature --upstream--> master --upstream--> origin/master
|
||||||
|
|
||||||
|
Which you prefer is a matter of personal preference. If you do
|
||||||
|
prefer the former, then you should add branches such as \"master\",
|
||||||
|
\"next\", and \"maint\" to the value of this options."
|
||||||
|
:package-version '(magit . "2.4.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(repeat string))
|
||||||
|
|
||||||
|
(defcustom magit-branch-adjust-remote-upstream-alist nil
|
||||||
|
"Alist of upstreams to be used when branching from remote branches.
|
||||||
|
|
||||||
|
When creating a local branch from an ephemeral branch located
|
||||||
|
on a remote, e.g. a feature or hotfix branch, then that remote
|
||||||
|
branch should usually not be used as the upstream branch, since
|
||||||
|
the push-remote already allows accessing it and having both the
|
||||||
|
upstream and the push-remote reference the same related branch
|
||||||
|
would be wasteful. Instead a branch like \"maint\" or \"master\"
|
||||||
|
should be used as the upstream.
|
||||||
|
|
||||||
|
This option allows specifying the branch that should be used as
|
||||||
|
the upstream when branching certain remote branches. The value
|
||||||
|
is an alist of the form ((UPSTREAM . RULE)...). The first
|
||||||
|
matching element is used, the following elements are ignored.
|
||||||
|
|
||||||
|
UPSTREAM is the branch to be used as the upstream for branches
|
||||||
|
specified by RULE. It can be a local or a remote branch.
|
||||||
|
|
||||||
|
RULE can either be a regular expression, matching branches whose
|
||||||
|
upstream should be the one specified by UPSTREAM. Or it can be
|
||||||
|
a list of the only branches that should *not* use UPSTREAM; all
|
||||||
|
other branches will. Matching is done after stripping the remote
|
||||||
|
part of the name of the branch that is being branched from.
|
||||||
|
|
||||||
|
If you use a finite set of non-ephemeral branches across all your
|
||||||
|
repositories, then you might use something like:
|
||||||
|
|
||||||
|
((\"origin/master\" \"master\" \"next\" \"maint\"))
|
||||||
|
|
||||||
|
Or if the names of all your ephemeral branches contain a slash,
|
||||||
|
at least in some repositories, then a good value could be:
|
||||||
|
|
||||||
|
((\"origin/master\" . \"/\"))
|
||||||
|
|
||||||
|
Of course you can also fine-tune:
|
||||||
|
|
||||||
|
((\"origin/maint\" . \"\\\\\\=`hotfix/\")
|
||||||
|
(\"origin/master\" . \"\\\\\\=`feature/\"))
|
||||||
|
|
||||||
|
If you use remote branches as UPSTREAM, then you might also want
|
||||||
|
to set `magit-branch-prefer-remote-upstream' to a non-nil value.
|
||||||
|
However, I recommend that you use local branches as UPSTREAM."
|
||||||
|
:package-version '(magit . "2.9.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(repeat (cons (string :tag "Use upstream")
|
||||||
|
(choice :tag "for branches"
|
||||||
|
(regexp :tag "matching")
|
||||||
|
(repeat :tag "except"
|
||||||
|
(string :tag "branch"))))))
|
||||||
|
|
||||||
|
(defcustom magit-branch-rename-push-target t
|
||||||
|
"Whether the push-remote setup is preserved when renaming a branch.
|
||||||
|
|
||||||
|
The command `magit-branch-rename' renames a branch named OLD to
|
||||||
|
NEW. This option controls how much of the push-remote setup is
|
||||||
|
preserved when doing so.
|
||||||
|
|
||||||
|
When nil, then preserve nothing and unset `branch.OLD.pushRemote'.
|
||||||
|
|
||||||
|
When `local-only', then first set `branch.NEW.pushRemote' to the
|
||||||
|
same value as `branch.OLD.pushRemote', provided the latter is
|
||||||
|
actually set and unless the former already has another value.
|
||||||
|
|
||||||
|
When t, then rename the branch named OLD on the remote specified
|
||||||
|
by `branch.OLD.pushRemote' to NEW, provided OLD exists on that
|
||||||
|
remote and unless NEW already exists on the remote.
|
||||||
|
|
||||||
|
When `forge-only' and the `forge' package is available, then
|
||||||
|
behave like `t' if the remote points to a repository on a forge
|
||||||
|
(currently Github or Gitlab), otherwise like `local-only'.
|
||||||
|
|
||||||
|
Another supported but obsolete value is `github-only'. It is a
|
||||||
|
misnomer because it now treated as an alias for `forge-only'."
|
||||||
|
:package-version '(magit . "2.90.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(choice
|
||||||
|
(const :tag "Don't preserve push-remote setup" nil)
|
||||||
|
(const :tag "Preserve push-remote setup" local-only)
|
||||||
|
(const :tag "... and rename corresponding branch on remote" t)
|
||||||
|
(const :tag "... but only if remote is on a forge" forge-only)))
|
||||||
|
|
||||||
|
(defcustom magit-branch-direct-configure t
|
||||||
|
"Whether the command `magit-branch' shows Git variables.
|
||||||
|
When set to nil, no variables are displayed by this transient
|
||||||
|
command, instead the sub-transient `magit-branch-configure'
|
||||||
|
has to be used to view and change branch related variables."
|
||||||
|
:package-version '(magit . "2.7.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-published-branches '("origin/master")
|
||||||
|
"List of branches that are considered to be published."
|
||||||
|
:package-version '(magit . "2.13.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(repeat string))
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-branch "magit" nil t)
|
||||||
|
(define-transient-command magit-branch (branch)
|
||||||
|
"Add, configure or remove a branch."
|
||||||
|
:man-page "git-branch"
|
||||||
|
["Variables"
|
||||||
|
:if (lambda ()
|
||||||
|
(and magit-branch-direct-configure
|
||||||
|
(oref transient--prefix scope)))
|
||||||
|
("d" magit-branch.<branch>.description)
|
||||||
|
("u" magit-branch.<branch>.merge/remote)
|
||||||
|
("r" magit-branch.<branch>.rebase)
|
||||||
|
("p" magit-branch.<branch>.pushRemote)]
|
||||||
|
[["Checkout"
|
||||||
|
("b" "branch/revision" magit-checkout)
|
||||||
|
("l" "local branch" magit-branch-checkout)
|
||||||
|
(6 "o" "new orphan" magit-branch-orphan)]
|
||||||
|
[""
|
||||||
|
("c" "new branch" magit-branch-and-checkout)
|
||||||
|
("s" "new spin-off" magit-branch-spinoff)
|
||||||
|
(5 "w" "new worktree" magit-worktree-checkout)]
|
||||||
|
["Create"
|
||||||
|
("n" "new branch" magit-branch-create)
|
||||||
|
("S" "new spin-out" magit-branch-spinout)
|
||||||
|
(5 "W" "new worktree" magit-worktree-branch)]
|
||||||
|
["Do"
|
||||||
|
("C" "configure..." magit-branch-configure)
|
||||||
|
("m" "rename" magit-branch-rename)
|
||||||
|
("x" "reset" magit-branch-reset)
|
||||||
|
("k" "delete" magit-branch-delete)]
|
||||||
|
[""
|
||||||
|
(7 "h" "shelve" magit-branch-shelve)
|
||||||
|
(7 "H" "unshelve" magit-branch-unshelve)]]
|
||||||
|
(interactive (list (magit-get-current-branch)))
|
||||||
|
(transient-setup 'magit-branch nil nil :scope branch))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-checkout (revision)
|
||||||
|
"Checkout REVISION, updating the index and the working tree.
|
||||||
|
If REVISION is a local branch, then that becomes the current
|
||||||
|
branch. If it is something else, then `HEAD' becomes detached.
|
||||||
|
Checkout fails if the working tree or the staging area contain
|
||||||
|
changes.
|
||||||
|
\n(git checkout REVISION)."
|
||||||
|
(interactive (list (magit-read-other-branch-or-commit "Checkout")))
|
||||||
|
(when (string-match "\\`heads/\\(.+\\)" revision)
|
||||||
|
(setq revision (match-string 1 revision)))
|
||||||
|
(magit-run-git "checkout" revision))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-create (branch start-point)
|
||||||
|
"Create BRANCH at branch or revision START-POINT."
|
||||||
|
(interactive (magit-branch-read-args "Create branch"))
|
||||||
|
(magit-call-git "branch" branch start-point)
|
||||||
|
(magit-branch-maybe-adjust-upstream branch start-point)
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-and-checkout (branch start-point)
|
||||||
|
"Create and checkout BRANCH at branch or revision START-POINT."
|
||||||
|
(interactive (magit-branch-read-args "Create and checkout branch"))
|
||||||
|
(if (string-match-p "^stash@{[0-9]+}$" start-point)
|
||||||
|
(magit-run-git "stash" "branch" branch start-point)
|
||||||
|
(magit-call-git "checkout" "-b" branch start-point)
|
||||||
|
(magit-branch-maybe-adjust-upstream branch start-point)
|
||||||
|
(magit-refresh)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-or-checkout (arg &optional start-point)
|
||||||
|
"Hybrid between `magit-checkout' and `magit-branch-and-checkout'.
|
||||||
|
|
||||||
|
Ask the user for an existing branch or revision. If the user
|
||||||
|
input actually can be resolved as a branch or revision, then
|
||||||
|
check that out, just like `magit-checkout' would.
|
||||||
|
|
||||||
|
Otherwise create and checkout a new branch using the input as
|
||||||
|
its name. Before doing so read the starting-point for the new
|
||||||
|
branch. This is similar to what `magit-branch-and-checkout'
|
||||||
|
does."
|
||||||
|
(interactive
|
||||||
|
(let ((arg (magit-read-other-branch-or-commit "Checkout")))
|
||||||
|
(list arg
|
||||||
|
(and (not (magit-commit-p arg))
|
||||||
|
(magit-read-starting-point "Create and checkout branch" arg)))))
|
||||||
|
(when (string-match "\\`heads/\\(.+\\)" arg)
|
||||||
|
(setq arg (match-string 1 arg)))
|
||||||
|
(if start-point
|
||||||
|
(magit-branch-and-checkout arg start-point)
|
||||||
|
(magit-checkout arg)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-checkout (branch &optional start-point)
|
||||||
|
"Checkout an existing or new local branch.
|
||||||
|
|
||||||
|
Read a branch name from the user offering all local branches and
|
||||||
|
a subset of remote branches as candidates. Omit remote branches
|
||||||
|
for which a local branch by the same name exists from the list
|
||||||
|
of candidates. The user can also enter a completely new branch
|
||||||
|
name.
|
||||||
|
|
||||||
|
- If the user selects an existing local branch, then check that
|
||||||
|
out.
|
||||||
|
|
||||||
|
- If the user selects a remote branch, then create and checkout
|
||||||
|
a new local branch with the same name. Configure the selected
|
||||||
|
remote branch as push target.
|
||||||
|
|
||||||
|
- If the user enters a new branch name, then create and check
|
||||||
|
that out, after also reading the starting-point from the user.
|
||||||
|
|
||||||
|
In the latter two cases the upstream is also set. Whether it is
|
||||||
|
set to the chosen START-POINT or something else depends on the
|
||||||
|
value of `magit-branch-adjust-remote-upstream-alist', just like
|
||||||
|
when using `magit-branch-and-checkout'."
|
||||||
|
(interactive
|
||||||
|
(let* ((current (magit-get-current-branch))
|
||||||
|
(local (magit-list-local-branch-names))
|
||||||
|
(remote (--filter (and (string-match "[^/]+/" it)
|
||||||
|
(not (member (substring it (match-end 0))
|
||||||
|
(cons "HEAD" local))))
|
||||||
|
(magit-list-remote-branch-names)))
|
||||||
|
(choices (nconc (delete current local) remote))
|
||||||
|
(atpoint (magit-branch-at-point))
|
||||||
|
(choice (magit-completing-read
|
||||||
|
"Checkout branch" choices
|
||||||
|
nil nil nil 'magit-revision-history
|
||||||
|
(or (car (member atpoint choices))
|
||||||
|
(and atpoint
|
||||||
|
(car (member (and (string-match "[^/]+/" atpoint)
|
||||||
|
(substring atpoint (match-end 0)))
|
||||||
|
choices)))))))
|
||||||
|
(cond ((member choice remote)
|
||||||
|
(list (and (string-match "[^/]+/" choice)
|
||||||
|
(substring choice (match-end 0)))
|
||||||
|
choice))
|
||||||
|
((member choice local)
|
||||||
|
(list choice))
|
||||||
|
(t
|
||||||
|
(list choice (magit-read-starting-point "Create" choice))))))
|
||||||
|
(if (not start-point)
|
||||||
|
(magit-checkout branch)
|
||||||
|
(when (magit-anything-modified-p)
|
||||||
|
(user-error "Cannot checkout when there are uncommitted changes"))
|
||||||
|
(magit-branch-and-checkout branch start-point)
|
||||||
|
(when (magit-remote-branch-p start-point)
|
||||||
|
(pcase-let ((`(,remote . ,remote-branch)
|
||||||
|
(magit-split-branch-name start-point)))
|
||||||
|
(when (and (equal branch remote-branch)
|
||||||
|
(not (equal remote (magit-get "remote.pushDefault"))))
|
||||||
|
(magit-set remote "branch" branch "pushRemote"))))))
|
||||||
|
|
||||||
|
(defun magit-branch-maybe-adjust-upstream (branch start-point)
|
||||||
|
(--when-let
|
||||||
|
(or (and (magit-get-upstream-branch branch)
|
||||||
|
(magit-get-indirect-upstream-branch start-point))
|
||||||
|
(and (magit-remote-branch-p start-point)
|
||||||
|
(let ((name (cdr (magit-split-branch-name start-point))))
|
||||||
|
(car (--first (if (listp (cdr it))
|
||||||
|
(not (member name (cdr it)))
|
||||||
|
(string-match-p (cdr it) name))
|
||||||
|
magit-branch-adjust-remote-upstream-alist)))))
|
||||||
|
(magit-call-git "branch" (concat "--set-upstream-to=" it) branch)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-orphan (branch start-point)
|
||||||
|
"Create and checkout an orphan BRANCH with contents from revision START-POINT."
|
||||||
|
(interactive (magit-branch-read-args "Create and checkout orphan branch"))
|
||||||
|
(magit-run-git "checkout" "--orphan" branch start-point))
|
||||||
|
|
||||||
|
(defun magit-branch-read-args (prompt &optional default-start)
|
||||||
|
(if magit-branch-read-upstream-first
|
||||||
|
(let ((choice (magit-read-starting-point prompt nil default-start)))
|
||||||
|
(if (magit-rev-verify choice)
|
||||||
|
(list (magit-read-string-ns
|
||||||
|
(if magit-completing-read--silent-default
|
||||||
|
(format "%s (starting at `%s')" prompt choice)
|
||||||
|
"Name for new branch")
|
||||||
|
(let ((def (mapconcat #'identity
|
||||||
|
(cdr (split-string choice "/"))
|
||||||
|
"/")))
|
||||||
|
(and (member choice (magit-list-remote-branch-names))
|
||||||
|
(not (member def (magit-list-local-branch-names)))
|
||||||
|
def)))
|
||||||
|
choice)
|
||||||
|
(if (eq magit-branch-read-upstream-first 'fallback)
|
||||||
|
(list choice
|
||||||
|
(magit-read-starting-point prompt choice default-start))
|
||||||
|
(user-error "Not a valid starting-point: %s" choice))))
|
||||||
|
(let ((branch (magit-read-string-ns (concat prompt " named"))))
|
||||||
|
(list branch (magit-read-starting-point prompt branch default-start)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-spinout (branch &optional from)
|
||||||
|
"Create new branch from the unpushed commits.
|
||||||
|
Like `magit-branch-spinoff' but remain on the current branch.
|
||||||
|
If there are any uncommitted changes, then behave exactly like
|
||||||
|
`magit-branch-spinoff'."
|
||||||
|
(interactive (list (magit-read-string-ns "Spin out branch")
|
||||||
|
(car (last (magit-region-values 'commit)))))
|
||||||
|
(magit--branch-spinoff branch from nil))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-spinoff (branch &optional from)
|
||||||
|
"Create new branch from the unpushed commits.
|
||||||
|
|
||||||
|
Create and checkout a new branch starting at and tracking the
|
||||||
|
current branch. That branch in turn is reset to the last commit
|
||||||
|
it shares with its upstream. If the current branch has no
|
||||||
|
upstream or no unpushed commits, then the new branch is created
|
||||||
|
anyway and the previously current branch is not touched.
|
||||||
|
|
||||||
|
This is useful to create a feature branch after work has already
|
||||||
|
began on the old branch (likely but not necessarily \"master\").
|
||||||
|
|
||||||
|
If the current branch is a member of the value of option
|
||||||
|
`magit-branch-prefer-remote-upstream' (which see), then the
|
||||||
|
current branch will be used as the starting point as usual, but
|
||||||
|
the upstream of the starting-point may be used as the upstream
|
||||||
|
of the new branch, instead of the starting-point itself.
|
||||||
|
|
||||||
|
If optional FROM is non-nil, then the source branch is reset
|
||||||
|
to `FROM~', instead of to the last commit it shares with its
|
||||||
|
upstream. Interactively, FROM is only ever non-nil, if the
|
||||||
|
region selects some commits, and among those commits, FROM is
|
||||||
|
the commit that is the fewest commits ahead of the source
|
||||||
|
branch.
|
||||||
|
|
||||||
|
The commit at the other end of the selection actually does not
|
||||||
|
matter, all commits between FROM and `HEAD' are moved to the new
|
||||||
|
branch. If FROM is not reachable from `HEAD' or is reachable
|
||||||
|
from the source branch's upstream, then an error is raised."
|
||||||
|
(interactive (list (magit-read-string-ns "Spin off branch")
|
||||||
|
(car (last (magit-region-values 'commit)))))
|
||||||
|
(magit--branch-spinoff branch from t))
|
||||||
|
|
||||||
|
(defun magit--branch-spinoff (branch from checkout)
|
||||||
|
(when (magit-branch-p branch)
|
||||||
|
(user-error "Cannot spin off %s. It already exists" branch))
|
||||||
|
(when (and (not checkout)
|
||||||
|
(magit-anything-modified-p))
|
||||||
|
(message "Staying on HEAD due to uncommitted changes")
|
||||||
|
(setq checkout t))
|
||||||
|
(if-let ((current (magit-get-current-branch)))
|
||||||
|
(let ((tracked (magit-get-upstream-branch current))
|
||||||
|
base)
|
||||||
|
(when from
|
||||||
|
(unless (magit-rev-ancestor-p from current)
|
||||||
|
(user-error "Cannot spin off %s. %s is not reachable from %s"
|
||||||
|
branch from current))
|
||||||
|
(when (and tracked
|
||||||
|
(magit-rev-ancestor-p from tracked))
|
||||||
|
(user-error "Cannot spin off %s. %s is ancestor of upstream %s"
|
||||||
|
branch from tracked)))
|
||||||
|
(let ((magit-process-raise-error t))
|
||||||
|
(if checkout
|
||||||
|
(magit-call-git "checkout" "-b" branch current)
|
||||||
|
(magit-call-git "branch" branch current)))
|
||||||
|
(--when-let (magit-get-indirect-upstream-branch current)
|
||||||
|
(magit-call-git "branch" "--set-upstream-to" it branch))
|
||||||
|
(when (and tracked
|
||||||
|
(setq base
|
||||||
|
(if from
|
||||||
|
(concat from "^")
|
||||||
|
(magit-git-string "merge-base" current tracked)))
|
||||||
|
(not (magit-rev-eq base current)))
|
||||||
|
(if checkout
|
||||||
|
(magit-call-git "update-ref" "-m"
|
||||||
|
(format "reset: moving to %s" base)
|
||||||
|
(concat "refs/heads/" current) base)
|
||||||
|
(magit-call-git "reset" "--hard" base))))
|
||||||
|
(if checkout
|
||||||
|
(magit-call-git "checkout" "-b" branch)
|
||||||
|
(magit-call-git "branch" branch)))
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-reset (branch to &optional set-upstream)
|
||||||
|
"Reset a branch to the tip of another branch or any other commit.
|
||||||
|
|
||||||
|
When the branch being reset is the current branch, then do a
|
||||||
|
hard reset. If there are any uncommitted changes, then the user
|
||||||
|
has to confirm the reset because those changes would be lost.
|
||||||
|
|
||||||
|
This is useful when you have started work on a feature branch but
|
||||||
|
realize it's all crap and want to start over.
|
||||||
|
|
||||||
|
When resetting to another branch and a prefix argument is used,
|
||||||
|
then also set the target branch as the upstream of the branch
|
||||||
|
that is being reset."
|
||||||
|
(interactive
|
||||||
|
(let* ((atpoint (magit-local-branch-at-point))
|
||||||
|
(branch (magit-read-local-branch "Reset branch" atpoint)))
|
||||||
|
(list branch
|
||||||
|
(magit-completing-read (format "Reset %s to" branch)
|
||||||
|
(delete branch (magit-list-branch-names))
|
||||||
|
nil nil nil 'magit-revision-history
|
||||||
|
(or (and (not (equal branch atpoint)) atpoint)
|
||||||
|
(magit-get-upstream-branch branch)))
|
||||||
|
current-prefix-arg)))
|
||||||
|
(let ((inhibit-magit-refresh t))
|
||||||
|
(if (equal branch (magit-get-current-branch))
|
||||||
|
(if (and (magit-anything-modified-p)
|
||||||
|
(not (yes-or-no-p
|
||||||
|
"Uncommitted changes will be lost. Proceed? ")))
|
||||||
|
(user-error "Abort")
|
||||||
|
(magit-reset-hard to))
|
||||||
|
(magit-call-git "update-ref"
|
||||||
|
"-m" (format "reset: moving to %s" to)
|
||||||
|
(magit-git-string "rev-parse" "--symbolic-full-name"
|
||||||
|
branch)
|
||||||
|
to))
|
||||||
|
(when (and set-upstream (magit-branch-p to))
|
||||||
|
(magit-set-upstream-branch branch to)
|
||||||
|
(magit-branch-maybe-adjust-upstream branch to)))
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-delete (branches &optional force)
|
||||||
|
"Delete one or multiple branches.
|
||||||
|
If the region marks multiple branches, then offer to delete
|
||||||
|
those, otherwise prompt for a single branch to be deleted,
|
||||||
|
defaulting to the branch at point."
|
||||||
|
;; One would expect this to be a command as simple as, for example,
|
||||||
|
;; `magit-branch-rename'; but it turns out everyone wants to squeeze
|
||||||
|
;; a bit of extra functionality into this one, including myself.
|
||||||
|
(interactive
|
||||||
|
(let ((branches (magit-region-values 'branch t))
|
||||||
|
(force current-prefix-arg))
|
||||||
|
(if (> (length branches) 1)
|
||||||
|
(magit-confirm t nil "Delete %i branches" nil branches)
|
||||||
|
(setq branches
|
||||||
|
(list (magit-read-branch-prefer-other
|
||||||
|
(if force "Force delete branch" "Delete branch")))))
|
||||||
|
(unless force
|
||||||
|
(when-let ((unmerged (-remove #'magit-branch-merged-p branches)))
|
||||||
|
(if (magit-confirm 'delete-unmerged-branch
|
||||||
|
"Delete unmerged branch %s"
|
||||||
|
"Delete %i unmerged branches"
|
||||||
|
'noabort unmerged)
|
||||||
|
(setq force branches)
|
||||||
|
(or (setq branches (-difference branches unmerged))
|
||||||
|
(user-error "Abort")))))
|
||||||
|
(list branches force)))
|
||||||
|
(let* ((refs (mapcar #'magit-ref-fullname branches))
|
||||||
|
(ambiguous (--remove it refs)))
|
||||||
|
(when ambiguous
|
||||||
|
(user-error
|
||||||
|
"%s ambiguous. Please cleanup using git directly."
|
||||||
|
(let ((len (length ambiguous)))
|
||||||
|
(cond
|
||||||
|
((= len 1)
|
||||||
|
(format "%s is" (-first #'magit-ref-ambiguous-p branches)))
|
||||||
|
((= len (length refs))
|
||||||
|
(format "These %s names are" len))
|
||||||
|
(t
|
||||||
|
(format "%s of these names are" len))))))
|
||||||
|
(cond
|
||||||
|
((string-match "^refs/remotes/\\([^/]+\\)" (car refs))
|
||||||
|
(let* ((remote (match-string 1 (car refs)))
|
||||||
|
(offset (1+ (length remote))))
|
||||||
|
;; Assume the branches actually still exists on the remote.
|
||||||
|
(magit-run-git-async
|
||||||
|
"push" remote (--map (concat ":" (substring it offset)) branches))
|
||||||
|
;; If that is not the case, then this deletes the tracking branches.
|
||||||
|
(set-process-sentinel
|
||||||
|
magit-this-process
|
||||||
|
(apply-partially 'magit-delete-remote-branch-sentinel remote refs))))
|
||||||
|
((> (length branches) 1)
|
||||||
|
(setq branches (delete (magit-get-current-branch) branches))
|
||||||
|
(mapc 'magit-branch-maybe-delete-pr-remote branches)
|
||||||
|
(mapc 'magit-branch-unset-pushRemote branches)
|
||||||
|
(magit-run-git "branch" (if force "-D" "-d") branches))
|
||||||
|
(t ; And now for something completely different.
|
||||||
|
(let* ((branch (car branches))
|
||||||
|
(prompt (format "Branch %s is checked out. " branch)))
|
||||||
|
(when (equal branch (magit-get-current-branch))
|
||||||
|
(pcase (if (or (equal branch "master")
|
||||||
|
(not (magit-rev-verify "master")))
|
||||||
|
(magit-read-char-case prompt nil
|
||||||
|
(?d "[d]etach HEAD & delete" 'detach)
|
||||||
|
(?a "[a]bort" 'abort))
|
||||||
|
(magit-read-char-case prompt nil
|
||||||
|
(?d "[d]etach HEAD & delete" 'detach)
|
||||||
|
(?c "[c]heckout master & delete" 'master)
|
||||||
|
(?a "[a]bort" 'abort)))
|
||||||
|
(`detach (unless (or (equal force '(4))
|
||||||
|
(member branch force)
|
||||||
|
(magit-branch-merged-p branch t))
|
||||||
|
(magit-confirm 'delete-unmerged-branch
|
||||||
|
"Delete unmerged branch %s" ""
|
||||||
|
nil (list branch)))
|
||||||
|
(magit-call-git "checkout" "--detach"))
|
||||||
|
(`master (unless (or (equal force '(4))
|
||||||
|
(member branch force)
|
||||||
|
(magit-branch-merged-p branch "master"))
|
||||||
|
(magit-confirm 'delete-unmerged-branch
|
||||||
|
"Delete unmerged branch %s" ""
|
||||||
|
nil (list branch)))
|
||||||
|
(magit-call-git "checkout" "master"))
|
||||||
|
(`abort (user-error "Abort")))
|
||||||
|
(setq force t))
|
||||||
|
(magit-branch-maybe-delete-pr-remote branch)
|
||||||
|
(magit-branch-unset-pushRemote branch)
|
||||||
|
(magit-run-git "branch" (if force "-D" "-d") branch))))))
|
||||||
|
|
||||||
|
(put 'magit-branch-delete 'interactive-only t)
|
||||||
|
|
||||||
|
(defun magit-branch-maybe-delete-pr-remote (branch)
|
||||||
|
(when-let ((remote (magit-get "branch" branch "pullRequestRemote")))
|
||||||
|
(let* ((variable (format "remote.%s.fetch" remote))
|
||||||
|
(refspecs (magit-get-all variable)))
|
||||||
|
(unless (member (format "+refs/heads/*:refs/remotes/%s/*" remote)
|
||||||
|
refspecs)
|
||||||
|
(let ((refspec
|
||||||
|
(if (equal (magit-get "branch" branch "pushRemote") remote)
|
||||||
|
(format "+refs/heads/%s:refs/remotes/%s/%s"
|
||||||
|
branch remote branch)
|
||||||
|
(let ((merge (magit-get "branch" branch "merge")))
|
||||||
|
(and merge
|
||||||
|
(string-prefix-p "refs/heads/" merge)
|
||||||
|
(setq merge (substring merge 11))
|
||||||
|
(format "+refs/heads/%s:refs/remotes/%s/%s"
|
||||||
|
merge remote merge))))))
|
||||||
|
(when (member refspec refspecs)
|
||||||
|
(if (and (= (length refspecs) 1)
|
||||||
|
(magit-confirm 'delete-pr-remote
|
||||||
|
(format "Also delete remote %s (%s)" remote
|
||||||
|
"no pull-request branch remains")
|
||||||
|
nil t))
|
||||||
|
(magit-call-git "remote" "rm" remote)
|
||||||
|
(magit-call-git "config" "--unset-all" variable
|
||||||
|
(format "^%s$" (regexp-quote refspec))))))))))
|
||||||
|
|
||||||
|
(defun magit-branch-unset-pushRemote (branch)
|
||||||
|
(magit-set nil "branch" branch "pushRemote"))
|
||||||
|
|
||||||
|
(defun magit-delete-remote-branch-sentinel (remote refs process event)
|
||||||
|
(when (memq (process-status process) '(exit signal))
|
||||||
|
(if (= (process-exit-status process) 1)
|
||||||
|
(if-let ((on-remote (--map (concat "refs/remotes/" remote "/" it)
|
||||||
|
(magit-remote-list-branches remote)))
|
||||||
|
(rest (--filter (and (not (member it on-remote))
|
||||||
|
(magit-ref-exists-p it))
|
||||||
|
refs)))
|
||||||
|
(progn
|
||||||
|
(process-put process 'inhibit-refresh t)
|
||||||
|
(magit-process-sentinel process event)
|
||||||
|
(setq magit-this-error nil)
|
||||||
|
(message "Some remote branches no longer exist. %s"
|
||||||
|
"Deleting just the local tracking refs instead...")
|
||||||
|
(dolist (ref rest)
|
||||||
|
(magit-call-git "update-ref" "-d" ref))
|
||||||
|
(magit-refresh)
|
||||||
|
(message "Deleting local remote-tracking refs...done"))
|
||||||
|
(magit-process-sentinel process event))
|
||||||
|
(magit-process-sentinel process event))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-rename (old new &optional force)
|
||||||
|
"Rename the branch named OLD to NEW.
|
||||||
|
|
||||||
|
With a prefix argument FORCE, rename even if a branch named NEW
|
||||||
|
already exists.
|
||||||
|
|
||||||
|
If `branch.OLD.pushRemote' is set, then unset it. Depending on
|
||||||
|
the value of `magit-branch-rename-push-target' (which see) maybe
|
||||||
|
set `branch.NEW.pushRemote' and maybe rename the push-target on
|
||||||
|
the remote."
|
||||||
|
(interactive
|
||||||
|
(let ((branch (magit-read-local-branch "Rename branch")))
|
||||||
|
(list branch
|
||||||
|
(magit-read-string-ns (format "Rename branch '%s' to" branch)
|
||||||
|
nil 'magit-revision-history)
|
||||||
|
current-prefix-arg)))
|
||||||
|
(when (string-match "\\`heads/\\(.+\\)" old)
|
||||||
|
(setq old (match-string 1 old)))
|
||||||
|
(when (equal old new)
|
||||||
|
(user-error "Old and new branch names are the same"))
|
||||||
|
(magit-call-git "branch" (if force "-M" "-m") old new)
|
||||||
|
(when magit-branch-rename-push-target
|
||||||
|
(let ((remote (magit-get-push-remote old))
|
||||||
|
(old-specific (magit-get "branch" old "pushRemote"))
|
||||||
|
(new-specific (magit-get "branch" new "pushRemote")))
|
||||||
|
(when (and old-specific (or force (not new-specific)))
|
||||||
|
;; Keep the target setting branch specific, even if that is
|
||||||
|
;; redundant. But if a branch by the same name existed before
|
||||||
|
;; and the rename isn't forced, then do not change a leftover
|
||||||
|
;; setting. Such a leftover setting may or may not conform to
|
||||||
|
;; what we expect here...
|
||||||
|
(magit-set old-specific "branch" new "pushRemote"))
|
||||||
|
(when (and (equal (magit-get-push-remote new) remote)
|
||||||
|
;; ...and if it does not, then we must abort.
|
||||||
|
(not (eq magit-branch-rename-push-target 'local-only))
|
||||||
|
(or (not (memq magit-branch-rename-push-target
|
||||||
|
'(forge-only github-only)))
|
||||||
|
(and (require (quote forge) nil t)
|
||||||
|
(fboundp 'forge--forge-remote-p)
|
||||||
|
(forge--forge-remote-p remote))))
|
||||||
|
(let ((old-target (magit-get-push-branch old t))
|
||||||
|
(new-target (magit-get-push-branch new t))
|
||||||
|
(remote (magit-get-push-remote new)))
|
||||||
|
(when (and old-target
|
||||||
|
(not new-target)
|
||||||
|
(magit-y-or-n-p (format "Also rename %S to %S on \"%s\""
|
||||||
|
old new remote)))
|
||||||
|
;; Rename on (i.e. within) the remote, but only if the
|
||||||
|
;; destination ref doesn't exist yet. If that ref already
|
||||||
|
;; exists, then it probably is of some value and we better
|
||||||
|
;; not touch it. Ignore what the local ref points at,
|
||||||
|
;; i.e. if the local and the remote ref didn't point at
|
||||||
|
;; the same commit before the rename then keep it that way.
|
||||||
|
(magit-call-git "push" "-v" remote
|
||||||
|
(format "%s:refs/heads/%s" old-target new)
|
||||||
|
(format ":refs/heads/%s" old)))))))
|
||||||
|
(magit-branch-unset-pushRemote old)
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-shelve (branch)
|
||||||
|
"Shelve a BRANCH.
|
||||||
|
Rename \"refs/heads/BRANCH\" to \"refs/shelved/BRANCH\",
|
||||||
|
and also rename the respective reflog file."
|
||||||
|
(interactive (list (magit-read-other-local-branch "Shelve branch")))
|
||||||
|
(let ((old (concat "refs/heads/" branch))
|
||||||
|
(new (concat "refs/shelved/" branch)))
|
||||||
|
(magit-git "update-ref" new old "")
|
||||||
|
(magit--rename-reflog-file old new)
|
||||||
|
(magit-branch-unset-pushRemote branch)
|
||||||
|
(magit-run-git "branch" "-D" branch)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-branch-unshelve (branch)
|
||||||
|
"Unshelve a BRANCH
|
||||||
|
Rename \"refs/shelved/BRANCH\" to \"refs/heads/BRANCH\",
|
||||||
|
and also rename the respective reflog file."
|
||||||
|
(interactive
|
||||||
|
(list (magit-completing-read
|
||||||
|
"Unshelve branch"
|
||||||
|
(--map (substring it 8)
|
||||||
|
(magit-list-refnames "refs/shelved"))
|
||||||
|
nil t)))
|
||||||
|
(let ((old (concat "refs/shelved/" branch))
|
||||||
|
(new (concat "refs/heads/" branch)))
|
||||||
|
(magit-git "update-ref" new old "")
|
||||||
|
(magit--rename-reflog-file old new)
|
||||||
|
(magit-run-git "update-ref" "-d" old)))
|
||||||
|
|
||||||
|
(defun magit--rename-reflog-file (old new)
|
||||||
|
(let ((old (magit-git-dir (concat "logs/" old)))
|
||||||
|
(new (magit-git-dir (concat "logs/" new))))
|
||||||
|
(when (file-exists-p old)
|
||||||
|
(make-directory (file-name-directory new) t)
|
||||||
|
(rename-file old new t))))
|
||||||
|
|
||||||
|
;;; Configure
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-branch-configure "magit-branch" nil t)
|
||||||
|
(define-transient-command magit-branch-configure (branch)
|
||||||
|
"Configure a branch."
|
||||||
|
:man-page "git-branch"
|
||||||
|
[:description
|
||||||
|
(lambda ()
|
||||||
|
(concat
|
||||||
|
(propertize "Configure " 'face 'transient-heading)
|
||||||
|
(propertize (oref transient--prefix scope) 'face 'magit-branch-local)))
|
||||||
|
("d" magit-branch.<branch>.description)
|
||||||
|
("u" magit-branch.<branch>.merge/remote)
|
||||||
|
("r" magit-branch.<branch>.rebase)
|
||||||
|
("p" magit-branch.<branch>.pushRemote)]
|
||||||
|
["Configure repository defaults"
|
||||||
|
("R" magit-pull.rebase)
|
||||||
|
("P" magit-remote.pushDefault)]
|
||||||
|
["Configure branch creation"
|
||||||
|
("a m" magit-branch.autoSetupMerge)
|
||||||
|
("a r" magit-branch.autoSetupRebase)]
|
||||||
|
(interactive
|
||||||
|
(list (or (and (not current-prefix-arg)
|
||||||
|
(not (and magit-branch-direct-configure
|
||||||
|
(eq current-transient-command 'magit-branch)))
|
||||||
|
(magit-get-current-branch))
|
||||||
|
(magit--read-branch-scope))))
|
||||||
|
(transient-setup 'magit-branch-configure nil nil :scope branch))
|
||||||
|
|
||||||
|
(defun magit--read-branch-scope (&optional obj)
|
||||||
|
(magit-read-local-branch
|
||||||
|
(if obj
|
||||||
|
(format "Set %s for branch"
|
||||||
|
(format (oref obj variable) "<name>"))
|
||||||
|
"Configure branch")))
|
||||||
|
|
||||||
|
(define-suffix-command magit-branch.<branch>.description (branch)
|
||||||
|
"Edit the description of BRANCH."
|
||||||
|
:class 'magit--git-variable
|
||||||
|
:transient nil
|
||||||
|
:variable "branch.%s.description"
|
||||||
|
(interactive (list (oref current-transient-prefix scope)))
|
||||||
|
(magit-run-git-with-editor "branch" "--edit-description" branch))
|
||||||
|
|
||||||
|
(add-hook 'find-file-hook 'magit-branch-description-check-buffers)
|
||||||
|
|
||||||
|
(defun magit-branch-description-check-buffers ()
|
||||||
|
(and buffer-file-name
|
||||||
|
(string-match-p "/\\(BRANCH\\|EDIT\\)_DESCRIPTION\\'" buffer-file-name)))
|
||||||
|
|
||||||
|
(defclass magit--git-branch:upstream (magit--git-variable)
|
||||||
|
((format :initform " %k %m %M\n %r %R")))
|
||||||
|
|
||||||
|
(define-infix-command magit-branch.<branch>.merge/remote ()
|
||||||
|
:class 'magit--git-branch:upstream)
|
||||||
|
|
||||||
|
(cl-defmethod transient-init-value ((obj magit--git-branch:upstream))
|
||||||
|
(when-let ((branch (oref transient--prefix scope))
|
||||||
|
(remote (magit-get "branch" branch "remote"))
|
||||||
|
(merge (magit-get "branch" branch "merge")))
|
||||||
|
(oset obj value (list remote merge))))
|
||||||
|
|
||||||
|
(cl-defmethod transient-infix-read ((obj magit--git-branch:upstream))
|
||||||
|
(if (oref obj value)
|
||||||
|
(oset obj value nil)
|
||||||
|
(magit-read-upstream-branch (oref transient--prefix scope) "Upstream")))
|
||||||
|
|
||||||
|
(cl-defmethod transient-infix-set ((obj magit--git-branch:upstream) refname)
|
||||||
|
(magit-set-upstream-branch (oref transient--prefix scope) refname)
|
||||||
|
(oset obj value
|
||||||
|
(let ((branch (oref transient--prefix scope)))
|
||||||
|
(when-let ((r (magit-get "branch" branch "remote"))
|
||||||
|
(m (magit-get "branch" branch "merge")))
|
||||||
|
(list r m))))
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
(cl-defmethod transient-format ((obj magit--git-branch:upstream))
|
||||||
|
(let ((branch (oref transient--prefix scope)))
|
||||||
|
(format-spec
|
||||||
|
(oref obj format)
|
||||||
|
`((?k . ,(transient-format-key obj))
|
||||||
|
(?r . ,(format "branch.%s.remote" branch))
|
||||||
|
(?m . ,(format "branch.%s.merge" branch))
|
||||||
|
(?R . ,(transient-format-value obj #'car))
|
||||||
|
(?M . ,(transient-format-value obj #'cadr))))))
|
||||||
|
|
||||||
|
(cl-defmethod transient-format-value ((obj magit--git-branch:upstream) key)
|
||||||
|
(if-let ((value (funcall key (oref obj value))))
|
||||||
|
(propertize value 'face 'transient-argument)
|
||||||
|
(propertize "unset" 'face 'transient-inactive-argument)))
|
||||||
|
|
||||||
|
(define-infix-command magit-branch.<branch>.rebase ()
|
||||||
|
:class 'magit--git-variable:choices
|
||||||
|
:scope 'magit--read-branch-scope
|
||||||
|
:variable "branch.%s.rebase"
|
||||||
|
:fallback "pull.rebase"
|
||||||
|
:choices '("true" "false")
|
||||||
|
:default "false")
|
||||||
|
|
||||||
|
(define-infix-command magit-branch.<branch>.pushRemote ()
|
||||||
|
:class 'magit--git-variable:choices
|
||||||
|
:scope 'magit--read-branch-scope
|
||||||
|
:variable "branch.%s.pushRemote"
|
||||||
|
:fallback "remote.pushDefault"
|
||||||
|
:choices 'magit-list-remotes)
|
||||||
|
|
||||||
|
(define-infix-command magit-pull.rebase ()
|
||||||
|
:class 'magit--git-variable:choices
|
||||||
|
:variable "pull.rebase"
|
||||||
|
:choices '("true" "false")
|
||||||
|
:default "false")
|
||||||
|
|
||||||
|
(define-infix-command magit-remote.pushDefault ()
|
||||||
|
:class 'magit--git-variable:choices
|
||||||
|
:variable "remote.pushDefault"
|
||||||
|
:choices 'magit-list-remotes)
|
||||||
|
|
||||||
|
(define-infix-command magit-branch.autoSetupMerge ()
|
||||||
|
:class 'magit--git-variable:choices
|
||||||
|
:variable "branch.autoSetupMerge"
|
||||||
|
:choices '("always" "true" "false")
|
||||||
|
:default "true")
|
||||||
|
|
||||||
|
(define-infix-command magit-branch.autoSetupRebase ()
|
||||||
|
:class 'magit--git-variable:choices
|
||||||
|
:variable "branch.autoSetupRebase"
|
||||||
|
:choices '("always" "local" "remote" "never")
|
||||||
|
:default "never")
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-branch)
|
||||||
|
;;; magit-branch.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-branch.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-branch.elc
Normal file
Binary file not shown.
267
elpa/magit-20191030.1315/magit-clone.el
Normal file
267
elpa/magit-20191030.1315/magit-clone.el
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
;;; magit-clone.el --- clone a repository -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2008-2019 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 clone commands.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defcustom magit-clone-set-remote-head nil
|
||||||
|
"Whether cloning creates the symbolic-ref `<remote>/HEAD'."
|
||||||
|
:package-version '(magit . "2.4.2")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-clone-set-remote.pushDefault 'ask
|
||||||
|
"Whether to set the value of `remote.pushDefault' after cloning.
|
||||||
|
|
||||||
|
If t, then set without asking. If nil, then don't set. If
|
||||||
|
`ask', then ask."
|
||||||
|
:package-version '(magit . "2.4.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(choice (const :tag "set" t)
|
||||||
|
(const :tag "ask" ask)
|
||||||
|
(const :tag "don't set" nil)))
|
||||||
|
|
||||||
|
(defcustom magit-clone-default-directory nil
|
||||||
|
"Default directory to use when `magit-clone' reads destination.
|
||||||
|
If nil (the default), then use the value of `default-directory'.
|
||||||
|
If a directory, then use that. If a function, then call that
|
||||||
|
with the remote url as only argument and use the returned value."
|
||||||
|
:package-version '(magit . "2.90.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(choice (const :tag "value of default-directory")
|
||||||
|
(directory :tag "constant directory")
|
||||||
|
(function :tag "function's value")))
|
||||||
|
|
||||||
|
(defcustom magit-clone-always-transient nil
|
||||||
|
"Whether `magit-clone' always acts as a transient prefix command.
|
||||||
|
If nil, then a prefix argument has to be used to show the transient
|
||||||
|
popup instead of invoking the default suffix `magit-clone-regular'
|
||||||
|
directly."
|
||||||
|
:package-version '(magit . "2.91.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-clone-name-alist
|
||||||
|
'(("\\`\\(?:github:\\|gh:\\)?\\([^:]+\\)\\'" "github.com" "github.user")
|
||||||
|
("\\`\\(?:gitlab:\\|gl:\\)\\([^:]+\\)\\'" "gitlab.com" "gitlab.user"))
|
||||||
|
"Alist mapping repository names to repository urls.
|
||||||
|
|
||||||
|
Each element has the form (REGEXP HOSTNAME USER). When the user
|
||||||
|
enters a name when a cloning command asks for a name or url, then
|
||||||
|
that is looked up in this list. The first element whose REGEXP
|
||||||
|
matches is used.
|
||||||
|
|
||||||
|
The format specified by option `magit-clone-url-format' is used
|
||||||
|
to turn the name into an url, using HOSTNAME and the repository
|
||||||
|
name. If the provided name contains a slash, then that is used.
|
||||||
|
Otherwise if the name omits the owner of the repository, then the
|
||||||
|
default user specified in the matched entry is used.
|
||||||
|
|
||||||
|
If USER contains a dot, then it is treated as a Git variable and
|
||||||
|
the value of that is used as the username. Otherwise it is used
|
||||||
|
as the username itself."
|
||||||
|
:package-version '(magit . "2.91.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(repeat (list regexp
|
||||||
|
(string :tag "hostname")
|
||||||
|
(string :tag "user name or git variable"))))
|
||||||
|
|
||||||
|
(defcustom magit-clone-url-format "git@%h:%n.git"
|
||||||
|
"Format used when turning repository names into urls.
|
||||||
|
%h is the hostname and %n is the repository name, including
|
||||||
|
the name of the owner. Also see `magit-clone-name-alist'."
|
||||||
|
:package-version '(magit . "2.91.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'regexp)
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-clone "magit-clone" nil t)
|
||||||
|
(define-transient-command magit-clone (&optional transient)
|
||||||
|
"Clone a repository."
|
||||||
|
:man-page "git-clone"
|
||||||
|
["Fetch arguments"
|
||||||
|
("-B" "Clone a single branch" "--single-branch")
|
||||||
|
("-n" "Do not clone tags" "--no-tags")
|
||||||
|
("-S" "Clones submodules" "--recurse-submodules" :level 6)
|
||||||
|
("-l" "Do not optimize" "--no-local" :level 7)]
|
||||||
|
["Setup arguments"
|
||||||
|
("-o" "Set name of remote" ("-o" "--origin="))
|
||||||
|
("-b" "Set HEAD branch" ("-b" "--branch="))
|
||||||
|
("-g" "Separate git directory" "--separate-git-dir="
|
||||||
|
transient-read-directory :level 7)
|
||||||
|
("-t" "Use template directory" "--template="
|
||||||
|
transient-read-existing-directory :level 6)]
|
||||||
|
["Local sharing arguments"
|
||||||
|
("-s" "Share objects" ("-s" "--shared" :level 7))
|
||||||
|
("-h" "Do not use hardlinks" "--no-hardlinks")]
|
||||||
|
["Clone"
|
||||||
|
("C" "regular" magit-clone-regular)
|
||||||
|
("s" "shallow" magit-clone-shallow)
|
||||||
|
("d" "shallow since date" magit-clone-shallow-since :level 7)
|
||||||
|
("e" "shallow excluding" magit-clone-shallow-exclude :level 7)
|
||||||
|
("b" "bare" magit-clone-bare)
|
||||||
|
("m" "mirror" magit-clone-mirror)]
|
||||||
|
(interactive (list (or magit-clone-always-transient current-prefix-arg)))
|
||||||
|
(if transient
|
||||||
|
(transient-setup #'magit-clone)
|
||||||
|
(call-interactively #'magit-clone-regular)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-clone-regular (repository directory args)
|
||||||
|
"Create a clone of REPOSITORY in DIRECTORY.
|
||||||
|
Then show the status buffer for the new repository."
|
||||||
|
(interactive (magit-clone-read-args))
|
||||||
|
(magit-clone-internal repository directory args))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-clone-shallow (repository directory args depth)
|
||||||
|
"Create a shallow clone of REPOSITORY in DIRECTORY.
|
||||||
|
Then show the status buffer for the new repository.
|
||||||
|
With a prefix argument read the DEPTH of the clone;
|
||||||
|
otherwise use 1."
|
||||||
|
(interactive (append (magit-clone-read-args)
|
||||||
|
(list (if current-prefix-arg
|
||||||
|
(read-number "Depth: " 1)
|
||||||
|
1))))
|
||||||
|
(magit-clone-internal repository directory
|
||||||
|
(cons (format "--depth=%s" depth) args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-clone-shallow-since (repository directory args date)
|
||||||
|
"Create a shallow clone of REPOSITORY in DIRECTORY.
|
||||||
|
Then show the status buffer for the new repository.
|
||||||
|
Exclude commits before DATE, which is read from the
|
||||||
|
user."
|
||||||
|
(interactive (append (magit-clone-read-args)
|
||||||
|
(list (transient-read-date "Exclude commits before: "
|
||||||
|
nil nil))))
|
||||||
|
(magit-clone-internal repository directory
|
||||||
|
(cons (format "--shallow-since=%s" date) args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-clone-shallow-exclude (repository directory args exclude)
|
||||||
|
"Create a shallow clone of REPOSITORY in DIRECTORY.
|
||||||
|
Then show the status buffer for the new repository.
|
||||||
|
Exclude commits reachable from EXCLUDE, which is a
|
||||||
|
branch or tag read from the user."
|
||||||
|
(interactive (append (magit-clone-read-args)
|
||||||
|
(list (read-string "Exclude commits reachable from: "))))
|
||||||
|
(magit-clone-internal repository directory
|
||||||
|
(cons (format "--shallow-exclude=%s" exclude) args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-clone-bare (repository directory args)
|
||||||
|
"Create a bare clone of REPOSITORY in DIRECTORY.
|
||||||
|
Then show the status buffer for the new repository."
|
||||||
|
(interactive (magit-clone-read-args))
|
||||||
|
(magit-clone-internal repository directory (cons "--bare" args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-clone-mirror (repository directory args)
|
||||||
|
"Create a mirror of REPOSITORY in DIRECTORY.
|
||||||
|
Then show the status buffer for the new repository."
|
||||||
|
(interactive (magit-clone-read-args))
|
||||||
|
(magit-clone-internal repository directory (cons "--mirror" args)))
|
||||||
|
|
||||||
|
(defun magit-clone-internal (repository directory args)
|
||||||
|
(run-hooks 'magit-credential-hook)
|
||||||
|
(setq directory (file-name-as-directory (expand-file-name directory)))
|
||||||
|
(magit-run-git-async "clone" args "--" repository
|
||||||
|
(magit-convert-filename-for-git directory))
|
||||||
|
;; Don't refresh the buffer we're calling from.
|
||||||
|
(process-put magit-this-process 'inhibit-refresh t)
|
||||||
|
(set-process-sentinel
|
||||||
|
magit-this-process
|
||||||
|
(lambda (process event)
|
||||||
|
(when (memq (process-status process) '(exit signal))
|
||||||
|
(let ((magit-process-raise-error t))
|
||||||
|
(magit-process-sentinel process event)))
|
||||||
|
(when (and (eq (process-status process) 'exit)
|
||||||
|
(= (process-exit-status process) 0))
|
||||||
|
(unless (memq (car args) '("--bare" "--mirror"))
|
||||||
|
(let ((default-directory directory))
|
||||||
|
(when (or (eq magit-clone-set-remote.pushDefault t)
|
||||||
|
(and magit-clone-set-remote.pushDefault
|
||||||
|
(y-or-n-p "Set `remote.pushDefault' to \"origin\"? ")))
|
||||||
|
(setf (magit-get "remote.pushDefault") "origin"))
|
||||||
|
(unless magit-clone-set-remote-head
|
||||||
|
(magit-remote-unset-head "origin"))))
|
||||||
|
(with-current-buffer (process-get process 'command-buf)
|
||||||
|
(magit-status-setup-buffer directory))))))
|
||||||
|
|
||||||
|
(defun magit-clone-read-args ()
|
||||||
|
(let ((repo (magit-clone-read-repository)))
|
||||||
|
(list repo
|
||||||
|
(read-directory-name
|
||||||
|
"Clone to: "
|
||||||
|
(if (functionp magit-clone-default-directory)
|
||||||
|
(funcall magit-clone-default-directory repo)
|
||||||
|
magit-clone-default-directory)
|
||||||
|
nil nil
|
||||||
|
(and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" repo)
|
||||||
|
(match-string 1 repo)))
|
||||||
|
(transient-args 'magit-clone))))
|
||||||
|
|
||||||
|
(defun magit-clone-read-repository ()
|
||||||
|
(magit-read-char-case "Clone from " nil
|
||||||
|
(?u "[u]rl or name"
|
||||||
|
(let ((str (magit-read-string-ns "Clone from url or name")))
|
||||||
|
(if (string-match-p "\\(://\\|@\\)" str)
|
||||||
|
str
|
||||||
|
(magit-clone--name-to-url str))))
|
||||||
|
(?p "[p]ath"
|
||||||
|
(read-directory-name "Clone repository: "))
|
||||||
|
(?l "or [l]ocal url"
|
||||||
|
(concat "file://" (read-directory-name "Clone repository: file://")))))
|
||||||
|
|
||||||
|
(defun magit-clone--name-to-url (name)
|
||||||
|
(or (-some
|
||||||
|
(pcase-lambda (`(,re ,host ,user))
|
||||||
|
(and (string-match re name)
|
||||||
|
(let ((repo (match-string 1 name)))
|
||||||
|
(format-spec
|
||||||
|
magit-clone-url-format
|
||||||
|
`((?h . ,host)
|
||||||
|
(?n . ,(if (string-match-p "/" repo)
|
||||||
|
repo
|
||||||
|
(if (string-match-p "\\." user)
|
||||||
|
(if-let ((user (magit-get user)))
|
||||||
|
(concat user "/" repo)
|
||||||
|
(user-error
|
||||||
|
"Set %S or specify owner explicitly" user))
|
||||||
|
(concat user "/" repo)))))))))
|
||||||
|
magit-clone-name-alist)
|
||||||
|
(user-error "Not an url and no matching entry in `%s'"
|
||||||
|
'magit-clone-name-alist)))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-clone)
|
||||||
|
;;; magit-clone.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-clone.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-clone.elc
Normal file
Binary file not shown.
570
elpa/magit-20191030.1315/magit-commit.el
Normal file
570
elpa/magit-20191030.1315/magit-commit.el
Normal file
@@ -0,0 +1,570 @@
|
|||||||
|
;;; magit-commit.el --- create Git commits -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2008-2019 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 commands for creating Git commits. These
|
||||||
|
;; commands just initiate the commit, support for writing the commit
|
||||||
|
;; messages is implemented in `git-commit.el'.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
(require 'magit-sequence)
|
||||||
|
|
||||||
|
(eval-when-compile (require 'epa)) ; for `epa-protocol'
|
||||||
|
(eval-when-compile (require 'epg))
|
||||||
|
(eval-when-compile (require 'subr-x))
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defcustom magit-commit-ask-to-stage 'verbose
|
||||||
|
"Whether to ask to stage all unstaged changes when committing and nothing is staged."
|
||||||
|
:package-version '(magit . "2.3.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(choice (const :tag "Ask" t)
|
||||||
|
(const :tag "Ask showing diff" verbose)
|
||||||
|
(const :tag "Stage without confirmation" stage)
|
||||||
|
(const :tag "Don't ask" nil)))
|
||||||
|
|
||||||
|
(defcustom magit-commit-show-diff t
|
||||||
|
"Whether the relevant diff is automatically shown when committing."
|
||||||
|
:package-version '(magit . "2.3.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-commit-extend-override-date t
|
||||||
|
"Whether using `magit-commit-extend' changes the committer date."
|
||||||
|
:package-version '(magit . "2.3.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-commit-reword-override-date t
|
||||||
|
"Whether using `magit-commit-reword' changes the committer date."
|
||||||
|
:package-version '(magit . "2.3.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-commit-squash-confirm t
|
||||||
|
"Whether the commit targeted by squash and fixup has to be confirmed.
|
||||||
|
When non-nil then the commit at point (if any) is used as default
|
||||||
|
choice, otherwise it has to be confirmed. This option only
|
||||||
|
affects `magit-commit-squash' and `magit-commit-fixup'. The
|
||||||
|
\"instant\" variants always require confirmation because making
|
||||||
|
an error while using those is harder to recover from."
|
||||||
|
:package-version '(magit . "2.1.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-post-commit-hook nil
|
||||||
|
"Hook run after creating a commit without the user editing a message.
|
||||||
|
|
||||||
|
This hook is run by `magit-refresh' if `this-command' is a member
|
||||||
|
of `magit-post-stage-hook-commands'. This only includes commands
|
||||||
|
named `magit-commit-*' that do *not* require that the user edits
|
||||||
|
the commit message in a buffer and then finishes by pressing
|
||||||
|
\\<with-editor-mode-map>\\[with-editor-finish].
|
||||||
|
|
||||||
|
Also see `git-commit-post-finish-hook'."
|
||||||
|
:package-version '(magit . "2.90.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type 'hook)
|
||||||
|
|
||||||
|
(defvar magit-post-commit-hook-commands
|
||||||
|
'(magit-commit-extend
|
||||||
|
magit-commit-fixup
|
||||||
|
magit-commit-augment
|
||||||
|
magit-commit-instant-fixup
|
||||||
|
magit-commit-instant-squash))
|
||||||
|
|
||||||
|
;;; Popup
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-commit "magit-commit" nil t)
|
||||||
|
(define-transient-command magit-commit ()
|
||||||
|
"Create a new commit or replace an existing commit."
|
||||||
|
:info-manual "(magit)Initiating a Commit"
|
||||||
|
:man-page "git-commit"
|
||||||
|
["Arguments"
|
||||||
|
("-a" "Stage all modified and deleted files" ("-a" "--all"))
|
||||||
|
("-e" "Allow empty commit" "--allow-empty")
|
||||||
|
("-v" "Show diff of changes to be committed" ("-v" "--verbose"))
|
||||||
|
("-n" "Disable hooks" ("-n" "--no-verify"))
|
||||||
|
("-R" "Claim authorship and reset author date" "--reset-author")
|
||||||
|
(magit:--author :description "Override the author")
|
||||||
|
(7 "-D" "Override the author date" "--date=" transient-read-date)
|
||||||
|
("-s" "Add Signed-off-by line" ("-s" "--signoff"))
|
||||||
|
(5 magit:--gpg-sign)
|
||||||
|
(magit-commit:--reuse-message)]
|
||||||
|
[["Create"
|
||||||
|
("c" "Commit" magit-commit-create)]
|
||||||
|
["Edit HEAD"
|
||||||
|
("e" "Extend" magit-commit-extend)
|
||||||
|
("w" "Reword" magit-commit-reword)
|
||||||
|
("a" "Amend" magit-commit-amend)
|
||||||
|
(6 "n" "Reshelve" magit-commit-reshelve)]
|
||||||
|
["Edit"
|
||||||
|
("f" "Fixup" magit-commit-fixup)
|
||||||
|
("s" "Squash" magit-commit-squash)
|
||||||
|
("A" "Augment" magit-commit-augment)
|
||||||
|
(6 "x" "Absorb changes" magit-commit-absorb)]
|
||||||
|
[""
|
||||||
|
("F" "Instant fixup" magit-commit-instant-fixup)
|
||||||
|
("S" "Instant squash" magit-commit-instant-squash)]]
|
||||||
|
(interactive)
|
||||||
|
(if-let ((buffer (magit-commit-message-buffer)))
|
||||||
|
(switch-to-buffer buffer)
|
||||||
|
(transient-setup 'magit-commit)))
|
||||||
|
|
||||||
|
(defun magit-commit-arguments nil
|
||||||
|
(transient-args 'magit-commit))
|
||||||
|
|
||||||
|
(define-infix-argument magit:--gpg-sign ()
|
||||||
|
:description "Sign using gpg"
|
||||||
|
:class 'transient-option
|
||||||
|
:shortarg "-S"
|
||||||
|
:argument "--gpg-sign="
|
||||||
|
:allow-empty t
|
||||||
|
:reader 'magit-read-gpg-secret-key)
|
||||||
|
|
||||||
|
(defvar magit-gpg-secret-key-hist nil)
|
||||||
|
|
||||||
|
(defun magit-read-gpg-secret-key (prompt &optional initial-input history)
|
||||||
|
(require 'epa)
|
||||||
|
(let* ((keys (mapcar
|
||||||
|
(lambda (obj)
|
||||||
|
(let ((key (epg-sub-key-id (car (epg-key-sub-key-list obj))))
|
||||||
|
(author
|
||||||
|
(when-let ((id-obj (car (epg-key-user-id-list obj))))
|
||||||
|
(let ((id-str (epg-user-id-string id-obj)))
|
||||||
|
(if (stringp id-str)
|
||||||
|
id-str
|
||||||
|
(epg-decode-dn id-obj))))))
|
||||||
|
(propertize key 'display (concat key " " author))))
|
||||||
|
(epg-list-keys (epg-make-context epa-protocol) nil t)))
|
||||||
|
(choice (completing-read prompt keys nil nil nil
|
||||||
|
history nil initial-input)))
|
||||||
|
(set-text-properties 0 (length choice) nil choice)
|
||||||
|
choice))
|
||||||
|
|
||||||
|
(define-infix-argument magit-commit:--reuse-message ()
|
||||||
|
:description "Reuse commit message"
|
||||||
|
:class 'transient-option
|
||||||
|
:shortarg "-C"
|
||||||
|
:argument "--reuse-message="
|
||||||
|
:reader 'magit-read-reuse-message
|
||||||
|
:history-key 'magit-revision-history)
|
||||||
|
|
||||||
|
(defun magit-read-reuse-message (prompt &optional default history)
|
||||||
|
(magit-completing-read prompt (magit-list-refnames)
|
||||||
|
nil nil nil history
|
||||||
|
(or default
|
||||||
|
(and (magit-rev-verify "ORIG_HEAD")
|
||||||
|
"ORIG_HEAD"))))
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-create (&optional args)
|
||||||
|
"Create a new commit on `HEAD'.
|
||||||
|
With a prefix argument, amend to the commit at `HEAD' instead.
|
||||||
|
\n(git commit [--amend] ARGS)"
|
||||||
|
(interactive (if current-prefix-arg
|
||||||
|
(list (cons "--amend" (magit-commit-arguments)))
|
||||||
|
(list (magit-commit-arguments))))
|
||||||
|
(when (member "--all" args)
|
||||||
|
(setq this-command 'magit-commit-all))
|
||||||
|
(when (setq args (magit-commit-assert args))
|
||||||
|
(let ((default-directory (magit-toplevel)))
|
||||||
|
(magit-run-git-with-editor "commit" args))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-amend (&optional args)
|
||||||
|
"Amend the last commit.
|
||||||
|
\n(git commit --amend ARGS)"
|
||||||
|
(interactive (list (magit-commit-arguments)))
|
||||||
|
(magit-commit-amend-assert)
|
||||||
|
(magit-run-git-with-editor "commit" "--amend" args))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-extend (&optional args override-date)
|
||||||
|
"Amend the last commit, without editing the message.
|
||||||
|
|
||||||
|
With a prefix argument keep the committer date, otherwise change
|
||||||
|
it. The option `magit-commit-extend-override-date' can be used
|
||||||
|
to inverse the meaning of the prefix argument. \n(git commit
|
||||||
|
--amend --no-edit)"
|
||||||
|
(interactive (list (magit-commit-arguments)
|
||||||
|
(if current-prefix-arg
|
||||||
|
(not magit-commit-extend-override-date)
|
||||||
|
magit-commit-extend-override-date)))
|
||||||
|
(when (setq args (magit-commit-assert args (not override-date)))
|
||||||
|
(magit-commit-amend-assert)
|
||||||
|
(let ((process-environment process-environment))
|
||||||
|
(unless override-date
|
||||||
|
(push (magit-rev-format "GIT_COMMITTER_DATE=%cD") process-environment))
|
||||||
|
(magit-run-git-with-editor "commit" "--amend" "--no-edit" args))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-reword (&optional args override-date)
|
||||||
|
"Reword the last commit, ignoring staged changes.
|
||||||
|
|
||||||
|
With a prefix argument keep the committer date, otherwise change
|
||||||
|
it. The option `magit-commit-reword-override-date' can be used
|
||||||
|
to inverse the meaning of the prefix argument.
|
||||||
|
|
||||||
|
Non-interactively respect the optional OVERRIDE-DATE argument
|
||||||
|
and ignore the option.
|
||||||
|
\n(git commit --amend --only)"
|
||||||
|
(interactive (list (magit-commit-arguments)
|
||||||
|
(if current-prefix-arg
|
||||||
|
(not magit-commit-reword-override-date)
|
||||||
|
magit-commit-reword-override-date)))
|
||||||
|
(magit-commit-amend-assert)
|
||||||
|
(let ((process-environment process-environment))
|
||||||
|
(unless override-date
|
||||||
|
(push (magit-rev-format "GIT_COMMITTER_DATE=%cD") process-environment))
|
||||||
|
(cl-pushnew "--allow-empty" args :test #'equal)
|
||||||
|
(magit-run-git-with-editor "commit" "--amend" "--only" args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-fixup (&optional commit args)
|
||||||
|
"Create a fixup commit.
|
||||||
|
|
||||||
|
With a prefix argument the target COMMIT has to be confirmed.
|
||||||
|
Otherwise the commit at point may be used without confirmation
|
||||||
|
depending on the value of option `magit-commit-squash-confirm'."
|
||||||
|
(interactive (list (magit-commit-at-point)
|
||||||
|
(magit-commit-arguments)))
|
||||||
|
(magit-commit-squash-internal "--fixup" commit args))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-squash (&optional commit args)
|
||||||
|
"Create a squash commit, without editing the squash message.
|
||||||
|
|
||||||
|
With a prefix argument the target COMMIT has to be confirmed.
|
||||||
|
Otherwise the commit at point may be used without confirmation
|
||||||
|
depending on the value of option `magit-commit-squash-confirm'."
|
||||||
|
(interactive (list (magit-commit-at-point)
|
||||||
|
(magit-commit-arguments)))
|
||||||
|
(magit-commit-squash-internal "--squash" commit args))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-augment (&optional commit args)
|
||||||
|
"Create a squash commit, editing the squash message.
|
||||||
|
|
||||||
|
With a prefix argument the target COMMIT has to be confirmed.
|
||||||
|
Otherwise the commit at point may be used without confirmation
|
||||||
|
depending on the value of option `magit-commit-squash-confirm'."
|
||||||
|
(interactive (list (magit-commit-at-point)
|
||||||
|
(magit-commit-arguments)))
|
||||||
|
(magit-commit-squash-internal "--squash" commit args nil t))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-instant-fixup (&optional commit args)
|
||||||
|
"Create a fixup commit targeting COMMIT and instantly rebase."
|
||||||
|
(interactive (list (magit-commit-at-point)
|
||||||
|
(magit-commit-arguments)))
|
||||||
|
(magit-commit-squash-internal "--fixup" commit args t))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-instant-squash (&optional commit args)
|
||||||
|
"Create a squash commit targeting COMMIT and instantly rebase."
|
||||||
|
(interactive (list (magit-commit-at-point)
|
||||||
|
(magit-commit-arguments)))
|
||||||
|
(magit-commit-squash-internal "--squash" commit args t))
|
||||||
|
|
||||||
|
(defun magit-commit-squash-internal
|
||||||
|
(option commit &optional args rebase edit confirmed)
|
||||||
|
(when-let ((args (magit-commit-assert args t)))
|
||||||
|
(when commit
|
||||||
|
(when (and rebase (not (magit-rev-ancestor-p commit "HEAD")))
|
||||||
|
(magit-read-char-case
|
||||||
|
(format "%s isn't an ancestor of HEAD. " commit) nil
|
||||||
|
(?c "[c]reate without rebasing" (setq rebase nil))
|
||||||
|
(?s "[s]elect other" (setq commit nil))
|
||||||
|
(?a "[a]bort" (user-error "Quit")))))
|
||||||
|
(when commit
|
||||||
|
(setq commit (magit-rebase-interactive-assert commit t)))
|
||||||
|
(if (and commit
|
||||||
|
(or confirmed
|
||||||
|
(not (or rebase
|
||||||
|
current-prefix-arg
|
||||||
|
magit-commit-squash-confirm))))
|
||||||
|
(let ((magit-commit-show-diff nil))
|
||||||
|
(push (concat option "=" commit) args)
|
||||||
|
(unless edit
|
||||||
|
(push "--no-edit" args))
|
||||||
|
(if rebase
|
||||||
|
(magit-with-editor
|
||||||
|
(magit-call-git
|
||||||
|
"commit" "--no-gpg-sign"
|
||||||
|
(-remove-first
|
||||||
|
(apply-partially #'string-match-p "\\`--gpg-sign=")
|
||||||
|
args)))
|
||||||
|
(magit-run-git-with-editor "commit" args))
|
||||||
|
t) ; The commit was created; used by below lambda.
|
||||||
|
(magit-log-select
|
||||||
|
(lambda (commit)
|
||||||
|
(when (and (magit-commit-squash-internal option commit args
|
||||||
|
rebase edit t)
|
||||||
|
rebase)
|
||||||
|
(magit-commit-amend-assert commit)
|
||||||
|
(magit-rebase-interactive-1 commit
|
||||||
|
(list "--autosquash" "--autostash" "--keep-empty")
|
||||||
|
"" "true" nil t)))
|
||||||
|
(format "Type %%p on a commit to %s into it,"
|
||||||
|
(substring option 2))
|
||||||
|
nil nil nil commit)
|
||||||
|
(when magit-commit-show-diff
|
||||||
|
(let ((magit-display-buffer-noselect t))
|
||||||
|
(apply #'magit-diff-staged nil (magit-diff-arguments)))))))
|
||||||
|
|
||||||
|
(defun magit-commit-amend-assert (&optional commit)
|
||||||
|
(--when-let (magit-list-publishing-branches commit)
|
||||||
|
(let ((m1 "This commit has already been published to ")
|
||||||
|
(m2 ".\nDo you really want to modify it"))
|
||||||
|
(magit-confirm 'amend-published
|
||||||
|
(concat m1 "%s" m2)
|
||||||
|
(concat m1 "%i public branches" m2)
|
||||||
|
nil it))))
|
||||||
|
|
||||||
|
(defun magit-commit-assert (args &optional strict)
|
||||||
|
(cond
|
||||||
|
((or (magit-anything-staged-p)
|
||||||
|
(and (magit-anything-unstaged-p)
|
||||||
|
;; ^ Everything of nothing is still nothing.
|
||||||
|
(member "--all" args))
|
||||||
|
(and (not strict)
|
||||||
|
;; ^ For amend variants that don't make sense otherwise.
|
||||||
|
(or (member "--amend" args)
|
||||||
|
(member "--allow-empty" args))))
|
||||||
|
(or args (list "--")))
|
||||||
|
((and (magit-rebase-in-progress-p)
|
||||||
|
(not (magit-anything-unstaged-p))
|
||||||
|
(y-or-n-p "Nothing staged. Continue in-progress rebase? "))
|
||||||
|
(setq this-command 'magit-rebase-continue)
|
||||||
|
(magit-run-git-sequencer "rebase" "--continue")
|
||||||
|
nil)
|
||||||
|
((and (file-exists-p (magit-git-dir "MERGE_MSG"))
|
||||||
|
(not (magit-anything-unstaged-p)))
|
||||||
|
(or args (list "--")))
|
||||||
|
((not (magit-anything-unstaged-p))
|
||||||
|
(user-error "Nothing staged (or unstaged)"))
|
||||||
|
(magit-commit-ask-to-stage
|
||||||
|
(when (eq magit-commit-ask-to-stage 'verbose)
|
||||||
|
(magit-diff-unstaged))
|
||||||
|
(prog1 (when (or (eq magit-commit-ask-to-stage 'stage)
|
||||||
|
(y-or-n-p "Nothing staged. Stage and commit all unstaged changes? "))
|
||||||
|
(magit-run-git "add" "-u" ".")
|
||||||
|
(or args (list "--")))
|
||||||
|
(when (and (eq magit-commit-ask-to-stage 'verbose)
|
||||||
|
(derived-mode-p 'magit-diff-mode))
|
||||||
|
(magit-mode-bury-buffer))))
|
||||||
|
(t
|
||||||
|
(user-error "Nothing staged"))))
|
||||||
|
|
||||||
|
(defvar magit--reshelve-history nil)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-commit-reshelve (date)
|
||||||
|
"Change the committer date and possibly the author date of `HEAD'.
|
||||||
|
|
||||||
|
If you are the author of `HEAD', then both dates are changed,
|
||||||
|
otherwise only the committer date. The current time is used
|
||||||
|
as the initial minibuffer input and the original author (if
|
||||||
|
that is you) or committer date is available as the previous
|
||||||
|
history element."
|
||||||
|
(interactive
|
||||||
|
(let ((author-p (magit-rev-author-p "HEAD")))
|
||||||
|
(push (magit-rev-format (if author-p "%ad" "%cd") "HEAD"
|
||||||
|
(concat "--date=format:%F %T %z"))
|
||||||
|
magit--reshelve-history)
|
||||||
|
(list (read-string (if author-p
|
||||||
|
"Change author and committer dates to: "
|
||||||
|
"Change committer date to: ")
|
||||||
|
(cons (format-time-string "%F %T %z") 17)
|
||||||
|
'magit--reshelve-history))))
|
||||||
|
(let ((process-environment process-environment))
|
||||||
|
(push (concat "GIT_COMMITTER_DATE=" date) process-environment)
|
||||||
|
(magit-run-git "commit" "--amend" "--no-edit"
|
||||||
|
(and (magit-rev-author-p "HEAD")
|
||||||
|
(concat "--date=" date)))))
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-commit-absorb "magit-commit" nil t)
|
||||||
|
(define-transient-command magit-commit-absorb (phase commit args)
|
||||||
|
"Spread unstaged changes across recent commits.
|
||||||
|
With a prefix argument use a transient command to select infix
|
||||||
|
arguments. This command requires the git-autofixup script, which
|
||||||
|
is available from https://github.com/torbiak/git-autofixup."
|
||||||
|
["Arguments"
|
||||||
|
(magit-autofixup:--context)
|
||||||
|
(magit-autofixup:--strict)]
|
||||||
|
["Actions"
|
||||||
|
("x" "Absorb" magit-commit-absorb)]
|
||||||
|
(interactive (if current-prefix-arg
|
||||||
|
(list 'transient nil nil)
|
||||||
|
(list 'select
|
||||||
|
(magit-get-upstream-branch)
|
||||||
|
(transient-args 'magit-commit-absorb))))
|
||||||
|
(if (eq phase 'transient)
|
||||||
|
(transient-setup 'magit-commit-absorb)
|
||||||
|
(unless (executable-find "git-autofixup")
|
||||||
|
(user-error "This command requires the git-autofixup script, which %s"
|
||||||
|
"is available from https://github.com/torbiak/git-autofixup"))
|
||||||
|
(when (magit-anything-staged-p)
|
||||||
|
(user-error "Cannot absorb when there are staged changes"))
|
||||||
|
(unless (magit-anything-unstaged-p)
|
||||||
|
(user-error "There are no unstaged changes that could be absorbed"))
|
||||||
|
(when commit
|
||||||
|
(setq commit (magit-rebase-interactive-assert commit t)))
|
||||||
|
(if (and commit (eq phase 'run))
|
||||||
|
(progn (magit-run-git-async "autofixup" "-vv" args commit) t)
|
||||||
|
(magit-log-select
|
||||||
|
(lambda (commit)
|
||||||
|
(with-no-warnings ; about non-interactive use
|
||||||
|
(magit-commit-absorb 'run commit args)))
|
||||||
|
nil nil nil nil commit))))
|
||||||
|
|
||||||
|
(define-infix-argument magit-autofixup:--context ()
|
||||||
|
:description "Diff context lines"
|
||||||
|
:class 'transient-option
|
||||||
|
:shortarg "-c"
|
||||||
|
:argument "--context="
|
||||||
|
:reader 'transient-read-number-N0)
|
||||||
|
|
||||||
|
(define-infix-argument magit-autofixup:--strict ()
|
||||||
|
:description "Strictness"
|
||||||
|
:class 'transient-option
|
||||||
|
:shortarg "-s"
|
||||||
|
:argument "--strict="
|
||||||
|
:reader 'transient-read-number-N0)
|
||||||
|
|
||||||
|
;;; Pending Diff
|
||||||
|
|
||||||
|
(defun magit-commit-diff ()
|
||||||
|
(when (and git-commit-mode magit-commit-show-diff)
|
||||||
|
(when-let ((diff-buffer (magit-get-mode-buffer 'magit-diff-mode)))
|
||||||
|
;; This window just started displaying the commit message
|
||||||
|
;; buffer. Without this that buffer would immediately be
|
||||||
|
;; replaced with the diff buffer. See #2632.
|
||||||
|
(unrecord-window-buffer nil diff-buffer))
|
||||||
|
(condition-case nil
|
||||||
|
(let ((args (car (magit-diff-arguments)))
|
||||||
|
(magit-inhibit-save-previous-winconf 'unset)
|
||||||
|
(magit-display-buffer-noselect t)
|
||||||
|
(inhibit-quit nil))
|
||||||
|
(message "Diffing changes to be committed (C-g to abort diffing)")
|
||||||
|
(cl-case last-command
|
||||||
|
(magit-commit
|
||||||
|
(magit-diff-staged nil args))
|
||||||
|
(magit-commit-all
|
||||||
|
(magit-diff-working-tree nil args))
|
||||||
|
((magit-commit-amend
|
||||||
|
magit-commit-reword
|
||||||
|
magit-rebase-reword-commit)
|
||||||
|
(magit-diff-while-amending args))
|
||||||
|
(t (if (magit-anything-staged-p)
|
||||||
|
(magit-diff-staged nil args)
|
||||||
|
(magit-diff-while-amending args)))))
|
||||||
|
(quit))))
|
||||||
|
|
||||||
|
;; Mention `magit-diff-while-committing' because that's
|
||||||
|
;; always what I search for when I try to find this line.
|
||||||
|
(add-hook 'server-switch-hook 'magit-commit-diff)
|
||||||
|
|
||||||
|
(add-to-list 'with-editor-server-window-alist
|
||||||
|
(cons git-commit-filename-regexp 'switch-to-buffer))
|
||||||
|
|
||||||
|
;;; Message Utilities
|
||||||
|
|
||||||
|
(defun magit-commit-message-buffer ()
|
||||||
|
(let* ((find-file-visit-truename t) ; git uses truename of COMMIT_EDITMSG
|
||||||
|
(topdir (magit-toplevel)))
|
||||||
|
(--first (equal topdir (with-current-buffer it
|
||||||
|
(and git-commit-mode (magit-toplevel))))
|
||||||
|
(append (buffer-list (selected-frame))
|
||||||
|
(buffer-list)))))
|
||||||
|
|
||||||
|
(defvar magit-commit-add-log-insert-function 'magit-commit-add-log-insert
|
||||||
|
"Used by `magit-commit-add-log' to insert a single entry.")
|
||||||
|
|
||||||
|
(defun magit-commit-add-log ()
|
||||||
|
"Add a stub for the current change into the commit message buffer.
|
||||||
|
If no commit is in progress, then initiate it. Use the function
|
||||||
|
specified by variable `magit-commit-add-log-insert-function' to
|
||||||
|
actually insert the entry."
|
||||||
|
(interactive)
|
||||||
|
(pcase-let* ((hunk (and (magit-section-match 'hunk)
|
||||||
|
(magit-current-section)))
|
||||||
|
(log (magit-commit-message-buffer))
|
||||||
|
(`(,buf ,pos) (magit-diff-visit-file--noselect)))
|
||||||
|
(unless log
|
||||||
|
(unless (magit-commit-assert nil)
|
||||||
|
(user-error "Abort"))
|
||||||
|
(magit-commit-create)
|
||||||
|
(while (not (setq log (magit-commit-message-buffer)))
|
||||||
|
(sit-for 0.01)))
|
||||||
|
(magit--with-temp-position buf pos
|
||||||
|
(funcall magit-commit-add-log-insert-function log
|
||||||
|
(magit-file-relative-name)
|
||||||
|
(and hunk (add-log-current-defun))))))
|
||||||
|
|
||||||
|
(defun magit-commit-add-log-insert (buffer file defun)
|
||||||
|
(with-current-buffer buffer
|
||||||
|
(undo-boundary)
|
||||||
|
(goto-char (point-max))
|
||||||
|
(while (re-search-backward (concat "^" comment-start) nil t))
|
||||||
|
(save-restriction
|
||||||
|
(narrow-to-region (point-min) (point))
|
||||||
|
(cond ((re-search-backward (format "* %s\\(?: (\\([^)]+\\))\\)?: " file)
|
||||||
|
nil t)
|
||||||
|
(when (equal (match-string 1) defun)
|
||||||
|
(setq defun nil))
|
||||||
|
(re-search-forward ": "))
|
||||||
|
(t
|
||||||
|
(when (re-search-backward "^[\\*(].+\n" nil t)
|
||||||
|
(goto-char (match-end 0)))
|
||||||
|
(while (re-search-forward "^[^\\*\n].*\n" nil t))
|
||||||
|
(if defun
|
||||||
|
(progn (insert (format "* %s (%s): \n" file defun))
|
||||||
|
(setq defun nil))
|
||||||
|
(insert (format "* %s: \n" file)))
|
||||||
|
(backward-char)
|
||||||
|
(unless (looking-at "\n[\n\\']")
|
||||||
|
(insert ?\n)
|
||||||
|
(backward-char))))
|
||||||
|
(when defun
|
||||||
|
(forward-line)
|
||||||
|
(let ((limit (save-excursion
|
||||||
|
(and (re-search-forward "^\\*" nil t)
|
||||||
|
(point)))))
|
||||||
|
(unless (or (looking-back (format "(%s): " defun)
|
||||||
|
(line-beginning-position))
|
||||||
|
(re-search-forward (format "^(%s): " defun) limit t))
|
||||||
|
(while (re-search-forward "^[^\\*\n].*\n" limit t))
|
||||||
|
(insert (format "(%s): \n" defun))
|
||||||
|
(backward-char)))))))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-commit)
|
||||||
|
;;; magit-commit.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-commit.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-commit.elc
Normal file
Binary file not shown.
139
elpa/magit-20191030.1315/magit-core.el
Normal file
139
elpa/magit-20191030.1315/magit-core.el
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
;;; magit-core.el --- core functionality -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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 requires several other libraries, so that yet other
|
||||||
|
;; libraries can just require this one, instead of having to require
|
||||||
|
;; all the other ones. In other words this separates the low-level
|
||||||
|
;; stuff from the rest. It also defines some Custom groups.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'magit-utils)
|
||||||
|
(require 'magit-section)
|
||||||
|
(require 'magit-git)
|
||||||
|
(require 'magit-mode)
|
||||||
|
(require 'magit-margin)
|
||||||
|
(require 'magit-process)
|
||||||
|
(require 'magit-transient)
|
||||||
|
(require 'magit-autorevert)
|
||||||
|
|
||||||
|
(when (magit--libgit-available-p)
|
||||||
|
(condition-case err
|
||||||
|
(require 'magit-libgit)
|
||||||
|
(error
|
||||||
|
(setq magit-inhibit-libgit 'error)
|
||||||
|
(message "Error while loading `magit-libgit': %S" err)
|
||||||
|
(message "That is not fatal. The `libegit2' module just won't be used."))))
|
||||||
|
|
||||||
|
(defgroup magit nil
|
||||||
|
"Controlling Git from Emacs."
|
||||||
|
:link '(url-link "https://magit.vc")
|
||||||
|
:link '(info-link "(magit)FAQ")
|
||||||
|
:link '(info-link "(magit)")
|
||||||
|
:group 'tools)
|
||||||
|
|
||||||
|
(defgroup magit-essentials nil
|
||||||
|
"Options that every Magit user should briefly think about.
|
||||||
|
|
||||||
|
Each of these options falls into one or more of these categories:
|
||||||
|
|
||||||
|
* Options that affect Magit's behavior in fundamental ways.
|
||||||
|
* Options that affect safety.
|
||||||
|
* Options that affect performance.
|
||||||
|
* Options that are of a personal nature."
|
||||||
|
:link '(info-link "(magit)Essential Settings")
|
||||||
|
:group 'magit)
|
||||||
|
|
||||||
|
(defgroup magit-miscellaneous nil
|
||||||
|
"Miscellaneous Magit options."
|
||||||
|
:group 'magit)
|
||||||
|
|
||||||
|
(defgroup magit-commands nil
|
||||||
|
"Options controlling behavior of certain commands."
|
||||||
|
:group 'magit)
|
||||||
|
|
||||||
|
(defgroup magit-git-arguments nil
|
||||||
|
"Options controlling what arguments are passed to Git.
|
||||||
|
|
||||||
|
Most of these options can be set using the respective popup,
|
||||||
|
and it is recommended that you do that because then you can
|
||||||
|
be certain that Magit supports the arguments that you select.
|
||||||
|
|
||||||
|
An option `magit-NAME-argument' specifies the arguments that
|
||||||
|
are enabled by default by the popup `magit-NAME-popup'."
|
||||||
|
:link '(info-link "(magit-popup)Customizing Existing Popups")
|
||||||
|
:link '(info-link "(magit-popup)Usage")
|
||||||
|
:group 'magit-commands)
|
||||||
|
|
||||||
|
(defgroup magit-modes nil
|
||||||
|
"Modes used or provided by Magit."
|
||||||
|
:group 'magit)
|
||||||
|
|
||||||
|
(defgroup magit-buffers nil
|
||||||
|
"Options concerning Magit buffers."
|
||||||
|
:link '(info-link "(magit)Modes and Buffers")
|
||||||
|
:group 'magit)
|
||||||
|
|
||||||
|
(defgroup magit-refresh nil
|
||||||
|
"Options controlling how Magit buffers are refreshed."
|
||||||
|
:link '(info-link "(magit)Automatic Refreshing of Magit Buffers")
|
||||||
|
:group 'magit
|
||||||
|
:group 'magit-buffers)
|
||||||
|
|
||||||
|
(defgroup magit-faces nil
|
||||||
|
"Faces used by Magit."
|
||||||
|
:group 'magit
|
||||||
|
:group 'faces)
|
||||||
|
|
||||||
|
(defgroup magit-extensions nil
|
||||||
|
"Extensions to Magit."
|
||||||
|
:group 'magit)
|
||||||
|
|
||||||
|
(custom-add-to-group 'magit-modes 'git-commit 'custom-group)
|
||||||
|
(custom-add-to-group 'magit-faces 'git-commit-faces 'custom-group)
|
||||||
|
(custom-add-to-group 'magit-modes 'git-rebase 'custom-group)
|
||||||
|
(custom-add-to-group 'magit-faces 'git-rebase-faces 'custom-group)
|
||||||
|
(custom-add-to-group 'magit-process 'with-editor 'custom-group)
|
||||||
|
|
||||||
|
(defgroup magit-related nil
|
||||||
|
"Options that are relevant to Magit but that are defined elsewhere."
|
||||||
|
:link '(custom-group-link vc)
|
||||||
|
:link '(custom-group-link smerge)
|
||||||
|
:link '(custom-group-link ediff)
|
||||||
|
:link '(custom-group-link auto-revert)
|
||||||
|
:group 'magit
|
||||||
|
:group 'magit-extensions
|
||||||
|
:group 'magit-essentials)
|
||||||
|
|
||||||
|
(custom-add-to-group 'magit-related 'auto-revert-check-vc-info 'custom-variable)
|
||||||
|
(custom-add-to-group 'magit-auto-revert 'auto-revert-check-vc-info 'custom-variable)
|
||||||
|
|
||||||
|
(custom-add-to-group 'magit-related 'ediff-window-setup-function 'custom-variable)
|
||||||
|
(custom-add-to-group 'magit-related 'smerge-refine-ignore-whitespace 'custom-variable)
|
||||||
|
(custom-add-to-group 'magit-related 'vc-follow-symlinks 'custom-variable)
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-core)
|
||||||
|
;;; magit-core.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-core.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-core.elc
Normal file
Binary file not shown.
3129
elpa/magit-20191030.1315/magit-diff.el
Normal file
3129
elpa/magit-20191030.1315/magit-diff.el
Normal file
File diff suppressed because it is too large
Load Diff
BIN
elpa/magit-20191030.1315/magit-diff.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-diff.elc
Normal file
Binary file not shown.
511
elpa/magit-20191030.1315/magit-ediff.el
Normal file
511
elpa/magit-20191030.1315/magit-ediff.el
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
;;; magit-ediff.el --- Ediff extension for Magit -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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 provides basic support for Ediff.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
(require 'ediff)
|
||||||
|
(require 'smerge-mode)
|
||||||
|
|
||||||
|
(defvar smerge-ediff-buf)
|
||||||
|
(defvar smerge-ediff-windows)
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defgroup magit-ediff nil
|
||||||
|
"Ediff support for Magit."
|
||||||
|
:link '(info-link "(magit)Ediffing")
|
||||||
|
:group 'magit-extensions)
|
||||||
|
|
||||||
|
(defcustom magit-ediff-quit-hook
|
||||||
|
'(magit-ediff-cleanup-auxiliary-buffers
|
||||||
|
magit-ediff-restore-previous-winconf)
|
||||||
|
"Hooks to run after finishing Ediff, when that was invoked using Magit.
|
||||||
|
The hooks are run in the Ediff control buffer. This is similar
|
||||||
|
to `ediff-quit-hook' but takes the needs of Magit into account.
|
||||||
|
The `ediff-quit-hook' is ignored by Ediff sessions which were
|
||||||
|
invoked using Magit."
|
||||||
|
:package-version '(magit . "2.2.0")
|
||||||
|
:group 'magit-ediff
|
||||||
|
:type 'hook
|
||||||
|
:get 'magit-hook-custom-get
|
||||||
|
:options '(magit-ediff-cleanup-auxiliary-buffers
|
||||||
|
magit-ediff-restore-previous-winconf))
|
||||||
|
|
||||||
|
(defcustom magit-ediff-dwim-show-on-hunks nil
|
||||||
|
"Whether `magit-ediff-dwim' runs show variants on hunks.
|
||||||
|
If non-nil, `magit-ediff-show-staged' or
|
||||||
|
`magit-ediff-show-unstaged' are called based on what section the
|
||||||
|
hunk is in. Otherwise, `magit-ediff-dwim' runs
|
||||||
|
`magit-ediff-stage' when point is on an uncommitted hunk."
|
||||||
|
:package-version '(magit . "2.2.0")
|
||||||
|
:group 'magit-ediff
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom magit-ediff-show-stash-with-index t
|
||||||
|
"Whether `magit-ediff-show-stash' shows the state of the index.
|
||||||
|
|
||||||
|
If non-nil, use a third Ediff buffer to distinguish which changes
|
||||||
|
in the stash were staged. In cases where the stash contains no
|
||||||
|
staged changes, fall back to a two-buffer Ediff.
|
||||||
|
|
||||||
|
More specifically, a stash is a merge commit, stash@{N}, with
|
||||||
|
potentially three parents.
|
||||||
|
|
||||||
|
* stash@{N}^1 represents the `HEAD' commit at the time the stash
|
||||||
|
was created.
|
||||||
|
|
||||||
|
* stash@{N}^2 records any changes that were staged when the stash
|
||||||
|
was made.
|
||||||
|
|
||||||
|
* stash@{N}^3, if it exists, contains files that were untracked
|
||||||
|
when stashing.
|
||||||
|
|
||||||
|
If this option is non-nil, `magit-ediff-show-stash' will run
|
||||||
|
Ediff on a file using three buffers: one for stash@{N}, another
|
||||||
|
for stash@{N}^1, and a third for stash@{N}^2.
|
||||||
|
|
||||||
|
Otherwise, Ediff uses two buffers, comparing
|
||||||
|
stash@{N}^1..stash@{N}. Along with any unstaged changes, changes
|
||||||
|
in the index commit, stash@{N}^2, will be shown in this
|
||||||
|
comparison unless they conflicted with changes in the working
|
||||||
|
tree at the time of stashing."
|
||||||
|
:package-version '(magit . "2.6.0")
|
||||||
|
:group 'magit-ediff
|
||||||
|
:type 'boolean)
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
|
||||||
|
(defvar magit-ediff-previous-winconf nil)
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-ediff "magit-ediff" nil)
|
||||||
|
(define-transient-command magit-ediff ()
|
||||||
|
"Show differences using the Ediff package."
|
||||||
|
:info-manual "(ediff)"
|
||||||
|
["Ediff"
|
||||||
|
[("E" "Dwim" magit-ediff-dwim)
|
||||||
|
("s" "Stage" magit-ediff-stage)
|
||||||
|
("m" "Resolve" magit-ediff-resolve)]
|
||||||
|
[("u" "Show unstaged" magit-ediff-show-unstaged)
|
||||||
|
("i" "Show staged" magit-ediff-show-staged)
|
||||||
|
("w" "Show worktree" magit-ediff-show-working-tree)]
|
||||||
|
[("c" "Show commit" magit-ediff-show-commit)
|
||||||
|
("r" "Show range" magit-ediff-compare)
|
||||||
|
("z" "Show stash" magit-ediff-show-stash)]])
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-resolve (file)
|
||||||
|
"Resolve outstanding conflicts in FILE using Ediff.
|
||||||
|
FILE has to be relative to the top directory of the repository.
|
||||||
|
|
||||||
|
In the rare event that you want to manually resolve all
|
||||||
|
conflicts, including those already resolved by Git, use
|
||||||
|
`ediff-merge-revisions-with-ancestor'."
|
||||||
|
(interactive
|
||||||
|
(let ((current (magit-current-file))
|
||||||
|
(unmerged (magit-unmerged-files)))
|
||||||
|
(unless unmerged
|
||||||
|
(user-error "There are no unresolved conflicts"))
|
||||||
|
(list (magit-completing-read "Resolve file" unmerged nil t nil nil
|
||||||
|
(car (member current unmerged))))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(with-current-buffer (find-file-noselect file)
|
||||||
|
(smerge-ediff)
|
||||||
|
(setq-local
|
||||||
|
ediff-quit-hook
|
||||||
|
(lambda ()
|
||||||
|
(let ((bufC ediff-buffer-C)
|
||||||
|
(bufS smerge-ediff-buf))
|
||||||
|
(with-current-buffer bufS
|
||||||
|
(when (yes-or-no-p (format "Conflict resolution finished; save %s? "
|
||||||
|
buffer-file-name))
|
||||||
|
(erase-buffer)
|
||||||
|
(insert-buffer-substring bufC)
|
||||||
|
(save-buffer))))
|
||||||
|
(when (buffer-live-p ediff-buffer-A) (kill-buffer ediff-buffer-A))
|
||||||
|
(when (buffer-live-p ediff-buffer-B) (kill-buffer ediff-buffer-B))
|
||||||
|
(when (buffer-live-p ediff-buffer-C) (kill-buffer ediff-buffer-C))
|
||||||
|
(when (buffer-live-p ediff-ancestor-buffer)
|
||||||
|
(kill-buffer ediff-ancestor-buffer))
|
||||||
|
(let ((magit-ediff-previous-winconf smerge-ediff-windows))
|
||||||
|
(run-hooks 'magit-ediff-quit-hook)))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-stage (file)
|
||||||
|
"Stage and unstage changes to FILE using Ediff.
|
||||||
|
FILE has to be relative to the top directory of the repository."
|
||||||
|
(interactive
|
||||||
|
(let ((files (magit-tracked-files)))
|
||||||
|
(list (magit-completing-read "Selectively stage file" files nil t nil nil
|
||||||
|
(car (member (magit-current-file) files))))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(let* ((conf (current-window-configuration))
|
||||||
|
(bufA (magit-get-revision-buffer "HEAD" file))
|
||||||
|
(bufB (magit-get-revision-buffer "{index}" file))
|
||||||
|
(bufBrw (and bufB (with-current-buffer bufB (not buffer-read-only))))
|
||||||
|
(bufC (get-file-buffer file))
|
||||||
|
(fileBufC (or bufC (find-file-noselect file)))
|
||||||
|
(coding-system-for-read
|
||||||
|
(with-current-buffer fileBufC buffer-file-coding-system)))
|
||||||
|
(ediff-buffers3
|
||||||
|
(or bufA (magit-find-file-noselect "HEAD" file))
|
||||||
|
(with-current-buffer (magit-find-file-index-noselect file t)
|
||||||
|
(setq buffer-read-only nil)
|
||||||
|
(current-buffer))
|
||||||
|
fileBufC
|
||||||
|
`((lambda ()
|
||||||
|
(setq-local
|
||||||
|
ediff-quit-hook
|
||||||
|
(lambda ()
|
||||||
|
(and (buffer-live-p ediff-buffer-B)
|
||||||
|
(buffer-modified-p ediff-buffer-B)
|
||||||
|
(with-current-buffer ediff-buffer-B
|
||||||
|
(magit-update-index)))
|
||||||
|
(and (buffer-live-p ediff-buffer-C)
|
||||||
|
(buffer-modified-p ediff-buffer-C)
|
||||||
|
(with-current-buffer ediff-buffer-C
|
||||||
|
(when (y-or-n-p
|
||||||
|
(format "Save file %s? " buffer-file-name))
|
||||||
|
(save-buffer))))
|
||||||
|
,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
|
||||||
|
,@(if bufB
|
||||||
|
(unless bufBrw '((with-current-buffer ediff-buffer-B
|
||||||
|
(setq buffer-read-only t))))
|
||||||
|
'((ediff-kill-buffer-carefully ediff-buffer-B)))
|
||||||
|
,@(unless bufC '((ediff-kill-buffer-carefully ediff-buffer-C)))
|
||||||
|
(let ((magit-ediff-previous-winconf ,conf))
|
||||||
|
(run-hooks 'magit-ediff-quit-hook))))))
|
||||||
|
'ediff-buffers3))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-compare (revA revB fileA fileB)
|
||||||
|
"Compare REVA:FILEA with REVB:FILEB using Ediff.
|
||||||
|
|
||||||
|
FILEA and FILEB have to be relative to the top directory of the
|
||||||
|
repository. If REVA or REVB is nil, then this stands for the
|
||||||
|
working tree state.
|
||||||
|
|
||||||
|
If the region is active, use the revisions on the first and last
|
||||||
|
line of the region. With a prefix argument, instead of diffing
|
||||||
|
the revisions, choose a revision to view changes along, starting
|
||||||
|
at the common ancestor of both revisions (i.e., use a \"...\"
|
||||||
|
range)."
|
||||||
|
(interactive
|
||||||
|
(pcase-let ((`(,revA ,revB) (magit-ediff-compare--read-revisions
|
||||||
|
nil current-prefix-arg)))
|
||||||
|
(nconc (list revA revB)
|
||||||
|
(magit-ediff-read-files revA revB))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(let ((conf (current-window-configuration))
|
||||||
|
(bufA (if revA
|
||||||
|
(magit-get-revision-buffer revA fileA)
|
||||||
|
(get-file-buffer fileA)))
|
||||||
|
(bufB (if revB
|
||||||
|
(magit-get-revision-buffer revB fileB)
|
||||||
|
(get-file-buffer fileB))))
|
||||||
|
(ediff-buffers
|
||||||
|
(or bufA (if revA
|
||||||
|
(magit-find-file-noselect revA fileA)
|
||||||
|
(find-file-noselect fileA)))
|
||||||
|
(or bufB (if revB
|
||||||
|
(magit-find-file-noselect revB fileB)
|
||||||
|
(find-file-noselect fileB)))
|
||||||
|
`((lambda ()
|
||||||
|
(setq-local
|
||||||
|
ediff-quit-hook
|
||||||
|
(lambda ()
|
||||||
|
,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
|
||||||
|
,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B)))
|
||||||
|
(let ((magit-ediff-previous-winconf ,conf))
|
||||||
|
(run-hooks 'magit-ediff-quit-hook))))))
|
||||||
|
'ediff-revision))))
|
||||||
|
|
||||||
|
(defun magit-ediff-compare--read-revisions (&optional arg mbase)
|
||||||
|
(let ((input (or arg (magit-diff-read-range-or-commit
|
||||||
|
"Compare range or commit"
|
||||||
|
nil mbase))))
|
||||||
|
(--if-let (magit-split-range input)
|
||||||
|
(-cons-to-list it)
|
||||||
|
(list input nil))))
|
||||||
|
|
||||||
|
(defun magit-ediff-read-files (revA revB &optional fileB)
|
||||||
|
"Read file in REVB, return it and the corresponding file in REVA.
|
||||||
|
When FILEB is non-nil, use this as REVB's file instead of
|
||||||
|
prompting for it."
|
||||||
|
(unless fileB
|
||||||
|
(setq fileB (magit-read-file-choice
|
||||||
|
(format "File to compare between %s and %s"
|
||||||
|
revA (or revB "the working tree"))
|
||||||
|
(magit-changed-files revA revB)
|
||||||
|
(format "No changed files between %s and %s"
|
||||||
|
revA (or revB "the working tree")))))
|
||||||
|
(list (or (car (member fileB (magit-revision-files revA)))
|
||||||
|
(cdr (assoc fileB (magit-renamed-files revB revA)))
|
||||||
|
(magit-read-file-choice
|
||||||
|
(format "File in %s to compare with %s in %s"
|
||||||
|
revA fileB (or revB "the working tree"))
|
||||||
|
(magit-changed-files revB revA)
|
||||||
|
(format "No files have changed between %s and %s"
|
||||||
|
revA revB)))
|
||||||
|
fileB))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-dwim ()
|
||||||
|
"Compare, stage, or resolve using Ediff.
|
||||||
|
This command tries to guess what file, and what commit or range
|
||||||
|
the user wants to compare, stage, or resolve using Ediff. It
|
||||||
|
might only be able to guess either the file, or range or commit,
|
||||||
|
in which case the user is asked about the other. It might not
|
||||||
|
always guess right, in which case the appropriate `magit-ediff-*'
|
||||||
|
command has to be used explicitly. If it cannot read the user's
|
||||||
|
mind at all, then it asks the user for a command to run."
|
||||||
|
(interactive)
|
||||||
|
(magit-section-case
|
||||||
|
(hunk (save-excursion
|
||||||
|
(goto-char (oref (oref it parent) start))
|
||||||
|
(magit-ediff-dwim)))
|
||||||
|
(t
|
||||||
|
(let ((range (magit-diff--dwim))
|
||||||
|
(file (magit-current-file))
|
||||||
|
command revA revB)
|
||||||
|
(pcase range
|
||||||
|
((and (guard (not magit-ediff-dwim-show-on-hunks))
|
||||||
|
(or `unstaged `staged))
|
||||||
|
(setq command (if (magit-anything-unmerged-p)
|
||||||
|
#'magit-ediff-resolve
|
||||||
|
#'magit-ediff-stage)))
|
||||||
|
(`unstaged (setq command #'magit-ediff-show-unstaged))
|
||||||
|
(`staged (setq command #'magit-ediff-show-staged))
|
||||||
|
(`(commit . ,value)
|
||||||
|
(setq command #'magit-ediff-show-commit)
|
||||||
|
(setq revB value))
|
||||||
|
(`(stash . ,value)
|
||||||
|
(setq command #'magit-ediff-show-stash)
|
||||||
|
(setq revB value))
|
||||||
|
((pred stringp)
|
||||||
|
(pcase-let ((`(,a ,b) (magit-ediff-compare--read-revisions range)))
|
||||||
|
(setq command #'magit-ediff-compare)
|
||||||
|
(setq revA a)
|
||||||
|
(setq revB b)))
|
||||||
|
(_
|
||||||
|
(when (derived-mode-p 'magit-diff-mode)
|
||||||
|
(pcase (magit-diff-type)
|
||||||
|
(`committed (pcase-let ((`(,a ,b)
|
||||||
|
(magit-ediff-compare--read-revisions
|
||||||
|
magit-buffer-range)))
|
||||||
|
(setq revA a)
|
||||||
|
(setq revB b)))
|
||||||
|
((guard (not magit-ediff-dwim-show-on-hunks))
|
||||||
|
(setq command #'magit-ediff-stage))
|
||||||
|
(`unstaged (setq command #'magit-ediff-show-unstaged))
|
||||||
|
(`staged (setq command #'magit-ediff-show-staged))
|
||||||
|
(`undefined (setq command nil))
|
||||||
|
(_ (setq command nil))))))
|
||||||
|
(cond ((not command)
|
||||||
|
(call-interactively
|
||||||
|
(magit-read-char-case
|
||||||
|
"Failed to read your mind; do you want to " t
|
||||||
|
(?c "[c]ommit" 'magit-ediff-show-commit)
|
||||||
|
(?r "[r]ange" 'magit-ediff-compare)
|
||||||
|
(?s "[s]tage" 'magit-ediff-stage)
|
||||||
|
(?v "resol[v]e" 'magit-ediff-resolve))))
|
||||||
|
((eq command 'magit-ediff-compare)
|
||||||
|
(apply 'magit-ediff-compare revA revB
|
||||||
|
(magit-ediff-read-files revA revB file)))
|
||||||
|
((eq command 'magit-ediff-show-commit)
|
||||||
|
(magit-ediff-show-commit revB))
|
||||||
|
((eq command 'magit-ediff-show-stash)
|
||||||
|
(magit-ediff-show-stash revB))
|
||||||
|
(file
|
||||||
|
(funcall command file))
|
||||||
|
(t
|
||||||
|
(call-interactively command)))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-show-staged (file)
|
||||||
|
"Show staged changes using Ediff.
|
||||||
|
|
||||||
|
This only allows looking at the changes; to stage, unstage,
|
||||||
|
and discard changes using Ediff, use `magit-ediff-stage'.
|
||||||
|
|
||||||
|
FILE must be relative to the top directory of the repository."
|
||||||
|
(interactive
|
||||||
|
(list (magit-read-file-choice "Show staged changes for file"
|
||||||
|
(magit-staged-files)
|
||||||
|
"No staged files")))
|
||||||
|
(let ((conf (current-window-configuration))
|
||||||
|
(bufA (magit-get-revision-buffer "HEAD" file))
|
||||||
|
(bufB (get-buffer (concat file ".~{index}~"))))
|
||||||
|
(ediff-buffers
|
||||||
|
(or bufA (magit-find-file-noselect "HEAD" file))
|
||||||
|
(or bufB (magit-find-file-index-noselect file t))
|
||||||
|
`((lambda ()
|
||||||
|
(setq-local
|
||||||
|
ediff-quit-hook
|
||||||
|
(lambda ()
|
||||||
|
,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
|
||||||
|
,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B)))
|
||||||
|
(let ((magit-ediff-previous-winconf ,conf))
|
||||||
|
(run-hooks 'magit-ediff-quit-hook))))))
|
||||||
|
'ediff-buffers)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-show-unstaged (file)
|
||||||
|
"Show unstaged changes using Ediff.
|
||||||
|
|
||||||
|
This only allows looking at the changes; to stage, unstage,
|
||||||
|
and discard changes using Ediff, use `magit-ediff-stage'.
|
||||||
|
|
||||||
|
FILE must be relative to the top directory of the repository."
|
||||||
|
(interactive
|
||||||
|
(list (magit-read-file-choice "Show unstaged changes for file"
|
||||||
|
(magit-unstaged-files)
|
||||||
|
"No unstaged files")))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(let ((conf (current-window-configuration))
|
||||||
|
(bufA (get-buffer (concat file ".~{index}~")))
|
||||||
|
(bufB (get-file-buffer file)))
|
||||||
|
(ediff-buffers
|
||||||
|
(or bufA (magit-find-file-index-noselect file t))
|
||||||
|
(or bufB (find-file-noselect file))
|
||||||
|
`((lambda ()
|
||||||
|
(setq-local
|
||||||
|
ediff-quit-hook
|
||||||
|
(lambda ()
|
||||||
|
,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
|
||||||
|
,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B)))
|
||||||
|
(let ((magit-ediff-previous-winconf ,conf))
|
||||||
|
(run-hooks 'magit-ediff-quit-hook))))))
|
||||||
|
'ediff-buffers))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-show-working-tree (file)
|
||||||
|
"Show changes between `HEAD' and working tree using Ediff.
|
||||||
|
FILE must be relative to the top directory of the repository."
|
||||||
|
(interactive
|
||||||
|
(list (magit-read-file-choice "Show changes in file"
|
||||||
|
(magit-changed-files "HEAD")
|
||||||
|
"No changed files")))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(let ((conf (current-window-configuration))
|
||||||
|
(bufA (magit-get-revision-buffer "HEAD" file))
|
||||||
|
(bufB (get-file-buffer file)))
|
||||||
|
(ediff-buffers
|
||||||
|
(or bufA (magit-find-file-noselect "HEAD" file))
|
||||||
|
(or bufB (find-file-noselect file))
|
||||||
|
`((lambda ()
|
||||||
|
(setq-local
|
||||||
|
ediff-quit-hook
|
||||||
|
(lambda ()
|
||||||
|
,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
|
||||||
|
,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B)))
|
||||||
|
(let ((magit-ediff-previous-winconf ,conf))
|
||||||
|
(run-hooks 'magit-ediff-quit-hook))))))
|
||||||
|
'ediff-buffers))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-show-commit (commit)
|
||||||
|
"Show changes introduced by COMMIT using Ediff."
|
||||||
|
(interactive (list (magit-read-branch-or-commit "Revision")))
|
||||||
|
(let ((revA (concat commit "^"))
|
||||||
|
(revB commit))
|
||||||
|
(apply #'magit-ediff-compare
|
||||||
|
revA revB
|
||||||
|
(magit-ediff-read-files revA revB (magit-current-file)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-ediff-show-stash (stash)
|
||||||
|
"Show changes introduced by STASH using Ediff.
|
||||||
|
`magit-ediff-show-stash-with-index' controls whether a
|
||||||
|
three-buffer Ediff is used in order to distinguish changes in the
|
||||||
|
stash that were staged."
|
||||||
|
(interactive (list (magit-read-stash "Stash")))
|
||||||
|
(pcase-let* ((revA (concat stash "^1"))
|
||||||
|
(revB (concat stash "^2"))
|
||||||
|
(revC stash)
|
||||||
|
(`(,fileA ,fileC) (magit-ediff-read-files revA revC))
|
||||||
|
(fileB fileC))
|
||||||
|
(if (and magit-ediff-show-stash-with-index
|
||||||
|
(member fileA (magit-changed-files revB revA)))
|
||||||
|
(let ((conf (current-window-configuration))
|
||||||
|
(bufA (magit-get-revision-buffer revA fileA))
|
||||||
|
(bufB (magit-get-revision-buffer revB fileB))
|
||||||
|
(bufC (magit-get-revision-buffer revC fileC)))
|
||||||
|
(ediff-buffers3
|
||||||
|
(or bufA (magit-find-file-noselect revA fileA))
|
||||||
|
(or bufB (magit-find-file-noselect revB fileB))
|
||||||
|
(or bufC (magit-find-file-noselect revC fileC))
|
||||||
|
`((lambda ()
|
||||||
|
(setq-local
|
||||||
|
ediff-quit-hook
|
||||||
|
(lambda ()
|
||||||
|
,@(unless bufA
|
||||||
|
'((ediff-kill-buffer-carefully ediff-buffer-A)))
|
||||||
|
,@(unless bufB
|
||||||
|
'((ediff-kill-buffer-carefully ediff-buffer-B)))
|
||||||
|
,@(unless bufC
|
||||||
|
'((ediff-kill-buffer-carefully ediff-buffer-C)))
|
||||||
|
(let ((magit-ediff-previous-winconf ,conf))
|
||||||
|
(run-hooks 'magit-ediff-quit-hook))))))
|
||||||
|
'ediff-buffers3))
|
||||||
|
(magit-ediff-compare revA revC fileA fileC))))
|
||||||
|
|
||||||
|
(defun magit-ediff-cleanup-auxiliary-buffers ()
|
||||||
|
(let* ((ctl-buf ediff-control-buffer)
|
||||||
|
(ctl-win (ediff-get-visible-buffer-window ctl-buf))
|
||||||
|
(ctl-frm ediff-control-frame)
|
||||||
|
(main-frame (cond ((window-live-p ediff-window-A)
|
||||||
|
(window-frame ediff-window-A))
|
||||||
|
((window-live-p ediff-window-B)
|
||||||
|
(window-frame ediff-window-B)))))
|
||||||
|
(ediff-kill-buffer-carefully ediff-diff-buffer)
|
||||||
|
(ediff-kill-buffer-carefully ediff-custom-diff-buffer)
|
||||||
|
(ediff-kill-buffer-carefully ediff-fine-diff-buffer)
|
||||||
|
(ediff-kill-buffer-carefully ediff-tmp-buffer)
|
||||||
|
(ediff-kill-buffer-carefully ediff-error-buffer)
|
||||||
|
(ediff-kill-buffer-carefully ediff-msg-buffer)
|
||||||
|
(ediff-kill-buffer-carefully ediff-debug-buffer)
|
||||||
|
(when (boundp 'ediff-patch-diagnostics)
|
||||||
|
(ediff-kill-buffer-carefully ediff-patch-diagnostics))
|
||||||
|
(cond ((and (ediff-window-display-p)
|
||||||
|
(frame-live-p ctl-frm))
|
||||||
|
(delete-frame ctl-frm))
|
||||||
|
((window-live-p ctl-win)
|
||||||
|
(delete-window ctl-win)))
|
||||||
|
(unless (ediff-multiframe-setup-p)
|
||||||
|
(ediff-kill-bottom-toolbar))
|
||||||
|
(ediff-kill-buffer-carefully ctl-buf)
|
||||||
|
(when (frame-live-p main-frame)
|
||||||
|
(select-frame main-frame))))
|
||||||
|
|
||||||
|
(defun magit-ediff-restore-previous-winconf ()
|
||||||
|
(set-window-configuration magit-ediff-previous-winconf))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-ediff)
|
||||||
|
;;; magit-ediff.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-ediff.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-ediff.elc
Normal file
Binary file not shown.
649
elpa/magit-20191030.1315/magit-extras.el
Normal file
649
elpa/magit-20191030.1315/magit-extras.el
Normal file
@@ -0,0 +1,649 @@
|
|||||||
|
;;; magit-extras.el --- additional functionality for Magit -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2008-2019 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.
|
||||||
|
|
||||||
|
;; 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:
|
||||||
|
|
||||||
|
;; Additional functionality for Magit.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'subr-x))
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
(declare-function dired-read-shell-command "dired-aux" (prompt arg files))
|
||||||
|
|
||||||
|
(defvar ido-exit)
|
||||||
|
(defvar ido-fallback)
|
||||||
|
|
||||||
|
(defgroup magit-extras nil
|
||||||
|
"Additional functionality for Magit."
|
||||||
|
:group 'magit-extensions)
|
||||||
|
|
||||||
|
;;; External Tools
|
||||||
|
|
||||||
|
(defcustom magit-gitk-executable
|
||||||
|
(or (and (eq system-type 'windows-nt)
|
||||||
|
(let ((exe (magit-git-string
|
||||||
|
"-c" "alias.X=!x() { which \"$1\" | cygpath -mf -; }; x"
|
||||||
|
"X" "gitk.exe")))
|
||||||
|
(and exe (file-executable-p exe) exe)))
|
||||||
|
(executable-find "gitk") "gitk")
|
||||||
|
"The Gitk executable."
|
||||||
|
:group 'magit-extras
|
||||||
|
:set-after '(magit-git-executable)
|
||||||
|
:type 'string)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-run-git-gui ()
|
||||||
|
"Run `git gui' for the current git repository."
|
||||||
|
(interactive)
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-process-file magit-git-executable nil 0 nil "gui")))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-run-git-gui-blame (commit filename &optional linenum)
|
||||||
|
"Run `git gui blame' on the given FILENAME and COMMIT.
|
||||||
|
Interactively run it for the current file and the `HEAD', with a
|
||||||
|
prefix or when the current file cannot be determined let the user
|
||||||
|
choose. When the current buffer is visiting FILENAME instruct
|
||||||
|
blame to center around the line point is on."
|
||||||
|
(interactive
|
||||||
|
(let (revision filename)
|
||||||
|
(when (or current-prefix-arg
|
||||||
|
(not (setq revision "HEAD"
|
||||||
|
filename (magit-file-relative-name nil 'tracked))))
|
||||||
|
(setq revision (magit-read-branch-or-commit "Blame from revision"))
|
||||||
|
(setq filename (magit-read-file-from-rev revision "Blame file")))
|
||||||
|
(list revision filename
|
||||||
|
(and (equal filename
|
||||||
|
(ignore-errors
|
||||||
|
(magit-file-relative-name buffer-file-name)))
|
||||||
|
(line-number-at-pos)))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(apply #'magit-process-file magit-git-executable nil 0 nil "gui" "blame"
|
||||||
|
`(,@(and linenum (list (format "--line=%d" linenum)))
|
||||||
|
,commit
|
||||||
|
,filename))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-run-gitk ()
|
||||||
|
"Run `gitk' in the current repository."
|
||||||
|
(interactive)
|
||||||
|
(magit-process-file magit-gitk-executable nil 0))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-run-gitk-branches ()
|
||||||
|
"Run `gitk --branches' in the current repository."
|
||||||
|
(interactive)
|
||||||
|
(magit-process-file magit-gitk-executable nil 0 nil "--branches"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-run-gitk-all ()
|
||||||
|
"Run `gitk --all' in the current repository."
|
||||||
|
(interactive)
|
||||||
|
(magit-process-file magit-gitk-executable nil 0 nil "--all"))
|
||||||
|
|
||||||
|
;;; Emacs Tools
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun ido-enter-magit-status ()
|
||||||
|
"Drop into `magit-status' from file switching.
|
||||||
|
|
||||||
|
This command does not work in Emacs 26.1.
|
||||||
|
See https://github.com/magit/magit/issues/3634
|
||||||
|
and https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31707.
|
||||||
|
|
||||||
|
To make this command available use something like:
|
||||||
|
|
||||||
|
(add-hook \\='ido-setup-hook
|
||||||
|
(lambda ()
|
||||||
|
(define-key ido-completion-map
|
||||||
|
(kbd \"C-x g\") \\='ido-enter-magit-status)))
|
||||||
|
|
||||||
|
Starting with Emacs 25.1 the Ido keymaps are defined just once
|
||||||
|
instead of every time Ido is invoked, so now you can modify it
|
||||||
|
like pretty much every other keymap:
|
||||||
|
|
||||||
|
(define-key ido-common-completion-map
|
||||||
|
(kbd \"C-x g\") \\='ido-enter-magit-status)"
|
||||||
|
(interactive)
|
||||||
|
(setq ido-exit 'fallback)
|
||||||
|
(setq ido-fallback 'magit-status) ; for Emacs >= 26.2
|
||||||
|
(with-no-warnings (setq fallback 'magit-status)) ; for Emacs 25
|
||||||
|
(exit-minibuffer))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-dired-jump (&optional other-window)
|
||||||
|
"Visit file at point using Dired.
|
||||||
|
With a prefix argument, visit in another window. If there
|
||||||
|
is no file at point, then instead visit `default-directory'."
|
||||||
|
(interactive "P")
|
||||||
|
(dired-jump other-window
|
||||||
|
(when-let ((file (magit-file-at-point)))
|
||||||
|
(expand-file-name (if (file-directory-p file)
|
||||||
|
(file-name-as-directory file)
|
||||||
|
file)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-dired-log (&optional follow)
|
||||||
|
"Show log for all marked files, or the current file."
|
||||||
|
(interactive "P")
|
||||||
|
(if-let ((topdir (magit-toplevel default-directory)))
|
||||||
|
(let ((args (car (magit-log-arguments)))
|
||||||
|
(files (dired-get-marked-files nil nil #'magit-file-tracked-p)))
|
||||||
|
(unless files
|
||||||
|
(user-error "No marked file is being tracked by Git"))
|
||||||
|
(when (and follow
|
||||||
|
(not (member "--follow" args))
|
||||||
|
(not (cdr files)))
|
||||||
|
(push "--follow" args))
|
||||||
|
(magit-log-setup-buffer
|
||||||
|
(list (or (magit-get-current-branch) "HEAD"))
|
||||||
|
args
|
||||||
|
(let ((default-directory topdir))
|
||||||
|
(mapcar #'file-relative-name files))
|
||||||
|
magit-log-buffer-file-locked))
|
||||||
|
(magit--not-inside-repository-error)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-do-async-shell-command (file)
|
||||||
|
"Open FILE with `dired-do-async-shell-command'.
|
||||||
|
Interactively, open the file at point."
|
||||||
|
(interactive (list (or (magit-file-at-point)
|
||||||
|
(completing-read "Act on file: "
|
||||||
|
(magit-list-files)))))
|
||||||
|
(require 'dired-aux)
|
||||||
|
(dired-do-async-shell-command
|
||||||
|
(dired-read-shell-command "& on %s: " current-prefix-arg (list file))
|
||||||
|
nil (list file)))
|
||||||
|
|
||||||
|
;;; Shift Selection
|
||||||
|
|
||||||
|
(defun magit--turn-on-shift-select-mode-p ()
|
||||||
|
(and shift-select-mode
|
||||||
|
this-command-keys-shift-translated
|
||||||
|
(not mark-active)
|
||||||
|
(not (eq (car-safe transient-mark-mode) 'only))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-previous-line (&optional arg try-vscroll)
|
||||||
|
"Like `previous-line' but with Magit-specific shift-selection.
|
||||||
|
|
||||||
|
Magit's selection mechanism is based on the region but selects an
|
||||||
|
area that is larger than the region. This causes `previous-line'
|
||||||
|
when invoked while holding the shift key to move up one line and
|
||||||
|
thereby select two lines. When invoked inside a hunk body this
|
||||||
|
command does not move point on the first invocation and thereby
|
||||||
|
it only selects a single line. Which inconsistency you prefer
|
||||||
|
is a matter of preference."
|
||||||
|
(declare (interactive-only
|
||||||
|
"use `forward-line' with negative argument instead."))
|
||||||
|
(interactive "p\np")
|
||||||
|
(unless arg (setq arg 1))
|
||||||
|
(let ((stay (or (magit-diff-inside-hunk-body-p)
|
||||||
|
(magit-section-position-in-heading-p))))
|
||||||
|
(if (and stay (= arg 1) (magit--turn-on-shift-select-mode-p))
|
||||||
|
(push-mark nil nil t)
|
||||||
|
(with-no-warnings
|
||||||
|
(handle-shift-selection)
|
||||||
|
(previous-line (if stay (max (1- arg) 1) arg) try-vscroll)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-next-line (&optional arg try-vscroll)
|
||||||
|
"Like `next-line' but with Magit-specific shift-selection.
|
||||||
|
|
||||||
|
Magit's selection mechanism is based on the region but selects
|
||||||
|
an area that is larger than the region. This causes `next-line'
|
||||||
|
when invoked while holding the shift key to move down one line
|
||||||
|
and thereby select two lines. When invoked inside a hunk body
|
||||||
|
this command does not move point on the first invocation and
|
||||||
|
thereby it only selects a single line. Which inconsistency you
|
||||||
|
prefer is a matter of preference."
|
||||||
|
(declare (interactive-only forward-line))
|
||||||
|
(interactive "p\np")
|
||||||
|
(unless arg (setq arg 1))
|
||||||
|
(let ((stay (or (magit-diff-inside-hunk-body-p)
|
||||||
|
(magit-section-position-in-heading-p))))
|
||||||
|
(if (and stay (= arg 1) (magit--turn-on-shift-select-mode-p))
|
||||||
|
(push-mark nil nil t)
|
||||||
|
(with-no-warnings
|
||||||
|
(handle-shift-selection)
|
||||||
|
(next-line (if stay (max (1- arg) 1) arg) try-vscroll)))))
|
||||||
|
|
||||||
|
;;; Clean
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-clean (&optional arg)
|
||||||
|
"Remove untracked files from the working tree.
|
||||||
|
With a prefix argument also remove ignored files,
|
||||||
|
with two prefix arguments remove ignored files only.
|
||||||
|
\n(git clean -f -d [-x|-X])"
|
||||||
|
(interactive "p")
|
||||||
|
(when (yes-or-no-p (format "Remove %s files? "
|
||||||
|
(pcase arg
|
||||||
|
(1 "untracked")
|
||||||
|
(4 "untracked and ignored")
|
||||||
|
(_ "ignored"))))
|
||||||
|
(magit-wip-commit-before-change)
|
||||||
|
(magit-run-git "clean" "-f" "-d" (pcase arg (4 "-x") (16 "-X")))))
|
||||||
|
|
||||||
|
(put 'magit-clean 'disabled t)
|
||||||
|
|
||||||
|
;;; ChangeLog
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-add-change-log-entry (&optional whoami file-name other-window)
|
||||||
|
"Find change log file and add date entry and item for current change.
|
||||||
|
This differs from `add-change-log-entry' (which see) in that
|
||||||
|
it acts on the current hunk in a Magit buffer instead of on
|
||||||
|
a position in a file-visiting buffer."
|
||||||
|
(interactive (list current-prefix-arg
|
||||||
|
(prompt-for-change-log-name)))
|
||||||
|
(pcase-let ((`(,buf ,pos) (magit-diff-visit-file--noselect)))
|
||||||
|
(magit--with-temp-position buf pos
|
||||||
|
(add-change-log-entry whoami file-name other-window))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-add-change-log-entry-other-window (&optional whoami file-name)
|
||||||
|
"Find change log file in other window and add entry and item.
|
||||||
|
This differs from `add-change-log-entry-other-window' (which see)
|
||||||
|
in that it acts on the current hunk in a Magit buffer instead of
|
||||||
|
on a position in a file-visiting buffer."
|
||||||
|
(interactive (and current-prefix-arg
|
||||||
|
(list current-prefix-arg
|
||||||
|
(prompt-for-change-log-name))))
|
||||||
|
(magit-add-change-log-entry whoami file-name t))
|
||||||
|
|
||||||
|
;;; Edit Line Commit
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-edit-line-commit (&optional type)
|
||||||
|
"Edit the commit that added the current line.
|
||||||
|
|
||||||
|
With a prefix argument edit the commit that removes the line,
|
||||||
|
if any. The commit is determined using `git blame' and made
|
||||||
|
editable using `git rebase --interactive' if it is reachable
|
||||||
|
from `HEAD', or by checking out the commit (or a branch that
|
||||||
|
points at it) otherwise."
|
||||||
|
(interactive (list (and current-prefix-arg 'removal)))
|
||||||
|
(let* ((chunk (magit-current-blame-chunk (or type 'addition)))
|
||||||
|
(rev (oref chunk orig-rev)))
|
||||||
|
(if (equal rev "0000000000000000000000000000000000000000")
|
||||||
|
(message "This line has not been committed yet")
|
||||||
|
(let ((rebase (magit-rev-ancestor-p rev "HEAD"))
|
||||||
|
(file (expand-file-name (oref chunk orig-file)
|
||||||
|
(magit-toplevel))))
|
||||||
|
(if rebase
|
||||||
|
(let ((magit--rebase-published-symbol 'edit-published))
|
||||||
|
(magit-rebase-edit-commit rev (magit-rebase-arguments)))
|
||||||
|
(magit-checkout (or (magit-rev-branch rev) rev)))
|
||||||
|
(unless (and buffer-file-name
|
||||||
|
(file-equal-p file buffer-file-name))
|
||||||
|
(let ((blame-type (and magit-blame-mode magit-blame-type)))
|
||||||
|
(if rebase
|
||||||
|
(set-process-sentinel
|
||||||
|
magit-this-process
|
||||||
|
(lambda (process event)
|
||||||
|
(magit-sequencer-process-sentinel process event)
|
||||||
|
(when (eq (process-status process) 'exit)
|
||||||
|
(find-file file)
|
||||||
|
(when blame-type
|
||||||
|
(magit-blame--pre-blame-setup blame-type)
|
||||||
|
(magit-blame--run (magit-blame-arguments))))))
|
||||||
|
(find-file file)
|
||||||
|
(when blame-type
|
||||||
|
(magit-blame--pre-blame-setup blame-type)
|
||||||
|
(magit-blame--run (magit-blame-arguments))))))))))
|
||||||
|
|
||||||
|
(put 'magit-edit-line-commit 'disabled t)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-diff-edit-hunk-commit (file)
|
||||||
|
"From a hunk, edit the respective commit and visit the file.
|
||||||
|
|
||||||
|
First visit the file being modified by the hunk at the correct
|
||||||
|
location using `magit-diff-visit-file'. This actually visits a
|
||||||
|
blob. When point is on a diff header, not within an individual
|
||||||
|
hunk, then this visits the blob the first hunk is about.
|
||||||
|
|
||||||
|
Then invoke `magit-edit-line-commit', which uses an interactive
|
||||||
|
rebase to make the commit editable, or if that is not possible
|
||||||
|
because the commit is not reachable from `HEAD' by checking out
|
||||||
|
that commit directly. This also causes the actual worktree file
|
||||||
|
to be visited.
|
||||||
|
|
||||||
|
Neither the blob nor the file buffer are killed when finishing
|
||||||
|
the rebase. If that is undesirable, then it might be better to
|
||||||
|
use `magit-rebase-edit-command' instead of this command."
|
||||||
|
(interactive (list (magit-file-at-point t t)))
|
||||||
|
(let ((magit-diff-visit-previous-blob nil))
|
||||||
|
(with-current-buffer
|
||||||
|
(magit-diff-visit-file--internal file nil #'pop-to-buffer-same-window)
|
||||||
|
(magit-edit-line-commit))))
|
||||||
|
|
||||||
|
(put 'magit-diff-edit-hunk-commit 'disabled t)
|
||||||
|
|
||||||
|
;;; Reshelve
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-reshelve-since (rev)
|
||||||
|
"Change the author and committer dates of the commits since REV.
|
||||||
|
|
||||||
|
Ask the user for the first reachable commit whose dates should
|
||||||
|
be changed. Then read the new date for that commit. The initial
|
||||||
|
minibuffer input and the previous history element offer good
|
||||||
|
values. The next commit will be created one minute later and so
|
||||||
|
on.
|
||||||
|
|
||||||
|
This command is only intended for interactive use and should only
|
||||||
|
be used on highly rearranged and unpublished history."
|
||||||
|
(interactive (list nil))
|
||||||
|
(cond
|
||||||
|
((not rev)
|
||||||
|
(let ((backup (concat "refs/original/refs/heads/"
|
||||||
|
(magit-get-current-branch))))
|
||||||
|
(when (and (magit-ref-p backup)
|
||||||
|
(not (magit-y-or-n-p
|
||||||
|
"Backup ref %s already exists. Override? " backup)))
|
||||||
|
(user-error "Abort")))
|
||||||
|
(magit-log-select 'magit-reshelve-since
|
||||||
|
"Type %p on a commit to reshelve it and the commits above it,"))
|
||||||
|
(t
|
||||||
|
(cl-flet ((adjust (time offset)
|
||||||
|
(format-time-string
|
||||||
|
"%F %T %z"
|
||||||
|
(+ (floor time)
|
||||||
|
(* offset 60)
|
||||||
|
(- (car (decode-time time)))))))
|
||||||
|
(let* ((start (concat rev "^"))
|
||||||
|
(range (concat start ".." (magit-get-current-branch)))
|
||||||
|
(time-rev (adjust (float-time (string-to-number
|
||||||
|
(magit-rev-format "%at" start)))
|
||||||
|
1))
|
||||||
|
(time-now (adjust (float-time)
|
||||||
|
(- (string-to-number
|
||||||
|
(magit-git-string "rev-list" "--count"
|
||||||
|
range))))))
|
||||||
|
(push time-rev magit--reshelve-history)
|
||||||
|
(let ((date (floor
|
||||||
|
(float-time
|
||||||
|
(date-to-time
|
||||||
|
(read-string "Date for first commit: "
|
||||||
|
time-now 'magit--reshelve-history))))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git-async
|
||||||
|
"filter-branch" "--force" "--env-filter"
|
||||||
|
(format "case $GIT_COMMIT in %s\nesac"
|
||||||
|
(mapconcat (lambda (rev)
|
||||||
|
(prog1 (format "%s) \
|
||||||
|
export GIT_AUTHOR_DATE=\"%s\"; \
|
||||||
|
export GIT_COMMITTER_DATE=\"%s\";;" rev date date)
|
||||||
|
(cl-incf date 60)))
|
||||||
|
(magit-git-lines "rev-list" "--reverse"
|
||||||
|
range)
|
||||||
|
" "))
|
||||||
|
range "--")
|
||||||
|
(set-process-sentinel
|
||||||
|
magit-this-process
|
||||||
|
(lambda (process event)
|
||||||
|
(when (memq (process-status process) '(exit signal))
|
||||||
|
(if (> (process-exit-status process) 0)
|
||||||
|
(magit-process-sentinel process event)
|
||||||
|
(process-put process 'inhibit-refresh t)
|
||||||
|
(magit-process-sentinel process event)
|
||||||
|
(magit-run-git "update-ref" "-d"
|
||||||
|
(concat "refs/original/refs/heads/"
|
||||||
|
(magit-get-current-branch))))))))))))))
|
||||||
|
|
||||||
|
;;; Revision Stack
|
||||||
|
|
||||||
|
(defvar magit-revision-stack nil)
|
||||||
|
|
||||||
|
(defcustom magit-pop-revision-stack-format
|
||||||
|
'("[%N: %h] " "%N: %H\n %s\n" "\\[\\([0-9]+\\)[]:]")
|
||||||
|
"Control how `magit-pop-revision-stack' inserts a revision.
|
||||||
|
|
||||||
|
The command `magit-pop-revision-stack' inserts a representation
|
||||||
|
of the revision last pushed to the `magit-revision-stack' into
|
||||||
|
the current buffer. It inserts text at point and/or near the end
|
||||||
|
of the buffer, and removes the consumed revision from the stack.
|
||||||
|
|
||||||
|
The entries on the stack have the format (HASH TOPLEVEL) and this
|
||||||
|
option has the format (POINT-FORMAT EOB-FORMAT INDEX-REGEXP), all
|
||||||
|
of which may be nil or a string (though either one of EOB-FORMAT
|
||||||
|
or POINT-FORMAT should be a string, and if INDEX-REGEXP is
|
||||||
|
non-nil, then the two formats should be too).
|
||||||
|
|
||||||
|
First INDEX-REGEXP is used to find the previously inserted entry,
|
||||||
|
by searching backward from point. The first submatch must match
|
||||||
|
the index number. That number is incremented by one, and becomes
|
||||||
|
the index number of the entry to be inserted. If you don't want
|
||||||
|
to number the inserted revisions, then use nil for INDEX-REGEXP.
|
||||||
|
|
||||||
|
If INDEX-REGEXP is non-nil, then both POINT-FORMAT and EOB-FORMAT
|
||||||
|
should contain \"%N\", which is replaced with the number that was
|
||||||
|
determined in the previous step.
|
||||||
|
|
||||||
|
Both formats, if non-nil and after removing %N, are then expanded
|
||||||
|
using `git show --format=FORMAT ...' inside TOPLEVEL.
|
||||||
|
|
||||||
|
The expansion of POINT-FORMAT is inserted at point, and the
|
||||||
|
expansion of EOB-FORMAT is inserted at the end of the buffer (if
|
||||||
|
the buffer ends with a comment, then it is inserted right before
|
||||||
|
that)."
|
||||||
|
:package-version '(magit . "2.3.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(list (choice (string :tag "Insert at point format")
|
||||||
|
(cons (string :tag "Insert at point format")
|
||||||
|
(repeat (string :tag "Argument to git show")))
|
||||||
|
(const :tag "Don't insert at point" nil))
|
||||||
|
(choice (string :tag "Insert at eob format")
|
||||||
|
(cons (string :tag "Insert at eob format")
|
||||||
|
(repeat (string :tag "Argument to git show")))
|
||||||
|
(const :tag "Don't insert at eob" nil))
|
||||||
|
(choice (regexp :tag "Find index regexp")
|
||||||
|
(const :tag "Don't number entries" nil))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-pop-revision-stack (rev toplevel)
|
||||||
|
"Insert a representation of a revision into the current buffer.
|
||||||
|
|
||||||
|
Pop a revision from the `magit-revision-stack' and insert it into
|
||||||
|
the current buffer according to `magit-pop-revision-stack-format'.
|
||||||
|
Revisions can be put on the stack using `magit-copy-section-value'
|
||||||
|
and `magit-copy-buffer-revision'.
|
||||||
|
|
||||||
|
If the stack is empty or with a prefix argument, instead read a
|
||||||
|
revision in the minibuffer. By using the minibuffer history this
|
||||||
|
allows selecting an item which was popped earlier or to insert an
|
||||||
|
arbitrary reference or revision without first pushing it onto the
|
||||||
|
stack.
|
||||||
|
|
||||||
|
When reading the revision from the minibuffer, then it might not
|
||||||
|
be possible to guess the correct repository. When this command
|
||||||
|
is called inside a repository (e.g. while composing a commit
|
||||||
|
message), then that repository is used. Otherwise (e.g. while
|
||||||
|
composing an email) then the repository recorded for the top
|
||||||
|
element of the stack is used (even though we insert another
|
||||||
|
revision). If not called inside a repository and with an empty
|
||||||
|
stack, or with two prefix arguments, then read the repository in
|
||||||
|
the minibuffer too."
|
||||||
|
(interactive
|
||||||
|
(if (or current-prefix-arg (not magit-revision-stack))
|
||||||
|
(let ((default-directory
|
||||||
|
(or (and (not (= (prefix-numeric-value current-prefix-arg) 16))
|
||||||
|
(or (magit-toplevel)
|
||||||
|
(cadr (car magit-revision-stack))))
|
||||||
|
(magit-read-repository))))
|
||||||
|
(list (magit-read-branch-or-commit "Insert revision")
|
||||||
|
default-directory))
|
||||||
|
(push (caar magit-revision-stack) magit-revision-history)
|
||||||
|
(pop magit-revision-stack)))
|
||||||
|
(if rev
|
||||||
|
(pcase-let ((`(,pnt-format ,eob-format ,idx-format)
|
||||||
|
magit-pop-revision-stack-format))
|
||||||
|
(let ((default-directory toplevel)
|
||||||
|
(idx (and idx-format
|
||||||
|
(save-excursion
|
||||||
|
(if (re-search-backward idx-format nil t)
|
||||||
|
(number-to-string
|
||||||
|
(1+ (string-to-number (match-string 1))))
|
||||||
|
"1"))))
|
||||||
|
pnt-args eob-args)
|
||||||
|
(when (listp pnt-format)
|
||||||
|
(setq pnt-args (cdr pnt-format))
|
||||||
|
(setq pnt-format (car pnt-format)))
|
||||||
|
(when (listp eob-format)
|
||||||
|
(setq eob-args (cdr eob-format))
|
||||||
|
(setq eob-format (car eob-format)))
|
||||||
|
(when pnt-format
|
||||||
|
(when idx-format
|
||||||
|
(setq pnt-format
|
||||||
|
(replace-regexp-in-string "%N" idx pnt-format t t)))
|
||||||
|
(magit-rev-insert-format pnt-format rev pnt-args)
|
||||||
|
(backward-delete-char 1))
|
||||||
|
(when eob-format
|
||||||
|
(when idx-format
|
||||||
|
(setq eob-format
|
||||||
|
(replace-regexp-in-string "%N" idx eob-format t t)))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-max))
|
||||||
|
(skip-syntax-backward ">s-")
|
||||||
|
(beginning-of-line)
|
||||||
|
(if (and comment-start (looking-at comment-start))
|
||||||
|
(while (looking-at comment-start)
|
||||||
|
(forward-line -1))
|
||||||
|
(forward-line)
|
||||||
|
(unless (= (current-column) 0)
|
||||||
|
(insert ?\n)))
|
||||||
|
(insert ?\n)
|
||||||
|
(magit-rev-insert-format eob-format rev eob-args)
|
||||||
|
(backward-delete-char 1)))))
|
||||||
|
(user-error "Revision stack is empty")))
|
||||||
|
|
||||||
|
(define-key git-commit-mode-map
|
||||||
|
(kbd "C-c C-w") 'magit-pop-revision-stack)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-copy-section-value ()
|
||||||
|
"Save the value of the current section for later use.
|
||||||
|
|
||||||
|
Save the section value to the `kill-ring', and, provided that
|
||||||
|
the current section is a commit, branch, or tag section, push
|
||||||
|
the (referenced) revision to the `magit-revision-stack' for use
|
||||||
|
with `magit-pop-revision-stack'.
|
||||||
|
|
||||||
|
When the current section is a branch or a tag, and a prefix
|
||||||
|
argument is used, then save the revision at its tip to the
|
||||||
|
`kill-ring' instead of the reference name.
|
||||||
|
|
||||||
|
When the region is active, then save that to the `kill-ring',
|
||||||
|
like `kill-ring-save' would, instead of behaving as described
|
||||||
|
above. If a prefix argument is used and the region is within a
|
||||||
|
hunk, strip the outer diff marker column."
|
||||||
|
(interactive)
|
||||||
|
(cond
|
||||||
|
((and current-prefix-arg
|
||||||
|
(magit-section-internal-region-p)
|
||||||
|
(magit-section-match 'hunk))
|
||||||
|
(deactivate-mark)
|
||||||
|
(kill-new (replace-regexp-in-string
|
||||||
|
"^[ \\+\\-]" ""
|
||||||
|
(buffer-substring-no-properties
|
||||||
|
(region-beginning) (region-end)))))
|
||||||
|
((use-region-p)
|
||||||
|
(copy-region-as-kill nil nil 'region))
|
||||||
|
(t
|
||||||
|
(when-let ((section (magit-current-section))
|
||||||
|
(value (oref section value)))
|
||||||
|
(magit-section-case
|
||||||
|
((branch commit module-commit tag)
|
||||||
|
(let ((default-directory default-directory) ref)
|
||||||
|
(magit-section-case
|
||||||
|
((branch tag)
|
||||||
|
(setq ref value))
|
||||||
|
(module-commit
|
||||||
|
(setq default-directory
|
||||||
|
(file-name-as-directory
|
||||||
|
(expand-file-name (magit-section-parent-value section)
|
||||||
|
(magit-toplevel))))))
|
||||||
|
(setq value (magit-rev-parse value))
|
||||||
|
(push (list value default-directory) magit-revision-stack)
|
||||||
|
(kill-new (message "%s" (or (and current-prefix-arg ref)
|
||||||
|
value)))))
|
||||||
|
(t (kill-new (message "%s" value))))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-copy-buffer-revision ()
|
||||||
|
"Save the revision of the current buffer for later use.
|
||||||
|
|
||||||
|
Save the revision shown in the current buffer to the `kill-ring'
|
||||||
|
and push it to the `magit-revision-stack'.
|
||||||
|
|
||||||
|
This command is mainly intended for use in `magit-revision-mode'
|
||||||
|
buffers, the only buffers where it is always unambiguous exactly
|
||||||
|
which revision should be saved.
|
||||||
|
|
||||||
|
Most other Magit buffers usually show more than one revision, in
|
||||||
|
some way or another, so this command has to select one of them,
|
||||||
|
and that choice might not always be the one you think would have
|
||||||
|
been the best pick.
|
||||||
|
|
||||||
|
In such buffers it is often more useful to save the value of
|
||||||
|
the current section instead, using `magit-copy-section-value'.
|
||||||
|
|
||||||
|
When the region is active, then save that to the `kill-ring',
|
||||||
|
like `kill-ring-save' would, instead of behaving as described
|
||||||
|
above."
|
||||||
|
(interactive)
|
||||||
|
(if (use-region-p)
|
||||||
|
(copy-region-as-kill nil nil 'region)
|
||||||
|
(when-let ((rev (or magit-buffer-revision
|
||||||
|
(cl-case major-mode
|
||||||
|
(magit-diff-mode
|
||||||
|
(if (string-match "\\.\\.\\.?\\(.+\\)"
|
||||||
|
magit-buffer-range)
|
||||||
|
(match-string 1 magit-buffer-range)
|
||||||
|
magit-buffer-range))
|
||||||
|
(magit-status-mode "HEAD")))))
|
||||||
|
(when (magit-commit-p rev)
|
||||||
|
(setq rev (magit-rev-parse rev))
|
||||||
|
(push (list rev default-directory) magit-revision-stack)
|
||||||
|
(kill-new (message "%s" rev))))))
|
||||||
|
|
||||||
|
;;; Miscellaneous
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-abort-dwim ()
|
||||||
|
"Abort current operation.
|
||||||
|
Depending on the context, this will abort a merge, a rebase, a
|
||||||
|
patch application, a cherry-pick, a revert, or a bisect."
|
||||||
|
(interactive)
|
||||||
|
(cond ((magit-merge-in-progress-p) (magit-merge-abort))
|
||||||
|
((magit-rebase-in-progress-p) (magit-rebase-abort))
|
||||||
|
((magit-am-in-progress-p) (magit-am-abort))
|
||||||
|
((magit-sequencer-in-progress-p) (magit-sequencer-abort))
|
||||||
|
((magit-bisect-in-progress-p) (magit-bisect-reset))))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-extras)
|
||||||
|
;;; magit-extras.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-extras.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-extras.elc
Normal file
Binary file not shown.
186
elpa/magit-20191030.1315/magit-fetch.el
Normal file
186
elpa/magit-20191030.1315/magit-fetch.el
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
;;; magit-fetch.el --- download objects and refs -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2008-2019 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 fetch commands.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
;;; Options
|
||||||
|
|
||||||
|
(defcustom magit-fetch-modules-jobs 4
|
||||||
|
"Number of submodules to fetch in parallel.
|
||||||
|
Ignored for Git versions before v2.8.0."
|
||||||
|
:package-version '(magit . "2.12.0")
|
||||||
|
:group 'magit-commands
|
||||||
|
:type '(choice (const :tag "one at a time" nil) number))
|
||||||
|
|
||||||
|
;;; Commands
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-fetch "magit-fetch" nil t)
|
||||||
|
(define-transient-command magit-fetch ()
|
||||||
|
"Fetch from another repository."
|
||||||
|
:man-page "git-fetch"
|
||||||
|
["Arguments"
|
||||||
|
("-p" "Prune deleted branches" ("-p" "--prune"))
|
||||||
|
("-t" "Fetch all tags" ("-t" "--tags"))]
|
||||||
|
["Fetch from"
|
||||||
|
("p" magit-fetch-from-pushremote)
|
||||||
|
("u" magit-fetch-from-upstream)
|
||||||
|
("e" "elsewhere" magit-fetch-other)
|
||||||
|
("a" "all remotes" magit-fetch-all)]
|
||||||
|
["Fetch"
|
||||||
|
("o" "another branch" magit-fetch-branch)
|
||||||
|
("r" "explicit refspec" magit-fetch-refspec)
|
||||||
|
("m" "submodules" magit-fetch-modules)]
|
||||||
|
["Configure"
|
||||||
|
("C" "variables..." magit-branch-configure)])
|
||||||
|
|
||||||
|
(defun magit-fetch-arguments ()
|
||||||
|
(transient-args 'magit-fetch))
|
||||||
|
|
||||||
|
(defun magit-git-fetch (remote args)
|
||||||
|
(run-hooks 'magit-credential-hook)
|
||||||
|
(magit-run-git-async "fetch" remote args))
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-fetch-from-pushremote "magit-fetch" nil t)
|
||||||
|
(define-suffix-command magit-fetch-from-pushremote (args)
|
||||||
|
"Fetch from the current push-remote.
|
||||||
|
|
||||||
|
When the push-remote is not configured, then read the push-remote
|
||||||
|
from the user, set it, and then fetch from it. With a prefix
|
||||||
|
argument the push-remote can be changed before fetching from it."
|
||||||
|
:description 'magit-fetch--pushremote-description
|
||||||
|
(interactive (list (magit-fetch-arguments)))
|
||||||
|
(let ((remote (magit-get-push-remote)))
|
||||||
|
(when (or current-prefix-arg
|
||||||
|
(not (member remote (magit-list-remotes))))
|
||||||
|
(let ((var (magit--push-remote-variable)))
|
||||||
|
(setq remote
|
||||||
|
(magit-read-remote (format "Set %s and fetch from there" var)))
|
||||||
|
(magit-set remote var)))
|
||||||
|
(magit-git-fetch remote args)))
|
||||||
|
|
||||||
|
(defun magit-fetch--pushremote-description ()
|
||||||
|
(let* ((branch (magit-get-current-branch))
|
||||||
|
(remote (magit-get-push-remote branch))
|
||||||
|
(v (magit--push-remote-variable branch t)))
|
||||||
|
(cond
|
||||||
|
((member remote (magit-list-remotes)) remote)
|
||||||
|
(remote
|
||||||
|
(format "%s, replacing invalid" v))
|
||||||
|
(t
|
||||||
|
(format "%s, setting that" v)))))
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-fetch-from-upstream "magit-fetch" nil t)
|
||||||
|
(define-suffix-command magit-fetch-from-upstream (remote args)
|
||||||
|
"Fetch from the \"current\" remote, usually the upstream.
|
||||||
|
|
||||||
|
If the upstream is configured for the current branch and names
|
||||||
|
an existing remote, then use that. Otherwise try to use another
|
||||||
|
remote: If only a single remote is configured, then use that.
|
||||||
|
Otherwise if a remote named \"origin\" exists, then use that.
|
||||||
|
|
||||||
|
If no remote can be determined, then this command is not available
|
||||||
|
from the `magit-fetch' transient prefix and invoking it directly
|
||||||
|
results in an error."
|
||||||
|
:if (lambda () (magit-get-current-remote t))
|
||||||
|
:description (lambda () (magit-get-current-remote t))
|
||||||
|
(interactive (list (magit-get-current-remote t)
|
||||||
|
(magit-fetch-arguments)))
|
||||||
|
(unless remote
|
||||||
|
(error "The \"current\" remote could not be determined"))
|
||||||
|
(magit-git-fetch remote args))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-fetch-other (remote args)
|
||||||
|
"Fetch from another repository."
|
||||||
|
(interactive (list (magit-read-remote "Fetch remote")
|
||||||
|
(magit-fetch-arguments)))
|
||||||
|
(magit-git-fetch remote args))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-fetch-branch (remote branch args)
|
||||||
|
"Fetch a BRANCH from a REMOTE."
|
||||||
|
(interactive
|
||||||
|
(let ((remote (magit-read-remote-or-url "Fetch from remote or url")))
|
||||||
|
(list remote
|
||||||
|
(magit-read-remote-branch "Fetch branch" remote)
|
||||||
|
(magit-fetch-arguments))))
|
||||||
|
(magit-git-fetch remote (cons branch args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-fetch-refspec (remote refspec args)
|
||||||
|
"Fetch a REFSPEC from a REMOTE."
|
||||||
|
(interactive
|
||||||
|
(let ((remote (magit-read-remote-or-url "Fetch from remote or url")))
|
||||||
|
(list remote
|
||||||
|
(magit-read-refspec "Fetch using refspec" remote)
|
||||||
|
(magit-fetch-arguments))))
|
||||||
|
(magit-git-fetch remote (cons refspec args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-fetch-all (args)
|
||||||
|
"Fetch from all remotes."
|
||||||
|
(interactive (list (magit-fetch-arguments)))
|
||||||
|
(magit-git-fetch nil (cons "--all" args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-fetch-all-prune ()
|
||||||
|
"Fetch from all remotes, and prune.
|
||||||
|
Prune remote tracking branches for branches that have been
|
||||||
|
removed on the respective remote."
|
||||||
|
(interactive)
|
||||||
|
(run-hooks 'magit-credential-hook)
|
||||||
|
(magit-run-git-async "remote" "update" "--prune"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-fetch-all-no-prune ()
|
||||||
|
"Fetch from all remotes."
|
||||||
|
(interactive)
|
||||||
|
(run-hooks 'magit-credential-hook)
|
||||||
|
(magit-run-git-async "remote" "update"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-fetch-modules (&optional all)
|
||||||
|
"Fetch all submodules.
|
||||||
|
|
||||||
|
Option `magit-fetch-modules-jobs' controls how many submodules
|
||||||
|
are being fetched in parallel. Also fetch the super-repository,
|
||||||
|
because `git-fetch' does not support not doing that. With a
|
||||||
|
prefix argument fetch all remotes."
|
||||||
|
(interactive "P")
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git-async
|
||||||
|
"fetch" "--verbose" "--recurse-submodules"
|
||||||
|
(and magit-fetch-modules-jobs
|
||||||
|
(version<= "2.8.0" (magit-git-version))
|
||||||
|
(list "-j" (number-to-string magit-fetch-modules-jobs)))
|
||||||
|
(and all "--all"))))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-fetch)
|
||||||
|
;;; magit-fetch.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-fetch.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-fetch.elc
Normal file
Binary file not shown.
558
elpa/magit-20191030.1315/magit-files.el
Normal file
558
elpa/magit-20191030.1315/magit-files.el
Normal file
@@ -0,0 +1,558 @@
|
|||||||
|
;;; magit-files.el --- finding files -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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 support for finding blobs, staged files,
|
||||||
|
;; and Git configuration files. It also implements modes useful in
|
||||||
|
;; buffers visiting files and blobs, and the commands used by those
|
||||||
|
;; modes.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'subr-x))
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
;;; Find Blob
|
||||||
|
|
||||||
|
(defvar magit-find-file-hook nil)
|
||||||
|
(add-hook 'magit-find-file-hook #'magit-blob-mode)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-find-file (rev file)
|
||||||
|
"View FILE from REV.
|
||||||
|
Switch to a buffer visiting blob REV:FILE, creating one if none
|
||||||
|
already exists. If prior to calling this command the current
|
||||||
|
buffer and/or cursor position is about the same file, then go
|
||||||
|
to the line and column corresponding to that location."
|
||||||
|
(interactive (magit-find-file-read-args "Find file"))
|
||||||
|
(magit-find-file--internal rev file #'pop-to-buffer-same-window))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-find-file-other-window (rev file)
|
||||||
|
"View FILE from REV, in another window.
|
||||||
|
Switch to a buffer visiting blob REV:FILE, creating one if none
|
||||||
|
already exists. If prior to calling this command the current
|
||||||
|
buffer and/or cursor position is about the same file, then go to
|
||||||
|
the line and column corresponding to that location."
|
||||||
|
(interactive (magit-find-file-read-args "Find file in other window"))
|
||||||
|
(magit-find-file--internal rev file #'switch-to-buffer-other-window))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-find-file-other-frame (rev file)
|
||||||
|
"View FILE from REV, in another frame.
|
||||||
|
Switch to a buffer visiting blob REV:FILE, creating one if none
|
||||||
|
already exists. If prior to calling this command the current
|
||||||
|
buffer and/or cursor position is about the same file, then go to
|
||||||
|
the line and column corresponding to that location."
|
||||||
|
(interactive (magit-find-file-read-args "Find file in other frame"))
|
||||||
|
(magit-find-file--internal rev file #'switch-to-buffer-other-frame))
|
||||||
|
|
||||||
|
(defun magit-find-file-read-args (prompt)
|
||||||
|
(let ((pseudo-revs '("{worktree}" "{index}")))
|
||||||
|
(if-let ((rev (magit-completing-read "Find file from revision"
|
||||||
|
(append pseudo-revs
|
||||||
|
(magit-list-refnames nil t))
|
||||||
|
nil nil nil 'magit-revision-history
|
||||||
|
(or (magit-branch-or-commit-at-point)
|
||||||
|
(magit-get-current-branch)))))
|
||||||
|
(list rev (magit-read-file-from-rev (if (member rev pseudo-revs)
|
||||||
|
"HEAD"
|
||||||
|
rev)
|
||||||
|
prompt))
|
||||||
|
(user-error "Nothing selected"))))
|
||||||
|
|
||||||
|
(defun magit-find-file--internal (rev file fn)
|
||||||
|
(let ((buf (magit-find-file-noselect rev file))
|
||||||
|
line col)
|
||||||
|
(when-let ((visited-file (magit-file-relative-name)))
|
||||||
|
(setq line (line-number-at-pos))
|
||||||
|
(setq col (current-column))
|
||||||
|
(cond
|
||||||
|
((not (equal visited-file file)))
|
||||||
|
((equal magit-buffer-revision rev))
|
||||||
|
((equal rev "{worktree}")
|
||||||
|
(setq line (magit-diff-visit--offset file magit-buffer-revision line)))
|
||||||
|
((equal rev "{index}")
|
||||||
|
(setq line (magit-diff-visit--offset file nil line)))
|
||||||
|
(magit-buffer-revision
|
||||||
|
(setq line (magit-diff-visit--offset
|
||||||
|
file (concat magit-buffer-revision ".." rev) line)))
|
||||||
|
(t
|
||||||
|
(setq line (magit-diff-visit--offset file (list "-R" rev) line)))))
|
||||||
|
(funcall fn buf)
|
||||||
|
(when line
|
||||||
|
(with-current-buffer buf
|
||||||
|
(widen)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(forward-line (1- line))
|
||||||
|
(move-to-column col)))
|
||||||
|
buf))
|
||||||
|
|
||||||
|
(defun magit-find-file-noselect (rev file)
|
||||||
|
"Read FILE from REV into a buffer and return the buffer.
|
||||||
|
REV is a revision or one of \"{worktree}\" or \"{index}\".
|
||||||
|
FILE must be relative to the top directory of the repository."
|
||||||
|
(magit-find-file-noselect-1 rev file))
|
||||||
|
|
||||||
|
(defun magit-find-file-noselect-1 (rev file &optional revert)
|
||||||
|
"Read FILE from REV into a buffer and return the buffer.
|
||||||
|
REV is a revision or one of \"{worktree}\" or \"{index}\".
|
||||||
|
FILE must be relative to the top directory of the repository.
|
||||||
|
Non-nil REVERT means to revert the buffer. If `ask-revert',
|
||||||
|
then only after asking. A non-nil value for REVERT is ignored if REV is
|
||||||
|
\"{worktree}\"."
|
||||||
|
(if (equal rev "{worktree}")
|
||||||
|
(find-file-noselect (expand-file-name file (magit-toplevel)))
|
||||||
|
(let ((topdir (magit-toplevel)))
|
||||||
|
(when (file-name-absolute-p file)
|
||||||
|
(setq file (file-relative-name file topdir)))
|
||||||
|
(with-current-buffer (magit-get-revision-buffer-create rev file)
|
||||||
|
(when (or (not magit-buffer-file-name)
|
||||||
|
(if (eq revert 'ask-revert)
|
||||||
|
(y-or-n-p (format "%s already exists; revert it? "
|
||||||
|
(buffer-name))))
|
||||||
|
revert)
|
||||||
|
(setq magit-buffer-revision
|
||||||
|
(if (equal rev "{index}")
|
||||||
|
"{index}"
|
||||||
|
(magit-rev-format "%H" rev)))
|
||||||
|
(setq magit-buffer-refname rev)
|
||||||
|
(setq magit-buffer-file-name (expand-file-name file topdir))
|
||||||
|
(setq default-directory
|
||||||
|
(let ((dir (file-name-directory magit-buffer-file-name)))
|
||||||
|
(if (file-exists-p dir) dir topdir)))
|
||||||
|
(setq-local revert-buffer-function #'magit-revert-rev-file-buffer)
|
||||||
|
(revert-buffer t t)
|
||||||
|
(run-hooks (if (equal rev "{index}")
|
||||||
|
'magit-find-index-hook
|
||||||
|
'magit-find-file-hook)))
|
||||||
|
(current-buffer)))))
|
||||||
|
|
||||||
|
(defun magit-get-revision-buffer-create (rev file)
|
||||||
|
(magit-get-revision-buffer rev file t))
|
||||||
|
|
||||||
|
(defun magit-get-revision-buffer (rev file &optional create)
|
||||||
|
(funcall (if create 'get-buffer-create 'get-buffer)
|
||||||
|
(format "%s.~%s~" file (subst-char-in-string ?/ ?_ rev))))
|
||||||
|
|
||||||
|
(defun magit-revert-rev-file-buffer (_ignore-auto noconfirm)
|
||||||
|
(when (or noconfirm
|
||||||
|
(and (not (buffer-modified-p))
|
||||||
|
(catch 'found
|
||||||
|
(dolist (regexp revert-without-query)
|
||||||
|
(when (string-match regexp magit-buffer-file-name)
|
||||||
|
(throw 'found t)))))
|
||||||
|
(yes-or-no-p (format "Revert buffer from Git %s? "
|
||||||
|
(if (equal magit-buffer-refname "{index}")
|
||||||
|
"index"
|
||||||
|
(concat "revision " magit-buffer-refname)))))
|
||||||
|
(let* ((inhibit-read-only t)
|
||||||
|
(default-directory (magit-toplevel))
|
||||||
|
(file (file-relative-name magit-buffer-file-name))
|
||||||
|
(coding-system-for-read (or coding-system-for-read 'undecided)))
|
||||||
|
(erase-buffer)
|
||||||
|
(magit-git-insert "cat-file" "-p"
|
||||||
|
(if (equal magit-buffer-refname "{index}")
|
||||||
|
(concat ":" file)
|
||||||
|
(concat magit-buffer-refname ":" file)))
|
||||||
|
(setq buffer-file-coding-system last-coding-system-used))
|
||||||
|
(let ((buffer-file-name magit-buffer-file-name)
|
||||||
|
(after-change-major-mode-hook
|
||||||
|
(remq 'global-diff-hl-mode-enable-in-buffers
|
||||||
|
after-change-major-mode-hook)))
|
||||||
|
(normal-mode t))
|
||||||
|
(setq buffer-read-only t)
|
||||||
|
(set-buffer-modified-p nil)
|
||||||
|
(goto-char (point-min))))
|
||||||
|
|
||||||
|
;;; Find Index
|
||||||
|
|
||||||
|
(defvar magit-find-index-hook nil)
|
||||||
|
|
||||||
|
(defun magit-find-file-index-noselect (file &optional revert)
|
||||||
|
"Read FILE from the index into a buffer and return the buffer.
|
||||||
|
FILE must to be relative to the top directory of the repository."
|
||||||
|
(magit-find-file-noselect-1 "{index}" file (or revert 'ask-revert)))
|
||||||
|
|
||||||
|
(defun magit-update-index ()
|
||||||
|
"Update the index with the contents of the current buffer.
|
||||||
|
The current buffer has to be visiting a file in the index, which
|
||||||
|
is done using `magit-find-index-noselect'."
|
||||||
|
(interactive)
|
||||||
|
(let ((file (magit-file-relative-name)))
|
||||||
|
(unless (equal magit-buffer-refname "{index}")
|
||||||
|
(user-error "%s isn't visiting the index" file))
|
||||||
|
(if (y-or-n-p (format "Update index with contents of %s" (buffer-name)))
|
||||||
|
(let ((index (make-temp-file "index"))
|
||||||
|
(buffer (current-buffer)))
|
||||||
|
(when magit-wip-before-change-mode
|
||||||
|
(magit-wip-commit-before-change (list file) " before un-/stage"))
|
||||||
|
(let ((coding-system-for-write buffer-file-coding-system))
|
||||||
|
(with-temp-file index
|
||||||
|
(insert-buffer-substring buffer)))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-call-git "update-index" "--cacheinfo"
|
||||||
|
(substring (magit-git-string "ls-files" "-s" file)
|
||||||
|
0 6)
|
||||||
|
(magit-git-string "hash-object" "-t" "blob" "-w"
|
||||||
|
(concat "--path=" file)
|
||||||
|
"--" index)
|
||||||
|
file))
|
||||||
|
(set-buffer-modified-p nil)
|
||||||
|
(when magit-wip-after-apply-mode
|
||||||
|
(magit-wip-commit-after-apply (list file) " after un-/stage")))
|
||||||
|
(message "Abort")))
|
||||||
|
(--when-let (magit-get-mode-buffer 'magit-status-mode)
|
||||||
|
(with-current-buffer it (magit-refresh)))
|
||||||
|
t)
|
||||||
|
|
||||||
|
;;; Find Config File
|
||||||
|
|
||||||
|
(defun magit-find-git-config-file (filename &optional wildcards)
|
||||||
|
"Edit a file located in the current repository's git directory.
|
||||||
|
|
||||||
|
When \".git\", located at the root of the working tree, is a
|
||||||
|
regular file, then that makes it cumbersome to open a file
|
||||||
|
located in the actual git directory.
|
||||||
|
|
||||||
|
This command is like `find-file', except that it temporarily
|
||||||
|
binds `default-directory' to the actual git directory, while
|
||||||
|
reading the FILENAME."
|
||||||
|
(interactive
|
||||||
|
(let ((default-directory (magit-git-dir)))
|
||||||
|
(find-file-read-args "Find file: "
|
||||||
|
(confirm-nonexistent-file-or-buffer))))
|
||||||
|
(find-file filename wildcards))
|
||||||
|
|
||||||
|
(defun magit-find-git-config-file-other-window (filename &optional wildcards)
|
||||||
|
"Edit a file located in the current repository's git directory, in another window.
|
||||||
|
|
||||||
|
When \".git\", located at the root of the working tree, is a
|
||||||
|
regular file, then that makes it cumbersome to open a file
|
||||||
|
located in the actual git directory.
|
||||||
|
|
||||||
|
This command is like `find-file-other-window', except that it
|
||||||
|
temporarily binds `default-directory' to the actual git
|
||||||
|
directory, while reading the FILENAME."
|
||||||
|
(interactive
|
||||||
|
(let ((default-directory (magit-git-dir)))
|
||||||
|
(find-file-read-args "Find file in other window: "
|
||||||
|
(confirm-nonexistent-file-or-buffer))))
|
||||||
|
(find-file-other-window filename wildcards))
|
||||||
|
|
||||||
|
(defun magit-find-git-config-file-other-frame (filename &optional wildcards)
|
||||||
|
"Edit a file located in the current repository's git directory, in another frame.
|
||||||
|
|
||||||
|
When \".git\", located at the root of the working tree, is a
|
||||||
|
regular file, then that makes it cumbersome to open a file
|
||||||
|
located in the actual git directory.
|
||||||
|
|
||||||
|
This command is like `find-file-other-frame', except that it
|
||||||
|
temporarily binds `default-directory' to the actual git
|
||||||
|
directory, while reading the FILENAME."
|
||||||
|
(interactive
|
||||||
|
(let ((default-directory (magit-git-dir)))
|
||||||
|
(find-file-read-args "Find file in other frame: "
|
||||||
|
(confirm-nonexistent-file-or-buffer))))
|
||||||
|
(find-file-other-frame filename wildcards))
|
||||||
|
|
||||||
|
;;; File Mode
|
||||||
|
|
||||||
|
(defvar magit-file-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(define-key map "\C-xg" 'magit-status)
|
||||||
|
(define-key map "\C-x\M-g" 'magit-dispatch)
|
||||||
|
(define-key map "\C-c\M-g" 'magit-file-dispatch)
|
||||||
|
map)
|
||||||
|
"Keymap for `magit-file-mode'.")
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-file-dispatch "magit" nil t)
|
||||||
|
(define-transient-command magit-file-dispatch ()
|
||||||
|
"Invoke a Magit command that acts on the visited file."
|
||||||
|
:info-manual "(magit) Minor Mode for Buffers Visiting Files"
|
||||||
|
["Actions"
|
||||||
|
[("s" "Stage" magit-stage-file)
|
||||||
|
("u" "Unstage" magit-unstage-file)
|
||||||
|
("c" "Commit" magit-commit)
|
||||||
|
("e" "Edit line" magit-edit-line-commit)]
|
||||||
|
[("D" "Diff..." magit-diff)
|
||||||
|
("d" "Diff" magit-diff-buffer-file)
|
||||||
|
("g" "Status" magit-status-here)]
|
||||||
|
[("L" "Log..." magit-log)
|
||||||
|
("l" "Log" magit-log-buffer-file)
|
||||||
|
("t" "Trace" magit-log-trace-definition)]
|
||||||
|
[("B" "Blame..." magit-blame)
|
||||||
|
("b" "Blame" magit-blame-addition)
|
||||||
|
("r" "...removal" magit-blame-removal)
|
||||||
|
("f" "...reverse" magit-blame-reverse)
|
||||||
|
("m" "Blame echo" magit-blame-echo)
|
||||||
|
("q" "Quit blame" magit-blame-quit)]
|
||||||
|
[("p" "Prev blob" magit-blob-previous)
|
||||||
|
("n" "Next blob" magit-blob-next)
|
||||||
|
("v" "Goto blob" magit-find-file)
|
||||||
|
("V" "Goto file" magit-blob-visit-file)]
|
||||||
|
[(5 "C-c r" "Rename file" magit-file-rename)
|
||||||
|
(5 "C-c d" "Delete file" magit-file-delete)
|
||||||
|
(5 "C-c u" "Untrack file" magit-file-untrack)
|
||||||
|
(5 "C-c c" "Checkout file" magit-file-checkout)]])
|
||||||
|
|
||||||
|
(defvar magit-file-mode-lighter "")
|
||||||
|
|
||||||
|
(define-minor-mode magit-file-mode
|
||||||
|
"Enable some Magit features in a file-visiting buffer.
|
||||||
|
|
||||||
|
Currently this only adds the following key bindings.
|
||||||
|
\n\\{magit-file-mode-map}"
|
||||||
|
:package-version '(magit . "2.2.0")
|
||||||
|
:lighter magit-file-mode-lighter
|
||||||
|
:keymap magit-file-mode-map)
|
||||||
|
|
||||||
|
(defun magit-file-mode-turn-on ()
|
||||||
|
(and buffer-file-name
|
||||||
|
(magit-inside-worktree-p t)
|
||||||
|
(magit-file-mode)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(define-globalized-minor-mode global-magit-file-mode
|
||||||
|
magit-file-mode magit-file-mode-turn-on
|
||||||
|
:package-version '(magit . "2.13.0")
|
||||||
|
:link '(info-link "(magit)Minor Mode for Buffers Visiting Files")
|
||||||
|
:group 'magit-essentials
|
||||||
|
:group 'magit-modes
|
||||||
|
:init-value t)
|
||||||
|
;; Unfortunately `:init-value t' only sets the value of the mode
|
||||||
|
;; variable but does not cause the mode function to be called, and we
|
||||||
|
;; cannot use `:initialize' to call that explicitly because the option
|
||||||
|
;; is defined before the functions, so we have to do it here.
|
||||||
|
(cl-eval-when (load eval)
|
||||||
|
(when global-magit-file-mode
|
||||||
|
(global-magit-file-mode 1)))
|
||||||
|
|
||||||
|
;;; Blob Mode
|
||||||
|
|
||||||
|
(defvar magit-blob-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(cond ((featurep 'jkl)
|
||||||
|
(define-key map "i" 'magit-blob-previous)
|
||||||
|
(define-key map "k" 'magit-blob-next)
|
||||||
|
(define-key map "j" 'magit-blame-addition)
|
||||||
|
(define-key map "l" 'magit-blame-removal)
|
||||||
|
(define-key map "f" 'magit-blame-reverse))
|
||||||
|
(t
|
||||||
|
(define-key map "p" 'magit-blob-previous)
|
||||||
|
(define-key map "n" 'magit-blob-next)
|
||||||
|
(define-key map "b" 'magit-blame-addition)
|
||||||
|
(define-key map "r" 'magit-blame-removal)
|
||||||
|
(define-key map "f" 'magit-blame-reverse)))
|
||||||
|
(define-key map "q" 'magit-kill-this-buffer)
|
||||||
|
map)
|
||||||
|
"Keymap for `magit-blob-mode'.")
|
||||||
|
|
||||||
|
(define-minor-mode magit-blob-mode
|
||||||
|
"Enable some Magit features in blob-visiting buffers.
|
||||||
|
|
||||||
|
Currently this only adds the following key bindings.
|
||||||
|
\n\\{magit-blob-mode-map}"
|
||||||
|
:package-version '(magit . "2.3.0"))
|
||||||
|
|
||||||
|
(defun magit-blob-next ()
|
||||||
|
"Visit the next blob which modified the current file."
|
||||||
|
(interactive)
|
||||||
|
(if magit-buffer-file-name
|
||||||
|
(magit-blob-visit (or (magit-blob-successor magit-buffer-revision
|
||||||
|
magit-buffer-file-name)
|
||||||
|
magit-buffer-file-name))
|
||||||
|
(if (buffer-file-name (buffer-base-buffer))
|
||||||
|
(user-error "You have reached the end of time")
|
||||||
|
(user-error "Buffer isn't visiting a file or blob"))))
|
||||||
|
|
||||||
|
(defun magit-blob-previous ()
|
||||||
|
"Visit the previous blob which modified the current file."
|
||||||
|
(interactive)
|
||||||
|
(if-let ((file (or magit-buffer-file-name
|
||||||
|
(buffer-file-name (buffer-base-buffer)))))
|
||||||
|
(--if-let (magit-blob-ancestor magit-buffer-revision file)
|
||||||
|
(magit-blob-visit it)
|
||||||
|
(user-error "You have reached the beginning of time"))
|
||||||
|
(user-error "Buffer isn't visiting a file or blob")))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-blob-visit-file ()
|
||||||
|
"View the file from the worktree corresponding to the current blob.
|
||||||
|
When visiting a blob or the version from the index, then go to
|
||||||
|
the same location in the respective file in the working tree."
|
||||||
|
(interactive)
|
||||||
|
(if-let ((file (magit-file-relative-name)))
|
||||||
|
(magit-find-file--internal "{worktree}" file #'pop-to-buffer-same-window)
|
||||||
|
(user-error "Not visiting a blob")))
|
||||||
|
|
||||||
|
(defun magit-blob-visit (blob-or-file)
|
||||||
|
(if (stringp blob-or-file)
|
||||||
|
(find-file blob-or-file)
|
||||||
|
(pcase-let ((`(,rev ,file) blob-or-file))
|
||||||
|
(magit-find-file rev file)
|
||||||
|
(apply #'message "%s (%s %s ago)"
|
||||||
|
(magit-rev-format "%s" rev)
|
||||||
|
(magit--age (magit-rev-format "%ct" rev))))))
|
||||||
|
|
||||||
|
(defun magit-blob-ancestor (rev file)
|
||||||
|
(let ((lines (magit-with-toplevel
|
||||||
|
(magit-git-lines "log" "-2" "--format=%H" "--name-only"
|
||||||
|
"--follow" (or rev "HEAD") "--" file))))
|
||||||
|
(if rev (cddr lines) (butlast lines 2))))
|
||||||
|
|
||||||
|
(defun magit-blob-successor (rev file)
|
||||||
|
(let ((lines (magit-with-toplevel
|
||||||
|
(magit-git-lines "log" "--format=%H" "--name-only" "--follow"
|
||||||
|
"HEAD" "--" file))))
|
||||||
|
(catch 'found
|
||||||
|
(while lines
|
||||||
|
(if (equal (nth 2 lines) rev)
|
||||||
|
(throw 'found (list (nth 0 lines) (nth 1 lines)))
|
||||||
|
(setq lines (nthcdr 2 lines)))))))
|
||||||
|
|
||||||
|
;;; File Commands
|
||||||
|
|
||||||
|
(defun magit-file-rename (file newname)
|
||||||
|
"Rename the FILE to NEWNAME.
|
||||||
|
If FILE isn't tracked in Git, fallback to using `rename-file'."
|
||||||
|
(interactive
|
||||||
|
(let* ((file (magit-read-file "Rename file"))
|
||||||
|
(dir (file-name-directory file))
|
||||||
|
(newname (read-file-name (format "Rename %s to file: " file)
|
||||||
|
(and dir (expand-file-name dir)))))
|
||||||
|
(list (expand-file-name file (magit-toplevel))
|
||||||
|
(expand-file-name newname))))
|
||||||
|
(let ((oldbuf (get-file-buffer file)))
|
||||||
|
(when (and oldbuf (buffer-modified-p oldbuf))
|
||||||
|
(user-error "Save %s before moving it" file))
|
||||||
|
(when (file-exists-p newname)
|
||||||
|
(user-error "%s already exists" newname))
|
||||||
|
(if (magit-file-tracked-p (magit-convert-filename-for-git file))
|
||||||
|
(magit-call-git "mv"
|
||||||
|
(magit-convert-filename-for-git file)
|
||||||
|
(magit-convert-filename-for-git newname))
|
||||||
|
(rename-file file newname current-prefix-arg))
|
||||||
|
(when oldbuf
|
||||||
|
(with-current-buffer oldbuf
|
||||||
|
(let ((buffer-read-only buffer-read-only))
|
||||||
|
(set-visited-file-name newname nil t))
|
||||||
|
(if (fboundp 'vc-refresh-state)
|
||||||
|
(vc-refresh-state)
|
||||||
|
(with-no-warnings
|
||||||
|
(vc-find-file-hook))))))
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
(defun magit-file-untrack (files &optional force)
|
||||||
|
"Untrack the selected FILES or one file read in the minibuffer.
|
||||||
|
|
||||||
|
With a prefix argument FORCE do so even when the files have
|
||||||
|
staged as well as unstaged changes."
|
||||||
|
(interactive (list (or (--if-let (magit-region-values 'file t)
|
||||||
|
(progn
|
||||||
|
(unless (magit-file-tracked-p (car it))
|
||||||
|
(user-error "Already untracked"))
|
||||||
|
(magit-confirm-files 'untrack it "Untrack"))
|
||||||
|
(list (magit-read-tracked-file "Untrack file"))))
|
||||||
|
current-prefix-arg))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git "rm" "--cached" (and force "--force") "--" files)))
|
||||||
|
|
||||||
|
(defun magit-file-delete (files &optional force)
|
||||||
|
"Delete the selected FILES or one file read in the minibuffer.
|
||||||
|
|
||||||
|
With a prefix argument FORCE do so even when the files have
|
||||||
|
uncommitted changes. When the files aren't being tracked in
|
||||||
|
Git, then fallback to using `delete-file'."
|
||||||
|
(interactive (list (--if-let (magit-region-values 'file t)
|
||||||
|
(magit-confirm-files 'delete it "Delete")
|
||||||
|
(list (magit-read-file "Delete file")))
|
||||||
|
current-prefix-arg))
|
||||||
|
(if (magit-file-tracked-p (car files))
|
||||||
|
(magit-call-git "rm" (and force "--force") "--" files)
|
||||||
|
(let ((topdir (magit-toplevel)))
|
||||||
|
(dolist (file files)
|
||||||
|
(delete-file (expand-file-name file topdir) t))))
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-file-checkout (rev file)
|
||||||
|
"Checkout FILE from REV."
|
||||||
|
(interactive
|
||||||
|
(let ((rev (magit-read-branch-or-commit
|
||||||
|
"Checkout from revision" magit-buffer-revision)))
|
||||||
|
(list rev (magit-read-file-from-rev rev "Checkout file"))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git "checkout" rev "--" file)))
|
||||||
|
|
||||||
|
;;; Read File
|
||||||
|
|
||||||
|
(defvar magit-read-file-hist nil)
|
||||||
|
|
||||||
|
(defun magit-read-file-from-rev (rev prompt &optional default)
|
||||||
|
(let ((files (magit-revision-files rev)))
|
||||||
|
(magit-completing-read
|
||||||
|
prompt files nil t nil 'magit-read-file-hist
|
||||||
|
(car (member (or default (magit-current-file)) files)))))
|
||||||
|
|
||||||
|
(defun magit-read-file (prompt &optional tracked-only)
|
||||||
|
(let ((choices (nconc (magit-list-files)
|
||||||
|
(unless tracked-only (magit-untracked-files)))))
|
||||||
|
(magit-completing-read
|
||||||
|
prompt choices nil t nil nil
|
||||||
|
(car (member (or (magit-section-value-if '(file submodule))
|
||||||
|
(magit-file-relative-name nil tracked-only))
|
||||||
|
choices)))))
|
||||||
|
|
||||||
|
(defun magit-read-tracked-file (prompt)
|
||||||
|
(magit-read-file prompt t))
|
||||||
|
|
||||||
|
(defun magit-read-file-choice (prompt files &optional error default)
|
||||||
|
"Read file from FILES.
|
||||||
|
|
||||||
|
If FILES has only one member, return that instead of prompting.
|
||||||
|
If FILES has no members, give a user error. ERROR can be given
|
||||||
|
to provide a more informative error.
|
||||||
|
|
||||||
|
If DEFAULT is non-nil, use this as the default value instead of
|
||||||
|
`magit-current-file'."
|
||||||
|
(pcase (length files)
|
||||||
|
(0 (user-error (or error "No file choices")))
|
||||||
|
(1 (car files))
|
||||||
|
(_ (magit-completing-read
|
||||||
|
prompt files nil t nil 'magit-read-file-hist
|
||||||
|
(car (member (or default (magit-current-file)) files))))))
|
||||||
|
|
||||||
|
(defun magit-read-changed-file (rev-or-range prompt &optional default)
|
||||||
|
(magit-read-file-choice
|
||||||
|
prompt
|
||||||
|
(magit-changed-files rev-or-range)
|
||||||
|
default
|
||||||
|
(concat "No file changed in " rev-or-range)))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-files)
|
||||||
|
;;; magit-files.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-files.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-files.elc
Normal file
Binary file not shown.
2302
elpa/magit-20191030.1315/magit-git.el
Normal file
2302
elpa/magit-20191030.1315/magit-git.el
Normal file
File diff suppressed because it is too large
Load Diff
BIN
elpa/magit-20191030.1315/magit-git.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-git.elc
Normal file
Binary file not shown.
197
elpa/magit-20191030.1315/magit-gitignore.el
Normal file
197
elpa/magit-20191030.1315/magit-gitignore.el
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
;;; magit-gitignore.el --- intentionally untracked files -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2008-2019 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 gitignore commands.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'subr-x))
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
|
||||||
|
;;; Transient
|
||||||
|
|
||||||
|
;;;###autoload (autoload 'magit-gitignore "magit-gitignore" nil t)
|
||||||
|
(define-transient-command magit-gitignore ()
|
||||||
|
"Instruct Git to ignore a file or pattern."
|
||||||
|
:man-page "gitignore"
|
||||||
|
["Gitignore"
|
||||||
|
("t" "shared at toplevel (.gitignore)"
|
||||||
|
magit-gitignore-in-topdir)
|
||||||
|
("s" "shared in subdirectory (path/to/.gitignore)"
|
||||||
|
magit-gitignore-in-subdir)
|
||||||
|
("p" "privately (.git/info/exclude)"
|
||||||
|
magit-gitignore-in-gitdir)
|
||||||
|
("g" magit-gitignore-on-system
|
||||||
|
:if (lambda () (magit-get "core.excludesfile"))
|
||||||
|
:description (lambda ()
|
||||||
|
(format "privately for all repositories (%s)"
|
||||||
|
(magit-get "core.excludesfile"))))]
|
||||||
|
["Skip worktree"
|
||||||
|
(7 "w" "do skip worktree" magit-skip-worktree)
|
||||||
|
(7 "W" "do not skip worktree" magit-no-skip-worktree)]
|
||||||
|
["Assume unchanged"
|
||||||
|
(7 "u" "do assume unchanged" magit-assume-unchanged)
|
||||||
|
(7 "U" "do not assume unchanged" magit-no-assume-unchanged)])
|
||||||
|
|
||||||
|
;;; Gitignore Commands
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-gitignore-in-topdir (rule)
|
||||||
|
"Add the Git ignore RULE to the top-level \".gitignore\" file.
|
||||||
|
Since this file is tracked, it is shared with other clones of the
|
||||||
|
repository. Also stage the file."
|
||||||
|
(interactive (list (magit-gitignore-read-pattern)))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit--gitignore rule ".gitignore")
|
||||||
|
(magit-run-git "add" ".gitignore")))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-gitignore-in-subdir (rule directory)
|
||||||
|
"Add the Git ignore RULE to a \".gitignore\" file.
|
||||||
|
Prompted the user for a directory and add the rule to the
|
||||||
|
\".gitignore\" file in that directory. Since such files are
|
||||||
|
tracked, they are shared with other clones of the repository.
|
||||||
|
Also stage the file."
|
||||||
|
(interactive (list (magit-gitignore-read-pattern)
|
||||||
|
(read-directory-name "Limit rule to files in: ")))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(let ((file (expand-file-name ".gitignore" directory)))
|
||||||
|
(magit--gitignore rule file)
|
||||||
|
(magit-run-git "add" ".gitignore"))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-gitignore-in-gitdir (rule)
|
||||||
|
"Add the Git ignore RULE to \"$GIT_DIR/info/exclude\".
|
||||||
|
Rules in that file only affects this clone of the repository."
|
||||||
|
(interactive (list (magit-gitignore-read-pattern)))
|
||||||
|
(magit--gitignore rule (magit-git-dir "info/exclude"))
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-gitignore-on-system (rule)
|
||||||
|
"Add the Git ignore RULE to the file specified by `core.excludesFile'.
|
||||||
|
Rules that are defined in that file affect all local repositories."
|
||||||
|
(interactive (list (magit-gitignore-read-pattern)))
|
||||||
|
(magit--gitignore rule
|
||||||
|
(or (magit-get "core.excludesFile")
|
||||||
|
(error "Variable `core.excludesFile' isn't set")))
|
||||||
|
(magit-refresh))
|
||||||
|
|
||||||
|
(defun magit--gitignore (rule file)
|
||||||
|
(when-let ((directory (file-name-directory file)))
|
||||||
|
(make-directory directory t))
|
||||||
|
(with-temp-buffer
|
||||||
|
(when (file-exists-p file)
|
||||||
|
(insert-file-contents file))
|
||||||
|
(goto-char (point-max))
|
||||||
|
(unless (bolp)
|
||||||
|
(insert "\n"))
|
||||||
|
(insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" rule))
|
||||||
|
(insert "\n")
|
||||||
|
(write-region nil nil file)))
|
||||||
|
|
||||||
|
(defun magit-gitignore-read-pattern ()
|
||||||
|
(let* ((default (magit-current-file))
|
||||||
|
(base (car magit-buffer-diff-files))
|
||||||
|
(base (and base (file-directory-p base) base))
|
||||||
|
(choices
|
||||||
|
(delete-dups
|
||||||
|
(--mapcat
|
||||||
|
(cons (concat "/" it)
|
||||||
|
(when-let ((ext (file-name-extension it)))
|
||||||
|
(list (concat "/" (file-name-directory it) "*." ext)
|
||||||
|
(concat "*." ext))))
|
||||||
|
(sort (nconc
|
||||||
|
(magit-untracked-files nil base)
|
||||||
|
;; The untracked section of the status buffer lists
|
||||||
|
;; directories containing only untracked files.
|
||||||
|
;; Add those as candidates.
|
||||||
|
(-filter #'directory-name-p
|
||||||
|
(magit-list-files
|
||||||
|
"--other" "--exclude-standard" "--directory"
|
||||||
|
"--no-empty-directory" "--" base)))
|
||||||
|
#'string-lessp)))))
|
||||||
|
(when default
|
||||||
|
(setq default (concat "/" default))
|
||||||
|
(unless (member default choices)
|
||||||
|
(setq default (concat "*." (file-name-extension default)))
|
||||||
|
(unless (member default choices)
|
||||||
|
(setq default nil))))
|
||||||
|
(magit-completing-read "File or pattern to ignore"
|
||||||
|
choices nil nil nil nil default)))
|
||||||
|
|
||||||
|
;;; Skip Worktree Commands
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-skip-worktree (file)
|
||||||
|
"Call \"git update-index --skip-worktree -- FILE\"."
|
||||||
|
(interactive
|
||||||
|
(list (magit-read-file-choice "Skip worktree for"
|
||||||
|
(magit-with-toplevel
|
||||||
|
(cl-set-difference
|
||||||
|
(magit-list-files)
|
||||||
|
(magit-skip-worktree-files))))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git "update-index" "--skip-worktree" "--" file)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-no-skip-worktree (file)
|
||||||
|
"Call \"git update-index --no-skip-worktree -- FILE\"."
|
||||||
|
(interactive
|
||||||
|
(list (magit-read-file-choice "Do not skip worktree for"
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-skip-worktree-files)))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git "update-index" "--no-skip-worktree" "--" file)))
|
||||||
|
|
||||||
|
;;; Assume Unchanged Commands
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-assume-unchanged (file)
|
||||||
|
"Call \"git update-index --assume-unchanged -- FILE\"."
|
||||||
|
(interactive
|
||||||
|
(list (magit-read-file-choice "Assume file to be unchanged"
|
||||||
|
(magit-with-toplevel
|
||||||
|
(cl-set-difference
|
||||||
|
(magit-list-files)
|
||||||
|
(magit-assume-unchanged-files))))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git "update-index" "--assume-unchanged" "--" file)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-no-assume-unchanged (file)
|
||||||
|
"Call \"git update-index --no-assume-unchanged -- FILE\"."
|
||||||
|
(interactive
|
||||||
|
(list (magit-read-file-choice "Do not assume file to be unchanged"
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-assume-unchanged-files)))))
|
||||||
|
(magit-with-toplevel
|
||||||
|
(magit-run-git "update-index" "--no-assume-unchanged" "--" file)))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-gitignore)
|
||||||
|
;;; magit-gitignore.el ends here
|
||||||
BIN
elpa/magit-20191030.1315/magit-gitignore.elc
Normal file
BIN
elpa/magit-20191030.1315/magit-gitignore.elc
Normal file
Binary file not shown.
245
elpa/magit-20191030.1315/magit-imenu.el
Normal file
245
elpa/magit-20191030.1315/magit-imenu.el
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
;;; magit-imenu.el --- Integrate Imenu in magit major modes -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2010-2019 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: Damien Cassou <damien@cassou.me>
|
||||||
|
;; 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:
|
||||||
|
|
||||||
|
;; Emacs' major modes can facilitate navigation in their buffers by
|
||||||
|
;; supporting Imenu. In such major modes, launching Imenu (M-x imenu)
|
||||||
|
;; makes Emacs display a list of items (e.g., function definitions in
|
||||||
|
;; a programming major mode). Selecting an item from this list moves
|
||||||
|
;; point to this item.
|
||||||
|
|
||||||
|
;; magit-imenu.el adds Imenu support to every major mode in Magit.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'subr-x))
|
||||||
|
|
||||||
|
(require 'magit)
|
||||||
|
(require 'git-rebase)
|
||||||
|
|
||||||
|
;;; Core
|
||||||
|
|
||||||
|
(defun magit-imenu--index-function (entry-types menu-types)
|
||||||
|
"Return an alist of imenu entries in current buffer.
|
||||||
|
|
||||||
|
ENTRY-TYPES is a list of section types to be selected through
|
||||||
|
`imenu'.
|
||||||
|
|
||||||
|
MENU-TYPES is a list of section types containing elements of
|
||||||
|
ENTRY-TYPES. Elements of MENU-TYPES are are used to categories
|
||||||
|
elements of ENTRY-TYPES.
|
||||||
|
|
||||||
|
This function is used as a helper for functions set as
|
||||||
|
`imenu-create-index-function'."
|
||||||
|
(let ((entries (make-hash-table :test 'equal)))
|
||||||
|
(goto-char (point-max))
|
||||||
|
(while (magit-section--backward-find
|
||||||
|
(lambda ()
|
||||||
|
(let* ((section (magit-current-section))
|
||||||
|
(type (oref section type))
|
||||||
|
(parent (oref section parent))
|
||||||
|
(parent-type (oref parent type)))
|
||||||
|
(and (-contains-p entry-types type)
|
||||||
|
(-contains-p menu-types parent-type)))))
|
||||||
|
(let* ((section (magit-current-section))
|
||||||
|
(name (buffer-substring-no-properties
|
||||||
|
(line-beginning-position)
|
||||||
|
(line-end-position)))
|
||||||
|
(parent (oref section parent))
|
||||||
|
(parent-title (buffer-substring-no-properties
|
||||||
|
(oref parent start)
|
||||||
|
(1- (oref parent content)))))
|
||||||
|
(puthash parent-title
|
||||||
|
(cons (cons name (point))
|
||||||
|
(gethash parent-title entries (list)))
|
||||||
|
entries)))
|
||||||
|
(mapcar (lambda (menu-title)
|
||||||
|
(cons menu-title (gethash menu-title entries)))
|
||||||
|
(hash-table-keys entries))))
|
||||||
|
|
||||||
|
;;; Log mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--log-prev-index-position-function ()
|
||||||
|
"Move point to previous line in current buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-prev-index-position-function'."
|
||||||
|
(magit-section--backward-find
|
||||||
|
(lambda ()
|
||||||
|
(-contains-p '(commit stash)
|
||||||
|
(oref (magit-current-section) type)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--log-extract-index-name-function ()
|
||||||
|
"Return imenu name for line at point.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-extract-index-name-function'. Point should be at the
|
||||||
|
beginning of the line."
|
||||||
|
(save-match-data
|
||||||
|
(looking-at "\\([^ ]+\\)[ *|]+\\(.+\\)$")
|
||||||
|
(format "%s: %s"
|
||||||
|
(match-string-no-properties 1)
|
||||||
|
(match-string-no-properties 2))))
|
||||||
|
|
||||||
|
;;; Diff mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--diff-prev-index-position-function ()
|
||||||
|
"Move point to previous file line in current buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-prev-index-position-function'."
|
||||||
|
(magit-section--backward-find
|
||||||
|
(lambda ()
|
||||||
|
(let ((section (magit-current-section)))
|
||||||
|
(and (magit-file-section-p section)
|
||||||
|
(not (equal (oref (oref section parent) type)
|
||||||
|
'diffstat)))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--diff-extract-index-name-function ()
|
||||||
|
"Return imenu name for line at point.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-extract-index-name-function'. Point should be at the
|
||||||
|
beginning of the line."
|
||||||
|
(buffer-substring-no-properties (line-beginning-position)
|
||||||
|
(line-end-position)))
|
||||||
|
|
||||||
|
;;; Status mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--status-create-index-function ()
|
||||||
|
"Return an alist of all imenu entries in current buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-create-index-function'."
|
||||||
|
(magit-imenu--index-function
|
||||||
|
'(file commit stash)
|
||||||
|
'(unpushed unstaged unpulled untracked staged stashes)))
|
||||||
|
|
||||||
|
;;;; Refs mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--refs-create-index-function ()
|
||||||
|
"Return an alist of all imenu entries in current buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-create-index-function'."
|
||||||
|
(magit-imenu--index-function
|
||||||
|
'(branch commit tag)
|
||||||
|
'(local remote tags)))
|
||||||
|
|
||||||
|
;;;; Cherry mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--cherry-create-index-function ()
|
||||||
|
"Return an alist of all imenu entries in current buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-create-index-function'."
|
||||||
|
(magit-imenu--index-function
|
||||||
|
'(commit)
|
||||||
|
'(cherries)))
|
||||||
|
|
||||||
|
;;;; Submodule list mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--submodule-prev-index-position-function ()
|
||||||
|
"Move point to previous line in magit-submodule-list buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-prev-index-position-function'."
|
||||||
|
(unless (bobp)
|
||||||
|
(forward-line -1)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--submodule-extract-index-name-function ()
|
||||||
|
"Return imenu name for line at point.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-extract-index-name-function'. Point should be at the
|
||||||
|
beginning of the line."
|
||||||
|
(elt (tabulated-list-get-entry) 0))
|
||||||
|
|
||||||
|
;;;; Repolist mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--repolist-prev-index-position-function ()
|
||||||
|
"Move point to previous line in magit-repolist buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-prev-index-position-function'."
|
||||||
|
(unless (bobp)
|
||||||
|
(forward-line -1)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--repolist-extract-index-name-function ()
|
||||||
|
"Return imenu name for line at point.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-extract-index-name-function'. Point should be at the
|
||||||
|
beginning of the line."
|
||||||
|
(let ((entry (tabulated-list-get-entry)))
|
||||||
|
(format "%s (%s)"
|
||||||
|
(elt entry 0)
|
||||||
|
(elt entry (1- (length entry))))))
|
||||||
|
|
||||||
|
;;;; Process mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--process-prev-index-position-function ()
|
||||||
|
"Move point to previous process in magit-process buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-prev-index-position-function'."
|
||||||
|
(magit-section--backward-find
|
||||||
|
(lambda ()
|
||||||
|
(eq (oref (magit-current-section) type) 'process))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--process-extract-index-name-function ()
|
||||||
|
"Return imenu name for line at point.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-extract-index-name-function'. Point should be at the
|
||||||
|
beginning of the line."
|
||||||
|
(buffer-substring-no-properties (line-beginning-position)
|
||||||
|
(line-end-position)))
|
||||||
|
|
||||||
|
;;;; Rebase mode
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--rebase-prev-index-position-function ()
|
||||||
|
"Move point to previous commit in git-rebase buffer.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-prev-index-position-function'."
|
||||||
|
(catch 'found
|
||||||
|
(while (not (bobp))
|
||||||
|
(git-rebase-backward-line)
|
||||||
|
(when (git-rebase-line-p)
|
||||||
|
(throw 'found t)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun magit-imenu--rebase-extract-index-name-function ()
|
||||||
|
"Return imenu name for line at point.
|
||||||
|
This function is used as a value for
|
||||||
|
`imenu-extract-index-name-function'. Point should be at the
|
||||||
|
beginning of the line."
|
||||||
|
(buffer-substring-no-properties (line-beginning-position)
|
||||||
|
(line-end-position)))
|
||||||
|
|
||||||
|
;;; _
|
||||||
|
(provide 'magit-imenu)
|
||||||
|
;;; magit-imenu.el ends here
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user