Commit b34fa669 authored by Jonas Bernoulli's avatar Jonas Bernoulli

add and improve many doc-strings

parent fc212568
......@@ -94,6 +94,7 @@
:group 'magit-backup)
(defun magit-maybe-backup ()
"If `magit-backup-mode' is enabled, create a backup stash."
(when (and magit-backup-mode
(magit-rev-parse "--verify" "HEAD"))
(magit-stash-save (concat "WIP on " (magit-stash-summary))
......@@ -102,6 +103,7 @@
nil t t magit-backup-ref)))
(defun magit-insert-backups ()
"Insert `stashes' section showing reflog for `magit-backup-ref'."
(magit-insert-stashes magit-backup-ref "Backups:"))
;;; magit-backup.el ends soon
......
......@@ -77,7 +77,7 @@ other actions from the bisect popup (\
;;;###autoload
(defun magit-bisect-reset ()
"After bisecting cleanup bisection state and return to original HEAD."
"After bisecting, cleanup bisection state and return to original HEAD."
(interactive)
(when (magit-confirm 'reset-bisect)
(magit-run-git "bisect" "reset")
......@@ -127,6 +127,7 @@ to test. This command lets Git choose a different one."
(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"))
......@@ -146,6 +147,7 @@ to test. This command lets Git choose a different one."
(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:")
......@@ -154,6 +156,7 @@ to test. This command lets Git choose a different one."
"--format=%h%d %s" "--decorate=full"))))
(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:")
......
......@@ -112,7 +112,8 @@ and then turned on again when turning on the latter."
(define-key map "P" 'magit-blame-previous-chunk-same-commit)
(define-key map "q" 'magit-blame-quit)
(define-key map "t" 'magit-blame-toggle-headings)
map))
map)
"Keymap for `magit-blame-mode'.")
(defvar-local magit-blame-buffer-read-only nil)
(defvar-local magit-blame-cache nil)
......@@ -356,7 +357,7 @@ only arguments available from `magit-blame-popup' should be used."
format (seconds-to-time (+ time (* (/ tz 100) 60 60) (* (% tz 100) 60)))))
(defun magit-blame-quit ()
"Turn of Magit-Blame mode.
"Turn off Magit-Blame mode.
If the buffer was created during a recursive blame,
then also kill the buffer."
(interactive)
......@@ -365,7 +366,8 @@ then also kill the buffer."
(magit-blame-mode -1)))
(defvar magit-blame-goto-chunk-hook
'(magit-log-maybe-show-commit))
'(magit-log-maybe-show-commit)
"Hook run by `magit-blame-next-chunk' and `magit-blame-previous-chunk'.")
(defun magit-blame-next-chunk ()
"Move to the next chunk."
......
......@@ -293,7 +293,8 @@ depending on the value of option `magit-commit-squash-confirm'.
(magit-completing-read prompt keys nil nil nil 'magit-gpg-secret-key-hist
(car (or magit-gpg-secret-key-hist keys)))))
(defvar magit-commit-add-log-insert-function 'magit-commit-add-log-insert)
(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 hunk into the commit message buffer.
......
......@@ -404,7 +404,11 @@ The following `format'-like specs are supported:
(?p "[p]atience" "patience")
(?h "[h]istogram" "histogram")))
(defvar magit-diff-switch-buffer-function 'pop-to-buffer)
(defvar magit-diff-switch-buffer-function 'pop-to-buffer
"Function used to display and possibly select a diff buffer.
This variable is mainly intended for internal use, allowing a
different function to be used under certain circumstances.
If you do change the global value this might lead to problems.")
;;;###autoload
(defun magit-diff-dwim (&optional args)
......@@ -484,6 +488,10 @@ a commit read from the minibuffer."
;;;###autoload
(defun magit-diff-while-committing (&optional args)
"While committing, show the changes that are about to be committed.
While amending, invoking the command again toggles between
showing just the new changes or all the changes that will
be commited."
(interactive (list (magit-diff-arguments)))
(let* ((toplevel (magit-get-top-dir))
(diff-buf (magit-mode-get-buffer magit-diff-buffer-name-format
......@@ -669,6 +677,17 @@ Customize variable `magit-diff-refine-hunk' to change the default mode."
(message "magit-diff-refine-hunk: %s" magit-diff-refine-hunk)))
(defun magit-diff-visit-file (file &optional other-window force-worktree)
"From a diff, visit the corresponding file at the appropriate position.
When the file is already being displayed in another window of the
same frame, then just select that window and adjust point. With
a prefix argument also display in another window.
If the diff shows changes in the worktree, the index, or HEAD,
then visit the actual file. Otherwise when the diff is about
an older commit, then visit the respective blob using
`magit-find-file'. Also see `magit-diff-visit-file-worktree'
which, as the name suggests always visits the actual file."
(interactive (list (magit-file-at-point) current-prefix-arg))
(if (file-accessible-directory-p file)
(magit-diff-visit-directory file other-window)
......@@ -704,6 +723,20 @@ Customize variable `magit-diff-refine-hunk' to change the default mode."
(smerge-start-session))))
(defun magit-diff-visit-file-worktree (file &optional other-window)
"From a diff, visit the corresponding file at the appropriate position.
When the file is already being displayed in another window of the
same frame, then just select that window and adjust point. With
a prefix argument also display in another window.
The actual file in the worktree is visited. The positions in the
hunk headers get less useful the \"older\" the changes are, and
as a result, jumping to the appropriate position gets less
reliable.
Also see `magit-diff-visit-file-worktree' which visits the
respective blob, unless the diff shows changes in the worktree,
the index, or HEAD."
(interactive (list (magit-file-at-point) current-prefix-arg))
(magit-diff-visit-file file other-window t))
......@@ -1207,6 +1240,7 @@ Type \\[magit-reverse] to reverse the change at point in the worktree.
(magit-define-section-jumper unstaged "Unstaged changes")
(defun magit-insert-unstaged-changes ()
"Insert section showing unstaged changes."
(magit-insert-section (unstaged)
(magit-insert-heading "Unstaged changes:")
(magit-git-wash #'magit-diff-wash-diffs
......@@ -1225,6 +1259,7 @@ Type \\[magit-reverse] to reverse the change at point in the worktree.
(magit-define-section-jumper staged "Staged changes")
(defun magit-insert-staged-changes ()
"Insert section showing staged changes."
(magit-insert-section (staged)
(magit-insert-heading "Staged changes:")
(magit-git-wash #'magit-diff-wash-diffs
......@@ -1233,6 +1268,22 @@ Type \\[magit-reverse] to reverse the change at point in the worktree.
;;; Diff Type
(defun magit-diff-type (&optional section)
"Return the diff type of SECTION.
The returned type is one of the symbols `staged', `unstaged',
`committed', or `undefined'. This type serves a similar purpose
as the general type common to all sections (which is stored in
the `type' slot of the corresponding `magit-section' struct) but
takes additional information into account.
The section has to be a `diff' or `hunk' section, or a section
whose children are of type `diff'. If optional SECTION is nil,
return the diff type for the current section. In buffers whose
major mode is `magit-diff-mode' SECTION is ignored and the type
is determined using other means. In `magit-revision-mode'
buffers the type is always `committed'.
Do not confuse this with `magit-diff-scope' (which see)."
(--when-let (or section (magit-current-section))
(cond ((derived-mode-p 'magit-diff-mode)
(if (car magit-refresh-args)
......@@ -1256,6 +1307,22 @@ Type \\[magit-reverse] to reverse the change at point in the worktree.
(t 'undefined))))
(defun magit-diff-scope (&optional section strict singular)
"Return the diff scope of SECTION.
A diff's \"scope\" describes what part of a diff is selected, it
is a symbol, one of `hunk', `hunks', `file', `files', or `list'.
When the region is active and selects a valid group of sections,
then the type is plural. If the region is not active then it is
singular. If optional SINGULAR is non-nil, then always return a
singular. If optional SECTION is non-nil, the return the scope
of that, ignoring the region.
If optional STRICT is non-nil then return nil if the diff type of
the section at point is `untracked' or the section at point is not
actually a `diff' but a `diffstat' section.
Do not confuse this with `magit-diff-type' (which see).
Also see `magit-current-selection'."
(let ((siblings (and (not singular) (magit-region-sections))))
(setq section (or section (car siblings) (magit-current-section)))
(when (and section
......@@ -1287,11 +1354,16 @@ Type \\[magit-reverse] to reverse the change at point in the worktree.
;;; Diff Highlight
(defun magit-diff-unhighlight (section)
"Remove the highlighting of the diff-related SECTION."
(when (eq (magit-section-type section) 'hunk)
(magit-diff-paint-hunk section)
t))
(defun magit-diff-highlight (section siblings)
"Highlight the diff-related SECTION and return non-nil.
If SECTION is not a diff-related section, then do nothing and
return nil. If SIBLINGS is non-nil then it is a list of siblings
of SECTION including SECTION and all of them are highlighted."
(-when-let (scope (magit-diff-scope section t))
(cond ((eq scope 'region)
(magit-diff-paint-hunk section nil t)
......
......@@ -73,7 +73,7 @@
'("--no-pager" "--literal-pathspecs" "-c" "core.preloadindex=true")
"Standard options when running Git.
Be careful what you add here, especially if you are using
tramp to connect to servers with ancient Git versions."
Tramp to connect to servers with ancient Git versions."
:group 'magit-process
:type '(repeat string))
......@@ -115,8 +115,17 @@ manager but it will be used in more places in the future."
;;; Git
(defun magit-process-git-arguments (args)
"Prepare ARGS for a function that invokes Git.
Magit has many specialized functions for running Git; they all
pass arguments through this function before handing them to Git,
to do the following.
* Flatten ARGS, removing nil arguments.
* Prepend `magit-git-standard-options' to ARGS.
* Quote arguments as required when using Powershell together
with Cygwin Git. See #816."
(setq args (-flatten args))
;; Kludge for Powershell in combination with Cygwin Git, see #816.
(when (and (eq system-type 'windows-nt)
(let ((case-fold-search t))
(string-match-p "cygwin" magit-git-executable)))
......@@ -237,6 +246,10 @@ non-nil return only the local part of tramp paths."
(file-name-as-directory (magit-expand-git-file-name it localname))))
(defun magit-toplevel-safe (&optional directory)
"Return the top-level directory for the repository containing DIRECTORY.
If optional DIRECTORY is nil use the `default-directory'. Unlike
with `magit-toplevel' the DIRECTORY does not have to exist."
(let ((default-directory
(file-name-as-directory (or directory default-directory))))
(while (not (file-accessible-directory-p default-directory))
......
......@@ -371,11 +371,19 @@ http://www.mail-archive.com/git@vger.kernel.org/msg51337.html"
;;;###autoload
(defun magit-log-current (revs &optional args files)
"Show log for the current branch.
When HEAD is detached or with a prefix argument show log for one
or more revs read from the minibuffer."
(interactive (magit-log-read-args t))
(magit-log revs args files))
;;;###autoload
(defun magit-log (revs &optional args files)
"Show log for one or more revs read from the minibuffer.
The user can input any revision or revisions separated by a
space, or even ranges, but only branches and tags, and a
representation of the commit at point, are available as
completion candidates."
(interactive (magit-log-read-args nil))
(magit-mode-setup magit-log-buffer-name-format nil
#'magit-log-mode
......@@ -394,6 +402,7 @@ http://www.mail-archive.com/git@vger.kernel.org/msg51337.html"
;;;###autoload
(defun magit-log-head (args)
"Show log for HEAD."
(interactive (list (magit-log-arguments)))
(magit-log "HEAD" args))
......@@ -496,6 +505,8 @@ Type \\[magit-reset-head] to reset HEAD to the commit at point.
(magit-format-log-margin)))
(defun magit-insert-log (revs &optional args files)
"Insert a oneline log section.
For internal use; don't add to a hook."
(magit-git-wash (apply-partially 'magit-log-wash-log 'oneline)
"log" (format "-%d" magit-log-cutoff-length) "--color"
(format "--format=%%h%s %s[%%an][%%at]%%s"
......@@ -509,6 +520,8 @@ Type \\[magit-reset-head] to reset HEAD to the commit at point.
revs "--" files))
(defun magit-insert-log-verbose (revs &optional args files)
"Insert a multiline log section.
For internal use; don't add to a hook."
(magit-git-wash (apply-partially 'magit-log-wash-log 'verbose)
"log" (format "-%d" magit-log-cutoff-length) "--color"
(if (member "--decorate" args)
......@@ -746,6 +759,9 @@ alist in `magit-log-format-unicode-graph-alist'."
(defun magit-log-maybe-show-more-entries (section)
"Automatically insert more commit sections in a log.
Only do so if `point' is on the \"show more\" section,
and `magit-log-auto-more' is non-nil."
(when (and (eq (magit-section-type section) 'longer)
magit-log-auto-more)
(magit-log-show-more-entries)
......@@ -753,6 +769,10 @@ alist in `magit-log-format-unicode-graph-alist'."
(magit-section-forward)))
(defun magit-log-maybe-show-commit (&optional section)
"Automatically show commit at point in another window.
If the section at point is a `commit' section and the value of
`magit-diff-auto-show-p' calls for it, then show that commit in
another window, using `magit-show-commit'."
(--when-let
(or (and section
(eq (magit-section-type section) 'commit)
......@@ -819,6 +839,9 @@ alist in `magit-log-format-unicode-graph-alist'."
'magit-log-select-quit))))
(defun magit-log-select-pick ()
"Select the commit at point and act on it.
Call `magit-log-select-pick-function' with the selected
commit as argument."
(interactive)
(let ((fun magit-log-select-pick-function)
(rev (magit-commit-at-point)))
......@@ -826,6 +849,7 @@ alist in `magit-log-format-unicode-graph-alist'."
(funcall fun rev)))
(defun magit-log-select-quit ()
"Abort selecting a commit, don't act on any commit."
(interactive)
(kill-buffer (current-buffer))
(when magit-log-select-quit-function
......@@ -865,10 +889,12 @@ Type \\[magit-cherry-pick] to cherry-pick the commit at point.
(run-hooks 'magit-cherry-sections-hook)))
(defun magit-insert-cherry-headers ()
"Insert headers appropriate for `magit-cherry-mode' buffers."
(magit-insert-status-headers (nth 1 magit-refresh-args)
(nth 0 magit-refresh-args)))
(defun magit-insert-cherry-commits ()
"Insert commit sections into a `magit-cherry-mode' buffer."
(magit-insert-section (cherries)
(magit-insert-heading "Cherry commits:")
(apply 'magit-insert-cherry-commits-1 magit-refresh-args)))
......@@ -947,12 +973,18 @@ Type \\[magit-reset-head] to reset HEAD to the commit at point.
(magit-define-section-jumper unpulled "Unpulled commits")
(defun magit-insert-unpulled-commits ()
"Insert section showing unpulled commits."
(-when-let (tracked (magit-get-tracked-branch nil t))
(magit-insert-section (unpulled)
(magit-insert-heading "Unpulled commits:")
(magit-insert-log (concat "HEAD.." tracked) magit-log-section-args))))
(defun magit-insert-unpulled-or-recent-commits ()
"Insert section showing unpulled or recent commits.
If an upstream is configured for the current branch and it is
ahead of the current branch, then show the missing commits,
otherwise show the last `magit-log-section-commit-count'
commits. "
(let ((tracked (magit-get-tracked-branch nil t)))
(if (and tracked (not (equal (magit-rev-parse "HEAD")
(magit-rev-parse tracked))))
......@@ -960,12 +992,19 @@ Type \\[magit-reset-head] to reset HEAD to the commit at point.
(magit-insert-recent-commits))))
(defun magit-insert-recent-commits ()
"Insert section showing recent commits.
Show the last `magit-log-section-commit-count' commits."
(magit-insert-section (recent)
(magit-insert-heading "Recent commits:")
(magit-insert-log nil (cons (format "-%d" magit-log-section-commit-count)
magit-log-section-args))))
(defun magit-insert-unpulled-cherries ()
"Insert section showing unpulled commits.
Like `magit-insert-unpulled-commits' but prefix each commit
which has not been applied yet (i.e. a commit with a patch-id
not shared with any local commit) with \"+\", and all others
with \"-\"."
(-when-let (tracked (magit-get-tracked-branch nil t))
(magit-insert-section (unpulled)
(magit-insert-heading "Unpulled commits:")
......@@ -973,6 +1012,8 @@ Type \\[magit-reset-head] to reset HEAD to the commit at point.
"cherry" "-v" (magit-abbrev-arg) (magit-get-current-branch) tracked))))
(defun magit-insert-unpulled-module-commits ()
"Insert sections for all submodules with unpulled commits.
This sections can be expanded to show the respective commits."
(-when-let (modules (magit-get-submodules))
(magit-insert-section section (unpulled-modules)
(magit-insert-heading "Unpulled modules:")
......@@ -1001,12 +1042,18 @@ Type \\[magit-reset-head] to reset HEAD to the commit at point.
(magit-define-section-jumper unpushed "Unpushed commits")
(defun magit-insert-unpushed-commits ()
"Insert section showing unpushed commits."
(-when-let (tracked (magit-get-tracked-branch nil t))
(magit-insert-section (unpushed)
(magit-insert-heading "Unpushed commits:")
(magit-insert-log (concat tracked "..HEAD") magit-log-section-args))))
(defun magit-insert-unpushed-cherries ()
"Insert section showing unpushed commits.
Like `magit-insert-unpushed-commits' but prefix each commit
which has not been applied to upstream yet (i.e. a commit with
a patch-id not shared with any upstream commit) with \"+\", and
all others with \"-\"."
(-when-let (tracked (magit-get-tracked-branch nil t))
(magit-insert-section (unpushed)
(magit-insert-heading "Unpushed commits:")
......@@ -1014,6 +1061,8 @@ Type \\[magit-reset-head] to reset HEAD to the commit at point.
"cherry" "-v" (magit-abbrev-arg) tracked))))
(defun magit-insert-unpushed-module-commits ()
"Insert sections for all submodules with unpushed commits.
These sections can be expanded to show the respective commits."
(-when-let (modules (magit-get-submodules))
(magit-insert-section section (unpushed-modules)
(magit-insert-heading "Unpushed modules:")
......
......@@ -451,9 +451,12 @@ tracked in the current repository."
(with-current-buffer buffer (magit-refresh-buffer)))
(magit-revert-buffers t))
(defvar magit-refresh-buffer-hook nil)
(defvar magit-refresh-buffer-hook nil
"Hook run after refreshing a file-visiting buffer.")
(defun magit-refresh-buffer ()
"Refresh the current Magit buffer.
Uses the buffer-local `magit-refresh-function'."
(when magit-refresh-function
(let* ((buffer (current-buffer))
(windows
......@@ -482,6 +485,9 @@ tracked in the current repository."
(magit-section-update-highlight))))
(defun magit-revert-buffers (&optional force)
"Refresh the current file-visiting buffer.
The buffer is only refreshed if `magit-auto-revert-mode'
is turned on or optional FORCE is non-nil."
(when (or force magit-auto-revert-mode)
(-when-let (topdir (magit-toplevel-safe))
(let ((tracked (magit-revision-files "HEAD"))
......
This diff is collapsed.
......@@ -61,7 +61,9 @@ until one of them returns non-nil."
'(magit-diff-unhighlight)
"Functions used to unhighlight the previously current section.
Each function is run with the current section as only argument
until one of them returns non-nil."
until one of them returns non-nil. Most sections are properly
unhighlighted without requiring a specialized unhighligher,
diff-related sections being the only exception."
:package-version '(magit . "2.1.0")
:group 'magit-section
:type 'hook
......@@ -200,13 +202,18 @@ If there is no previous sibling section, then move to the parent."
(defvar magit-section-movement-hook
'(magit-hunk-set-window-start
magit-log-maybe-show-commit
magit-log-maybe-show-more-entries))
magit-log-maybe-show-more-entries)
"Hook run by `magit-section-goto'.
That function in turn is used by all section movement commands.")
(defun magit-section-set-window-start (section)
"Ensure the beginning of SECTION is visible."
(unless (pos-visible-in-window-p (magit-section-end section))
(set-window-start (selected-window) (magit-section-start section))))
(defun magit-hunk-set-window-start (section)
"Ensure the beginning of the `hunk' SECTION is visible.
It the SECTION has a different type, then do nothing."
(when (eq (magit-section-type section) 'hunk)
(magit-section-set-window-start section)))
......@@ -531,10 +538,49 @@ at point."
(defvar magit-insert-section--parent nil "For internal use only.")
(defvar magit-insert-section--oldroot nil "For internal use only.")
(defvar magit-section-set-visibility-hook '(magit-diff-set-visibility))
(defvar magit-section-set-visibility-hook '(magit-diff-set-visibility)
"Hook used to set the initial visibility of a section.
Stop at the first function that returns non-nil. The value
should be `show' or `hide'. If no function returns non-nil
determine the visibility as usual (see `magit-insert-section').")
(defmacro magit-insert-section (&rest args)
"\n\n(fn [NAME] (TYPE &optional VALUE HIDE) &rest BODY)"
"Insert a section at point.
TYPE is the section type, a symbol. Many commands that act on
the current section behave differently depending on that type.
Also if a variable `magit-TYPE-section-map' exists, then use
that as the text-property `keymap' of all text belonging to the
section (but this may be overwritten in subsections).
Optional VALUE is the value of the section, usually a string
that is required when acting on the section.
When optional HIDE is non-nil collapse the section body by
default, i.e. when first creating the section, but not when
refreshing the buffer. Else expand it by default. This can be
overwritten using `magit-section-set-visibility-hook'. When a
section is recreated during a refresh, then the visibility of
predecessor is inherited and HIDE is ignored (but the hook is
still honored).
BODY is any number of forms that actually insert the section's
heading and body. Optional NAME, if specified, has to be a
symbol, which is then bound to the struct of the section being
inserted.
Before BODY is evaluated the `start' of the section object is set
to the value of `point' and after BODY was evaluated its `end' is
set to the new value of `point'; BODY is responsible for moving
`point' forward.
If it turns out inside BODY that the section is empty, then
`magit-cancel-section' can be used to abort and remove all traces
of the partially inserted section. This can happen when creating
a section by washing Git's output and Git didn't actually output
anything this time around.
\(fn [NAME] (TYPE &optional VALUE HIDE) &rest BODY)"
(declare (indent defun)
(debug ([&optional symbolp] (symbolp &optional form form) body)))
(let ((s (if (symbolp (car args))
......@@ -598,6 +644,32 @@ at point."
(throw 'cancel-section nil))))
(defun magit-insert-heading (&rest args)
"Insert the heading for the section currently being inserted.
This function should only be used inside `magit-insert-section'.
When called without any arguments, then just set the `content'
slot of the object representing the section being inserted to
a marker at `point'. The section should only contain a single
line when this function is used like this.
When called with arguments ARGS, which have to be strings, then
insert those strings at point. The section should not contain
any text before this happens and afterwards it should again only
contain a single line. If the `face' property is set anywhere
inside any of these strings, then insert all of them unchanged.
Otherwise use the `magit-section-heading' face for all inserted
text.
The `content' property of the secton struct is the end of the
heading (which lasts from `start' to `content') and the beginning
of the the body (which lasts from `content' to `end'). If the
value of `content' is nil, then the section has no heading and
its body cannot be collapsed. If a section does have a heading
then its height must be exactly one line, including a trailing
newline character. This isn't enforced, you are responsible for
getting it right. The only exception is that this function does
insert a newline character if necessary."
(declare (indent defun))
(when args
(let ((heading (apply #'concat args)))
......@@ -610,6 +682,14 @@ at point."
(setf (magit-section-content magit-insert-section--current) (point-marker)))
(defun magit-insert-child-count (section)
"Modify SECTION's heading to contain number of child sections.
If `magit-section-show-child-count' is non-nil and the SECTION
has children and its heading ends with \":\", then replace that
with \" (N)\", where N is the number of child sections.
This function is called by `magit-insert-section' after that has
evaluated its BODY. Admittedly that's a bit of a hack."
;; This has to be fast, not pretty!
(let (content count)
(when (and magit-section-show-child-count
......@@ -623,6 +703,23 @@ at point."
(delete-char 1)))))
(defun magit-insert (string &optional face &rest args)
"Insert the strings STRING and ARGS at point.
First insert STRING, possibly doing some crazy things as
described below; then insert ARGS as is, in a totally sane
fashion.
This function owes its existence to the fact that Emacs does
not implement negative overlay priorities, and that some time
in the past it was decided that this is not acceptable and that
such negative prioritize have to be faked. I wish we had shown
some restrain, but here we are. At least this madness is now
contained in this function and `magit-put-face-property'.
Insert STRING and then create an overlay on the inserted text,
which sets the `face' property. If optional FACE is non-nil,
then use that face. Otherwise use the first `face' property
found in STRING."
(if face
(let ((start (point)))
(insert string)
......@@ -674,6 +771,10 @@ at point."
magit-section-unhighlight-sections)))
(defun magit-section-highlight (section siblings)
"Highlight SECTION and if non-nil all SIBLINGS.
This function works for any section but produces undesirable
effects for diff related sections, which by default are
highlighted using `magit-diff-highlight'."
(cond (siblings
(magit-face-remap-set-base 'region 'face-override-spec)
(magit-section-make-overlay (magit-section-start (car siblings))
......@@ -733,6 +834,12 @@ at point."
(when section (magit-section-value section)))
(defun magit-section-siblings (section &optional direction)
"Return a list of the sibling sections of SECTION.
If optional DIRECTION is `prev' then return siblings that come
before SECTION, if it is `next' then return siblings that come
after SECTION. For all other values return all siblings
including SECTION itself."
(-when-let (parent (magit-section-parent section))
(let ((siblings (magit-section-children parent)))
(pcase direction
......@@ -741,6 +848,14 @@ at point."
(_ (remq section siblings))))))
(defun magit-region-values (&rest types)
"Return a list of the values of the selected sections.
Also see `magit-region-sections' whose doc-string explains when a
region is a valid section selection. If the region is not active
or is not a valid section selection, then return nil. If optional
TYPES is non-nil then the selection not only has to be valid; the
types of all selected sections additionally have to match one of
TYPES, or nil is returned."
(when (use-region-p)
(let ((sections (magit-region-sections)))
(when (or (not types)
......@@ -748,6 +863,22 @@ at point."
(mapcar 'magit-section-value sections)))))
(defun magit-region-sections ()
"Return a list of the selected sections.
When the region is active and constitutes a valid section
selection, then return a list of all selected sections. This is
the case when the region begins in the heading of a section and
ends in the heading of a sibling of that first section. When
the selection is not valid then return nil. Most commands that
can act on the selected sections, then instead just act on the
current section, the one point is in.
When the region looks like it would in any other buffer then
the selection is invalid. When the selection is valid then the
region uses the `magit-section-highlight'. This does not apply
to diffs were things get a bit more complicated, but even here
if the region looks like it usually does, then that's not a
valid selection as far as this function is concerned."
(when (use-region-p)
(let* ((rbeg (region-beginning))
(rend (region-end))
......
......@@ -77,11 +77,18 @@
;;; Common
(defun magit-run-git-sequencer (&rest args)
"Call Git synchronously in a separate process, and refresh.
This is like `magit-run-git-with-editor' (which see) except that
the process sentinel is `magit-sequencer-process-sentinel'."
(apply #'magit-run-git-with-editor args)
(set-process-sentinel magit-this-process #'magit-sequencer-process-sentinel)
magit-this-process)
(defun magit-sequencer-process-sentinel (process event)
"Process sentinel used when running sequence commands.
Run the regular `magit-process-sentinel' and then, if the
sequence stops at a commit, make the section representing
that commit the current section by moving `point' there."
(when (memq (process-status process) '(exit signal))
(magit-process-sentinel process event)
(--when-let (magit-mode-get-buffer
......@@ -102,6 +109,7 @@
;;;###autoload
(defun magit-sequencer-continue ()
"Resume the current cherry-pick or revert sequence."
(interactive)
(if (magit-sequencer-in-progress-p)
(if (magit-anything-unstaged-p)
......@@ -112,6 +120,7 @@
;;;###autoload
(defun magit-sequencer-skip ()
"Skip the stopped at commit during a cherry-pick or revert sequence."
(interactive)
(if (magit-sequencer-in-progress-p)
(progn (magit-call-git "reset" "--hard")
......@@ -120,6 +129,8 @@
;;;###autoload
(defun magit-sequencer-abort ()
"Abort the current cherry-pick or revert sequence.
This discards all changes made since the sequence started."
(interactive)
(if (magit-sequencer-in-progress-p)
(magit-run-git-sequencer
......@@ -156,6 +167,10 @@
;;;###autoload
(defun magit-cherry-pick (commit &optional args)
"Cherry-pick COMMIT.
Prompt for a commit, defaulting to the commit at point. If
the region selects multiple commits, then pick all of them,
without prompting."
(interactive (magit-cherry-pick-read-args "Cherry-pick"))
(magit-assert-one-parent (car (if (listp commit)
commit
......@@ -165,6 +180,10 @@
;;;###autoload
(defun magit-cherry-apply (commit &optional args)
"Apply the changes in COMMIT but do not commit them.
Prompt for a commit, defaulting to the commit at point. If
the region selects multiple commits, then apply all of them,
without prompting."
(interactive (magit-cherry-pick-read-args "Apply commit"))
(magit-assert-one-parent commit "cherry-pick")
(magit-run-git-sequencer "cherry-pick" "--no-commit"
......@@ -197,12 +216,20 @@
;;;###autoload
(defun magit-revert (commit &optional args)
"Revert COMMIT by creating a new commit.
Prompt for a commit, defaulting to the commit at point. If
the region selects multiple commits, then revert all of them,
without prompting."
(interactive (magit-revert-read-args "Revert commit"))
(magit-assert-one-parent commit "revert")
(magit-run-git-sequencer "revert" args commit))