update packages and add valign
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
;; Generated package description from adaptive-wrap.el -*- no-byte-compile: t -*-
|
||||
(define-package "adaptive-wrap" "0.8" "Smart line-wrapping with wrap-prefix" 'nil :commit "026c35f59174febab2bcdb3c50fb8344c248671c" :url "https://elpa.gnu.org/packages/adaptive-wrap.html" :authors '(("Stephen Berman" . "stephen.berman@gmx.net") ("Stefan Monnier" . "monnier@iro.umontreal.ca")) :maintainer '(("Stephen Berman" . "stephen.berman@gmx.net") ("Stefan Monnier" . "monnier@iro.umontreal.ca")))
|
||||
(define-package "adaptive-wrap" "0.9" "Smart line-wrapping with wrap-prefix" '((emacs "24.1")) :commit "e929b38c12f17aa6f8d6270326301d61fbb09cab" :url "https://elpa.gnu.org/packages/adaptive-wrap.html" :authors '(("Stephen Berman" . "stephen.berman@gmx.net") ("Stefan Monnier" . "monnier@iro.umontreal.ca")) :maintainer '(("Stephen Berman" . "stephen.berman@gmx.net") ("Stefan Monnier" . "monnier@iro.umontreal.ca")))
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
;;; adaptive-wrap.el --- Smart line-wrapping with wrap-prefix
|
||||
;;; adaptive-wrap.el --- Smart line-wrapping with wrap-prefix -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2011-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Stephen Berman <stephen.berman@gmx.net>
|
||||
;; Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
;; Version: 0.8
|
||||
;; Package-Requires: ((emacs "24.1"))
|
||||
;; Version: 0.9
|
||||
|
||||
;; 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
|
||||
@@ -17,7 +18,7 @@
|
||||
;; 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/>.
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
@@ -26,6 +27,12 @@
|
||||
;; word-wrapped in a way similar to what you'd get with M-q using
|
||||
;; adaptive-fill-mode, but without actually changing the buffer's text.
|
||||
|
||||
;;; News:
|
||||
|
||||
;; Since version 0.8:
|
||||
|
||||
;; - Use `lexical-binding'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defcustom adaptive-wrap-extra-indent 0
|
||||
@@ -104,7 +111,8 @@ extra indent = 2
|
||||
""))))
|
||||
|
||||
(defun adaptive-wrap-fill-context-prefix (beg end)
|
||||
"Like `fill-context-prefix', but with length adjusted by `adaptive-wrap-extra-indent'."
|
||||
"Like `fill-context-prefix', but with length adjusted.
|
||||
How much to adjust it is decided by `adaptive-wrap-extra-indent'."
|
||||
(let* ((fcp
|
||||
;; `fill-context-prefix' ignores prefixes that look like paragraph
|
||||
;; starts, in order to avoid inadvertently creating a new paragraph
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"Alternative M-x with extra features."
|
||||
'((emacs "24.4")
|
||||
(s "0"))
|
||||
:url "http://github.com/DarwinAwardWinner/amx/"
|
||||
:url "https://github.com/DarwinAwardWinner/amx/"
|
||||
:commit "1c2428d21e9d2ee8bee944b572a39ca8c91ca13b"
|
||||
:revdesc "1c2428d21e9d"
|
||||
:keywords '("convenience" "usability" "completion")
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "async" "20251005.634"
|
||||
(define-package "async" "20260318.1803"
|
||||
"Asynchronous processing in Emacs."
|
||||
'((emacs "24.4"))
|
||||
:url "https://github.com/jwiegley/emacs-async"
|
||||
:commit "31cb2fea8f4bc7a593acd76187a89075d8075500"
|
||||
:revdesc "31cb2fea8f4b"
|
||||
:commit "5faab28916603bb324d9faba057021ce028ca847"
|
||||
:revdesc "5faab2891660"
|
||||
:keywords '("async")
|
||||
:authors '(("John Wiegley" . "jwiegley@gmail.com"))
|
||||
:maintainers '(("Thierry Volpiatto" . "thievol@posteo.net")))
|
||||
|
||||
+11
-13
@@ -6,12 +6,12 @@
|
||||
;; Maintainer: Thierry Volpiatto <thievol@posteo.net>
|
||||
|
||||
;; Created: 18 Jun 2012
|
||||
;; Package-Version: 20251005.634
|
||||
;; Package-Revision: 31cb2fea8f4b
|
||||
;; Package-Version: 20260318.1803
|
||||
;; Package-Revision: 5faab2891660
|
||||
;; Package-Requires: ((emacs "24.4"))
|
||||
|
||||
;; Keywords: async
|
||||
;; X-URL: https://github.com/jwiegley/emacs-async
|
||||
;; URL: https://github.com/jwiegley/emacs-async
|
||||
|
||||
;; 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
|
||||
@@ -284,15 +284,13 @@ is used."
|
||||
(move-marker async-read-marker (point)))))))
|
||||
|
||||
(defun async--receive-sexp (&optional stream)
|
||||
;; FIXME: Why use `utf-8-auto' instead of `utf-8-unix'? This is
|
||||
;; a communication channel over which we have complete control,
|
||||
;; so we get to choose exactly which encoding and EOL we use, isn't
|
||||
;; it?
|
||||
;; UPDATE: We use now `utf-8-emacs-unix' instead of `utf-8-auto' as
|
||||
;; recommended in bug#165.
|
||||
;; We use `utf-8-emacs-unix' for the communication channel between
|
||||
;; parent and child Emacs processes. This encoding can represent any
|
||||
;; character that Emacs is capable of processing and gives us full
|
||||
;; control over the EOL format. (See bug#165)
|
||||
(let ((sexp (decode-coding-string (base64-decode-string (read stream))
|
||||
'utf-8-emacs-unix))
|
||||
;; Parent expects UTF-8 encoded text.
|
||||
;; Parent expects utf-8-emacs-unix encoded text.
|
||||
(coding-system-for-write 'utf-8-emacs-unix))
|
||||
(if async-debug
|
||||
(message "Received sexp {{{%s}}}" (pp-to-string sexp)))
|
||||
@@ -324,8 +322,8 @@ is used."
|
||||
|
||||
(defun async-batch-invoke ()
|
||||
"Called from the child Emacs process' command line."
|
||||
;; Make sure 'message' and 'prin1' encode stuff in UTF-8, as parent
|
||||
;; process expects.
|
||||
;; Make sure 'message' and 'prin1' encode stuff in utf-8-emacs-unix,
|
||||
;; as parent process expects.
|
||||
(let ((coding-system-for-write 'utf-8-emacs-unix)
|
||||
(args-left command-line-args-left))
|
||||
(setq async-in-child-emacs t
|
||||
@@ -560,7 +558,7 @@ passed to FINISH-FUNC). Call `async-get' on such a future always
|
||||
returns nil. It can still be useful, however, as an argument to
|
||||
`async-ready' or `async-wait'."
|
||||
(let ((sexp start-func)
|
||||
;; Subordinate Emacs will send text encoded in UTF-8.
|
||||
;; Subordinate Emacs will send text encoded in utf-8-emacs-unix.
|
||||
(coding-system-for-read 'utf-8-emacs-unix))
|
||||
(setq async--procvar
|
||||
(apply 'async-start-process
|
||||
|
||||
@@ -237,7 +237,7 @@ CSL tests."
|
||||
"<span style=\"text-decoration:underline;\">" x "</span>")))
|
||||
(vertical-align-sub . ,(lambda (x) (concat "<sub>" x "</sub>")))
|
||||
(vertical-align-sup . ,(lambda (x) (concat "<sup>" x "</sup>")))
|
||||
(vertical-align-baseline . ,(lambda (x) (concat "<span style=\"baseline\">" x "</span>")))
|
||||
(vertical-align-baseline . ,(lambda (x) (concat "<span class=\"baseline\">" x "</span>")))
|
||||
(display-left-margin . ,(lambda (x) (concat "\n <div class=\"csl-left-margin\">"
|
||||
x "</div>")))
|
||||
(display-right-inline . ,(lambda (x) (concat "<div class=\"csl-right-inline\">"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "citeproc" "20251103.716"
|
||||
(define-package "citeproc" "20260113.1047"
|
||||
"A CSL 1.0.2 Citation Processor."
|
||||
'((emacs "26")
|
||||
(dash "2.13.0")
|
||||
@@ -11,8 +11,8 @@
|
||||
(parsebib "2.4")
|
||||
(compat "28.1"))
|
||||
:url "https://github.com/andras-simonyi/citeproc-el"
|
||||
:commit "a3d62ab8e40a75fcfc6e4c0c107e3137b4db6db8"
|
||||
:revdesc "a3d62ab8e40a"
|
||||
:commit "4bde999a41803fe519ea80eab8b813d53503eebd"
|
||||
:revdesc "4bde999a4180"
|
||||
:keywords '("bib")
|
||||
:authors '(("András Simonyi" . "andras.simonyi@gmail.com"))
|
||||
:maintainers '(("András Simonyi" . "andras.simonyi@gmail.com")))
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
;; URL: https://github.com/andras-simonyi/citeproc-el
|
||||
;; Keywords: bib
|
||||
;; Package-Requires: ((emacs "26") (dash "2.13.0") (s "1.12.0") (f "0.18.0") (queue "0.2") (string-inflection "1.0") (org "9") (parsebib "2.4")(compat "28.1"))
|
||||
;; Package-Version: 20251103.716
|
||||
;; Package-Revision: a3d62ab8e40a
|
||||
;; Package-Version: 20260113.1047
|
||||
;; Package-Revision: 4bde999a4180
|
||||
|
||||
;; 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-dabbrev-code.el --- dabbrev-like company-mode backend for code -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2021-2024 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2021-2025 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -153,8 +153,8 @@ comments or strings."
|
||||
(pcase company-dabbrev-code-other-buffers
|
||||
(`t (list major-mode))
|
||||
(`code company-dabbrev-code-modes)
|
||||
((pred functionp) (funcall company-dabbrev-code-other-buffers (current-buffer)))
|
||||
(`all `all))
|
||||
(`all `all)
|
||||
((pred functionp) (funcall company-dabbrev-code-other-buffers (current-buffer))))
|
||||
(not company-dabbrev-code-everywhere)))
|
||||
:expire t
|
||||
:check-tag
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "company" "20251021.2211"
|
||||
(define-package "company" "20260331.245"
|
||||
"Modular text completion framework."
|
||||
'((emacs "26.1"))
|
||||
:url "http://company-mode.github.io/"
|
||||
:commit "4ff89f7369227fbb89fe721d1db707f1af74cd0f"
|
||||
:revdesc "4ff89f736922"
|
||||
:commit "59626254bbac187fc2b8d7a189aca90976ab36a8"
|
||||
:revdesc "59626254bbac"
|
||||
:keywords '("abbrev" "convenience" "matching")
|
||||
:maintainers '(("Dmitry Gutov" . "dmitry@gutov.dev")))
|
||||
|
||||
+11
-9
@@ -5,8 +5,8 @@
|
||||
;; Author: Nikolaj Schumacher
|
||||
;; Maintainer: Dmitry Gutov <dmitry@gutov.dev>
|
||||
;; URL: http://company-mode.github.io/
|
||||
;; Package-Version: 20251021.2211
|
||||
;; Package-Revision: 4ff89f736922
|
||||
;; Package-Version: 20260331.245
|
||||
;; Package-Revision: 59626254bbac
|
||||
;; Keywords: abbrev, convenience, matching
|
||||
;; Package-Requires: ((emacs "26.1"))
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
(defface company-tooltip
|
||||
'((((class color) (min-colors 88) (background light))
|
||||
(:foreground "black" :background "cornsilk"))
|
||||
(:foreground "black" :background "ghostwhite"))
|
||||
(((class color) (min-colors 88) (background dark))
|
||||
(:background "gray26"))
|
||||
(t (:foreground "black" :background "yellow")))
|
||||
@@ -88,7 +88,7 @@
|
||||
|
||||
(defface company-tooltip-selection
|
||||
'((((class color) (min-colors 88) (background light))
|
||||
(:background "light blue"))
|
||||
(:background "lavender"))
|
||||
(((class color) (min-colors 88) (background dark))
|
||||
(:background "gray31"))
|
||||
(t (:background "green")))
|
||||
@@ -149,7 +149,7 @@
|
||||
|
||||
(defface company-tooltip-scrollbar-thumb
|
||||
'((((background light))
|
||||
:background "indian red")
|
||||
:background "lightpink3")
|
||||
(((background dark))
|
||||
:background "gray33"))
|
||||
"Face used for the tooltip scrollbar thumb (bar).")
|
||||
@@ -161,7 +161,7 @@
|
||||
|
||||
(defface company-tooltip-scrollbar-track
|
||||
'((((background light))
|
||||
:background "wheat")
|
||||
:background "thistle")
|
||||
(((background dark))
|
||||
:background "gray28"))
|
||||
"Face used for the tooltip scrollbar track (trough).")
|
||||
@@ -4163,7 +4163,7 @@ but adjust the expected values appropriately."
|
||||
left
|
||||
right)
|
||||
(when scrollbar-bounds
|
||||
(company--scrollbar i scrollbar-bounds)))
|
||||
(company--scrollbar i scrollbar-bounds selected)))
|
||||
new)))
|
||||
|
||||
(when remainder
|
||||
@@ -4180,7 +4180,7 @@ but adjust the expected values appropriately."
|
||||
(upper (+ lower size -1)))
|
||||
(cons lower upper))))
|
||||
|
||||
(defun company--scrollbar (i bounds)
|
||||
(defun company--scrollbar (i bounds selected)
|
||||
(let* ((scroll-width (ceiling (* (default-font-width)
|
||||
company-tooltip-scrollbar-width))))
|
||||
(propertize " "
|
||||
@@ -4188,7 +4188,9 @@ but adjust the expected values appropriately."
|
||||
'face
|
||||
(if (and (>= i (car bounds)) (<= i (cdr bounds)))
|
||||
'company-tooltip-scrollbar-thumb
|
||||
'company-tooltip-scrollbar-track))))
|
||||
(if selected
|
||||
'company-tooltip-selection
|
||||
'company-tooltip)))))
|
||||
|
||||
(defun company--right-margin (limit length)
|
||||
(if (or (not (eq company-tooltip-offset-display 'scrollbar))
|
||||
|
||||
+32
-32
@@ -1,4 +1,4 @@
|
||||
This is company.info, produced by makeinfo version 7.2 from
|
||||
This is company.info, produced by makeinfo version 7.3 from
|
||||
company.texi.
|
||||
|
||||
This user manual is for Company version 1.0.3-snapshot
|
||||
@@ -352,11 +352,11 @@ core settings that influence its overall behavior.
|
||||
|
||||
-- User Option: company-minimum-prefix-length
|
||||
This is one of the values (together with ‘company-idle-delay’),
|
||||
based on which Company auto-stars looking up completion candidates.
|
||||
This option configures how many characters have to be typed in by a
|
||||
user before candidates start to be collected and displayed. An
|
||||
often choice nowadays is to configure this option to a lower number
|
||||
than the default value of ‘3’.
|
||||
based on which Company auto-starts looking up completion
|
||||
candidates. This option configures how many characters have to be
|
||||
typed in by a user before candidates start to be collected and
|
||||
displayed. An often choice nowadays is to configure this option to
|
||||
a lower number than the default value of ‘3’.
|
||||
|
||||
-- User Option: company-idle-delay
|
||||
This is the second of the options that configure Company's
|
||||
@@ -1786,32 +1786,32 @@ Ref: Commands-Footnote-110079
|
||||
Node: Customization10246
|
||||
Node: Customization Interface10718
|
||||
Node: Configuration File11251
|
||||
Ref: company-selection-wrap-around13563
|
||||
Node: Frontends16052
|
||||
Node: Tooltip Frontends17021
|
||||
Ref: Tooltip Frontends-Footnote-127717
|
||||
Node: Preview Frontends27954
|
||||
Ref: Preview Frontends-Footnote-129212
|
||||
Node: Echo Frontends29339
|
||||
Node: Candidates Search30868
|
||||
Node: Filter Candidates32200
|
||||
Node: Quick Access a Candidate32980
|
||||
Node: Backends34598
|
||||
Node: Backends Usage Basics35628
|
||||
Ref: Backends Usage Basics-Footnote-137060
|
||||
Node: Grouped Backends37144
|
||||
Node: Package Backends38655
|
||||
Node: Code Completion39582
|
||||
Node: Text Completion45099
|
||||
Node: File Name Completion49523
|
||||
Node: Template Expansion51069
|
||||
Node: Candidates Post-Processing51788
|
||||
Node: Troubleshooting54365
|
||||
Node: Index56036
|
||||
Node: Key Index56199
|
||||
Node: Variable Index57698
|
||||
Node: Function Index62551
|
||||
Node: Concept Index67251
|
||||
Ref: company-selection-wrap-around13565
|
||||
Node: Frontends16054
|
||||
Node: Tooltip Frontends17023
|
||||
Ref: Tooltip Frontends-Footnote-127719
|
||||
Node: Preview Frontends27956
|
||||
Ref: Preview Frontends-Footnote-129214
|
||||
Node: Echo Frontends29341
|
||||
Node: Candidates Search30870
|
||||
Node: Filter Candidates32202
|
||||
Node: Quick Access a Candidate32982
|
||||
Node: Backends34600
|
||||
Node: Backends Usage Basics35630
|
||||
Ref: Backends Usage Basics-Footnote-137062
|
||||
Node: Grouped Backends37146
|
||||
Node: Package Backends38657
|
||||
Node: Code Completion39584
|
||||
Node: Text Completion45101
|
||||
Node: File Name Completion49525
|
||||
Node: Template Expansion51071
|
||||
Node: Candidates Post-Processing51790
|
||||
Node: Troubleshooting54367
|
||||
Node: Index56038
|
||||
Node: Key Index56201
|
||||
Node: Variable Index57700
|
||||
Node: Function Index62553
|
||||
Node: Concept Index67253
|
||||
|
||||
End Tag Table
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "cond-let" "20251101.1942"
|
||||
(define-package "cond-let" "20260201.1500"
|
||||
"Additional and improved binding conditionals."
|
||||
'((emacs "28.1"))
|
||||
:url "https://github.com/tarsius/cond-let"
|
||||
:commit "288b7d36563223ebaf64cb220a3b270bdffb63f1"
|
||||
:revdesc "288b7d365632"
|
||||
:commit "8bf87d45e169ebc091103b2aae325aece3aa804d"
|
||||
:revdesc "8bf87d45e169"
|
||||
:keywords '("extensions"))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; cond-let.el --- Additional and improved binding conditionals -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2025 Jonas Bernoulli
|
||||
;; Copyright (C) 2025-2026 Jonas Bernoulli
|
||||
|
||||
;; May contain traces of Emacs, which is
|
||||
;; Copyright (C) 1985-2025 Free Software Foundation, Inc.
|
||||
@@ -9,8 +9,8 @@
|
||||
;; Homepage: https://github.com/tarsius/cond-let
|
||||
;; Keywords: extensions
|
||||
|
||||
;; Package-Version: 20251101.1942
|
||||
;; Package-Revision: 288b7d365632
|
||||
;; Package-Version: 20260201.1500
|
||||
;; Package-Revision: 8bf87d45e169
|
||||
;; Package-Requires: ((emacs "28.1"))
|
||||
|
||||
;; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
@@ -30,14 +30,16 @@
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This is an ALPHA release!
|
||||
;; Breaking changes are possible!
|
||||
;; This is a BETA release!
|
||||
;; Breaking changes are unlikely but still possible!
|
||||
;; See https://github.com/tarsius/cond-let/wiki.
|
||||
|
||||
;; Emacs provides the binding conditionals `if-let', `if-let*',
|
||||
;; `when-let', `when-let*', `and-let*' and `while-let'.
|
||||
|
||||
;; This package implements the missing `and-let' and `while-let*',
|
||||
;; and the original `cond-let', `cond-let*', `and$' and `and>'.
|
||||
;; and the original `cond-let', `cond-let*', `when$', `and$' and
|
||||
;; `and>'.
|
||||
|
||||
;; This package additionally provides more consistent and improved
|
||||
;; implementations of the binding conditionals already provided by
|
||||
@@ -61,6 +63,7 @@
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let"))
|
||||
;; End:
|
||||
@@ -73,8 +76,8 @@
|
||||
;; Due to limitations of the shorthand implementation this has to be
|
||||
;; done for each individual library. "dir-locals.el" cannot be used.
|
||||
|
||||
;; If you use `and$' and `and>', you might want to add this to your
|
||||
;; configuration:
|
||||
;; If you use `when$', `and$' and `and>', you might want to add this
|
||||
;; to your configuration:
|
||||
|
||||
;; (with-eval-after-load 'cond-let
|
||||
;; (font-lock-add-keywords 'emacs-lisp-mode
|
||||
@@ -452,7 +455,7 @@ BODY must be one or more expressions. If VARLIST is empty, do nothing
|
||||
and return nil.
|
||||
|
||||
\(fn VARLIST BODY...)"
|
||||
(declare (debug (form form)))
|
||||
(declare (indent 1) (debug (form form)))
|
||||
`(let (($ ,varform))
|
||||
(when $
|
||||
,bodyform ,@body)))
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "counsel" "20250329.1401"
|
||||
(define-package "counsel" "20260214.1004"
|
||||
"Various completion functions using Ivy."
|
||||
'((emacs "24.5")
|
||||
(ivy "0.15.1")
|
||||
(swiper "0.15.1"))
|
||||
:url "https://github.com/abo-abo/swiper"
|
||||
:commit "e33b028ed4b1258a211c87fd5fe801bed25de429"
|
||||
:revdesc "e33b028ed4b1"
|
||||
:commit "ee79f68215ae7e2b8a38ba6bf7f82b3fe57dc16c"
|
||||
:revdesc "ee79f68215ae"
|
||||
:keywords '("convenience" "matching" "tools")
|
||||
:authors '(("Oleh Krehel" . "ohwoeowho@gmail.com"))
|
||||
:maintainers '(("Basil L. Contovounesios" . "basil@contovou.net")))
|
||||
|
||||
+210
-153
@@ -1,12 +1,12 @@
|
||||
;;; counsel.el --- Various completion functions using Ivy -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2015-2025 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2015-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Oleh Krehel <ohwoeowho@gmail.com>
|
||||
;; Maintainer: Basil L. Contovounesios <basil@contovou.net>
|
||||
;; URL: https://github.com/abo-abo/swiper
|
||||
;; Package-Version: 20250329.1401
|
||||
;; Package-Revision: e33b028ed4b1
|
||||
;; Package-Version: 20260214.1004
|
||||
;; Package-Revision: ee79f68215ae
|
||||
;; Package-Requires: ((emacs "24.5") (ivy "0.15.1") (swiper "0.15.1"))
|
||||
;; Keywords: convenience, matching, tools
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'ivy)
|
||||
(require 'swiper)
|
||||
|
||||
@@ -424,11 +425,10 @@ Update the minibuffer with the amount of lines collected every
|
||||
(defun counsel-irony ()
|
||||
"Inline C/C++ completion using Irony."
|
||||
(interactive)
|
||||
(irony-completion-candidates-async 'counsel-irony-callback))
|
||||
(irony-completion-candidates-async #'counsel-irony-callback))
|
||||
|
||||
(defun counsel-irony-callback (candidates)
|
||||
"Callback function for Irony to search among CANDIDATES."
|
||||
(interactive)
|
||||
(let* ((symbol-bounds (irony-completion-symbol-bounds))
|
||||
(beg (car symbol-bounds))
|
||||
(end (cdr symbol-bounds))
|
||||
@@ -456,7 +456,8 @@ Update the minibuffer with the amount of lines collected every
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-.") #'counsel-find-symbol)
|
||||
(define-key map (kbd "C-,") #'counsel--info-lookup-symbol)
|
||||
map))
|
||||
map)
|
||||
"Keymap for Counsel commands that describe symbols.")
|
||||
|
||||
(ivy-set-actions
|
||||
'counsel-describe-variable
|
||||
@@ -472,12 +473,15 @@ Used by commands `counsel-describe-symbol',
|
||||
"Jump to the definition of the current symbol."
|
||||
(interactive)
|
||||
(ivy-exit-with-action #'counsel--find-symbol))
|
||||
(function-put #'counsel-find-symbol 'no-counsel-M-x t)
|
||||
(ivy--no-M-x #'counsel-find-symbol #'ivy--minibuffer-p)
|
||||
|
||||
(defun counsel--info-lookup-symbol ()
|
||||
"Lookup the current symbol in the info docs."
|
||||
(interactive)
|
||||
(ivy-exit-with-action #'counsel-info-lookup-symbol))
|
||||
(ivy-exit-with-action
|
||||
(lambda (x)
|
||||
(counsel-info-lookup-symbol (ivy--action-cand-to-str x)))))
|
||||
(ivy--no-M-x #'counsel--info-lookup-symbol #'ivy--minibuffer-p)
|
||||
|
||||
(defun counsel--push-xref-marker (&optional m)
|
||||
"Compatibility shim for `xref-push-marker-stack'."
|
||||
@@ -496,10 +500,11 @@ Used by commands `counsel-describe-symbol',
|
||||
(ring-insert find-tag-marker-ring (or m (point-marker)))))
|
||||
|
||||
(defun counsel--find-symbol (x)
|
||||
"Find symbol definition that corresponds to string X."
|
||||
"Find symbol definition that corresponds to action candidate X."
|
||||
(with-ivy-window
|
||||
(counsel--push-xref-marker)
|
||||
(let ((full-name (get-text-property 0 'full-name x)))
|
||||
(let* ((x (ivy--action-cand-to-str x))
|
||||
(full-name (get-text-property 0 'full-name x)))
|
||||
(if full-name
|
||||
(find-library full-name)
|
||||
(let ((sym (read x)))
|
||||
@@ -532,7 +537,7 @@ Used by commands `counsel-describe-symbol',
|
||||
|
||||
(defun counsel-describe-variable-transformer (var)
|
||||
"Propertize VAR if it's a custom variable."
|
||||
(if (custom-variable-p (intern var))
|
||||
(if (custom-variable-p (intern-soft var))
|
||||
(ivy-append-face var 'ivy-highlight-face)
|
||||
var))
|
||||
|
||||
@@ -551,7 +556,8 @@ Variables declared using `defcustom' are highlighted according to
|
||||
:keymap counsel-describe-map
|
||||
:preselect (ivy-thing-at-point)
|
||||
:action (lambda (x)
|
||||
(funcall counsel-describe-variable-function (intern x)))
|
||||
(funcall counsel-describe-variable-function
|
||||
(counsel--action-cand-to-interned x)))
|
||||
:caller 'counsel-describe-variable)))
|
||||
|
||||
(ivy-configure 'counsel-describe-variable
|
||||
@@ -571,7 +577,7 @@ Variables declared using `defcustom' are highlighted according to
|
||||
|
||||
(defun counsel-describe-function-transformer (function-name)
|
||||
"Propertize FUNCTION-NAME if it's an interactive function."
|
||||
(if (commandp (intern function-name))
|
||||
(if (commandp (intern-soft function-name))
|
||||
(ivy-append-face function-name 'ivy-highlight-face)
|
||||
function-name))
|
||||
|
||||
@@ -585,9 +591,15 @@ Variables declared using `defcustom' are highlighted according to
|
||||
(function-item ivy-thing-at-point)
|
||||
(function-item ivy-function-called-at-point)))
|
||||
|
||||
(defun counsel--action-cand-to-interned (x)
|
||||
"Try to return Ivy action argument X as an existing symbol.
|
||||
Not quite the dual of `ivy--action-cand-to-str'."
|
||||
(intern-soft (if (consp x) (car x) x)))
|
||||
|
||||
(defun counsel--describe-function (candidate)
|
||||
"Pass string CANDIDATE to `counsel-describe-function-function'."
|
||||
(funcall counsel-describe-function-function (intern candidate)))
|
||||
(funcall counsel-describe-function-function
|
||||
(counsel--action-cand-to-interned candidate)))
|
||||
|
||||
;;;###autoload
|
||||
(defun counsel-describe-function ()
|
||||
@@ -600,7 +612,7 @@ to `ivy-highlight-face'."
|
||||
(ivy-read "Describe function: " obarray
|
||||
:predicate (lambda (sym)
|
||||
(or (fboundp sym)
|
||||
(get sym 'function-documentation)))
|
||||
(function-get sym 'function-documentation)))
|
||||
:require-match t
|
||||
:history 'counsel-describe-symbol-history
|
||||
:keymap counsel-describe-map
|
||||
@@ -637,7 +649,8 @@ to `ivy-highlight-face'."
|
||||
:keymap counsel-describe-map
|
||||
:preselect (ivy-thing-at-point)
|
||||
:action (lambda (x)
|
||||
(funcall counsel-describe-symbol-function (intern x)))
|
||||
(funcall counsel-describe-symbol-function
|
||||
(counsel--action-cand-to-interned x)))
|
||||
:caller 'counsel-describe-symbol)))
|
||||
|
||||
(ivy-configure 'counsel-describe-symbol
|
||||
@@ -846,6 +859,7 @@ With prefix arg MODE a query for the symbol help mode is offered."
|
||||
;;;; `counsel-M-x'
|
||||
|
||||
(defface counsel-key-binding
|
||||
;; Default Emacs 28 `help-key-binding' doesn't look great in parentheses.
|
||||
'((t :inherit font-lock-keyword-face))
|
||||
"Face used by `counsel-M-x' for key bindings."
|
||||
:group 'ivy-faces)
|
||||
@@ -874,7 +888,7 @@ With prefix arg MODE a query for the symbol help mode is offered."
|
||||
(concat cmd
|
||||
(when (and (symbolp alias) counsel-alias-expand)
|
||||
(format " (%s)" alias))
|
||||
(when key
|
||||
(when (and key suggest-key-bindings)
|
||||
;; Prefer `<f2>' over `C-x 6' where applicable
|
||||
(let ((i (cl-search [?\C-x ?6] key)))
|
||||
(when i
|
||||
@@ -884,114 +898,149 @@ With prefix arg MODE a query for the symbol help mode is offered."
|
||||
(lookup-key map dup))
|
||||
(setq key dup)))))
|
||||
(setq key (key-description key))
|
||||
(put-text-property 0 (length key) 'face 'counsel-key-binding key)
|
||||
(setq key (propertize key 'face 'counsel-key-binding))
|
||||
(format " (%s)" key)))))
|
||||
|
||||
(defvar amx-initialized)
|
||||
(defvar amx-cache)
|
||||
(declare-function amx-initialize "ext:amx")
|
||||
(declare-function amx-detect-new-commands "ext:amx")
|
||||
(declare-function amx-update "ext:amx")
|
||||
(declare-function amx-rank "ext:amx")
|
||||
(defvar smex-initialized-p)
|
||||
(defvar smex-ido-cache)
|
||||
(declare-function smex-initialize "ext:smex")
|
||||
(declare-function smex-detect-new-commands "ext:smex")
|
||||
(declare-function smex-update "ext:smex")
|
||||
(declare-function smex-rank "ext:smex")
|
||||
(defcustom counsel-M-x-collection 'auto
|
||||
"Where to source `counsel-M-x' completion candidates from.
|
||||
`obarray' - Use the default M-x collection built into Emacs.
|
||||
`amx' - Source candidates from the external `amx' package.
|
||||
`smex' - Source candidates from the external `smex' package.
|
||||
`auto' - Automatically detect one of the previous options,
|
||||
falling back to `obarray'. This is the default.
|
||||
The value can alternatively be a function of no arguments
|
||||
that returns a completion table suitable for `ivy-read'."
|
||||
:package-version '(counsel . "0.16.0")
|
||||
:type '(choice (const :tag "Built-in" obarray)
|
||||
(const :tag "Amx package" amx)
|
||||
(const :tag "Smex package" smex)
|
||||
(const :tag "Auto-detect" auto)
|
||||
(function :tag "Custom function")))
|
||||
|
||||
(defun counsel--M-x-externs ()
|
||||
"Return `counsel-M-x' candidates from external packages.
|
||||
The return value is a list of strings. The currently supported
|
||||
packages are, in order of precedence, `amx' and `smex'."
|
||||
(cond ((require 'amx nil t)
|
||||
(defun counsel--M-x-collection ()
|
||||
"Return a completion table obeying `counsel-M-x-collection'."
|
||||
(let ((src counsel-M-x-collection))
|
||||
(cond ((eq src 'obarray) obarray)
|
||||
((eq src 'auto)
|
||||
(cond ((ivy--feature-p 'amx)
|
||||
(counsel--amx-collection))
|
||||
((ivy--feature-p 'smex)
|
||||
(counsel--smex-collection))
|
||||
(obarray)))
|
||||
((eq src 'amx)
|
||||
(unless (ivy--feature-p 'amx)
|
||||
(user-error "Package `amx' not installed"))
|
||||
(counsel--amx-collection))
|
||||
((eq src 'smex)
|
||||
(unless (ivy--feature-p 'smex)
|
||||
(user-error "Package `smex' not installed"))
|
||||
(counsel--smex-collection))
|
||||
((functionp src) (funcall src))
|
||||
((user-error "Unknown `counsel-M-x-collection': %S" src)))))
|
||||
|
||||
(defun counsel--M-x-extern-rank (cmd)
|
||||
"Tell external `counsel-M-x-collection' that CMD was selected."
|
||||
(declare-function amx-rank "ext:amx")
|
||||
(declare-function smex-rank "ext:smex")
|
||||
(let ((src counsel-M-x-collection))
|
||||
(cond ((and (memq src '(auto amx))
|
||||
(bound-and-true-p amx-initialized))
|
||||
(amx-rank cmd))
|
||||
((and (memq src '(auto smex))
|
||||
(bound-and-true-p smex-initialized-p))
|
||||
(smex-rank cmd)))))
|
||||
|
||||
(defun counsel--amx-collection ()
|
||||
"Return `counsel-M-x' candidates from the `amx' package."
|
||||
(declare-function amx-detect-new-commands "ext:amx")
|
||||
(declare-function amx-initialize "ext:amx")
|
||||
(declare-function amx-update "ext:amx")
|
||||
(defvar amx-cache)
|
||||
(defvar amx-initialized)
|
||||
(unless amx-initialized
|
||||
(amx-initialize))
|
||||
(when (amx-detect-new-commands)
|
||||
(amx-update))
|
||||
(mapcar (lambda (entry)
|
||||
(symbol-name (car entry)))
|
||||
amx-cache))
|
||||
((require 'smex nil t)
|
||||
amx-cache)
|
||||
|
||||
(defun counsel--smex-collection ()
|
||||
"Return `counsel-M-x' candidates from the `smex' package."
|
||||
(declare-function smex-detect-new-commands "ext:smex")
|
||||
(declare-function smex-initialize "ext:smex")
|
||||
(declare-function smex-update "ext:smex")
|
||||
(defvar smex-ido-cache)
|
||||
(defvar smex-initialized-p)
|
||||
(unless smex-initialized-p
|
||||
(smex-initialize))
|
||||
(when (smex-detect-new-commands)
|
||||
(smex-update))
|
||||
smex-ido-cache)))
|
||||
smex-ido-cache)
|
||||
|
||||
(defun counsel--M-x-externs-predicate (cand)
|
||||
"Return non-nil if `counsel-M-x' should complete CAND.
|
||||
CAND is a string returned by `counsel--M-x-externs'."
|
||||
(not (get (intern cand) 'no-counsel-M-x)))
|
||||
|
||||
(defun counsel--M-x-make-predicate ()
|
||||
(defun counsel--M-x-predicate ()
|
||||
"Return a predicate for `counsel-M-x' in the current buffer."
|
||||
(defvar read-extended-command-predicate)
|
||||
(let ((buf (current-buffer)))
|
||||
(lambda (sym)
|
||||
(and (commandp sym)
|
||||
(not (get sym 'byte-obsolete-info))
|
||||
(not (get sym 'no-counsel-M-x))
|
||||
(cond ((not (bound-and-true-p read-extended-command-predicate)))
|
||||
((functionp read-extended-command-predicate)
|
||||
;; Should work with all completion table types.
|
||||
(lambda (key &optional _val)
|
||||
(when (consp key) (setq key (car key)))
|
||||
(when (stringp key) (setq key (intern key)))
|
||||
(and (commandp key)
|
||||
(not (function-get key 'byte-obsolete-info))
|
||||
(not (function-get key 'no-counsel-M-x))
|
||||
;; New in Emacs 28.
|
||||
(let ((pred (bound-and-true-p read-extended-command-predicate)))
|
||||
(or (not (functionp pred))
|
||||
(condition-case-unless-debug err
|
||||
(funcall read-extended-command-predicate sym buf)
|
||||
(funcall pred key buf)
|
||||
(error (message "read-extended-command-predicate: %s: %s"
|
||||
sym (error-message-string err))))))))))
|
||||
key (error-message-string err))))))))))
|
||||
|
||||
(defun counsel--M-x-prompt ()
|
||||
"String for `M-x' plus the string representation of `current-prefix-arg'."
|
||||
(concat (cond ((null current-prefix-arg)
|
||||
nil)
|
||||
((eq current-prefix-arg '-)
|
||||
"- ")
|
||||
((integerp current-prefix-arg)
|
||||
(format "%d " current-prefix-arg))
|
||||
((= (car current-prefix-arg) 4)
|
||||
"C-u ")
|
||||
(t
|
||||
(format "%d " (car current-prefix-arg))))
|
||||
(defun counsel--M-x-prompt (arg)
|
||||
"Prompt for `counsel-M-x' preceded by a printed form of prefix ARG."
|
||||
(concat (cond ((null arg) ())
|
||||
((eq (car-safe arg) 4) "C-u ")
|
||||
((or (eq arg '-)
|
||||
(integerp (or (car-safe arg) arg)))
|
||||
(format "%s " (or (car-safe arg) arg))))
|
||||
"M-x "))
|
||||
|
||||
(defvar counsel-M-x-history nil
|
||||
"History for `counsel-M-x'.")
|
||||
|
||||
(defun counsel-M-x-action (cmd)
|
||||
"Execute CMD."
|
||||
(setq cmd (intern
|
||||
(subst-char-in-string ?\s ?- (string-remove-prefix "^" cmd))))
|
||||
(cond ((bound-and-true-p amx-initialized)
|
||||
(amx-rank cmd))
|
||||
((bound-and-true-p smex-initialized-p)
|
||||
(smex-rank cmd)))
|
||||
(setq prefix-arg current-prefix-arg)
|
||||
"Execute CMD from `counsel-M-x'."
|
||||
;; Currently CMD is a string either following `ivy-immediate-done',
|
||||
;; or for all collection types but alist, where CMD is the original
|
||||
;; cons. There is no harm in allowing other atoms through.
|
||||
(setq cmd (cond ((stringp cmd)
|
||||
(or (intern-soft cmd)
|
||||
;; For the benefit of `ivy-immediate-done'.
|
||||
(intern (subst-char-in-string
|
||||
?\s ?- (string-remove-prefix "^" cmd)))))
|
||||
((consp cmd) (intern-soft (car cmd)))
|
||||
(cmd)))
|
||||
(counsel--M-x-extern-rank cmd)
|
||||
;; As per `execute-extended-command'.
|
||||
(setq this-command cmd)
|
||||
(setq real-this-command cmd)
|
||||
(command-execute cmd 'record))
|
||||
(let ((prefix-arg (or ivy-current-prefix-arg current-prefix-arg)))
|
||||
(command-execute cmd 'record)))
|
||||
|
||||
;;;###autoload
|
||||
(defun counsel-M-x (&optional initial-input)
|
||||
"Ivy version of `execute-extended-command'.
|
||||
Optional INITIAL-INPUT is the initial input in the minibuffer.
|
||||
This function integrates with either the `amx' or `smex' package
|
||||
when available, in that order of precedence."
|
||||
This function integrates with either the `amx' or `smex' package when
|
||||
available, in that order of precedence; see `counsel-M-x-collection'."
|
||||
(interactive)
|
||||
;; When `counsel-M-x' returns, `last-command' would be set to
|
||||
;; `counsel-M-x' because :action hasn't been invoked yet.
|
||||
;; Instead, preserve the old value of `this-command'.
|
||||
(setq this-command last-command)
|
||||
(setq real-this-command real-last-command)
|
||||
(let ((externs (counsel--M-x-externs)))
|
||||
(ivy-read (counsel--M-x-prompt) (or externs obarray)
|
||||
:predicate (if externs
|
||||
#'counsel--M-x-externs-predicate
|
||||
(counsel--M-x-make-predicate))
|
||||
(ivy-read (counsel--M-x-prompt current-prefix-arg)
|
||||
(counsel--M-x-collection)
|
||||
:predicate (counsel--M-x-predicate)
|
||||
:require-match t
|
||||
:history 'counsel-M-x-history
|
||||
:action #'counsel-M-x-action
|
||||
:keymap counsel-describe-map
|
||||
:initial-input initial-input
|
||||
:caller 'counsel-M-x)))
|
||||
:caller 'counsel-M-x))
|
||||
|
||||
(ivy-configure 'counsel-M-x
|
||||
:initial-input "^"
|
||||
@@ -1208,13 +1257,13 @@ See `execute-extended-command' for further information."
|
||||
"Find symbol definition of candidate X.
|
||||
See `counsel--find-symbol' for further information."
|
||||
(let ((cmd (cddr x)))
|
||||
(counsel--find-symbol (symbol-name cmd))))
|
||||
(counsel--find-symbol cmd)))
|
||||
|
||||
(defun counsel-descbinds-action-info (x)
|
||||
"Display symbol definition of candidate X, as found in the relevant manual.
|
||||
See `info-lookup-symbol' for further information."
|
||||
(let ((cmd (cddr x)))
|
||||
(counsel-info-lookup-symbol (symbol-name cmd))))
|
||||
(counsel-info-lookup-symbol cmd)))
|
||||
|
||||
;;;###autoload
|
||||
(defun counsel-descbinds (&optional prefix buffer)
|
||||
@@ -1752,6 +1801,7 @@ When CMD is non-nil, prompt for a specific \"git grep\" command."
|
||||
(unless (ivy-state-dynamic-collection ivy-last)
|
||||
(setq ivy--all-candidates
|
||||
(all-completions "" #'counsel-git-grep-function))))
|
||||
(ivy--no-M-x #'counsel-git-grep-switch-cmd #'ivy--minibuffer-p t)
|
||||
|
||||
(defun counsel--normalize-grep-match (str)
|
||||
;; Prepend ./ if necessary:
|
||||
@@ -1809,6 +1859,7 @@ When CMD is non-nil, prompt for a specific \"git grep\" command."
|
||||
(find-file file-name)
|
||||
(goto-char (point-min)))
|
||||
(perform-replace from to t t nil))))))))))
|
||||
(ivy--no-M-x #'counsel-git-grep-query-replace #'ivy--minibuffer-p)
|
||||
|
||||
;;;; `counsel-git-stash'
|
||||
|
||||
@@ -1974,20 +2025,12 @@ currently checked out."
|
||||
;;; File
|
||||
;;;; `counsel-find-file'
|
||||
|
||||
(defvar counsel-find-file-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-DEL") #'counsel-up-directory)
|
||||
(define-key map (kbd "C-<backspace>") #'counsel-up-directory)
|
||||
(define-key map (kbd "`") #'counsel-file-jump-from-find)
|
||||
(define-key map (kbd "C-`") (ivy-make-magic-action #'counsel-find-file "b"))
|
||||
(define-key map `[remap ,#'undo] #'counsel-find-file-undo)
|
||||
map))
|
||||
|
||||
(defun counsel-file-jump-from-find ()
|
||||
"Switch to `counsel-file-jump' from `counsel-find-file'."
|
||||
(interactive)
|
||||
(ivy-quit-and-run
|
||||
(counsel-file-jump ivy-text (ivy-state-directory ivy-last))))
|
||||
(ivy--no-M-x #'counsel-file-jump-from-find #'ivy--minibuffer-p)
|
||||
|
||||
(when (executable-find "git")
|
||||
(add-to-list 'ivy-ffap-url-functions 'counsel-github-url-p)
|
||||
@@ -2084,18 +2127,29 @@ choose between `yes-or-no-p' and `y-or-n-p'; otherwise default to
|
||||
(when win (with-selected-window win (ivy--cd dir)))))
|
||||
|
||||
(ivy-set-actions
|
||||
'counsel-find-file
|
||||
'(("j" find-file-other-window "other window")
|
||||
("f" find-file-other-frame "other frame")
|
||||
("b" counsel-find-file-cd-bookmark-action "cd bookmark")
|
||||
("x" counsel-find-file-extern "open externally")
|
||||
("r" counsel-find-file-as-root "open as root")
|
||||
("R" find-file-read-only "read only")
|
||||
("l" find-file-literally "open literally")
|
||||
("k" counsel-find-file-delete "delete")
|
||||
("c" counsel-find-file-copy "copy file")
|
||||
("m" counsel-find-file-move "move or rename")
|
||||
("d" counsel-find-file-mkdir-action "mkdir")))
|
||||
#'counsel-find-file
|
||||
`(("j" ,#'find-file-other-window "other window")
|
||||
("f" ,#'find-file-other-frame "other frame")
|
||||
("b" ,#'counsel-find-file-cd-bookmark-action "cd bookmark")
|
||||
("x" ,#'counsel-find-file-extern "open externally")
|
||||
("r" ,#'counsel-find-file-as-root "open as root")
|
||||
("R" ,#'find-file-read-only "read only")
|
||||
("l" ,#'find-file-literally "open literally")
|
||||
("k" ,#'counsel-find-file-delete "delete")
|
||||
("c" ,#'counsel-find-file-copy "copy file")
|
||||
("m" ,#'counsel-find-file-move "move or rename")
|
||||
("d" ,#'counsel-find-file-mkdir-action "mkdir")))
|
||||
|
||||
(defvar counsel-find-file-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-DEL") #'counsel-up-directory)
|
||||
(define-key map (kbd "C-<backspace>") #'counsel-up-directory)
|
||||
(define-key map (kbd "`") #'counsel-file-jump-from-find)
|
||||
;; Needs to come after "b" action is defined.
|
||||
(define-key map (kbd "C-`") (ivy-make-magic-action #'counsel-find-file "b"))
|
||||
(define-key map `[remap ,#'undo] #'counsel-find-file-undo)
|
||||
map)
|
||||
"Keymap used during Counsel file name completion.")
|
||||
|
||||
(defcustom counsel-find-file-at-point nil
|
||||
"When non-nil, add file-at-point to the list of candidates."
|
||||
@@ -2247,10 +2301,10 @@ If USE-IGNORE is non-nil, try to generate a command that respects
|
||||
(let ((regex ivy--old-re))
|
||||
(if (= 0 (length regex))
|
||||
"cat"
|
||||
(let ((filter-cmd (cl-find-if
|
||||
(lambda (x)
|
||||
(let ((filter-cmd (cl-assoc-if
|
||||
(lambda (cmd)
|
||||
(executable-find
|
||||
(car (split-string (car x)))))
|
||||
(car (split-string cmd))))
|
||||
counsel-file-name-filter-alist))
|
||||
cmd)
|
||||
(when (and use-ignore ivy-use-ignore
|
||||
@@ -2339,11 +2393,13 @@ See variable `counsel-up-directory-level'."
|
||||
(ivy--cd up-dir)
|
||||
(setf (ivy-state-preselect ivy-last)
|
||||
(file-name-as-directory (file-name-nondirectory cur-dir)))))))
|
||||
(ivy--no-M-x #'counsel-up-directory #'ivy--minibuffer-p)
|
||||
|
||||
(defun counsel-down-directory ()
|
||||
"Descend into the current directory."
|
||||
(interactive)
|
||||
(ivy--directory-enter))
|
||||
(ivy--no-M-x #'counsel-down-directory #'ivy--minibuffer-p)
|
||||
|
||||
(defun counsel-find-file-undo ()
|
||||
(interactive)
|
||||
@@ -2354,6 +2410,7 @@ See variable `counsel-up-directory-level'."
|
||||
(when dir
|
||||
(ivy--cd dir)))
|
||||
(undo)))
|
||||
(ivy--no-M-x #'counsel-find-file-undo #'ivy--minibuffer-p)
|
||||
|
||||
(defun counsel-at-git-issue-p ()
|
||||
"When point is at an issue in a Git-versioned file, return the issue string."
|
||||
@@ -2562,10 +2619,8 @@ This function uses the `dom' library from Emacs 25.1 or later."
|
||||
"Return candidates for `counsel-buffer-or-recentf'."
|
||||
(recentf-mode)
|
||||
(let ((buffers (delq nil (mapcar #'buffer-file-name (buffer-list)))))
|
||||
(nconc
|
||||
buffers
|
||||
(cl-remove-if (lambda (f) (member f buffers))
|
||||
(counsel-recentf-candidates)))))
|
||||
(nconc buffers (cl-set-difference (counsel-recentf-candidates)
|
||||
buffers :test #'equal))))
|
||||
|
||||
;;;###autoload
|
||||
(defun counsel-buffer-or-recentf ()
|
||||
@@ -2648,24 +2703,24 @@ By default `counsel-bookmark' opens a dired buffer for directories."
|
||||
|
||||
;;;; `counsel-bookmarked-directory'
|
||||
|
||||
(defun counsel-bookmarked-directory--candidates ()
|
||||
"Get a list of bookmarked directories sorted by file path."
|
||||
(defun counsel--bookmarked-dirs ()
|
||||
"Return a list of bookmarked directories sorted by file name."
|
||||
(bookmark-maybe-load-default-file)
|
||||
(sort (cl-delete-if-not
|
||||
#'ivy--dirname-p
|
||||
(delq nil (mapcar #'bookmark-get-filename bookmark-alist)))
|
||||
(sort (cl-mapcan (lambda (bm)
|
||||
(let ((dir (bookmark-get-filename bm)))
|
||||
(and dir (ivy--dirname-p dir) (list dir))))
|
||||
bookmark-alist)
|
||||
#'string<))
|
||||
|
||||
;;;###autoload
|
||||
(defun counsel-bookmarked-directory ()
|
||||
"Ivy interface for bookmarked directories.
|
||||
|
||||
With a prefix argument, this command creates a new bookmark which points to the
|
||||
current value of `default-directory'."
|
||||
With a prefix argument, this command creates a new bookmark which points
|
||||
to the current value of `default-directory'."
|
||||
(interactive)
|
||||
(require 'bookmark)
|
||||
(ivy-read "Bookmarked directory: "
|
||||
(counsel-bookmarked-directory--candidates)
|
||||
(ivy-read "Bookmarked directory: " (counsel--bookmarked-dirs)
|
||||
:caller 'counsel-bookmarked-directory
|
||||
:action #'dired))
|
||||
|
||||
@@ -2829,17 +2884,19 @@ library, which see."
|
||||
"Location where to put the locatedb in case your home folder is encrypted."
|
||||
:type 'file)
|
||||
|
||||
(defun counsel-file-stale-p (fname seconds)
|
||||
"Return non-nil if FNAME was modified more than SECONDS ago."
|
||||
(> (float-time (time-since (nth 5 (file-attributes fname))))
|
||||
seconds))
|
||||
(defun counsel-file-stale-p (file seconds)
|
||||
"Return non-nil if FILE was modified more than SECONDS ago.
|
||||
Also return non-nil if FILE does not exist."
|
||||
(let ((mtime (nth 5 (file-attributes file))))
|
||||
(or (not mtime)
|
||||
(> (float-time (time-since mtime))
|
||||
seconds))))
|
||||
|
||||
(defun counsel--locate-updatedb ()
|
||||
(when (file-exists-p "~/.Private")
|
||||
(let ((db-fname (expand-file-name counsel-locate-db-path)))
|
||||
(setenv "LOCATE_PATH" db-fname)
|
||||
(when (or (not (file-exists-p db-fname))
|
||||
(counsel-file-stale-p db-fname 60))
|
||||
(when (counsel-file-stale-p db-fname 60)
|
||||
(message "Updating %s..." db-fname)
|
||||
(counsel--command
|
||||
"updatedb" "-l" "0" "-o" db-fname "-U" (expand-file-name "~"))))))
|
||||
@@ -3050,6 +3107,7 @@ FZF-PROMPT, if non-nil, is passed as `ivy-read' prompt argument."
|
||||
(interactive)
|
||||
(ivy-quit-and-run
|
||||
(counsel-find-file ivy-text (ivy-state-directory ivy-last))))
|
||||
(ivy--no-M-x #'counsel-find-file-from-jump #'ivy--minibuffer-p)
|
||||
|
||||
;;;###autoload
|
||||
(defun counsel-file-jump (&optional initial-input initial-directory)
|
||||
@@ -3115,9 +3173,9 @@ INITIAL-DIRECTORY, if non-nil, is used as the root directory for search."
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-l") #'ivy-call-and-recenter)
|
||||
(define-key map (kbd "M-q") #'counsel-git-grep-query-replace)
|
||||
(define-key map (kbd "C-'") #'swiper-avy)
|
||||
(define-key map (kbd "C-x C-d") #'counsel-cd)
|
||||
map))
|
||||
map)
|
||||
"Keymap for `counsel-ag'.")
|
||||
|
||||
(defcustom counsel-ag-base-command (list "ag" "--vimgrep" "%s")
|
||||
"Template for default `counsel-ag' command.
|
||||
@@ -3290,6 +3348,7 @@ Works for `counsel-git-grep', `counsel-ag', etc."
|
||||
(new-dir (counsel-read-directory-name "cd: " def-dir)))
|
||||
(ivy-quit-and-run
|
||||
(funcall (ivy-state-caller ivy-last) input new-dir))))
|
||||
(ivy--no-M-x #'counsel-cd #'ivy--minibuffer-p)
|
||||
|
||||
(defun counsel--grep-smart-case-flag ()
|
||||
(if (ivy--case-fold-p ivy-text)
|
||||
@@ -3457,8 +3516,8 @@ Example input with inclusion and exclusion file patterns:
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-l") #'ivy-call-and-recenter)
|
||||
(define-key map (kbd "M-q") #'swiper-query-replace)
|
||||
(define-key map (kbd "C-'") #'swiper-avy)
|
||||
map))
|
||||
map)
|
||||
"Keymap for `counsel-grep'.")
|
||||
|
||||
(defcustom counsel-grep-base-command "grep -E -n -e %s %s"
|
||||
"Format string used by `counsel-grep' to build a shell command.
|
||||
@@ -4469,14 +4528,12 @@ When ARG is non-nil, display all active evil registers."
|
||||
"Return completion alist for `counsel-package'."
|
||||
(unless package--initialized
|
||||
(package-initialize t))
|
||||
(if (or (not package-archive-contents)
|
||||
(cl-find-if (lambda (package-archive)
|
||||
(let ((fname
|
||||
(format
|
||||
"%s/archives/%s/archive-contents"
|
||||
package-user-dir (car package-archive))))
|
||||
(or (not (file-exists-p fname))
|
||||
(counsel-file-stale-p fname (* 4 60 60)))))
|
||||
(when (or (null package-archive-contents)
|
||||
(cl-some (lambda (archive)
|
||||
(let* ((fname (format "archives/%s/archive-contents"
|
||||
(car archive)))
|
||||
(fname (expand-file-name fname package-user-dir)))
|
||||
(counsel-file-stale-p fname (* 4 60 60))))
|
||||
package-archives))
|
||||
(package-refresh-contents))
|
||||
(sort (mapcar (lambda (entry)
|
||||
@@ -5099,6 +5156,7 @@ An extra action allows to switch to the process buffer."
|
||||
(delete-minibuffer-contents)
|
||||
(insert (substring-no-properties (car x))))
|
||||
:caller 'counsel-minibuffer-history)))
|
||||
(ivy--no-M-x #'counsel-minibuffer-history '(minibuffer-mode) t)
|
||||
|
||||
;;;; `counsel-esh-history'
|
||||
|
||||
@@ -5863,8 +5921,6 @@ You can insert or kill the name of the selected font."
|
||||
(define-key map (kbd "C-k") #'counsel-kmacro-kill)
|
||||
map))
|
||||
|
||||
;; Avoid (declare (modes ...)) warnings in Emacs < 28.
|
||||
(function-put #'counsel-kmacro-kill 'command-modes '(minibuffer-mode))
|
||||
(defun counsel-kmacro-kill ()
|
||||
"Kill the line, or delete the currently selected keyboard macro."
|
||||
(interactive)
|
||||
@@ -5877,6 +5933,7 @@ You can insert or kill the name of the selected font."
|
||||
(ivy-state-current ivy-last)
|
||||
(ivy-state-collection ivy-last)))
|
||||
(ivy--kill-current-candidate)))
|
||||
(ivy--no-M-x #'counsel-kmacro-kill #'ivy--minibuffer-p)
|
||||
|
||||
(defvar kmacro-counter)
|
||||
(defvar kmacro-counter-format-start)
|
||||
@@ -6492,12 +6549,11 @@ Any desktop entries that fail to parse are recorded in
|
||||
(eq counsel-linux-app-format-function
|
||||
counsel--linux-apps-cache-format-function)
|
||||
(equal new-files counsel--linux-apps-cached-files)
|
||||
(null (cl-find-if
|
||||
(lambda (file)
|
||||
(cl-notany (lambda (file)
|
||||
(time-less-p
|
||||
counsel--linux-apps-cache-timestamp
|
||||
(nth 5 (file-attributes file))))
|
||||
new-files)))
|
||||
new-files))
|
||||
(setq counsel--linux-apps-cache (counsel-linux-apps-parse new-desktop-alist))
|
||||
(setq counsel--linux-apps-cache-format-function counsel-linux-app-format-function)
|
||||
(setq counsel--linux-apps-cache-timestamp (current-time))
|
||||
@@ -7010,15 +7066,16 @@ handling for the `counsel-compile' metadata."
|
||||
(insert (substring-no-properties
|
||||
cmd 0 (and (get-text-property 0 'cmd cmd)
|
||||
(next-single-property-change 0 'cmd cmd))))))
|
||||
(ivy--no-M-x #'counsel-compile-edit-command #'ivy--minibuffer-p)
|
||||
|
||||
;; Currently the only thing we do is override ivy's default insert
|
||||
;; Currently the only thing we do is override Ivy's default insert
|
||||
;; operation which doesn't include the metadata we want.
|
||||
(defvar counsel-compile-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map `[remap ,#'ivy-insert-current]
|
||||
#'counsel-compile-edit-command)
|
||||
map)
|
||||
"Additional ivy keybindings during command selection.")
|
||||
"Additional Ivy keybindings during command selection.")
|
||||
|
||||
;;;###autoload
|
||||
(defun counsel-compile (&optional dir)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "dash" "20250312.1307"
|
||||
(define-package "dash" "20260221.1346"
|
||||
"A modern list library for Emacs."
|
||||
'((emacs "24"))
|
||||
:url "https://github.com/magnars/dash.el"
|
||||
:commit "fcb5d831fc08a43f984242c7509870f30983c27c"
|
||||
:revdesc "fcb5d831fc08"
|
||||
:commit "d3a84021dbe48dba63b52ef7665651e0cf02e915"
|
||||
:revdesc "d3a84021dbe4"
|
||||
:keywords '("extensions" "lisp")
|
||||
:authors '(("Magnar Sveen" . "magnars@gmail.com"))
|
||||
:maintainers '(("Basil L. Contovounesios" . "basil@contovou.net")))
|
||||
|
||||
+17
-5
@@ -1,11 +1,11 @@
|
||||
;;; dash.el --- A modern list library for Emacs -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2012-2025 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2012-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>
|
||||
;; Maintainer: Basil L. Contovounesios <basil@contovou.net>
|
||||
;; Package-Version: 20250312.1307
|
||||
;; Package-Revision: fcb5d831fc08
|
||||
;; Package-Version: 20260221.1346
|
||||
;; Package-Revision: d3a84021dbe4
|
||||
;; Package-Requires: ((emacs "24"))
|
||||
;; Keywords: extensions, lisp
|
||||
;; URL: https://github.com/magnars/dash.el
|
||||
@@ -27,7 +27,19 @@
|
||||
|
||||
;; A modern list API for Emacs.
|
||||
;;
|
||||
;; See its overview at https://github.com/magnars/dash.el#functions.
|
||||
;; Dash is a utility library that affords functional programming
|
||||
;; patterns inspired by Clojure, particularly in the realm of list
|
||||
;; manipulation. Examples include higher-order functions (map, reduce,
|
||||
;; filter) and derivatives (drop, flatten, sum); function combinators
|
||||
;; (partial application, argument flipping, composition); and threading
|
||||
;; and anaphoric macros with destructuring support.
|
||||
;;
|
||||
;; Dash is particularly useful in providing a broad and consistent API
|
||||
;; across many Emacs versions.
|
||||
;;
|
||||
;; Documentation and examples are in the manual at Info node `(dash) Top'
|
||||
;; and on the web at https://elpa.gnu.org/packages/doc/dash.html, as well
|
||||
;; as in the project’s README.md file.
|
||||
|
||||
;;; Code:
|
||||
|
||||
@@ -1882,7 +1894,7 @@ LISTS, it is generally recommended to use `-unzip-lists' instead."
|
||||
"Return an infinite circular copy of LIST.
|
||||
The returned list cycles through the elements of LIST and repeats
|
||||
from the beginning."
|
||||
(declare (pure t) (side-effect-free t))
|
||||
(declare (side-effect-free t))
|
||||
;; Also works with sequences that aren't lists.
|
||||
(let ((newlist (append list ())))
|
||||
(nconc newlist newlist)))
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
This is dash.info, produced by makeinfo version 7.2 from dash.texi.
|
||||
This is dash.info, produced by makeinfo version 7.3 from dash.texi.
|
||||
|
||||
This manual is for Dash version 2.20.0.
|
||||
|
||||
Copyright © 2012-2025 Free Software Foundation, Inc.
|
||||
Copyright © 2012-2026 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU Free Documentation License,
|
||||
@@ -24,7 +24,7 @@ Dash
|
||||
|
||||
This manual is for Dash version 2.20.0.
|
||||
|
||||
Copyright © 2012-2025 Free Software Foundation, Inc.
|
||||
Copyright © 2012-2026 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU Free Documentation License,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
[38;5;97m▁▂▃▄▄▄▄▃▂▁[0m
|
||||
[38;5;97m ▃▅[48;5;97m▆ [0m[38;5;97m▇▆▃[0m
|
||||
[38;5;97m▁▅[48;5;97m[38;5;61m [38;5;97m [38;5;140m [38;5;231m▁▂▃▄▄▂[38;5;103m [38;5;97m [38;5;61m [0m[38;5;97m▅▁[0m
|
||||
[38;5;236m [38;5;97m▄[48;5;97m[38;5;61m [38;5;97m [38;5;97m [38;5;103m [48;5;231m[38;5;97m▇▆▆▄╸[38;5;231m [48;5;97m▊[38;5;97m [38;5;61m [0m[38;5;97m▄[0m
|
||||
[38;5;97m[7m▘[27m[38;5;97m[48;5;97m [38;5;97m [38;5;231m▅▆[48;5;231m▆[48;5;254m▇[48;5;231m[38;5;231m [38;5;231m▁[38;5;97m▁▂▂▂▃▃[48;5;97m[38;5;231m▘[38;5;97m [0m[38;5;97m[7m▝[27m[0m
|
||||
[38;5;97m▐[48;5;97m [48;5;231m▅▁[38;5;231m [48;5;103m[38;5;255m▂[48;5;97m[38;5;252m [38;5;97m [0m[38;5;97m▊[0m
|
||||
[38;5;97m[7m▎[27m[48;5;97m [38;5;97m [48;5;231m[38;5;97m▆▄▂[38;5;231m▁[48;5;97m[38;5;231m▆▄▂ [38;5;97m█[0m
|
||||
[38;5;97m[7m▉[27m[48;5;97m[38;5;97m [38;5;255m [38;5;231m▂▄▅▆▆[48;5;254m▆[48;5;231m[38;5;231m [38;5;231m▁[38;5;97m▂▃[48;5;97m[38;5;231m╴[38;5;97m [0m[38;5;97m▎[0m
|
||||
[48;5;97m [38;5;231m ▅[48;5;231m▇[48;5;231m [38;5;231m [38;5;97m▂▄▆[48;5;97m[38;5;255m [38;5;97m [38;5;61m [0m[38;5;97m▎[0m
|
||||
[38;5;97m▐[48;5;97m [38;5;231m▝[48;5;231m[38;5;231m [38;5;231m [48;5;97m▌[38;5;146m [38;5;97m [0m[38;5;97m[7m▗[27m[0m
|
||||
[38;5;97m[7m▖[27m[48;5;97m [48;5;231m▇▄▂[38;5;231m▂[38;5;231m [48;5;231m[38;5;231m▆[48;5;97m▆▆▅▅▅▅▅▅▄▃▖[38;5;97m [0m[38;5;97m[7m▗[27m[0m
|
||||
[38;5;97m[7m▂[27m[48;5;97m [38;5;253m [48;5;231m[38;5;97m▇▆▆▆▄━[38;5;146m⎻[38;5;231m▁[38;5;97m▁▃▅[48;5;97m[38;5;231m [38;5;97m [0m[38;5;97m[7m▗[27m[0m
|
||||
[38;5;97m[7m▅▁[27m[48;5;97m [38;5;254m─[38;5;231m─[48;5;231m[38;5;97m▅▅▅▆▇[48;5;97m[38;5;254m [38;5;97m [38;5;97m [0m[38;5;97m[7m▁▅[27m[0m
|
||||
[38;5;97m[7m▆▃▂[27m[48;5;97m [0m[38;5;97m[7m▂▃▅[27m[0m
|
||||
[38;5;97m[7m▇▅▄▃▃▃▃▃▃▄▅▇[27m[0m
|
||||
@@ -0,0 +1,14 @@
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣤⣤⣤⣤⣤⣤⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⡀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⠿⠟⠛⠛⠉⠉⠛⢿⣿⣿⣿⣷⣄⠀⠀⠀⠀
|
||||
⠀⠀⢀⣼⣿⣿⣿⣿⣿⡿⠿⠿⠿⠟⠛⠛⠛⠃⠀⠀⢈⣿⣿⣿⣿⣿⣧⡀⠀⠀
|
||||
⠀⠀⣾⣿⣿⣿⣿⣿⠁⠀⠀⠀⢀⣀⣤⣤⣤⣤⣶⣶⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀
|
||||
⠀⣸⣿⣿⣿⣿⣿⣿⣷⣤⡀⠀⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀
|
||||
⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠷⠦⠤⠀⠀⠉⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
|
||||
⠀⣿⣿⣿⣿⣿⠿⠋⠁⠀⠀⠀⢀⣀⣤⣤⣶⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
|
||||
⠀⢻⣿⣿⣿⡏⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀
|
||||
⠀⠈⢿⣿⣿⣿⣤⣀⠀⠀⠈⠙⠛⠛⠛⠿⠿⠿⠿⠿⠿⠿⣿⣿⣿⣿⣿⣿⠃⠀
|
||||
⠀⠀⠈⢿⣿⣿⣿⣿⣿⣶⣶⣤⣤⣤⣤⣤⠤⠄⠀⠀⢀⣠⣼⣿⣿⣿⡿⠃⠀⠀
|
||||
⠀⠀⠀⠀⠙⢿⣿⣿⣿⣿⣟⣛⣩⣭⣤⣤⣴⣶⣶⣿⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠛⠛⠿⠿⠿⠟⠛⠛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
@@ -0,0 +1,15 @@
|
||||
[38;2;143;133;191m▁[38;2;132;128;194m▁[38;2;134;127;191m▂[38;2;132;124;189m▂[38;2;131;125;192m▁[38;2;147;135;192m▁[0m
|
||||
[38;2;135;132;197m▁▃▅▇[48;2;131;128;196m[38;2;131;129;197m▅[48;2;131;129;197m[38;2;131;128;196m▄▄[48;2;130;127;195m[38;2;129;124;194m▃[48;2;129;125;194m[38;2;128;122;193m▄[48;2;129;123;193m[38;2;128;120;191m▄[48;2;128;121;192m[38;2;127;118;190m▄[48;2;129;120;190m[38;2;0;0;0m [0m[38;2;132;121;190m▇[38;2;130;118;188m▅[38;2;134;120;188m▃[0m
|
||||
[38;2;130;128;196m▂▆[48;2;131;129;197m[38;2;130;128;196m▘[38;2;131;129;197m [38;2;131;128;196m ▃[48;2;130;127;196m[38;2;129;124;194m▃[48;2;130;125;194m[38;2;0;0;0m [48;2;129;123;193m[38;2;201;199;226m▁[48;2;129;123;192m[38;2;229;228;241m▂[48;2;130;122;192m[38;2;239;238;246m▃[38;2;242;241;247m▄[38;2;253;252;253m▄[38;2;250;250;252m▄[38;2;246;245;249m▂[48;2;127;112;186m[38;2;0;0;0m [48;2;123;107;184m[38;2;123;105;182m▃[48;2;124;106;182m[38;2;0;0;0m [0m[38;2;125;105;181m▅[0m
|
||||
[38;2;131;129;197m[7m▘[27m[48;2;131;129;197m[38;2;131;129;196m▘[38;2;131;128;197m [38;2;130;127;196m▗[48;2;130;128;196m[38;2;129;125;194m▃[48;2;130;126;195m[38;2;129;123;193m▃[48;2;128;123;193m[38;2;151;145;201m▁[48;2;127;120;192m[38;2;179;174;214m▁[48;2;130;122;192m[38;2;200;197;225m▁[38;2;229;226;239m▁[38;2;246;246;249m▁[38;2;235;234;243m▂[38;2;251;250;252m▂[48;2;234;233;243m[38;2;146;134;195m╸[48;2;255;255;255m[38;2;255;254;255m╴[38;2;254;254;254m [48;2;123;104;181m[38;2;223;219;236m▊[48;2;122;102;181m[38;2;120;99;180m▄[48;2;121;100;180m[38;2;119;97;179m▅[48;2;120;98;179m[38;2;119;95;178m▄[48;2;119;96;178m[38;2;118;93;176m▄[0m[38;2;118;93;176m▅[0m
|
||||
[38;2;131;129;197m▗[48;2;131;129;197m[38;2;0;0;0m [48;2;131;129;197m[38;2;131;128;196m▂[38;2;130;126;195m▄[48;2;130;127;195m[38;2;129;124;194m▅[48;2;134;129;196m[38;2;0;0;0m [48;2;146;141;201m[38;2;242;241;248m▆[48;2;254;254;254m[38;2;255;255;255m▄▅▆━[48;2;255;255;255m[38;2;254;254;254m▄▅[48;2;252;252;253m[38;2;141;127;192m▃[48;2;250;249;252m[38;2;129;112;185m▃[48;2;248;247;250m[38;2;124;105;181m▃[48;2;243;242;248m[38;2;121;100;180m▃[48;2;241;239;246m[38;2;124;103;181m▄[48;2;119;96;178m[38;2;118;94;177m ▄[48;2;118;94;177m[38;2;117;92;175m▄[48;2;118;92;176m[38;2;117;90;174m▄[48;2;117;90;175m[38;2;116;88;173m▄[48;2;116;89;174m[38;2;116;86;172m▅[0m[38;2;116;86;172m[7m▝[27m[0m
|
||||
[38;2;133;129;195m[7m▘[27m[48;2;130;127;196m[38;2;129;124;194m▄[48;2;129;125;194m[38;2;128;122;193m▄[48;2;129;123;193m[38;2;128;120;192m▄[48;2;128;121;192m[38;2;127;118;190m▄[48;2;129;121;192m[38;2;127;117;190m▇[48;2;218;216;235m▅[48;2;255;255;255m[38;2;254;254;254m▄▁[48;2;254;254;254m[38;2;255;255;255m▌[48;2;127;110;185m[38;2;234;232;243m▂[48;2;127;110;185m[38;2;0;0;0m [48;2;123;105;182m[38;2;122;103;181m▄[48;2;122;103;181m[38;2;121;100;180m▄[48;2;121;101;180m[38;2;120;98;179m▄[48;2;120;99;180m[38;2;119;96;178m▅[48;2;119;97;179m[38;2;118;94;177m▄[48;2;119;95;177m[38;2;118;92;176m▄[48;2;118;93;176m[38;2;117;90;175m▄[48;2;117;91;175m[38;2;116;88;173m▄[48;2;117;89;174m[38;2;116;86;172m▄[48;2;116;87;173m[38;2;115;84;171m▄[48;2;115;85;171m[38;2;114;82;170m▄[48;2;115;83;170m[38;2;114;81;169m▄[48;2;114;81;169m[38;2;113;78;167m▄[0m[38;2;113;78;167m[7m▝[27m[0m
|
||||
[38;2;129;123;193m[7m▊[27m[48;2;129;123;193m[38;2;128;121;192m▄[48;2;128;121;192m[38;2;127;119;190m▃[48;2;128;120;191m[38;2;127;117;190m▅[48;2;127;118;190m[38;2;126;115;188m▄[48;2;126;116;189m[38;2;125;113;187m▄[48;2;126;114;188m[38;2;125;111;186m▅[48;2;125;112;186m[38;2;124;109;185m▅[48;2;124;108;184m[38;2;0;0;0m [48;2;201;196;224m[38;2;124;108;183m▆[48;2;233;231;242m[38;2;125;107;182m▄[48;2;239;237;246m[38;2;124;104;182m▂[48;2;244;243;248m[38;2;157;141;198m▁[48;2;127;110;185m[38;2;246;245;249m▆[48;2;117;91;175m[38;2;247;246;250m▄[48;2;117;91;175m[38;2;243;241;247m▂[48;2;117;91;175m[38;2;0;0;0m [48;2;117;91;175m[38;2;116;87;173m▁[48;2;117;90;174m▅[48;2;116;87;173m[38;2;115;85;171m▃[48;2;115;85;171m[38;2;114;82;170m▃[48;2;115;84;171m[38;2;114;81;169m▅[48;2;114;82;169m[38;2;113;79;168m▄[48;2;113;80;168m[38;2;112;77;166m▄[48;2;113;78;167m[38;2;112;75;165m▄[48;2;112;76;166m[38;2;112;73;164m▄[48;2;112;74;165m[38;2;113;72;165m▄[0m[38;2;113;72;165m▎[0m
|
||||
[38;2;127;118;190m[7m▌[27m[48;2;127;118;190m[38;2;126;115;188m▄[48;2;126;116;189m[38;2;125;113;187m▄[48;2;126;114;188m[38;2;125;111;186m▄[48;2;125;112;187m[38;2;124;109;185m▄[48;2;124;110;185m[38;2;123;108;184m▄[38;2;211;207;230m▁[38;2;242;241;247m▃[38;2;253;252;253m▄[48;2;128;110;184m[38;2;247;246;250m▆[48;2;254;254;254m[38;2;255;255;255m▄▅━━[48;2;255;255;255m[38;2;254;254;254m▄[48;2;239;237;245m[38;2;116;87;172m▂[48;2;233;229;241m[38;2;116;86;172m▃[48;2;115;84;170m[38;2;205;196;223m▘[48;2;115;84;170m[38;2;0;0;0m [48;2;114;82;170m[38;2;113;79;168m▄[48;2;114;80;168m[38;2;113;77;167m▄[48;2;113;78;167m[38;2;112;75;165m▃[48;2;112;77;166m[38;2;112;74;165m▅[48;2;112;74;165m[38;2;112;72;165m▄[48;2;112;72;165m[38;2;115;70;167m▂[48;2;114;71;166m[38;2;117;69;168m▃[48;2;116;69;168m[38;2;120;68;170m▂[0m[38;2;120;68;170m▌[0m
|
||||
[38;2;125;112;186m[7m▊[27m[48;2;125;112;186m[38;2;124;109;185m▃[48;2;125;111;186m[38;2;124;108;184m▅[48;2;124;109;185m[38;2;123;106;183m▅[48;2;124;107;183m[38;2;203;197;225m▗[48;2;254;254;254m[38;2;255;255;255m▗▆[48;2;255;255;255m [38;2;254;254;254m▃[48;2;240;237;245m[38;2;130;106;182m▃[48;2;224;219;236m[38;2;119;93;176m▅[48;2;209;202;226m[38;2;119;92;175m▇[48;2;117;88;173m[38;2;0;0;0m [48;2;116;87;172m[38;2;115;84;171m▅[48;2;115;84;171m[38;2;114;82;169m▃[48;2;115;83;170m[38;2;114;80;168m▅[48;2;114;81;169m[38;2;113;78;167m▅[48;2;113;79;167m[38;2;112;76;166m▄[48;2;113;77;167m[38;2;112;74;165m▅[48;2;112;75;165m[38;2;112;73;164m▅[48;2;112;73;164m[38;2;114;71;166m▃[48;2;114;71;165m[38;2;117;69;168m▂[48;2;116;70;167m[38;2;119;68;169m▃[48;2;117;69;168m[38;2;121;67;171m▄[48;2;120;68;171m[38;2;124;66;173m▃[48;2;123;66;173m[38;2;127;64;175m▃[0m[38;2;127;64;175m▎[0m
|
||||
[38;2;127;110;183m[7m▖[27m[48;2;123;105;182m[38;2;122;102;180m▃[48;2;122;103;181m[38;2;121;100;180m▄[38;2;242;241;246m▝[48;2;255;255;255m[38;2;254;254;254m▃[38;2;255;255;255m [48;2;254;254;255m▊[48;2;146;125;190m[38;2;222;216;234m▌[48;2;122;96;176m[38;2;0;0;0m [48;2;116;86;172m[38;2;113;81;170m▁[48;2;115;85;171m[38;2;114;82;170m▃[48;2;115;83;170m[38;2;114;81;169m▄[48;2;114;81;169m[38;2;113;78;167m▄[48;2;113;79;168m[38;2;112;76;166m▃[48;2;112;77;166m[38;2;112;74;165m▃[48;2;112;76;166m[38;2;112;73;164m▅[48;2;112;72;165m[38;2;0;0;0m [48;2;113;72;165m[38;2;116;70;168m▂[48;2;114;71;166m[38;2;118;69;169m▄[48;2;117;69;168m[38;2;121;67;171m▃[48;2;120;68;170m[38;2;124;66;173m▂[48;2;122;67;172m[38;2;127;65;174m▃[48;2;125;66;173m[38;2;129;64;176m▄[48;2;128;64;175m[38;2;131;63;177m▅[0m[38;2;131;63;177m[7m▗[27m[0m
|
||||
[48;2;119;97;179m [38;2;118;94;177m▃[48;2;119;96;178m[38;2;118;93;176m▅[48;2;119;96;178m[38;2;0;0;0m [48;2;226;221;237m[38;2;118;91;175m▄[48;2;248;247;250m[38;2;128;102;179m▃[48;2;255;255;255m[38;2;254;254;254m▄▃[48;2;254;254;254m[38;2;255;255;255m▆▄[48;2;142;117;185m[38;2;253;252;253m▆[48;2;254;254;254m[38;2;255;255;255m▃[48;2;115;79;168m[38;2;245;244;248m▆[48;2;113;76;166m[38;2;243;240;247m▆[48;2;112;73;164m[38;2;241;239;246m▆[38;2;253;252;253m▅[38;2;252;251;253m▅[48;2;126;66;174m[38;2;249;247;250m▅[48;2;126;66;174m[38;2;248;246;250m▄[48;2;126;66;174m[38;2;204;183;222m▖[48;2;127;65;175m[38;2;131;63;177m▄[48;2;131;63;177m[38;2;134;61;179m▃[48;2;133;62;178m[38;2;136;60;181m▄[0m[38;2;137;63;181m[7m▗[27m[0m
|
||||
[38;2;117;90;174m[7m▂[27m[48;2;117;90;174m[38;2;116;88;172m▄[48;2;116;88;173m[38;2;115;85;171m▄[48;2;116;86;172m[38;2;115;83;170m▄[48;2;115;84;171m[38;2;114;82;169m▄[48;2;114;82;169m[38;2;113;80;168m▄[48;2;115;81;169m[38;2;0;0;0m [48;2;211;203;226m[38;2;114;78;167m▇[48;2;210;201;225m▆[48;2;226;220;235m▆[38;2;210;201;225m[48;2;114;78;167m▁[48;2;114;78;167m[38;2;232;227;239m▃[48;2;114;78;167m[38;2;239;235;244m▄[48;2;239;235;244m[38;2;114;78;167m⎺[48;2;245;243;248m[38;2;142;90;183m▁[48;2;247;244;249m[38;2;136;75;180m▂[48;2;239;233;244m[38;2;133;65;178m▃[48;2;234;225;241m[38;2;136;68;180m▅[48;2;139;69;182m[38;2;0;0;0m [48;2;134;61;180m[38;2;138;59;182m▄[48;2;139;59;182m[38;2;0;0;0m [0m[38;2;139;59;182m[7m▂[27m[0m
|
||||
[38;2;117;85;170m[7m▂[27m[48;2;117;85;170m[38;2;0;0;0m [48;2;113;79;168m[38;2;112;76;166m▅[48;2;112;76;166m[38;2;0;0;0m [48;2;117;81;168m[38;2;186;171;208m⎻[48;2;181;163;207m[38;2;118;77;168m▅[48;2;217;209;229m[38;2;117;72;168m▅[48;2;221;212;232m[38;2;117;67;169m▅[48;2;236;232;242m[38;2;122;71;172m▆[48;2;245;243;247m[38;2;129;77;176m▇[48;2;202;186;219m[38;2;126;66;174m▇[48;2;129;67;176m[38;2;0;0;0m [48;2;132;63;177m[38;2;128;62;175m▘[48;2;132;62;178m[38;2;135;60;180m▃[48;2;134;61;179m[38;2;137;59;182m▃[48;2;137;60;181m[38;2;140;58;183m▃[48;2;143;63;185m[38;2;0;0;0m [0m[38;2;143;63;185m[7m▂[27m[0m[38;2;143;63;185m[7m▆[27m[0m
|
||||
[38;2;117;85;170m[7m▅[27m[38;2;112;76;166m[7m▃[27m[38;2;112;76;166m[7m▁[27m[38;2;119;70;169m[7m▁[27m[48;2;120;68;170m[38;2;124;66;173m▗[48;2;123;66;172m[38;2;128;65;175m▂[48;2;125;65;173m[38;2;129;63;176m▄[48;2;128;64;175m[38;2;131;63;177m▅[48;2;131;63;177m[38;2;135;61;180m▃[48;2;134;61;179m[38;2;137;59;181m▃[0m[38;2;137;60;181m[7m▁[27m[38;2;134;61;179m[7m▁[27m[38;2;134;61;179m[7m▃[27m[38;2;134;61;179m[7m▅[27m[0m
|
||||
[38;2;136;77;179m[7m▇▇▇▇[27m[0m
|
||||
@@ -1,10 +1,10 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "dashboard" "20250708.57"
|
||||
(define-package "dashboard" "20260402.436"
|
||||
"A startup screen extracted from Spacemacs."
|
||||
'((emacs "27.1"))
|
||||
:url "https://github.com/emacs-dashboard/emacs-dashboard"
|
||||
:commit "8c2cf0cfde4f5dac8c477f755380fffef6824108"
|
||||
:revdesc "8c2cf0cfde4f"
|
||||
:url "https://github.com/emacs-dashboard/dashboard"
|
||||
:commit "176d641a55543bda1f0c7506fb954702350c1857"
|
||||
:revdesc "176d641a5554"
|
||||
:keywords '("startup" "screen" "tools" "dashboard")
|
||||
:authors '(("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com"))
|
||||
:maintainers '(("Jen-Chieh" . "jcs090218@gmail.com")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; dashboard-widgets.el --- A startup screen extracted from Spacemacs -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (c) 2016-2025 emacs-dashboard maintainers
|
||||
;; Copyright (c) 2016-2026 emacs-dashboard maintainers
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
@@ -27,6 +27,7 @@
|
||||
(declare-function all-the-icons-icon-for-file "ext:all-the-icons.el")
|
||||
(declare-function all-the-icons-fileicon "ext:data-fileicons.el")
|
||||
(declare-function all-the-icons-octicon "ext:data-octicons.el")
|
||||
(declare-function ansi-color-apply-on-region "ext:ansi-color.el")
|
||||
(declare-function nerd-icons-icon-for-dir "ext:nerd-icons.el")
|
||||
(declare-function nerd-icons-icon-for-file "ext:nerd-icons.el")
|
||||
(declare-function nerd-icons-sucicon "ext:nerd-icons.el")
|
||||
@@ -35,6 +36,8 @@
|
||||
(declare-function bookmark-get-filename "ext:bookmark.el")
|
||||
(declare-function bookmark-all-names "ext:bookmark.el")
|
||||
(declare-function calendar-date-compare "ext:calendar.el")
|
||||
(declare-function dashboard-cycle-section-forward "ext:dashboard.el")
|
||||
(declare-function dashboard-cycle-section-backward "ext:dashboard.el")
|
||||
(declare-function projectile-cleanup-known-projects "ext:projectile.el")
|
||||
(declare-function projectile-load-known-projects "ext:projectile.el")
|
||||
(declare-function projectile-mode "ext:projectile.el")
|
||||
@@ -62,6 +65,8 @@
|
||||
(declare-function org-time-string-to-time "ext:org.el")
|
||||
(declare-function org-today "ext:org.el")
|
||||
(declare-function recentf-cleanup "ext:recentf.el")
|
||||
(declare-function ansi-color-apply-on-region "ext:ansi-color")
|
||||
(defvar dashboard-mode-map)
|
||||
(defvar org-level-faces)
|
||||
(defvar org-agenda-new-buffers)
|
||||
(defvar org-agenda-prefix-format)
|
||||
@@ -251,6 +256,18 @@ nerd-icons or (all-the-icons-faicon \"newspaper-o\") using all-the-icons."
|
||||
(concat dashboard-banners-directory "emacs.png")
|
||||
"Emacs banner image.")
|
||||
|
||||
(defconst dashboard-banner-logo-ansi-256color
|
||||
(concat dashboard-banners-directory "logo-256color.ans")
|
||||
"Emacs banner image.")
|
||||
|
||||
(defconst dashboard-banner-logo-ansi-truecolor
|
||||
(concat dashboard-banners-directory "logo-truecolor.ans")
|
||||
"Emacs banner image.")
|
||||
|
||||
(defconst dashboard-banner-logo-braille
|
||||
(concat dashboard-banners-directory "logo-braille.txt")
|
||||
"Emacs banner image.")
|
||||
|
||||
(defconst dashboard-banner-logo-png
|
||||
(concat dashboard-banners-directory "logo.png")
|
||||
"Emacs banner image.")
|
||||
@@ -261,7 +278,7 @@ nerd-icons or (all-the-icons-faicon \"newspaper-o\") using all-the-icons."
|
||||
:group 'dashboard)
|
||||
|
||||
(defcustom dashboard-banner-ascii "EMACS"
|
||||
"String to be shown in place of the startup banner
|
||||
"String to be shown in place of the startup banner.
|
||||
if `dashboard-startup-banner' is set to `ascii'."
|
||||
:type 'string
|
||||
:group 'dashboard)
|
||||
@@ -409,6 +426,29 @@ It can be a string or a string list for display random icons."
|
||||
Value can be
|
||||
- \\='official displays the official Emacs logo.
|
||||
- \\='logo displays an alternative Emacs logo.
|
||||
The logo can be displayed as a PNG image, or
|
||||
using unicode braille, depending on if Emacs is
|
||||
running as a GUI or in no-window mode.
|
||||
Assumes that the installed font includes braille.
|
||||
- \\='ascii: displays the logo using ASCII characters.
|
||||
- \\='logo-ansi-truecolor displays the logo using 24 bit
|
||||
ANSI color escape sequences, or using unicode braille,
|
||||
depending on what your device supports.
|
||||
Assumes that the installed font includes braille.
|
||||
Assumes the installed font includes block characters,
|
||||
without adding gaps around the edges of the cell.
|
||||
See Terminal Image Viewer README for more information:
|
||||
https://github.com/stefanhaustein/TerminalImageViewer
|
||||
- \\='logo-ansi-256color displays the logo using 256 color
|
||||
ANSI color escape sequences, or using unicode braille,
|
||||
depending on what your device supports.
|
||||
Assumes that the installed font includes braille.
|
||||
Assumes the installed font includes block characters,
|
||||
without adding gaps around the edges of the cell.
|
||||
See Terminal Image Viewer README for more information:
|
||||
https://github.com/stefanhaustein/TerminalImageViewer
|
||||
- \\='logo-braille displays the logo using unicode braille.
|
||||
Assumes that the installed font includes braille.
|
||||
- an integer which displays one of the text banners.
|
||||
- a string that specifies the path of an custom banner
|
||||
supported files types are gif/image/text/xbm.
|
||||
@@ -419,6 +459,9 @@ Value can be
|
||||
:type '(choice (const :tag "official" official)
|
||||
(const :tag "logo" logo)
|
||||
(const :tag "ascii" ascii)
|
||||
(const :tag "logo-ansi-truecolor" logo-ansi-truecolor)
|
||||
(const :tag "logo-ansi-256color" logo-ansi-256color)
|
||||
(const :tag "logo-braille" logo-braille)
|
||||
(integer :tag "index of a text banner")
|
||||
(string :tag "path to an image or text banner")
|
||||
(cons :tag "image and text banner"
|
||||
@@ -429,6 +472,9 @@ Value can be
|
||||
(const :tag "official" official)
|
||||
(const :tag "logo" logo)
|
||||
(const :tag "ascii" ascii)
|
||||
(const :tag "logo-ansi-truecolor" logo-ansi-truecolor)
|
||||
(const :tag "logo-ansi-256color" logo-ansi-256color)
|
||||
(const :tag "logo-braille" logo-braille)
|
||||
(integer :tag "index of a text banner"))))
|
||||
:group 'dashboard)
|
||||
|
||||
@@ -589,7 +635,7 @@ Set to nil for unbounded."
|
||||
;; TODO: Use function `string-pixel-width' after 29.1
|
||||
(defun dashboard-string-pixel-width (str)
|
||||
"Return the width of STR in pixels."
|
||||
(if (fboundp #'string-pixel-width)
|
||||
(if (fboundp 'string-pixel-width)
|
||||
(string-pixel-width str)
|
||||
(require 'shr)
|
||||
(shr-string-pixel-width str)))
|
||||
@@ -623,9 +669,7 @@ Set to nil for unbounded."
|
||||
search-label
|
||||
&optional no-next-line)
|
||||
"Insert a shortcut SHORTCUT-CHAR for a given SEARCH-LABEL.
|
||||
|
||||
SHORTCUT-ID is the section identifier.
|
||||
|
||||
Optionally, provide NO-NEXT-LINE to move the cursor forward a line."
|
||||
(let* (;; Ensure punctuation and upper case in search string is not
|
||||
;; used to construct the `defun'
|
||||
@@ -633,7 +677,6 @@ Optionally, provide NO-NEXT-LINE to move the cursor forward a line."
|
||||
;; remove symbol quote
|
||||
(sym (intern (replace-regexp-in-string "'" "" (format "dashboard-jump-to-%s" shortcut-id)))))
|
||||
`(progn
|
||||
(eval-when-compile (defvar dashboard-mode-map))
|
||||
(defun ,sym nil
|
||||
,(concat "Jump to " name ".
|
||||
This code is dynamically generated in `dashboard-insert-shortcut'.")
|
||||
@@ -643,7 +686,16 @@ This code is dynamically generated in `dashboard-insert-shortcut'.")
|
||||
,@(unless no-next-line '((forward-line 1)))
|
||||
(back-to-indentation))
|
||||
(eval-after-load 'dashboard
|
||||
(define-key dashboard-mode-map ,shortcut-char ',sym)))))
|
||||
(dashboard--define-shorcut-key-binding ,shortcut-id ,shortcut-char)))))
|
||||
|
||||
(defun dashboard--define-shorcut-key-binding (section keybinding)
|
||||
"Set `cycle-section's function for SECTION to KEYBINDING.
|
||||
in `dashboard-mode-map'."
|
||||
(define-key dashboard-mode-map (kbd keybinding)
|
||||
(dashboard-cycle-section-forward section))
|
||||
(define-key dashboard-mode-map
|
||||
(kbd (upcase keybinding))
|
||||
(dashboard-cycle-section-backward section)))
|
||||
|
||||
(defun dashboard-append (msg &optional _messagebuf)
|
||||
"Append MSG to dashboard buffer.
|
||||
@@ -735,7 +787,17 @@ When called with TIMES return a function that insert TIMES number of newlines."
|
||||
('logo
|
||||
(append (when (image-type-available-p 'png)
|
||||
(list :image dashboard-banner-logo-png))
|
||||
(list :text (dashboard-get-banner-path 1))))
|
||||
(list :text dashboard-banner-logo-braille)))
|
||||
('logo-ansi-truecolor
|
||||
(append (when (>= (display-color-cells) (expt 2 24))
|
||||
(list :text dashboard-banner-logo-ansi-truecolor))
|
||||
(list :text dashboard-banner-logo-braille)))
|
||||
('logo-ansi-256color
|
||||
(append (when (>= (display-color-cells) 256)
|
||||
(list :text dashboard-banner-logo-ansi-256color))
|
||||
(list :text dashboard-banner-logo-braille)))
|
||||
('logo-braille
|
||||
(append (list :text dashboard-banner-logo-braille)))
|
||||
('ascii
|
||||
(append (list :text dashboard-banner-ascii)))
|
||||
((pred integerp)
|
||||
@@ -809,6 +871,10 @@ Argument IMAGE-PATH path to the image."
|
||||
(if (file-exists-p txt)
|
||||
(insert-file-contents txt)
|
||||
(insert txt)))
|
||||
;; escape sequences will throw off text-width, must be done before
|
||||
(when (member txt (list dashboard-banner-logo-ansi-256color
|
||||
dashboard-banner-logo-ansi-truecolor))
|
||||
(ansi-color-apply-on-region start (point-max)))
|
||||
(put-text-property start (point-max) 'face 'dashboard-text-banner)
|
||||
(setq text-width (dashboard--find-max-width start (point-max)))
|
||||
(goto-char (point-max)))
|
||||
@@ -955,33 +1021,39 @@ Return a space if icon is not found."
|
||||
;;; Section list
|
||||
|
||||
(defmacro dashboard-insert-section-list (section-name list action &rest rest)
|
||||
"Insert into SECTION-NAME a LIST of items, expanding ACTION and passing REST
|
||||
to widget creation."
|
||||
"Insert into SECTION-NAME a LIST of items, expanding ACTION.
|
||||
REST is for widget creation."
|
||||
`(when (car ,list)
|
||||
(mapc
|
||||
(lambda (el)
|
||||
(let ((tag ,@rest))
|
||||
(let* ((tag ,@rest)
|
||||
(item tag))
|
||||
(insert "\n")
|
||||
(insert (spaces-string (or standard-indent tab-width 4)))
|
||||
|
||||
(when (and (dashboard-display-icons-p)
|
||||
dashboard-set-file-icons)
|
||||
(let* ((path (car (last (split-string ,@rest " - "))))
|
||||
(icon (if (and (not (file-remote-p path))
|
||||
(file-directory-p path))
|
||||
(dashboard-icon-for-dir path
|
||||
:height dashboard-icon-file-height
|
||||
:v-adjust dashboard-icon-file-v-adjust)
|
||||
(cond
|
||||
(let* ((path (get-text-property 0 'dashboard-path item))
|
||||
(icon (cond
|
||||
((or (string-equal ,section-name "Agenda for today:")
|
||||
(string-equal ,section-name "Agenda for the coming week:"))
|
||||
dashboard-agenda-item-icon)
|
||||
((file-remote-p path)
|
||||
((and (stringp path)
|
||||
(file-remote-p path))
|
||||
dashboard-remote-path-icon)
|
||||
(t (dashboard-icon-for-file (file-name-nondirectory path)
|
||||
((and (stringp path)
|
||||
(file-directory-p path))
|
||||
(dashboard-icon-for-dir
|
||||
path
|
||||
:height dashboard-icon-file-height
|
||||
:v-adjust dashboard-icon-file-v-adjust))))))
|
||||
(setq tag (concat icon " " ,@rest))))
|
||||
:v-adjust dashboard-icon-file-v-adjust))
|
||||
((stringp path)
|
||||
(dashboard-icon-for-file
|
||||
(file-name-nondirectory path)
|
||||
:height dashboard-icon-file-height
|
||||
:v-adjust dashboard-icon-file-v-adjust))
|
||||
(t ""))))
|
||||
(setq tag (concat icon " " item))))
|
||||
|
||||
(widget-create 'item
|
||||
:tag tag
|
||||
@@ -992,7 +1064,6 @@ to widget creation."
|
||||
:button-suffix ""
|
||||
:format "%[%t%]")))
|
||||
,list)))
|
||||
|
||||
;;
|
||||
;;; Footer
|
||||
|
||||
@@ -1198,6 +1269,26 @@ to widget creation."
|
||||
(defvar dashboard--recentf-cache-item-format nil
|
||||
"Cache to record the new generated align format.")
|
||||
|
||||
(defun dashboard-recentf--propertize-item (el)
|
||||
"Format EL from `dashboard-recentf-alist' and attach its real path."
|
||||
(let* ((file (dashboard-expand-path-alist el dashboard-recentf-alist))
|
||||
(filename (dashboard-f-filename file))
|
||||
(path (dashboard-extract-key-path-alist el dashboard-recentf-alist))
|
||||
(display
|
||||
(cl-case dashboard-recentf-show-base
|
||||
(`align
|
||||
(unless dashboard--recentf-cache-item-format
|
||||
(let* ((len-align (dashboard--align-length-by-type 'recents))
|
||||
(new-fmt (dashboard--generate-align-format
|
||||
dashboard-recentf-item-format len-align)))
|
||||
(setq dashboard--recentf-cache-item-format new-fmt)))
|
||||
(format dashboard--recentf-cache-item-format filename path))
|
||||
(`nil path)
|
||||
(t (format dashboard-recentf-item-format filename path)))))
|
||||
(if file
|
||||
(propertize display 'dashboard-path file)
|
||||
display)))
|
||||
|
||||
(defun dashboard-insert-recents (list-size)
|
||||
"Add the list of LIST-SIZE items from recently edited files."
|
||||
(setq dashboard--recentf-cache-item-format nil)
|
||||
@@ -1212,20 +1303,9 @@ to widget creation."
|
||||
'recents
|
||||
(dashboard-get-shortcut 'recents)
|
||||
`(lambda (&rest _)
|
||||
(find-file-existing (dashboard-expand-path-alist ,el dashboard-recentf-alist)))
|
||||
(let* ((file (dashboard-expand-path-alist el dashboard-recentf-alist))
|
||||
(filename (dashboard-f-filename file))
|
||||
(path (dashboard-extract-key-path-alist el dashboard-recentf-alist)))
|
||||
(cl-case dashboard-recentf-show-base
|
||||
(`align
|
||||
(unless dashboard--recentf-cache-item-format
|
||||
(let* ((len-align (dashboard--align-length-by-type 'recents))
|
||||
(new-fmt (dashboard--generate-align-format
|
||||
dashboard-recentf-item-format len-align)))
|
||||
(setq dashboard--recentf-cache-item-format new-fmt)))
|
||||
(format dashboard--recentf-cache-item-format filename path))
|
||||
(`nil path)
|
||||
(t (format dashboard-recentf-item-format filename path))))))
|
||||
(find-file-existing
|
||||
(dashboard-expand-path-alist ,el dashboard-recentf-alist)))
|
||||
(dashboard-recentf--propertize-item el)))
|
||||
|
||||
;;
|
||||
;;; Bookmarks
|
||||
@@ -1246,6 +1326,31 @@ to widget creation."
|
||||
(defvar dashboard--bookmarks-cache-item-format nil
|
||||
"Cache to record the new generated align format.")
|
||||
|
||||
(defun dashboard-bookmarks--format-name-and-path (filename short-path)
|
||||
"Format FILENAME and SHORT-PATH according to `dashboard-bookmarks-show-base'.
|
||||
Populate cache if needed."
|
||||
(cl-case dashboard-bookmarks-show-base
|
||||
(`align
|
||||
(unless dashboard--bookmarks-cache-item-format
|
||||
(let* ((len-align (dashboard--align-length-by-type 'bookmarks))
|
||||
(new-fmt (dashboard--generate-align-format
|
||||
dashboard-bookmarks-item-format len-align)))
|
||||
(setq dashboard--bookmarks-cache-item-format new-fmt)))
|
||||
(format dashboard--bookmarks-cache-item-format filename short-path))
|
||||
(`nil short-path)
|
||||
(t (format dashboard-bookmarks-item-format filename short-path))))
|
||||
|
||||
(defun dashboard-bookmarks--propertize-name-and-path (bookmark)
|
||||
"Format BOOKMARK before insertion.
|
||||
Get path and name from bookmark and add `dashboard-bookmarks-name' to properties"
|
||||
(if-let* ((path (bookmark-get-filename bookmark))
|
||||
(short-path (dashboard-shorten-path path 'bookmarks)))
|
||||
(propertize (dashboard-bookmarks--format-name-and-path
|
||||
bookmark short-path)
|
||||
'dashboard-bookmarks-name bookmark
|
||||
'dashboard-path path)
|
||||
bookmark))
|
||||
|
||||
(defun dashboard-insert-bookmarks (list-size)
|
||||
"Add the list of LIST-SIZE items of bookmarks."
|
||||
(require 'bookmark)
|
||||
@@ -1256,20 +1361,7 @@ to widget creation."
|
||||
'bookmarks
|
||||
(dashboard-get-shortcut 'bookmarks)
|
||||
`(lambda (&rest _) (bookmark-jump ,el))
|
||||
(if-let* ((filename el)
|
||||
(path (bookmark-get-filename el))
|
||||
(path-shorten (dashboard-shorten-path path 'bookmarks)))
|
||||
(cl-case dashboard-bookmarks-show-base
|
||||
(`align
|
||||
(unless dashboard--bookmarks-cache-item-format
|
||||
(let* ((len-align (dashboard--align-length-by-type 'bookmarks))
|
||||
(new-fmt (dashboard--generate-align-format
|
||||
dashboard-bookmarks-item-format len-align)))
|
||||
(setq dashboard--bookmarks-cache-item-format new-fmt)))
|
||||
(format dashboard--bookmarks-cache-item-format filename path-shorten))
|
||||
(`nil path-shorten)
|
||||
(t (format dashboard-bookmarks-item-format filename path-shorten)))
|
||||
el)))
|
||||
(dashboard-bookmarks--propertize-name-and-path el)))
|
||||
|
||||
;;
|
||||
;;; Projects
|
||||
@@ -1318,16 +1410,21 @@ be called with the root directory of the project to switch to."
|
||||
(let* ((file (dashboard-expand-path-alist el dashboard-projects-alist))
|
||||
(filename (dashboard-f-base file))
|
||||
(path (dashboard-extract-key-path-alist el dashboard-projects-alist)))
|
||||
(let ((display
|
||||
(cl-case dashboard-projects-show-base
|
||||
(`align
|
||||
(unless dashboard--projects-cache-item-format
|
||||
(let* ((len-align (dashboard--align-length-by-type 'projects))
|
||||
(let* ((len-align (dashboard--align-length-by-type
|
||||
'projects))
|
||||
(new-fmt (dashboard--generate-align-format
|
||||
dashboard-projects-item-format len-align)))
|
||||
(setq dashboard--projects-cache-item-format new-fmt)))
|
||||
(format dashboard--projects-cache-item-format filename path))
|
||||
(`nil path)
|
||||
(t (format dashboard-projects-item-format filename path))))))
|
||||
(t (format dashboard-projects-item-format filename path)))))
|
||||
(if file
|
||||
(propertize display 'dashboard-path file)
|
||||
display)))))
|
||||
|
||||
(defun dashboard-projects-backend-load-projects ()
|
||||
"Depending on `dashboard-projects-backend' load corresponding backend.
|
||||
@@ -1344,8 +1441,8 @@ Return function that returns a list of projects."
|
||||
(when dashboard-remove-missing-entry
|
||||
(dashboard-mute-apply
|
||||
(ignore-errors
|
||||
(dashboard-funcall-fboundp #'project-forget-zombie-projects))))
|
||||
(project-known-project-roots))
|
||||
(dashboard-funcall-fboundp 'project-forget-zombie-projects))))
|
||||
(dashboard-funcall-fboundp 'project-known-project-roots))
|
||||
(t
|
||||
(display-warning '(dashboard)
|
||||
"Invalid value for `dashboard-projects-backend'"
|
||||
@@ -1358,11 +1455,7 @@ over custom backends."
|
||||
(or dashboard-projects-switch-function
|
||||
(cl-case dashboard-projects-backend
|
||||
(`projectile 'projectile-switch-project-by-name)
|
||||
(`project-el
|
||||
(lambda (project)
|
||||
"This function is used to switch to `PROJECT'."
|
||||
(let ((default-directory project))
|
||||
(project-find-file))))
|
||||
(`project-el 'project-switch-project)
|
||||
(t
|
||||
(display-warning '(dashboard)
|
||||
"Invalid value for `dashboard-projects-backend'"
|
||||
@@ -1419,13 +1512,21 @@ each agenda entry."
|
||||
|
||||
(defcustom dashboard-agenda-tags-format 'identity
|
||||
"Function to format the org agenda tags.
|
||||
Any custom function would receives the tags from `org-get-tags'"
|
||||
Any custom function would receives the local tags from `org-get-tags'"
|
||||
:type '(choice
|
||||
(const :tag "Show tags" identity)
|
||||
(const :tag "Hide tags" ignore)
|
||||
(function :tag "Custom function"))
|
||||
:group 'dashboard)
|
||||
|
||||
(defcustom dashboard-agenda-tags-scope 'local
|
||||
"Scope when getting agenda tags for headline using `org-get-tags'."
|
||||
:type '(choice
|
||||
(const :tag "No tags" nil)
|
||||
(const :tag "Local tags (default)" local)
|
||||
(const :tag "Inherited tags" inherited))
|
||||
:group 'dashboard)
|
||||
|
||||
(defun dashboard-agenda-entry-format ()
|
||||
"Format agenda entry to show it on dashboard.
|
||||
|
||||
@@ -1481,9 +1582,14 @@ If not height is found on FACE or `dashboard-items-face' use `default'."
|
||||
(format-time-string dashboard-agenda-time-string-format time)))
|
||||
|
||||
(defun dashboard-agenda--formatted-tags ()
|
||||
"Apply `dashboard-agenda-tags-format' to org-element tags."
|
||||
"Apply `dashboard-agenda-tags-format' to the list of local `org-get-tags'."
|
||||
(when dashboard-agenda-tags-format
|
||||
(funcall dashboard-agenda-tags-format (org-get-tags))))
|
||||
(let ((tags (pcase dashboard-agenda-tags-scope
|
||||
((pred null) nil)
|
||||
('local (org-get-tags (point) t))
|
||||
('inherited (org-get-tags))
|
||||
(_ (user-error "Wrong value for `dashboard-agenda-tags-scope'")))))
|
||||
(funcall dashboard-agenda-tags-format tags))))
|
||||
|
||||
(defun dashboard-due-date-for-agenda ()
|
||||
"Return due-date for agenda period."
|
||||
|
||||
+44
-26
@@ -1,19 +1,19 @@
|
||||
;;; dashboard.el --- A startup screen extracted from Spacemacs -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (c) 2016-2025 emacs-dashboard maintainers
|
||||
;; Copyright (c) 2016-2026 emacs-dashboard maintainers
|
||||
;;
|
||||
;; Author : Rakan Al-Hneiti <rakan.alhneiti@gmail.com>
|
||||
;; Maintainer : Shen, Jen-Chieh <jcs090218@gmail.com>
|
||||
;; Ricardo Arredondo <ricardo.richo@gmail.com>
|
||||
;; URL : https://github.com/emacs-dashboard/emacs-dashboard
|
||||
;; URL : https://github.com/emacs-dashboard/dashboard
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; License: GPLv3
|
||||
;;
|
||||
;; Created: October 05, 2016
|
||||
;; Package-Version: 20250708.57
|
||||
;; Package-Revision: 8c2cf0cfde4f
|
||||
;; Package-Version: 20260402.436
|
||||
;; Package-Revision: 176d641a5554
|
||||
;; Keywords: startup, screen, tools, dashboard
|
||||
;; Package-Requires: ((emacs "27.1"))
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
;;
|
||||
;;; Externals
|
||||
|
||||
(declare-function bookmark-get-filename "ext:bookmark.el")
|
||||
(declare-function bookmark-all-names "ext:bookmark.el")
|
||||
(declare-function bookmark-get-filename "ext:bookmark.el")
|
||||
(declare-function bookmark-delete "ext:bookmark.el")
|
||||
(declare-function dashboard-ls--dirs "ext:dashboard-ls.el")
|
||||
(declare-function dashboard-ls--files "ext:dashboard-ls.el")
|
||||
(declare-function page-break-lines-mode "ext:page-break-lines.el")
|
||||
@@ -50,7 +51,6 @@
|
||||
"Extensible startup screen."
|
||||
:group 'applications)
|
||||
|
||||
;; Custom splash screen
|
||||
(defvar dashboard-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-p") #'dashboard-previous-line)
|
||||
@@ -273,32 +273,46 @@ example:
|
||||
(defun dashboard-cycle-section-forward (&optional section)
|
||||
"Cycle forward through the entries in SECTION.
|
||||
If SECTION is nil, cycle in the current section."
|
||||
(let ((target-section (or section (dashboard--current-section))))
|
||||
(if target-section
|
||||
(condition-case nil
|
||||
(progn
|
||||
(if section
|
||||
(lambda () "Cycle section forwards"
|
||||
(interactive)
|
||||
(widget-forward 1)
|
||||
(unless (eq target-section (dashboard--current-section))
|
||||
(dashboard--goto-section target-section)))
|
||||
(widget-forward 1))
|
||||
(widget-forward 1))))
|
||||
(unless (eq section (ignore-errors (dashboard--current-section)))
|
||||
(dashboard--goto-section section)))
|
||||
(lambda ()
|
||||
(interactive) "Cycle current-section forwards"
|
||||
(if (widget-at (point))
|
||||
(let ((current-section (ignore-errors (dashboard--current-section))))
|
||||
(widget-forward 1)
|
||||
(unless (eq current-section (ignore-errors (dashboard--current-section)))
|
||||
(dashboard--goto-section current-section)))
|
||||
(widget-forward 1)))))
|
||||
|
||||
(defun dashboard-cycle-section-backward (&optional section)
|
||||
"Cycle backward through the entries in SECTION.
|
||||
If SECTION is nil, cycle in the current section."
|
||||
(let ((target-section (or section (dashboard--current-section))))
|
||||
(if target-section
|
||||
(condition-case nil
|
||||
(progn
|
||||
(if section
|
||||
(lambda () "Cycle section backwards"
|
||||
(interactive)
|
||||
(widget-backward 1)
|
||||
(unless (eq target-section (dashboard--current-section))
|
||||
(progn
|
||||
(dashboard--goto-section target-section)
|
||||
(while (eq target-section (dashboard--current-section))
|
||||
(unless (eq section (ignore-errors (dashboard--current-section)))
|
||||
(dashboard--goto-section section)
|
||||
(while (eq section (ignore-errors (dashboard--current-section)))
|
||||
(widget-forward 1))
|
||||
(widget-backward 1)))
|
||||
(lambda () "Cycle current-section backwards"
|
||||
(interactive)
|
||||
(if (widget-at (point))
|
||||
(let ((current-section (ignore-errors (dashboard--current-section))))
|
||||
(widget-backward 1)
|
||||
(unless (eq current-section (ignore-errors (dashboard--current-section)))
|
||||
(dashboard--goto-section current-section)
|
||||
(unless (eq section (ignore-errors (dashboard--current-section)))
|
||||
(dashboard--goto-section section)
|
||||
(while (eq section (ignore-errors (dashboard--current-section)))
|
||||
(widget-forward 1))
|
||||
(widget-backward 1))))
|
||||
(widget-backward 1))
|
||||
(widget-backward 1))))
|
||||
(widget-backward 1)))))
|
||||
|
||||
(defun dashboard-section-1 ()
|
||||
"Navigate to section 1." (interactive) (dashboard--goto-section-by-index 1))
|
||||
@@ -429,7 +443,9 @@ Optional argument ARGS adviced function arguments."
|
||||
|
||||
(defun dashboard-remove-item-bookmarks ()
|
||||
"Remove a bookmarks from `bookmark-alist'."
|
||||
(interactive)) ; TODO: ..
|
||||
(interactive)
|
||||
(let ((bookmark-name (get-text-property (point) 'dashboard-bookmarks-name)))
|
||||
(bookmark-delete bookmark-name)))
|
||||
|
||||
(defun dashboard-remove-item-agenda ()
|
||||
"Remove an agenda from `org-agenda-files'."
|
||||
@@ -526,7 +542,9 @@ See `dashboard-item-generators' for all items available."
|
||||
"Insert the list of widgets into the buffer, FORCE-REFRESH is optional."
|
||||
(interactive)
|
||||
(let ((inhibit-redisplay t)
|
||||
(recentf-is-on (recentf-enabled-p))
|
||||
(recentf-is-on (or (recentf-enabled-p)
|
||||
(and (assq 'recents dashboard-items)
|
||||
(dashboard-mute-apply (recentf-mode 1)))))
|
||||
(origial-recentf-list recentf-list)
|
||||
(dashboard-num-recents (or (cdr (assoc 'recents dashboard-items)) 0)))
|
||||
(when recentf-is-on
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "diff-hl" "20251216.242"
|
||||
(define-package "diff-hl" "20260328.1925"
|
||||
"Highlight uncommitted changes using VC."
|
||||
'((cl-lib "0.2")
|
||||
(emacs "26.1"))
|
||||
:url "https://github.com/dgutov/diff-hl"
|
||||
:commit "e79aa49ad3cbbe85379cf6646db3aaacd3b04708"
|
||||
:revdesc "e79aa49ad3cb"
|
||||
:commit "b965e19e6e7f9933199e421849a49229207c1c9f"
|
||||
:revdesc "b965e19e6e7f"
|
||||
:keywords '("vc" "diff")
|
||||
:authors '(("Dmitry Gutov" . "dmitry@gutov.dev"))
|
||||
:maintainers '(("Dmitry Gutov" . "dmitry@gutov.dev")))
|
||||
|
||||
+27
-18
@@ -5,8 +5,8 @@
|
||||
;; Author: Dmitry Gutov <dmitry@gutov.dev>
|
||||
;; URL: https://github.com/dgutov/diff-hl
|
||||
;; Keywords: vc, diff
|
||||
;; Package-Version: 20251216.242
|
||||
;; Package-Revision: e79aa49ad3cb
|
||||
;; Package-Version: 20260328.1925
|
||||
;; Package-Revision: b965e19e6e7f
|
||||
;; Package-Requires: ((cl-lib "0.2") (emacs "26.1"))
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
@@ -143,6 +143,11 @@ enclosed in a `progn' form. ELSE-FORMS may be empty."
|
||||
:group 'diff-hl
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom diff-hl-next-previous-hunk-auto-recenter nil
|
||||
"Non-nil to `recenter' after `diff-hl-next-hunk' and `diff-hl-previous-hunk'."
|
||||
:group 'diff-hl
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom diff-hl-fallback-to-margin t
|
||||
"Non-nil to use margin instead of fringe on non-graphic displays.
|
||||
|
||||
@@ -316,10 +321,13 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or
|
||||
(expt text-scale-mode-step text-scale-mode-amount)
|
||||
1))
|
||||
(spacing (or (and (display-graphic-p) (default-value 'line-spacing)) 0))
|
||||
(total-spacing (pcase spacing
|
||||
((pred numberp) spacing)
|
||||
(`(,above . ,below) (+ above below))))
|
||||
(h (+ (ceiling (* (frame-char-height) scale))
|
||||
(if (floatp spacing)
|
||||
(truncate (* (frame-char-height) spacing))
|
||||
spacing)))
|
||||
(if (floatp total-spacing)
|
||||
(truncate (* (frame-char-height) total-spacing))
|
||||
total-spacing)))
|
||||
(w (min (frame-parameter nil (intern (format "%s-fringe" diff-hl-side)))
|
||||
diff-hl-bmp-max-width))
|
||||
(_ (when (zerop w) (setq w diff-hl-bmp-max-width)))
|
||||
@@ -483,11 +491,13 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or
|
||||
(hide-staged (and (eq backend 'Git) (not diff-hl-show-staged-changes))))
|
||||
(when backend
|
||||
(let ((state (vc-state file backend))
|
||||
;; Workaround for debbugs#78946.
|
||||
;; Workaround for debbugs#78946 for the `thread' async update method.
|
||||
;; This is fiddly, but we basically allow the thread to start, while
|
||||
;; prohibiting the async process call inside.
|
||||
;; That still makes it partially async.
|
||||
(diff-hl-update-async (and (not (eq window-system 'ns))
|
||||
;; That still makes it partially async on macOS.
|
||||
;; Or just use "simple async" if your Emacs is new enough.
|
||||
(diff-hl-update-async (or (and (eq diff-hl-update-async 'thread)
|
||||
(not (eq window-system 'ns)))
|
||||
(eq diff-hl-update-async t))))
|
||||
(cond
|
||||
((and
|
||||
@@ -581,11 +591,6 @@ contents as they are (or would be) after applying the changes in NEW."
|
||||
(setq old (cdr old)))
|
||||
ref))
|
||||
|
||||
(defun diff-hl-process-wait (buf)
|
||||
(let ((proc (get-buffer-process buf)))
|
||||
(while (process-live-p proc)
|
||||
(accept-process-output proc 0.01))))
|
||||
|
||||
(defun diff-hl-changes-from-buffer (buf)
|
||||
(with-current-buffer buf
|
||||
(let (res)
|
||||
@@ -765,8 +770,9 @@ Return a list of line overlays used."
|
||||
((eq (process-status proc) 'signal))
|
||||
;; If a process is running, set the sentinel.
|
||||
((eq (process-status proc) 'run)
|
||||
(set-process-sentinel
|
||||
proc
|
||||
(add-function
|
||||
:after
|
||||
(process-sentinel proc)
|
||||
(lambda (proc _status)
|
||||
;; Delegate to the parent cond for decision logic.
|
||||
(diff-hl--when-done buffer get-value callback proc))))
|
||||
@@ -1110,9 +1116,11 @@ its end position."
|
||||
"Go to the beginning of the next hunk in the current buffer."
|
||||
(interactive)
|
||||
(let ((overlay (diff-hl-search-next-hunk backward)))
|
||||
(if overlay
|
||||
(unless overlay
|
||||
(user-error "No further hunks found"))
|
||||
(goto-char (overlay-start overlay))
|
||||
(user-error "No further hunks found"))))
|
||||
(when diff-hl-next-previous-hunk-auto-recenter
|
||||
(recenter))))
|
||||
|
||||
(defun diff-hl-previous-hunk ()
|
||||
"Go to the beginning of the previous hunk in the current buffer."
|
||||
@@ -1120,7 +1128,8 @@ its end position."
|
||||
(diff-hl-next-hunk t))
|
||||
|
||||
(defun diff-hl-find-current-hunk ()
|
||||
(let (o)
|
||||
(let ((o)
|
||||
(diff-hl-next-previous-hunk-auto-recenter nil))
|
||||
(cond
|
||||
((diff-hl-hunk-overlay-at (point)))
|
||||
((setq o (diff-hl-search-next-hunk t))
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "emacsql" "20251130.1841"
|
||||
(define-package "emacsql" "20260401.1220"
|
||||
"High-level SQL database front-end."
|
||||
'((emacs "26.1"))
|
||||
:url "https://github.com/magit/emacsql"
|
||||
:commit "f177a41e93b92a4b1139a553eed5415ca33f439c"
|
||||
:revdesc "f177a41e93b9"
|
||||
:commit "2fe6d4562b32a170a750d5e80514fbb6b6694803"
|
||||
:revdesc "2fe6d4562b32"
|
||||
:authors '(("Christopher Wellons" . "wellons@nullprogram.com"))
|
||||
:maintainers '(("Jonas Bernoulli" . "emacs.emacsql@jonas.bernoulli.dev")))
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
;; Maintainer: Jonas Bernoulli <emacs.emacsql@jonas.bernoulli.dev>
|
||||
;; Homepage: https://github.com/magit/emacsql
|
||||
|
||||
;; Package-Version: 20251130.1841
|
||||
;; Package-Revision: f177a41e93b9
|
||||
;; Package-Version: 20260401.1220
|
||||
;; Package-Revision: 2fe6d4562b32
|
||||
;; Package-Requires: ((emacs "26.1"))
|
||||
|
||||
;; SPDX-License-Identifier: Unlicense
|
||||
@@ -38,7 +38,7 @@
|
||||
"The EmacSQL SQL database front-end."
|
||||
:group 'comm)
|
||||
|
||||
(defconst emacsql-version "4.3.3")
|
||||
(defconst emacsql-version "4.3.6")
|
||||
|
||||
(defvar emacsql-global-timeout 30
|
||||
"Maximum number of seconds to wait before bailing out on a SQL command.
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
(define-package "epl" "20180205.2049"
|
||||
"Emacs Package Library."
|
||||
'((cl-lib "0.3"))
|
||||
:url "http://github.com/cask/epl"
|
||||
:url "https://github.com/cask/epl"
|
||||
:commit "78ab7a85c08222cd15582a298a364774e3282ce6"
|
||||
:revdesc "78ab7a85c082"
|
||||
:keywords '("convenience")
|
||||
|
||||
+1
-1
@@ -16,4 +16,4 @@ File: dir, Node: Top This is the top of the INFO tree
|
||||
|
||||
Emacs
|
||||
* ESS: (ess). Emacs Speaks Statistics (R/S/S+, SAS,
|
||||
BUGS/JAGS and Stata).
|
||||
BUGS/NIMBLE and Stata).
|
||||
|
||||
+20
-10
@@ -58,18 +58,28 @@
|
||||
(cons "^[ \t]*\\(model\\|var\\)\\>"
|
||||
font-lock-keyword-face)
|
||||
|
||||
(cons (concat "\\<d\\(bern\\|beta\\|bin\\|cat\\|chisq\\|"
|
||||
"dexp\\|dirch\\|exp\\|\\(gen[.]\\)?gamma\\|hyper\\|"
|
||||
"interval\\|lnorm\\|logis\\|mnorm\\|mt\\|multi\\|"
|
||||
"negbin\\|norm\\(mix\\)?\\|par\\|pois\\|sum\\|t\\|"
|
||||
"unif\\|weib\\|wish\\)[ \t\n]*(")
|
||||
(cons (concat "\\<d\\(bern\\|beta\\|bin\\|binom\\|"
|
||||
"cat\\|chisq\\|chisqr\\|CRP\\|"
|
||||
"dexp\\|dirch\\|dirich\\|"
|
||||
"exp\\|\\(gen[.]\\|inv\\)?gamma\\|hyper\\|"
|
||||
"interval\\|lkj_corr_cholesky\\|laplace\\|lnorm\\|logis\\|"
|
||||
"mnorm\\|mt\\|multi\\|multinom\\|mvt\\|"
|
||||
"negbin\\|nbinom\\|norm\\(mix\\)?\\|par\\|pois\\|sum\\|t\\|"
|
||||
"unif\\|weib\\|weibull\\|\\(inv\\)?wish\\|wishart\\)[ \t\n]*(")
|
||||
font-lock-constant-face)
|
||||
|
||||
(cons (concat "\\<\\(abs\\|cos\\|C\\|dim\\|\\(i\\)?cloglog\\|equals\\|"
|
||||
"exp\\|for\\|inprod\\|interp[.]line\\|inverse\\|length\\|"
|
||||
"\\(i\\)?logit\\|logdet\\|logfact\\|loggam\\|max\\|mean\\|"
|
||||
"mexp\\|min\\|phi\\|pow\\|probit\\|prod\\|rank\\|round\\|"
|
||||
"sd\\|sin\\|sort\\|sqrt\\|step\\|sum\\|t\\|trunc\\|T\\)[ \t\n]*(")
|
||||
(cons (concat "\\<\\(abs\\|acos\\|acosh\\|asin\\|asinh\\|atan\\|atanh\\|"
|
||||
"asCol\\|asRow\\|backsolve\\|besselK\\|ceiling\\|chol\\|"
|
||||
"cos\\|C\\|dim\\|\\(i\\)?cloglog\\|cube\\|"
|
||||
"equals\\|exp\\|expm\\|expAv\\|expit\\|"
|
||||
"floor\\|for\\|forwardsolve\\|"
|
||||
"inprod\\|interp[.]lin\\(e\\)?\\|inverse\\|"
|
||||
"lgamma\\|length\\|lfactorial\\|"
|
||||
"log\\|log1p\\|\\(i\\)?logit\\|logdet\\|logfact\\|loggam\\|"
|
||||
"max\\|mean\\|mexp\\|min\\|pmax\\|pmin\\|"
|
||||
"phi\\|pow\\|\\(i\\)?probit\\|prod\\|rank\\|ranked\\|round\\|"
|
||||
"sd\\|sin\\|solve\\|sort\\|sqrt\\|step\\|sum\\|"
|
||||
"t\\|tan\\|trunc\\|T\\)[ \t\n]*(")
|
||||
font-lock-function-name-face)
|
||||
|
||||
;; .bmd files
|
||||
|
||||
+20
-19
@@ -29,14 +29,14 @@
|
||||
(require 'ess-utils)
|
||||
(defvar ess-bugs-command)
|
||||
(defvar ess-bugs-chains)
|
||||
(defvar ess-jags-command)
|
||||
(defvar ess-jags-chains)
|
||||
;;(defvar ess-jags-command)
|
||||
;;(defvar ess-jags-chains)
|
||||
(defvar ess-bugs-default-bins)
|
||||
|
||||
(declare-function ess-bugs-na-bug "ess-bugs-d")
|
||||
(declare-function ess-jags-na-bug "ess-jags-d")
|
||||
;;(declare-function ess-jags-na-bug "ess-jags-d")
|
||||
(declare-function ess-bugs-na-bmd "ess-bugs-d")
|
||||
(declare-function ess-jags-na-jmd "ess-jags-d")
|
||||
;;(declare-function ess-jags-na-jmd "ess-jags-d")
|
||||
|
||||
(defgroup ess-bugs nil
|
||||
"ESS: BUGS."
|
||||
@@ -140,8 +140,9 @@ Users whose default is not \\='sh, but are accessing a remote machine with
|
||||
(defvar ess-bugs-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (quote [f2]) #'ess-revert-wisely)
|
||||
(define-key map "\C-c\C-c" #'ess-bugs-next-action)
|
||||
(define-key map "=" #'ess-bugs-hot-arrow)
|
||||
;;(define-key map "\C-c\C-c" #'ess-bugs-next-action)
|
||||
(define-key map "<" #'ess-bugs-hot-arrow) ;; NIMBLE needs equals character
|
||||
;; (define-key map "=" #'ess-bugs-hot-arrow)
|
||||
;; (define-key map "_" #'ess-bugs-hot-arrow)
|
||||
map)
|
||||
"ESS[BUGS]: Keymap for mode.")
|
||||
@@ -191,20 +192,20 @@ and `ess-bugs-file-dir'."
|
||||
(interactive)
|
||||
(insert " <- "))
|
||||
|
||||
(defun ess-bugs-next-action ()
|
||||
"ESS[BUGS/JAGS]: Perform the appropriate next action."
|
||||
(interactive)
|
||||
(ess-bugs-file)
|
||||
;; (defun ess-bugs-next-action ()
|
||||
;; "ESS[BUGS/JAGS]: Perform the appropriate next action."
|
||||
;; (interactive)
|
||||
;; (ess-bugs-file)
|
||||
|
||||
(cond ((equal ".bug" ess-bugs-file-suffix) (ess-bugs-na-bug))
|
||||
((equal ".jag" ess-bugs-file-suffix) (ess-jags-na-bug))
|
||||
((equal ".bmd" ess-bugs-file-suffix)
|
||||
(ess-save-and-set-local-variables)
|
||||
(ess-bugs-na-bmd ess-bugs-command ess-bugs-chains))
|
||||
((equal ".jmd" ess-bugs-file-suffix)
|
||||
(ess-save-and-set-local-variables)
|
||||
(ess-jags-na-jmd ess-jags-command ess-jags-chains)))
|
||||
)
|
||||
;; (cond ((equal ".bug" ess-bugs-file-suffix) (ess-bugs-na-bug))
|
||||
;; ((equal ".jag" ess-bugs-file-suffix) (ess-jags-na-bug))
|
||||
;; ((equal ".bmd" ess-bugs-file-suffix)
|
||||
;; (ess-save-and-set-local-variables)
|
||||
;; (ess-bugs-na-bmd ess-bugs-command ess-bugs-chains))
|
||||
;; ((equal ".jmd" ess-bugs-file-suffix)
|
||||
;; (ess-save-and-set-local-variables)
|
||||
;; (ess-jags-na-jmd ess-jags-command ess-jags-chains)))
|
||||
;; )
|
||||
|
||||
(defun ess-bugs-sci-to-round-4-dp ()
|
||||
"ESS[BUGS]: round output from +/-0.000E+/-0 to 4 decimal places."
|
||||
|
||||
+15
-5
@@ -1,6 +1,6 @@
|
||||
;;; ess-custom.el --- Customize variables for ESS -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 1997-2025 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1997-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Rodney Sparapani
|
||||
;; Maintainer: ESS-help <ess-help@r-project.org>
|
||||
@@ -1571,11 +1571,21 @@ by `ess-function-template'."
|
||||
:group 'ess
|
||||
:type 'regexp)
|
||||
|
||||
(defcustom ess-r-outline-regexp
|
||||
"^[ \t]*#+ +.*\\(?:----\\|====\\|####\\)\\s-*$"
|
||||
"Regexp used to detect the beginning of R headings."
|
||||
(defcustom ess-r-outline-style 'none
|
||||
"Outline convention used by `ess-r-mode'.
|
||||
Choose between comment rulers like RStudio (\"### Section title ----\"),
|
||||
\"Org-like\" headings (\"### *** Section title\"), or no outline support.
|
||||
|
||||
When using the RStudio outline style, `ess-indent-with-fancy-comments'
|
||||
is automatically set to nil locally in the buffer. When switching back,
|
||||
the original local binding is restored; if the variable was not
|
||||
buffer-local, the current global default applies. You can also use
|
||||
(setq ess-style \\='RStudio) to achieve the same effect globally."
|
||||
:group 'ess-R
|
||||
:type 'regexp)
|
||||
:type '(choice (const :tag "No outline support" none)
|
||||
(const :tag "RStudio comment rulers" RStudio)
|
||||
(const :tag "Org-Like (### *** headings)" Org-like))
|
||||
:safe #'symbolp)
|
||||
|
||||
|
||||
; ess-inf: variables for inferior-ess.
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "ess" "20251212.937"
|
||||
(define-package "ess" "20260322.1703"
|
||||
"Emacs Speaks Statistics."
|
||||
'((emacs "25.1"))
|
||||
:url "https://ess.r-project.org/"
|
||||
:commit "e39ca8fa7fce703aa2851e83987a412737d575f0"
|
||||
:revdesc "e39ca8fa7fce"
|
||||
:commit "4e112590d1c13cfe464ca7de77837f1b956e4a9f"
|
||||
:revdesc "4e112590d1c1"
|
||||
:authors '(("David Smith" . "dsmith@stats.adelaide.edu.au")
|
||||
("A.J. Rossini" . "blindglobe@gmail.com")
|
||||
("Richard M. Heiberger" . "rmh@temple.edu")
|
||||
|
||||
+103
-5
@@ -1,6 +1,6 @@
|
||||
;;; ess-r-mode.el --- R customization -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 1997-2025 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 1997-2026 Free Software Foundation, Inc.
|
||||
;; Author: A.J. Rossini
|
||||
;; Created: 12 Jun 1997
|
||||
;; Maintainer: ESS-core <ESS-core@r-project.org>
|
||||
@@ -299,14 +299,111 @@ When t, loading a file into a namespaced will output information
|
||||
about which objects are exported and which stay hidden in the
|
||||
namespace.")
|
||||
|
||||
(defun ess-r-outline-level ()
|
||||
"R mode `outline-level` function."
|
||||
(defconst ess-r--outline-rstudio-regexp
|
||||
"^[ \t]*#+ +.*\\(?:----\\|====\\|####\\)\\s-*$"
|
||||
"R outline Regexp when `ess-r-outline-style' is `RStudio'.")
|
||||
|
||||
(defconst ess-r--outline-org-like-regexp
|
||||
"^\\(?:> \\)?###\\s-+\\(\\*+\\)\\s-+.*$"
|
||||
"R outline regexp used when `ess-r-outline-style' is `Org-like'.")
|
||||
|
||||
(defconst ess-r-outline-style-alist
|
||||
`((none
|
||||
(outline-regexp . "\\`a\\`")
|
||||
(outline-level . ,#'ess-r--outline-level-none))
|
||||
(RStudio
|
||||
(outline-regexp . ,ess-r--outline-rstudio-regexp)
|
||||
(outline-level . ,#'ess-r--outline-level-rstudio))
|
||||
(Org-like
|
||||
(outline-regexp . ,ess-r--outline-org-like-regexp)
|
||||
(outline-level . ,#'ess-r--outline-level-org-like)))
|
||||
"Mapping between outline styles and their regexp/level helpers.")
|
||||
|
||||
(defun ess-r--outline-style-definition (&optional style)
|
||||
"Return the style definition for STYLE, defaulting to `ess-r-outline-style'."
|
||||
(let ((style (or style ess-r-outline-style)))
|
||||
(or (assq style ess-r-outline-style-alist)
|
||||
(error "Unknown ESS outline style: %s" style))))
|
||||
|
||||
(defun ess-r--outline-style-value (key &optional style)
|
||||
"Return value for KEY in STYLE's definition."
|
||||
(cdr (assq key (cdr (ess-r--outline-style-definition style)))))
|
||||
|
||||
(defun ess-r--outline-level-rstudio ()
|
||||
"Compute outline level for `RStudio` style headings."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(if (looking-at "^[ \t]*\\(#+\\)\\s-")
|
||||
(length (match-string 1))
|
||||
1000)))
|
||||
|
||||
(defun ess-r--outline-level-org-like ()
|
||||
"Compute outline level for `Org-like` style headings."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(if (looking-at "^\\(?:> \\)?###\\s-+\\(\\*+\\)\\s-+")
|
||||
(length (match-string 1))
|
||||
1000)))
|
||||
|
||||
(defun ess-r--outline-level-none ()
|
||||
"Dummy outline level function for no outline support."
|
||||
1000)
|
||||
|
||||
(defun ess-r-outline-level ()
|
||||
"R mode `outline-level` dispatcher for the current outline style."
|
||||
(funcall (ess-r--outline-style-value 'outline-level)))
|
||||
|
||||
(defvar-local ess-r--saved-indent-with-fancy-comments nil
|
||||
"Saved state of `ess-indent-with-fancy-comments' before RStudio style.
|
||||
Stored as (VALUE . WAS-LOCAL) to restore both value and local binding.")
|
||||
|
||||
(defun ess-r-set-outline-style (&optional style)
|
||||
"Apply STYLE (or `ess-r-outline-style') to the current buffer.
|
||||
|
||||
When switching to RStudio style, `ess-indent-with-fancy-comments' is
|
||||
automatically set to nil locally. The previous value is saved and
|
||||
restored when switching to a different style."
|
||||
(interactive
|
||||
(list (intern (completing-read
|
||||
"Outline style"
|
||||
(mapcar (lambda (entry) (symbol-name (car entry)))
|
||||
ess-r-outline-style-alist)
|
||||
nil t nil nil
|
||||
(symbol-name (or ess-r-outline-style 'none))))))
|
||||
(let* ((style (or style ess-r-outline-style))
|
||||
(entry (ess-r--outline-style-definition style))
|
||||
(old-style ess-r-outline-style)
|
||||
(new-style (car entry)))
|
||||
;; Handle ess-indent-with-fancy-comments adjustment
|
||||
(cond
|
||||
;; Switching TO RStudio style
|
||||
((and (eq new-style 'RStudio)
|
||||
(not (eq old-style 'RStudio)))
|
||||
;; Save current value if not already saved
|
||||
(unless ess-r--saved-indent-with-fancy-comments
|
||||
(setq ess-r--saved-indent-with-fancy-comments
|
||||
(cons (if (local-variable-p 'ess-indent-with-fancy-comments)
|
||||
ess-indent-with-fancy-comments
|
||||
(default-value 'ess-indent-with-fancy-comments))
|
||||
(local-variable-p 'ess-indent-with-fancy-comments))))
|
||||
(setq-local ess-indent-with-fancy-comments nil))
|
||||
;; Switching FROM RStudio style to another
|
||||
((and (eq old-style 'RStudio)
|
||||
(not (eq new-style 'RStudio))
|
||||
ess-r--saved-indent-with-fancy-comments)
|
||||
;; Restore saved value and local state
|
||||
(let ((saved-value (car ess-r--saved-indent-with-fancy-comments))
|
||||
(saved-local (cdr ess-r--saved-indent-with-fancy-comments)))
|
||||
(if saved-local
|
||||
(setq-local ess-indent-with-fancy-comments saved-value)
|
||||
(when (local-variable-p 'ess-indent-with-fancy-comments)
|
||||
(kill-local-variable 'ess-indent-with-fancy-comments))))
|
||||
(setq ess-r--saved-indent-with-fancy-comments nil)))
|
||||
;; Apply outline style
|
||||
(setq-local ess-r-outline-style new-style)
|
||||
(setq-local outline-regexp (ess-r--outline-style-value 'outline-regexp style))
|
||||
(setq-local outline-level #'ess-r-outline-level)))
|
||||
|
||||
;; The syntax class for '\' is punctuation character to handle R 4.1
|
||||
;; lambdas. Inside strings it should be treated as an escape
|
||||
;; character which we ensure here.
|
||||
@@ -843,6 +940,8 @@ top level functions only."
|
||||
(setq-local electric-layout-rules '((?{ . after)))
|
||||
;; indentation
|
||||
(add-hook 'hack-local-variables-hook #'ess-set-style nil t)
|
||||
;; outline
|
||||
(add-hook 'hack-local-variables-hook #'ess-r-set-outline-style nil t)
|
||||
;; eldoc
|
||||
(ess--setup-eldoc #'ess-r-eldoc-function)
|
||||
;; auto-complete
|
||||
@@ -864,8 +963,7 @@ top level functions only."
|
||||
(when ess-imenu-use-S
|
||||
(imenu-add-to-menubar "Imenu-R"))
|
||||
;; outline
|
||||
(setq-local outline-level #'ess-r-outline-level)
|
||||
(setq-local outline-regexp ess-r-outline-regexp)
|
||||
(ess-r-set-outline-style)
|
||||
(setq-local beginning-of-defun-function #'ess-r-beginning-of-defun)
|
||||
(setq-local end-of-defun-function #'ess-r-end-of-defun)
|
||||
(ess-roxy-mode))
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ All Rd mode abbrevs start with a grave accent (`)."
|
||||
"dontshow" "donttest" "dots" "email" "emph" "enc" "env" "eqn" "figure" "file"
|
||||
"href"
|
||||
"ifelse" "if"
|
||||
"item" "kbd" "ldots" "linkS4class" "link" "method"
|
||||
"item" "kbd" "ldots" "linkS4class" "linkS4methods" "link" "method"
|
||||
"manual"
|
||||
"newcommand" "option" "out"
|
||||
"pkg" "sQuote" "renewcommand"
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@
|
||||
;;
|
||||
;; Maintainer: ESS Core Team <ESS-core@r-project.org>
|
||||
;; Created: 7 Jan 1994
|
||||
;; Package-Version: 20251212.937
|
||||
;; Package-Revision: e39ca8fa7fce
|
||||
;; Package-Version: 20260322.1703
|
||||
;; Package-Revision: 4e112590d1c1
|
||||
;; URL: https://ess.r-project.org/
|
||||
;; Package-Requires: ((emacs "25.1"))
|
||||
;; ESSR-Version: 1.8
|
||||
|
||||
+166
-286
@@ -1,8 +1,8 @@
|
||||
This is ess.info, produced by makeinfo version 7.2 from ess.texi.
|
||||
This is ess.info, produced by makeinfo version 7.3 from ess.texi.
|
||||
|
||||
INFO-DIR-SECTION Emacs
|
||||
START-INFO-DIR-ENTRY
|
||||
* ESS: (ess). Emacs Speaks Statistics (R/S/S+, SAS, BUGS/JAGS and Stata).
|
||||
* ESS: (ess). Emacs Speaks Statistics (R/S/S+, SAS, BUGS/NIMBLE and Stata).
|
||||
END-INFO-DIR-ENTRY
|
||||
|
||||
ESS -- Emacs Speaks Statistics
|
||||
@@ -14,7 +14,7 @@ File: ess.info, Node: Top, Next: Introduction, Up: (dir)
|
||||
ESS: Emacs Speaks Statistics
|
||||
****************************
|
||||
|
||||
ESS version 25.01.0
|
||||
ESS version 26.01.0
|
||||
|
||||
by A.J. Rossini,
|
||||
R.M. Heiberger,
|
||||
@@ -30,7 +30,7 @@ ESS version 25.01.0
|
||||
|
||||
Emacs Speaks Statistics (ESS) provides an intelligent, consistent
|
||||
interface between the user and the software. ESS interfaces with
|
||||
R, SAS, S-PLUS, BUGS/JAGS and other statistical analysis packages
|
||||
R, SAS, S-PLUS, BUGS/NIMBLE and other statistical analysis packages
|
||||
on GNU/Linux, other Unix-like systems such as macOS, and Microsoft
|
||||
Windows. ESS is itself a package within the Emacs text editor and
|
||||
uses Emacs features to streamline the creation and use of
|
||||
@@ -66,7 +66,6 @@ the file COPYING in the same directory as this file for more details.
|
||||
* ESS for R:: Overview of ESS features for the S family
|
||||
* ESS for SAS::
|
||||
* ESS for BUGS::
|
||||
* ESS for JAGS::
|
||||
* Mailing lists/bug reports:: How to get assistance with ESS
|
||||
* Customization:: Customizing ESS
|
||||
* Indices::
|
||||
@@ -79,7 +78,7 @@ File: ess.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top
|
||||
|
||||
ESS provides a generic interface, through Emacs, to statistical
|
||||
packages. It currently supports R (and the rest of the S family), SAS,
|
||||
BUGS/JAGS, Stata, and Julia with the level of support roughly in that
|
||||
BUGS/NIMBLE, Stata, and Julia with the level of support roughly in that
|
||||
order.
|
||||
|
||||
Throughout this manual, _Emacs_ refers to _GNU Emacs_ by the Free
|
||||
@@ -249,7 +248,14 @@ File: ess.info, Node: New features, Next: Credits, Prev: Features, Up: Intro
|
||||
1.2 New features in ESS
|
||||
=======================
|
||||
|
||||
Changes and New Features in 25.01.0:
|
||||
Changes and New Features in 26.01.0:
|
||||
• ESS[BUGS] is still relevant due to NIMBLE keeping the language
|
||||
alive. However, only syntax highlighting and key-presses will be
|
||||
supported moving forward. For example, the ‘<’ key now generates
|
||||
‘<-’ rather than the former ‘=’ since equals is a valid character
|
||||
in NIMBLE BUGS.
|
||||
|
||||
Changes and New Features in 25.01.0:
|
||||
|
||||
• polymode: In our transition from literate libraries (such as noweb
|
||||
documented below with respect to 19.04), we now recommend the
|
||||
@@ -3510,29 +3516,48 @@ File: ess.info, Node: Outline, Next: Toolbar, Prev: Imenu, Up: Extras
|
||||
R editing buffers integrate with ‘outline-minor-mode’. When you toggle
|
||||
the minor mode (for example via ‘M-x outline-minor-mode’ or by adding it
|
||||
to ‘ess-r-mode-hook’), ESS assigns ‘ess-r-outline-level’ to
|
||||
‘outline-level’ and installs ‘ess-r-outline-regexp’ so that comment
|
||||
headings drive folding. Lines that begin with one or more ‘#’, followed
|
||||
by text and a trailing marker of ‘----’, ‘====’, or ‘####’, are treated
|
||||
as outline headings. This matches the section markers convention
|
||||
adopted by RStudio.
|
||||
‘outline-level’ and configures ‘outline-regexp’ according to
|
||||
‘ess-r-outline-style’ so that comment headings drive folding. By
|
||||
default, outline support is disabled (‘none’), but you can enable it by
|
||||
setting ‘ess-r-outline-style’ to ‘RStudio’ or ‘Org-like’. With the
|
||||
‘RStudio’ style, lines that begin with one or more ‘#’, followed by text
|
||||
and a trailing marker of ‘----’, ‘====’, or ‘####’, are treated as
|
||||
outline headings. This matches the section markers convention adopted
|
||||
by RStudio.
|
||||
|
||||
# Setup ----
|
||||
## Data ----
|
||||
### Models ====
|
||||
#### Helpers ####
|
||||
|
||||
The number of leading ‘#’ characters sets the outline depth. Use
|
||||
standard Outline commands (such as ‘C-c C-t’) to cycle visibility once
|
||||
the minor mode is active. To enable Outlining automatically, add it to
|
||||
the R mode hook:
|
||||
The number of leading ‘#’ characters sets the outline depth. When
|
||||
using the RStudio outline style, ‘ess-indent-with-fancy-comments’ is
|
||||
automatically set to ‘nil’ locally in the buffer to prevent single-hash
|
||||
comments from being treated as right-margin comments with
|
||||
‘comment-column’ 40. When switching back to a different outline style,
|
||||
the original local binding is restored; if the variable was not
|
||||
buffer-local, the current global default applies.
|
||||
|
||||
Use standard Outline commands (such as ‘C-c C-t’) to cycle
|
||||
visibility once the minor mode is active. To enable Outlining
|
||||
automatically, add it to the R mode hook:
|
||||
|
||||
(add-hook 'ess-r-mode-hook #'outline-minor-mode)
|
||||
|
||||
-- User Option: ess-r-outline-regexp
|
||||
Regular expression used by ESS to recognise outline headings in R
|
||||
buffers. The default matches the RStudio-style sections shown
|
||||
above, but you can customise it if you prefer a different comment
|
||||
convention.
|
||||
-- User Option: ess-r-outline-style
|
||||
Select which outline convention ‘ess-r-mode’ should use. The
|
||||
default ‘none’ disables outline support to preserve backward
|
||||
compatibility. Set to ‘RStudio’ to recognise the comment rulers
|
||||
shown above, or choose ‘Org-like’ to match the ‘### * Section’
|
||||
pattern, inspired from org-mode:
|
||||
|
||||
### * Setup
|
||||
### ** Data
|
||||
### *** Models
|
||||
### **** Helpers
|
||||
|
||||
You can switch styles via ‘M-x ess-r-set-outline-style’ or by
|
||||
customizing this option.
|
||||
|
||||
|
||||
File: ess.info, Node: Toolbar, Next: Xref, Prev: Outline, Up: Extras
|
||||
@@ -3662,48 +3687,6 @@ polymode <https://github.com/polymode/poly-R/>,
|
||||
<https://polymode.github.io/>, or markdown-mode with edit-indirect
|
||||
<https://jblevins.org/projects/markdown-mode>.
|
||||
|
||||
ESS provides support for writing and processing Sweave
|
||||
(<https://leisch.userweb.mwn.de/Sweave/>), building up on Emacs'
|
||||
ess-noweb-mode for literate programming. When working on an Sweave
|
||||
document, the following key bindings are available:
|
||||
|
||||
-- Command: ess-swv-weave CHOOSE
|
||||
‘M-n s’ Run Sweave on the current .Rnw file. If CHOOSE is
|
||||
non-‘nil’, offer a menu of available weavers.
|
||||
|
||||
-- Command: ess-swv-latex
|
||||
‘M-n l’ Run LaTeX after Sweave'ing.
|
||||
|
||||
-- Command: ess-swv-PS
|
||||
‘M-n p’ Generate and display a postscript file after LaTeX'ing.
|
||||
|
||||
-- Command: ess-swv-PDF PDFLATEX-CMD
|
||||
‘M-n P’ Generate and display a PDF file after LaTeX'ing. Optional
|
||||
argument PDFLATEX-CMD is the command to use, which by default, is
|
||||
the command used to generate the PDF file is the first element of
|
||||
‘ess-swv-pdflatex-commands’.
|
||||
|
||||
-- User Option: ess-swv-pdflatex-commands
|
||||
Commands used by ‘ess-swv-PDF’ to run a version of pdflatex; the
|
||||
first entry is the default command.
|
||||
|
||||
Sweave'ing with ‘ess-swv-weave’ starts an inferior-ESS process, if
|
||||
one is not available. Other commands are available from the ‘Sweaving,
|
||||
Tangling, ...’ submenu of the Noweb menu.
|
||||
|
||||
AUCTeX (<https://www.gnu.org/software/auctex>) users may prefer to
|
||||
set the variable ‘ess-swv-plug-into-AUCTeX-p’ (available from the "ESS
|
||||
Sweave" customization group) to t. Alternatively, the same can be
|
||||
achieved by activating the entry "AUCTeX Interface" from the ‘Sweaving,
|
||||
Tangling, ...’ submenu, which toggles this variable on or off. When the
|
||||
interface is activated, new entries for Sweave'ing and LaTeX'ing
|
||||
thereafter are available from AUCTeX's "Command" menu. Sweave'ing can,
|
||||
thus, be done by ‘C-c C-c Sweave RET’ without an inferior-ESS process.
|
||||
Similarly, LaTeX'ing can be done by ‘C-c C-c LaTeXSweave RET’. In both
|
||||
cases, the process can be monitored with ‘C-c C-l’
|
||||
(‘TeX-recenter-output-buffer’). Open the viewer with ‘C-c C-v’
|
||||
(‘TeX-view’), as usual in AUCTeX.
|
||||
|
||||
|
||||
File: ess.info, Node: ESS for R, Next: ESS for SAS, Prev: Extras, Up: Top
|
||||
|
||||
@@ -4403,120 +4386,26 @@ File: ess.info, Node: ESS(SAS)--Windows, Prev: ESS(SAS)--Graphics, Up: ESS fo
|
||||
'submit-region' or paste them into SAS Display Manager.
|
||||
|
||||
|
||||
File: ess.info, Node: ESS for BUGS, Next: ESS for JAGS, Prev: ESS for SAS, Up: Top
|
||||
File: ess.info, Node: ESS for BUGS, Next: Mailing lists/bug reports, Prev: ESS for SAS, Up: Top
|
||||
|
||||
14 ESS for BUGS
|
||||
***************
|
||||
|
||||
ESS[BUGS] provides 5 features. First, BUGS syntax is described to allow
|
||||
for proper fontification of statements, distributions, functions,
|
||||
commands and comments in BUGS model files, command files and log files.
|
||||
Second, ESS creates templates for the command file from the model file
|
||||
so that a BUGS batch process can be defined by a single file. Third,
|
||||
ESS provides a BUGS batch script that allows ESS to set BUGS batch
|
||||
parameters. Fourth, key sequences are defined to create a command file
|
||||
and submit a BUGS batch process. Lastly, interactive submission of BUGS
|
||||
commands is also supported.
|
||||
ESS[BUGS] NIMBLE has re-vitalized the BUGS language. All previous
|
||||
instances of BUGS such as OpenBUGS and JAGS are now deprecated.
|
||||
Therefore, ESS suppors BUGS syntax to allow for proper fontification of
|
||||
statements, distributions, functions, commands and comments in
|
||||
BUGS/NIMBLE model files.
|
||||
|
||||
14.1 ESS[BUGS]-Model files
|
||||
==========================
|
||||
|
||||
Model files with the ‘.bug’ extension are edited in ESS[BUGS] mode.
|
||||
Three keys are bound for your use in ESS[BUGS], ‘F2’, ‘C-c C-c’ and ‘=’.
|
||||
‘F2’ performs the same action as it does in ESS[SAS], *Note
|
||||
ESS(SAS)--Function keys for batch processing::. ‘C-c C-c’ performs the
|
||||
function ‘ess-bugs-next-action’ which you will use a lot. Pressing it
|
||||
in an empty buffer for a model file will produce a template for you.
|
||||
‘=’ inserts the set operator, ‘<-’.
|
||||
|
||||
14.2 ESS[BUGS]-Command files
|
||||
============================
|
||||
|
||||
Files ending in ‘.bmd’ are used for BUGS command files. When you have
|
||||
finished editing your model file and press ‘C-c C-c’, a command file is
|
||||
created if one does not already exist. When you are finished editing
|
||||
your command file, pressing ‘C-c C-c’ again will submit your command
|
||||
file as a batch job.
|
||||
|
||||
14.3 ESS[BUGS]-Log files
|
||||
========================
|
||||
|
||||
The ‘.bog’ extension is used for BUGS log files. The command line
|
||||
generated by ESS creates the ‘.bog’ transcript file.
|
||||
|
||||
|
||||
File: ess.info, Node: ESS for JAGS, Next: Mailing lists/bug reports, Prev: ESS for BUGS, Up: Top
|
||||
File: ess.info, Node: Mailing lists/bug reports, Next: Customization, Prev: ESS for BUGS, Up: Top
|
||||
|
||||
15 ESS for JAGS
|
||||
***************
|
||||
|
||||
ESS[JAGS] provides 4 features. First, JAGS syntax is described to allow
|
||||
for proper fontification of statements, distributions, functions,
|
||||
commands and comments in JAGS model files, command files and log files.
|
||||
Second, ESS creates templates for the command file from the model file
|
||||
so that a JAGS batch process can be defined by a single file. Third,
|
||||
ESS provides a JAGS batch script that allows ESS to set JAGS batch
|
||||
parameters. Fourth, key sequences are defined to create a command file
|
||||
and submit a JAGS batch process.
|
||||
|
||||
15.1 ESS[JAGS]-Model files
|
||||
==========================
|
||||
|
||||
Files with the ‘.jag’ extension are edited in ESS[JAGS] mode. Three
|
||||
keys are bound for your use in ESS[JAGS], ‘F2’, ‘C-c C-c’ and ‘=’. ‘F2’
|
||||
performs the same action as it does in ESS[SAS], *Note
|
||||
ESS(SAS)--Function keys for batch processing::. ‘C-c C-c’ performs the
|
||||
function ‘ess-bugs-next-action’ which you will use a lot. Pressing it
|
||||
in an empty buffer for a model file will produce a template for you.
|
||||
‘=’ inserts the set operator, ‘<-’.
|
||||
|
||||
The first press of ‘C-c C-c’ will set up a template, including some
|
||||
necessary file-local variables in an empty buffer. These variables are
|
||||
‘ess-jags-chains’, ‘ess-jags-monitor’, ‘ess-jags-thin’,
|
||||
‘ess-jags-burnin’ and ‘ess-jags-update’; they appear in the ‘Local
|
||||
Variables’ section. When you are finished editing your model file,
|
||||
pressing ‘C-c C-c’ will perform the necessary actions to build your
|
||||
command file for you.
|
||||
|
||||
The ‘ess-jags-chains’ variable is the number of chains that you want
|
||||
to initialize and sample from; defaults to 1. The ‘ess-jags-monitor’
|
||||
variable is a list of variables that you want monitored: encase each
|
||||
variable in double quotes. When you press ‘C-c C-c’, the appropriate
|
||||
statements are created in the command file to monitor the list of
|
||||
variables. By default, no variables are explicitly monitored which
|
||||
means JAGS will implicitly monitor all "default" variables. The
|
||||
‘ess-jags-thin’ variable is the thinning parameter. By default, the
|
||||
thinning parameter is set to 1, i.e. no thinning. The
|
||||
‘ess-jags-burnin’ variable is the number of initial samples to discard.
|
||||
By default, the burnin parameter is set to 10000. The ‘ess-jags-update’
|
||||
variable is the number of post-burnin samples to keep. By default, the
|
||||
update parameter is set to 10000. Both ‘ess-jags-burnin’ and
|
||||
‘ess-jags-update’ are multiplied by ‘ess-jags-thin’ since JAGS does not
|
||||
do it automatically.
|
||||
|
||||
15.2 ESS[JAGS]-Command files
|
||||
============================
|
||||
|
||||
Files ending in ‘.jmd’ are for JAGS command files. For your ‘.jmd’
|
||||
file, there is only one variable, ‘ess-jags-command’, in the ‘Local
|
||||
Variables’ section. When you have finished editing your model file and
|
||||
press ‘C-c C-c’, a command file is created if one does not already
|
||||
exist. When you are finished editing your command file, pressing ‘C-c
|
||||
C-c’ again will submit your command file as a batch job. The
|
||||
‘ess-jags-command’ variable allows you to specify a different JAGS
|
||||
program to use to run your model; defaults to "jags".
|
||||
|
||||
15.3 ESS[JAGS]-Log files
|
||||
========================
|
||||
|
||||
The ‘.jog’ extension is used for JAGS log files. You may find ‘F2’
|
||||
useful to refresh the ‘.jog’ if the batch process over-writes or appends
|
||||
it.
|
||||
|
||||
|
||||
File: ess.info, Node: Mailing lists/bug reports, Next: Customization, Prev: ESS for JAGS, Up: Top
|
||||
|
||||
16 Bugs and Bug Reporting, Mailing Lists
|
||||
15 Bugs and Bug Reporting, Mailing Lists
|
||||
****************************************
|
||||
|
||||
* Menu:
|
||||
@@ -4529,7 +4418,7 @@ File: ess.info, Node: Mailing lists/bug reports, Next: Customization, Prev: E
|
||||
|
||||
File: ess.info, Node: Bugs, Next: Reporting Bugs, Up: Mailing lists/bug reports
|
||||
|
||||
16.1 Bugs
|
||||
15.1 Bugs
|
||||
=========
|
||||
|
||||
• Commands like ‘ess-display-help-on-object’ and list completion
|
||||
@@ -4569,7 +4458,7 @@ File: ess.info, Node: Bugs, Next: Reporting Bugs, Up: Mailing lists/bug repor
|
||||
|
||||
File: ess.info, Node: Reporting Bugs, Next: Mailing Lists, Prev: Bugs, Up: Mailing lists/bug reports
|
||||
|
||||
16.2 Reporting Bugs
|
||||
15.2 Reporting Bugs
|
||||
===================
|
||||
|
||||
Please post bug reports, suggestions etc. on our github issue tracker
|
||||
@@ -4594,7 +4483,7 @@ donations are also more than welcome.
|
||||
|
||||
File: ess.info, Node: Mailing Lists, Next: Help with Emacs, Prev: Reporting Bugs, Up: Mailing lists/bug reports
|
||||
|
||||
16.3 Mailing Lists
|
||||
15.3 Mailing Lists
|
||||
==================
|
||||
|
||||
There is a mailing list for discussions and announcements relating to
|
||||
@@ -4614,7 +4503,7 @@ this is a fairly low-volume mailing list.
|
||||
|
||||
File: ess.info, Node: Help with Emacs, Prev: Mailing Lists, Up: Mailing lists/bug reports
|
||||
|
||||
16.4 Help with Emacs
|
||||
15.4 Help with Emacs
|
||||
====================
|
||||
|
||||
Emacs is a complex editor with many abilities that we do not have space
|
||||
@@ -4726,9 +4615,6 @@ Key index
|
||||
* M-;: Indenting. (line 65)
|
||||
* M-?: Object names. (line 33)
|
||||
* M-C-q: Indenting. (line 49)
|
||||
* M-n l: Sweave and AUCTeX. (line 24)
|
||||
* M-n P: Sweave and AUCTeX. (line 30)
|
||||
* M-n s: Sweave and AUCTeX. (line 20)
|
||||
* M-RET: Resubmit. (line 10)
|
||||
* RET: Command-line editing. (line 10)
|
||||
* RET <1>: Resubmit. (line 18)
|
||||
@@ -4770,7 +4656,7 @@ Function and program index
|
||||
* dump(): Edit buffer. (line 35)
|
||||
* ess-change-directory: Package listing. (line 29)
|
||||
* ess-cleanup: Hot keys. (line 71)
|
||||
* ess-cleanup <1>: Help. (line 170)
|
||||
* ess-cleanup <1>: Help. (line 169)
|
||||
* ess-complete-object-name: Object names. (line 32)
|
||||
* ess-describe-help-mode: Help. (line 21)
|
||||
* ess-display-help-on-object: Hot keys. (line 65)
|
||||
@@ -4810,7 +4696,7 @@ Function and program index
|
||||
* ess-parse-errors: Hot keys. (line 54)
|
||||
* ess-parse-errors <1>: Error Checking. (line 9)
|
||||
* ess-quit: Hot keys. (line 70)
|
||||
* ess-quit <1>: Help. (line 170)
|
||||
* ess-quit <1>: Help. (line 169)
|
||||
* ess-R-complete-object-name: roxygen2. (line 80)
|
||||
* ess-r-outline-level: Outline. (line 6)
|
||||
* ess-r-package-list-available-packages: Package listing. (line 12)
|
||||
@@ -4843,10 +4729,6 @@ Function and program index
|
||||
* ess-submit-bug-report: Reporting Bugs. (line 6)
|
||||
* ess-switch-to-end-of-ESS: Help. (line 117)
|
||||
* ess-switch-to-inferior-or-script-buffer: Other. (line 12)
|
||||
* ess-swv-latex: Sweave and AUCTeX. (line 23)
|
||||
* ess-swv-PDF: Sweave and AUCTeX. (line 29)
|
||||
* ess-swv-PS: Sweave and AUCTeX. (line 26)
|
||||
* ess-swv-weave: Sweave and AUCTeX. (line 19)
|
||||
* ess-tracebug: ESS tracebug. (line 6)
|
||||
* ess-transcript-clean-region: Clean. (line 10)
|
||||
* ess-transcript-copy-command: Resubmit. (line 13)
|
||||
@@ -4913,14 +4795,13 @@ Variable index
|
||||
* ess-r-flymake-linters: ESS Flymake. (line 16)
|
||||
* ess-r-flymake-lintr-cache: ESS Flymake. (line 23)
|
||||
* ess-R-font-lock-keywords: Highlighting. (line 19)
|
||||
* ess-r-outline-regexp: Outline. (line 6)
|
||||
* ess-r-outline-regexp <1>: Outline. (line 27)
|
||||
* ess-r-outline-style: Outline. (line 6)
|
||||
* ess-r-outline-style <1>: Outline. (line 37)
|
||||
* ess-search-list: Source Directories. (line 62)
|
||||
* ess-source-directory: Source Directories. (line 22)
|
||||
* ess-style: Styles. (line 21)
|
||||
* ess-style-alist: Styles. (line 28)
|
||||
* ess-switch-to-end-of-proc-buffer: Other. (line 21)
|
||||
* ess-swv-pdflatex-commands: Sweave and AUCTeX. (line 35)
|
||||
* ess-use-eldoc: ESS ElDoc. (line 13)
|
||||
* ess-use-flymake: ESS Flymake. (line 12)
|
||||
* iESS program arguments: Customizing startup. (line 48)
|
||||
@@ -5091,111 +4972,110 @@ Concept Index
|
||||
|
||||
|
||||
Tag Table:
|
||||
Node: Top268
|
||||
Node: Introduction2906
|
||||
Node: Features5692
|
||||
Node: Current Features6518
|
||||
Node: New features10065
|
||||
Node: Credits37885
|
||||
Node: Manual41544
|
||||
Node: Installation44254
|
||||
Node: Installing from a third-party repository45191
|
||||
Node: Installing from source46138
|
||||
Node: Activating and Loading ESS47762
|
||||
Node: Check Installation48844
|
||||
Node: Interactive ESS49068
|
||||
Node: Starting up49913
|
||||
Node: Multiple ESS processes50673
|
||||
Node: ESS processes on Remote Computers51786
|
||||
Node: Customizing startup56013
|
||||
Node: Controlling buffer display58995
|
||||
Node: Entering commands61632
|
||||
Node: Command-line editing62794
|
||||
Node: Transcript64059
|
||||
Node: Last command65856
|
||||
Node: Process buffer motion67314
|
||||
Node: Transcript resubmit68857
|
||||
Node: Saving transcripts70854
|
||||
Node: Command History72688
|
||||
Node: Saving History76189
|
||||
Node: History expansion76970
|
||||
Node: Hot keys80361
|
||||
Node: Statistical Process running in ESS?84531
|
||||
Node: Emacsclient85878
|
||||
Node: Other86698
|
||||
Node: Evaluating code87741
|
||||
Node: Transcript Mode91673
|
||||
Node: Resubmit92846
|
||||
Node: Clean93921
|
||||
Node: Editing objects94921
|
||||
Node: Edit buffer96039
|
||||
Node: Loading98129
|
||||
Node: Error Checking99184
|
||||
Node: Indenting100257
|
||||
Node: Styles103409
|
||||
Node: Other edit buffer commands105911
|
||||
Node: Source Files107623
|
||||
Node: Source Directories112339
|
||||
Node: Help115548
|
||||
Node: Completion120250
|
||||
Node: Object names120465
|
||||
Node: Function arguments123179
|
||||
Node: Minibuffer completion124158
|
||||
Node: Company124656
|
||||
Node: Icicles125055
|
||||
Node: Developing with ESS126431
|
||||
Node: ESS tracebug126877
|
||||
Node: Getting started with tracebug129934
|
||||
Node: Editing documentation132220
|
||||
Node: R documentation files132772
|
||||
Node: roxygen2136587
|
||||
Node: Namespaced Evaluation141110
|
||||
Node: Extras143124
|
||||
Node: ESS ElDoc144216
|
||||
Node: ESS Flymake145796
|
||||
Node: Handy commands146926
|
||||
Node: Highlighting148203
|
||||
Node: Parens149254
|
||||
Node: Graphics149730
|
||||
Node: printer150401
|
||||
Node: X11151173
|
||||
Node: winjava151512
|
||||
Node: Imenu151924
|
||||
Node: Outline152779
|
||||
Node: Toolbar154091
|
||||
Node: Xref154501
|
||||
Node: Rdired154831
|
||||
Node: Package listing155910
|
||||
Node: Org157358
|
||||
Node: Sweave and AUCTeX158312
|
||||
Node: ESS for R160944
|
||||
Node: ESS(R)--Editing files161244
|
||||
Node: iESS(R)--Inferior ESS processes161749
|
||||
Node: Philosophies for using ESS(R)164468
|
||||
Node: Example ESS usage165395
|
||||
Node: ESS for SAS166799
|
||||
Node: ESS(SAS)--Design philosophy167526
|
||||
Node: ESS(SAS)--Editing files168463
|
||||
Node: ESS(SAS)--TAB key170407
|
||||
Node: ESS(SAS)--Batch SAS processes171821
|
||||
Node: ESS(SAS)--Function keys for batch processing177041
|
||||
Node: iESS(SAS)--Interactive SAS processes186948
|
||||
Node: iESS(SAS)--Common problems190890
|
||||
Node: ESS(SAS)--Graphics192504
|
||||
Node: ESS(SAS)--Windows193303
|
||||
Node: ESS for BUGS193887
|
||||
Node: ESS for JAGS195699
|
||||
Node: Mailing lists/bug reports199195
|
||||
Node: Bugs199459
|
||||
Node: Reporting Bugs201135
|
||||
Node: Mailing Lists202054
|
||||
Node: Help with Emacs202792
|
||||
Node: Customization203328
|
||||
Node: Indices204106
|
||||
Node: Key index204281
|
||||
Node: Function and program index209413
|
||||
Node: Variable index218979
|
||||
Node: Concept index222686
|
||||
Node: Top270
|
||||
Node: Introduction2893
|
||||
Node: Features5681
|
||||
Node: Current Features6507
|
||||
Node: New features10054
|
||||
Node: Credits38231
|
||||
Node: Manual41890
|
||||
Node: Installation44600
|
||||
Node: Installing from a third-party repository45537
|
||||
Node: Installing from source46484
|
||||
Node: Activating and Loading ESS48108
|
||||
Node: Check Installation49190
|
||||
Node: Interactive ESS49414
|
||||
Node: Starting up50259
|
||||
Node: Multiple ESS processes51019
|
||||
Node: ESS processes on Remote Computers52132
|
||||
Node: Customizing startup56359
|
||||
Node: Controlling buffer display59341
|
||||
Node: Entering commands61978
|
||||
Node: Command-line editing63140
|
||||
Node: Transcript64405
|
||||
Node: Last command66202
|
||||
Node: Process buffer motion67660
|
||||
Node: Transcript resubmit69203
|
||||
Node: Saving transcripts71200
|
||||
Node: Command History73034
|
||||
Node: Saving History76535
|
||||
Node: History expansion77316
|
||||
Node: Hot keys80707
|
||||
Node: Statistical Process running in ESS?84877
|
||||
Node: Emacsclient86224
|
||||
Node: Other87044
|
||||
Node: Evaluating code88087
|
||||
Node: Transcript Mode92019
|
||||
Node: Resubmit93192
|
||||
Node: Clean94267
|
||||
Node: Editing objects95267
|
||||
Node: Edit buffer96385
|
||||
Node: Loading98475
|
||||
Node: Error Checking99530
|
||||
Node: Indenting100603
|
||||
Node: Styles103755
|
||||
Node: Other edit buffer commands106257
|
||||
Node: Source Files107969
|
||||
Node: Source Directories112685
|
||||
Node: Help115894
|
||||
Node: Completion120596
|
||||
Node: Object names120811
|
||||
Node: Function arguments123525
|
||||
Node: Minibuffer completion124504
|
||||
Node: Company125002
|
||||
Node: Icicles125401
|
||||
Node: Developing with ESS126777
|
||||
Node: ESS tracebug127223
|
||||
Node: Getting started with tracebug130280
|
||||
Node: Editing documentation132566
|
||||
Node: R documentation files133118
|
||||
Node: roxygen2136933
|
||||
Node: Namespaced Evaluation141456
|
||||
Node: Extras143470
|
||||
Node: ESS ElDoc144562
|
||||
Node: ESS Flymake146142
|
||||
Node: Handy commands147272
|
||||
Node: Highlighting148549
|
||||
Node: Parens149600
|
||||
Node: Graphics150076
|
||||
Node: printer150747
|
||||
Node: X11151519
|
||||
Node: winjava151858
|
||||
Node: Imenu152270
|
||||
Node: Outline153125
|
||||
Node: Toolbar155358
|
||||
Node: Xref155768
|
||||
Node: Rdired156098
|
||||
Node: Package listing157177
|
||||
Node: Org158625
|
||||
Node: Sweave and AUCTeX159579
|
||||
Node: ESS for R160176
|
||||
Node: ESS(R)--Editing files160476
|
||||
Node: iESS(R)--Inferior ESS processes160981
|
||||
Node: Philosophies for using ESS(R)163700
|
||||
Node: Example ESS usage164627
|
||||
Node: ESS for SAS166031
|
||||
Node: ESS(SAS)--Design philosophy166758
|
||||
Node: ESS(SAS)--Editing files167695
|
||||
Node: ESS(SAS)--TAB key169639
|
||||
Node: ESS(SAS)--Batch SAS processes171053
|
||||
Node: ESS(SAS)--Function keys for batch processing176273
|
||||
Node: iESS(SAS)--Interactive SAS processes186180
|
||||
Node: iESS(SAS)--Common problems190122
|
||||
Node: ESS(SAS)--Graphics191736
|
||||
Node: ESS(SAS)--Windows192535
|
||||
Node: ESS for BUGS193119
|
||||
Node: Mailing lists/bug reports193675
|
||||
Node: Bugs193939
|
||||
Node: Reporting Bugs195615
|
||||
Node: Mailing Lists196534
|
||||
Node: Help with Emacs197272
|
||||
Node: Customization197808
|
||||
Node: Indices198586
|
||||
Node: Key index198761
|
||||
Node: Function and program index203674
|
||||
Node: Variable index212948
|
||||
Node: Concept index216582
|
||||
|
||||
End Tag Table
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
'((emacs "24.1")
|
||||
(s "1.7.0")
|
||||
(dash "2.2.0"))
|
||||
:url "http://github.com/rejeep/f.el"
|
||||
:url "https://github.com/rejeep/f.el"
|
||||
:commit "931b6d0667fe03e7bf1c6c282d6d8d7006143c52"
|
||||
:revdesc "931b6d0667fe"
|
||||
:keywords '("files" "directories")
|
||||
|
||||
@@ -254,7 +254,7 @@ argument to `flycheck-define-checker'.
|
||||
(fn SYMBOL CHECKER &optional FILE-NAME &rest CUSTOM-ARGS)" nil t)
|
||||
(function-put 'flycheck-def-config-file-var 'lisp-indent-function 3)
|
||||
(autoload 'flycheck-def-option-var "flycheck" "\
|
||||
Define SYMBOL as option variable with INIT-VALUE for CHECKER.
|
||||
Define SYMBOL as option variable with INIT-VALUE for CHECKERS.
|
||||
|
||||
SYMBOL is declared as customizable variable using `defcustom', to
|
||||
provide an option for the given syntax CHECKERS (a checker or a
|
||||
@@ -284,12 +284,7 @@ SYMBOL with `flycheck-def-executable-var'.
|
||||
|
||||
;;; Generated autoloads from flycheck-buttercup.el
|
||||
|
||||
(register-definition-prefixes "flycheck-buttercup" '("flycheck-buttercup-format-error-list"))
|
||||
|
||||
|
||||
;;; Generated autoloads from flycheck-ert.el
|
||||
|
||||
(register-definition-prefixes "flycheck-ert" '("flycheck-er"))
|
||||
(register-definition-prefixes "flycheck-buttercup" '("flycheck-buttercup-"))
|
||||
|
||||
;;; End of scraped data
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
(require 'buttercup)
|
||||
(require 'flycheck)
|
||||
(require 'seq)
|
||||
(require 'cl-lib)
|
||||
(require 'macroexp)
|
||||
|
||||
|
||||
;;; Buttercup helpers
|
||||
@@ -55,12 +57,14 @@
|
||||
;;; Data matchers
|
||||
|
||||
(buttercup-define-matcher :to-be-empty-string (s)
|
||||
"Match that S is an empty string."
|
||||
(let ((s (funcall s)))
|
||||
(if (equal s "")
|
||||
(cons t (format "Expected %S not be an empty string" s))
|
||||
(cons t (format "Expected %S not to be an empty string" s))
|
||||
(cons nil (format "Expected %S to be an empty string" s)))))
|
||||
|
||||
(buttercup-define-matcher :to-match-with-group (re s index match)
|
||||
"Match that regexp RE matches string S with MATCH in group INDEX."
|
||||
(let* ((re (funcall re))
|
||||
(s (funcall s))
|
||||
(index (funcall index))
|
||||
@@ -81,6 +85,7 @@
|
||||
;;; Emacs feature matchers
|
||||
|
||||
(buttercup-define-matcher :to-be-live (buffer)
|
||||
"Match that BUFFER is a live buffer."
|
||||
(let ((buffer (get-buffer (funcall buffer))))
|
||||
(if (buffer-live-p buffer)
|
||||
(cons t (format "Expected %S not to be a live buffer, but it is"
|
||||
@@ -89,6 +94,7 @@
|
||||
buffer)))))
|
||||
|
||||
(buttercup-define-matcher :to-be-visible (buffer)
|
||||
"Match that BUFFER is displayed in a window."
|
||||
(let ((buffer (get-buffer (funcall buffer))))
|
||||
(cond
|
||||
((and buffer (get-buffer-window buffer))
|
||||
@@ -104,6 +110,7 @@
|
||||
buffer))))))
|
||||
|
||||
(buttercup-define-matcher :to-be-local (symbol)
|
||||
"Match that SYMBOL is a buffer-local variable in the current buffer."
|
||||
(let ((symbol (funcall symbol)))
|
||||
(if (local-variable-p symbol)
|
||||
(cons t (format "Expected %S not to be a local variable, but it is"
|
||||
@@ -112,6 +119,7 @@
|
||||
symbol)))))
|
||||
|
||||
(buttercup-define-matcher :to-contain-match (buffer re)
|
||||
"Match that BUFFER contains text matching regexp RE."
|
||||
(let ((buffer (funcall buffer))
|
||||
(re (funcall re)))
|
||||
(if (not (get-buffer buffer))
|
||||
@@ -121,15 +129,16 @@ but is not a buffer" buffer re))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(if (re-search-forward re nil 'noerror)
|
||||
(cons t (format "Expected %S to contain a match \
|
||||
for %s, but it did not" buffer re))
|
||||
(cons nil (format "Expected %S not to contain a match for \
|
||||
%s but it did not." buffer re))))))))
|
||||
(cons t (format "Expected %S not to contain a match \
|
||||
for %s, but it did" buffer re))
|
||||
(cons nil (format "Expected %S to contain a match for \
|
||||
%s, but it did not." buffer re))))))))
|
||||
|
||||
|
||||
;;; Flycheck matchers
|
||||
|
||||
(buttercup-define-matcher :to-be-equal-flycheck-errors (a b)
|
||||
"Match that flycheck error lists A and B are equal."
|
||||
(let* ((a (funcall a))
|
||||
(b (funcall b))
|
||||
(a-formatted (flycheck-buttercup-format-error-list a))
|
||||
@@ -144,6 +153,426 @@ not to be equal to
|
||||
to be equal to
|
||||
%s" a-formatted b-formatted)))))
|
||||
|
||||
|
||||
;;; Internal variables
|
||||
|
||||
(defvar flycheck-buttercup--resource-directory nil
|
||||
"The directory to get resources from in this test suite.")
|
||||
|
||||
|
||||
;;; Resource management
|
||||
|
||||
(defun flycheck-buttercup-resource-filename (resource-file)
|
||||
"Determine the absolute file name of a RESOURCE-FILE.
|
||||
|
||||
Relative file names are expanded against
|
||||
`flycheck-buttercup--resource-directory'."
|
||||
(expand-file-name resource-file flycheck-buttercup--resource-directory))
|
||||
|
||||
(defun flycheck-buttercup-initialize (resource-dir)
|
||||
"Initialize a test suite with RESOURCE-DIR.
|
||||
|
||||
RESOURCE-DIR is the directory, `flycheck-buttercup-resource-filename'
|
||||
should use to lookup resource files."
|
||||
(when flycheck-buttercup--resource-directory
|
||||
(error "Test suite already initialized"))
|
||||
(setq flycheck-buttercup--resource-directory resource-dir))
|
||||
|
||||
|
||||
;;; Buffer utility macros
|
||||
|
||||
(defmacro flycheck-buttercup-with-temp-buffer (&rest body)
|
||||
"Eval BODY within a temporary buffer.
|
||||
|
||||
Like `with-temp-buffer', but resets the modification state of the
|
||||
temporary buffer to make sure that it is properly killed even if
|
||||
it has a backing file and is modified."
|
||||
(declare (indent 0) (debug t))
|
||||
`(with-temp-buffer
|
||||
(unwind-protect
|
||||
,(macroexp-progn body)
|
||||
;; Reset modification state of the buffer, and unlink it from its
|
||||
;; backing file, if any, because Emacs refuses to kill modified
|
||||
;; buffers with backing files, even if they are temporary.
|
||||
(set-buffer-modified-p nil)
|
||||
(set-visited-file-name nil 'no-query))))
|
||||
|
||||
(defmacro flycheck-buttercup-with-file-buffer (file-name &rest body)
|
||||
"Create a buffer from FILE-NAME and eval BODY.
|
||||
|
||||
BODY is evaluated with `current-buffer' being a buffer with the
|
||||
contents of FILE-NAME, its `visited-file-name' set to FILE-NAME,
|
||||
and `default-directory' set to the file's directory."
|
||||
(declare (indent 1) (debug t))
|
||||
`(let ((file-name ,file-name))
|
||||
(unless (file-exists-p file-name)
|
||||
(error "%s does not exist" file-name))
|
||||
(flycheck-buttercup-with-temp-buffer
|
||||
(insert-file-contents file-name 'visit)
|
||||
(set-visited-file-name file-name 'no-query)
|
||||
(cd (file-name-directory file-name))
|
||||
;; Mark the buffer as not modified, because we just loaded the
|
||||
;; file up to now.
|
||||
(set-buffer-modified-p nil)
|
||||
,@body)))
|
||||
|
||||
(defmacro flycheck-buttercup-with-help-buffer (&rest body)
|
||||
"Execute BODY and kill the help buffer afterwards.
|
||||
|
||||
Use this macro to test functions that create a Help buffer."
|
||||
(declare (indent 0))
|
||||
`(unwind-protect
|
||||
,(macroexp-progn body)
|
||||
(when (buffer-live-p (get-buffer (help-buffer)))
|
||||
(kill-buffer (help-buffer)))))
|
||||
|
||||
(defmacro flycheck-buttercup-with-global-mode (&rest body)
|
||||
"Execute BODY with Global Flycheck Mode enabled.
|
||||
|
||||
After BODY, restore the old state of Global Flycheck Mode."
|
||||
(declare (indent 0))
|
||||
`(let ((old-state global-flycheck-mode))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(global-flycheck-mode 1)
|
||||
,@body)
|
||||
(global-flycheck-mode (if old-state 1 -1)))))
|
||||
|
||||
(defmacro flycheck-buttercup-with-env (env &rest body)
|
||||
"Add ENV to `process-environment' in BODY.
|
||||
|
||||
Execute BODY with a `process-environment' which contains all
|
||||
variables from ENV added.
|
||||
|
||||
ENV is an alist, where each cons cell `(VAR . VALUE)' is a
|
||||
environment variable VAR to be added to `process-environment'
|
||||
with VALUE."
|
||||
(declare (indent 1))
|
||||
`(let ((process-environment (copy-sequence process-environment)))
|
||||
(pcase-dolist (`(,var . ,value) ,env)
|
||||
(setenv var value))
|
||||
,@body))
|
||||
|
||||
(defmacro flycheck-buttercup-with-resource-buffer (resource-file &rest body)
|
||||
"Create a temp buffer from a RESOURCE-FILE and execute BODY.
|
||||
|
||||
The absolute file name of RESOURCE-FILE is determined with
|
||||
`flycheck-buttercup-resource-filename'."
|
||||
(declare (indent 1))
|
||||
`(flycheck-buttercup-with-file-buffer
|
||||
(flycheck-buttercup-resource-filename ,resource-file)
|
||||
,@body))
|
||||
|
||||
|
||||
;;; Syntax checking in tests
|
||||
|
||||
(defvar-local flycheck-buttercup-syntax-checker-finished nil
|
||||
"Non-nil if the current checker has finished.")
|
||||
|
||||
(add-hook 'flycheck-after-syntax-check-hook
|
||||
(lambda ()
|
||||
(setq flycheck-buttercup-syntax-checker-finished t)))
|
||||
|
||||
(defconst flycheck-buttercup-checker-wait-time 10
|
||||
"Time to wait until a checker is finished in seconds.
|
||||
|
||||
After this time has elapsed, the checker is considered to have
|
||||
failed, and the test aborted with failure.")
|
||||
|
||||
(define-error 'flycheck-buttercup-syntax-check-timed-out
|
||||
"Syntax check timed out.")
|
||||
|
||||
(define-error 'flycheck-buttercup-suspicious-checker
|
||||
"Suspicious state from checker")
|
||||
|
||||
(defun flycheck-buttercup-wait-for-syntax-checker ()
|
||||
"Wait until the syntax check in the current buffer is finished.
|
||||
|
||||
Signal `flycheck-buttercup-syntax-check-timed-out' if the check
|
||||
does not complete within `flycheck-buttercup-checker-wait-time'
|
||||
seconds."
|
||||
(let ((starttime (float-time)))
|
||||
(while (and (not flycheck-buttercup-syntax-checker-finished)
|
||||
(< (- (float-time) starttime)
|
||||
flycheck-buttercup-checker-wait-time))
|
||||
(accept-process-output nil 0.02))
|
||||
(unless (< (- (float-time) starttime)
|
||||
flycheck-buttercup-checker-wait-time)
|
||||
(flycheck-stop)
|
||||
(signal 'flycheck-buttercup-syntax-check-timed-out nil)))
|
||||
(setq flycheck-buttercup-syntax-checker-finished nil))
|
||||
|
||||
(defun flycheck-buttercup-buffer-sync ()
|
||||
"Like `flycheck-buffer', but synchronously."
|
||||
(setq flycheck-buttercup-syntax-checker-finished nil)
|
||||
(expect (flycheck-running-p) :not :to-be-truthy)
|
||||
(flycheck-mode) ;; This will only start a deferred check,
|
||||
(expect (flycheck-get-checker-for-buffer) :to-be-truthy)
|
||||
(flycheck-buffer) ;; …so we need an explicit manual check
|
||||
;; After starting the check, the checker should either be running now, or
|
||||
;; already be finished (if it was fast).
|
||||
(expect (or flycheck-current-syntax-check
|
||||
flycheck-buttercup-syntax-checker-finished)
|
||||
:to-be-truthy)
|
||||
;; Also there should be no deferred check pending anymore
|
||||
(expect (flycheck-deferred-check-p) :not :to-be-truthy)
|
||||
(flycheck-buttercup-wait-for-syntax-checker))
|
||||
|
||||
(defun flycheck-buttercup-ensure-clear ()
|
||||
"Clear Flycheck errors and overlays from the current buffer.
|
||||
|
||||
Raise an assertion error if errors or overlays remain afterwards."
|
||||
(flycheck-clear)
|
||||
(expect flycheck-current-errors :not :to-be-truthy)
|
||||
(expect (seq-find (lambda (ov) (overlay-get ov 'flycheck-overlay))
|
||||
(overlays-in (point-min) (point-max)))
|
||||
:not :to-be-truthy))
|
||||
|
||||
|
||||
;;; Error utilities
|
||||
|
||||
(defun flycheck-buttercup-error-without-group (err)
|
||||
"Return a copy of ERR with the `group' property set to nil."
|
||||
(let ((copy (copy-flycheck-error err)))
|
||||
(setf (flycheck-error-group copy) nil)
|
||||
copy))
|
||||
|
||||
(defun flycheck-buttercup-sort-errors (errors)
|
||||
"Sort ERRORS by `flycheck-error-<'."
|
||||
(seq-sort #'flycheck-error-< errors))
|
||||
|
||||
|
||||
;;; Test assertions
|
||||
|
||||
(defun flycheck-buttercup-should-overlay (error)
|
||||
"Test that ERROR has a proper overlay in the current buffer.
|
||||
|
||||
ERROR is a Flycheck error object."
|
||||
(let* ((overlay (seq-find
|
||||
(lambda (ov)
|
||||
(equal (flycheck-buttercup-error-without-group
|
||||
(overlay-get ov 'flycheck-error))
|
||||
(flycheck-buttercup-error-without-group error)))
|
||||
(flycheck-overlays-in 0 (+ 1 (buffer-size)))))
|
||||
(region
|
||||
;; Overlays of errors from other files are on the first line
|
||||
(if (flycheck-relevant-error-other-file-p error)
|
||||
(cons (point-min)
|
||||
(save-excursion (goto-char (point-min))
|
||||
(line-end-position)))
|
||||
(flycheck-error-region-for-mode error 'symbols)))
|
||||
(level (flycheck-error-level error))
|
||||
(category (flycheck-error-level-overlay-category level))
|
||||
(face (get category 'face))
|
||||
(fringe-bitmap (flycheck-error-level-fringe-bitmap level))
|
||||
(fringe-face (flycheck-error-level-fringe-face level))
|
||||
(fringe-icon (list 'left-fringe fringe-bitmap fringe-face)))
|
||||
(expect overlay :to-be-truthy)
|
||||
(expect (overlay-get overlay 'flycheck-overlay) :to-be-truthy)
|
||||
(expect (overlay-start overlay) :to-equal (car region))
|
||||
(expect (overlay-end overlay) :to-equal (cdr region))
|
||||
(expect (overlay-get overlay 'face) :to-equal face)
|
||||
(expect (get-char-property 0 'display
|
||||
(overlay-get overlay 'before-string))
|
||||
:to-equal fringe-icon)
|
||||
(expect (overlay-get overlay 'category) :to-equal category)
|
||||
(expect (flycheck-buttercup-error-without-group
|
||||
(overlay-get overlay 'flycheck-error))
|
||||
:to-equal
|
||||
(flycheck-buttercup-error-without-group error))))
|
||||
|
||||
(defun flycheck-buttercup-should-errors (&rest errors)
|
||||
"Test that the current buffer has ERRORS.
|
||||
|
||||
ERRORS is a list of errors expected to be present in the current
|
||||
buffer. Each error is given as a list of arguments to
|
||||
`flycheck-error-new-at'.
|
||||
|
||||
If ERRORS are omitted, test that there are no errors at all in
|
||||
the current buffer.
|
||||
|
||||
With ERRORS, test that each error in ERRORS is present in the
|
||||
current buffer, and that the number of errors in the current
|
||||
buffer is equal to the number of given ERRORS. In other words,
|
||||
check that the buffer has all ERRORS, and no other errors."
|
||||
(let ((expected (flycheck-buttercup-sort-errors
|
||||
(mapcar (apply-partially #'apply #'flycheck-error-new-at)
|
||||
errors)))
|
||||
(current (flycheck-buttercup-sort-errors flycheck-current-errors)))
|
||||
(expect (mapcar #'flycheck-buttercup-error-without-group expected)
|
||||
:to-equal
|
||||
(mapcar #'flycheck-buttercup-error-without-group current))
|
||||
;; Check that related errors are the same
|
||||
(cl-mapcar
|
||||
(lambda (err1 err2)
|
||||
(expect (flycheck-buttercup-sort-errors
|
||||
(mapcar #'flycheck-buttercup-error-without-group
|
||||
(flycheck-related-errors err1 expected)))
|
||||
:to-equal
|
||||
(flycheck-buttercup-sort-errors
|
||||
(mapcar #'flycheck-buttercup-error-without-group
|
||||
(flycheck-related-errors err2)))))
|
||||
expected current)
|
||||
(mapc #'flycheck-buttercup-should-overlay expected))
|
||||
(expect (length errors)
|
||||
:to-equal
|
||||
(length (flycheck-overlays-in (point-min) (point-max)))))
|
||||
|
||||
(defun flycheck-buttercup-should-syntax-check-in-buffer (&rest errors)
|
||||
"Test a syntax check in the current buffer, expecting ERRORS.
|
||||
|
||||
This is like `flycheck-buttercup-should-syntax-check', but with a
|
||||
buffer in the right mode instead of a file."
|
||||
;; Load safe file-local variables because some tests depend on them
|
||||
(let ((enable-local-variables :safe)
|
||||
;; Disable all hooks at this place, to prevent 3rd party packages
|
||||
;; from interfering
|
||||
(hack-local-variables-hook))
|
||||
(hack-local-variables))
|
||||
;; Configure config file locating for unit tests
|
||||
(let ((process-hook-called 0)
|
||||
(suspicious nil))
|
||||
(add-hook 'flycheck-process-error-functions
|
||||
(lambda (_err)
|
||||
(setq process-hook-called (1+ process-hook-called))
|
||||
nil)
|
||||
nil :local)
|
||||
(add-hook 'flycheck-status-changed-functions
|
||||
(lambda (status)
|
||||
(when (eq status 'suspicious)
|
||||
(setq suspicious t)))
|
||||
nil :local)
|
||||
(flycheck-buttercup-buffer-sync)
|
||||
(when suspicious
|
||||
(signal 'flycheck-buttercup-suspicious-checker nil))
|
||||
(apply #'flycheck-buttercup-should-errors errors)
|
||||
(expect process-hook-called :to-equal (length errors)))
|
||||
(flycheck-buttercup-ensure-clear))
|
||||
|
||||
(defun flycheck-buttercup-should-syntax-check (resource-file modes &rest errors)
|
||||
"Test a syntax check in RESOURCE-FILE with MODES.
|
||||
|
||||
RESOURCE-FILE is the file to check. MODES is a single major mode
|
||||
symbol or a list thereof, specifying the major modes to syntax
|
||||
check with. If more than one major mode is specified, the test
|
||||
is run for each mode separately, so if you give three major
|
||||
modes, the entire test will run three times. ERRORS is the list
|
||||
of expected errors, as in `flycheck-buttercup-should-errors'. If
|
||||
omitted, the syntax check must not emit any errors. The errors
|
||||
are cleared after each test.
|
||||
|
||||
The syntax checker is selected via standard syntax checker
|
||||
selection. To test a specific checker, you need to set
|
||||
`flycheck-checker' or `flycheck-disabled-checkers' accordingly
|
||||
before using this predicate, depending on whether you want to use
|
||||
manual or automatic checker selection.
|
||||
|
||||
During the syntax check, configuration files of syntax checkers
|
||||
are also searched in the `config-files' sub-directory of the
|
||||
resource directory."
|
||||
(when (symbolp modes)
|
||||
(setq modes (list modes)))
|
||||
(dolist (mode modes)
|
||||
(unless (fboundp mode)
|
||||
(buttercup-skip (format "%S missing" mode)))
|
||||
(flycheck-buttercup-with-resource-buffer resource-file
|
||||
(funcall mode)
|
||||
(apply #'flycheck-buttercup-should-syntax-check-in-buffer errors))))
|
||||
|
||||
|
||||
;;; Additional matchers
|
||||
|
||||
(buttercup-define-matcher :to-be-at-flycheck-error (point-val n-val)
|
||||
"Match that POINT-VAL is at the N-VAL'th Flycheck error."
|
||||
(let* ((pt (funcall point-val))
|
||||
(n (funcall n-val))
|
||||
(error (nth (1- n) flycheck-current-errors))
|
||||
(mode flycheck-highlighting-mode)
|
||||
(region (flycheck-error-region-for-mode error mode))
|
||||
(at-error (and (member error (flycheck-overlay-errors-at pt))
|
||||
(= pt (car region)))))
|
||||
(if at-error
|
||||
(cons t (format "Expected point %s not to be at error %s, but it is"
|
||||
pt n))
|
||||
(let ((errors (flycheck-overlay-errors-at pt)))
|
||||
(if (null errors)
|
||||
(cons nil
|
||||
(format "Expected to be at error %s, but no error at point %s"
|
||||
n pt))
|
||||
(let ((pos (cl-position (car errors) flycheck-current-errors)))
|
||||
(cons nil
|
||||
(format "Expected to be at point %s and error %s, \
|
||||
but point %s is at error %s"
|
||||
(car (flycheck-error-region-for-mode
|
||||
(nth (1- n) flycheck-current-errors)
|
||||
flycheck-highlighting-mode))
|
||||
n pt (1+ pos)))))))))
|
||||
|
||||
|
||||
;;; Test case definitions
|
||||
|
||||
(defun flycheck-buttercup--parse-keys-and-body (keys-and-body)
|
||||
"Parse KEYS-AND-BODY into keyword-value pairs and body forms.
|
||||
|
||||
KEYS-AND-BODY is a list of alternating keyword-value pairs
|
||||
followed by body forms. Return a cons cell (KEYS . BODY)."
|
||||
(let ((keys nil)
|
||||
(body keys-and-body))
|
||||
(while (keywordp (car body))
|
||||
(let ((key (pop body))
|
||||
(val (pop body)))
|
||||
(push key keys)
|
||||
(push val keys)))
|
||||
(cons (nreverse keys) body)))
|
||||
|
||||
(defmacro flycheck-buttercup-def-checker-test (checker language name
|
||||
&rest keys-and-body)
|
||||
"Define a buttercup test case for a syntax CHECKER for LANGUAGE.
|
||||
|
||||
CHECKER is a symbol or a list of symbols denoting syntax checkers
|
||||
being tested by the test. The test case is skipped, if any of
|
||||
these checkers cannot be used. LANGUAGE is a symbol or a list of
|
||||
symbols denoting the programming languages supported by the
|
||||
syntax checkers. This is currently only used for naming the test
|
||||
appropriately.
|
||||
|
||||
NAME is a symbol denoting the local name of the test. The test
|
||||
itself is ultimately named
|
||||
`flycheck-define-checker/CHECKER/NAME'.
|
||||
|
||||
Optionally, the keyword arguments `:tags' and `:expected-result'
|
||||
may be given. `:expected-result :failed' will generate an `xit'
|
||||
instead of `it' to mark the test as pending.
|
||||
|
||||
The remaining forms KEYS-AND-BODY denote the body of the test
|
||||
case, including assertions and setup code."
|
||||
(declare (indent 3))
|
||||
(unless checker
|
||||
(error "No syntax checkers specified"))
|
||||
(unless language
|
||||
(error "No languages specified"))
|
||||
(let* ((checkers (if (symbolp checker) (list checker) checker))
|
||||
(checker (car checkers))
|
||||
(local-name (or name 'default))
|
||||
(full-name (format "flycheck-define-checker/%s/%s"
|
||||
checker local-name))
|
||||
(parsed (flycheck-buttercup--parse-keys-and-body keys-and-body))
|
||||
(keys (car parsed))
|
||||
(body (cdr parsed))
|
||||
(expected-result (plist-get keys :expected-result))
|
||||
(it-fn (if (eq expected-result :failed) 'xit 'it))
|
||||
(skip-forms (mapcar (lambda (c)
|
||||
`(assume
|
||||
;; Ignore non-command checkers
|
||||
(or (not (flycheck-checker-get ',c 'command))
|
||||
(executable-find
|
||||
(flycheck-checker-executable ',c)))))
|
||||
checkers)))
|
||||
`(,it-fn ,full-name
|
||||
(lambda ()
|
||||
,@skip-forms
|
||||
,@body))))
|
||||
|
||||
(provide 'flycheck-buttercup)
|
||||
|
||||
;; Disable byte compilation for this library, to prevent package.el choking on a
|
||||
|
||||
@@ -1,451 +0,0 @@
|
||||
;;; flycheck-ert.el --- Flycheck: ERT extensions -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2017-2018 Flycheck contributors
|
||||
;; Copyright (C) 2013-2016 Sebastian Wiesner and Flycheck contributors
|
||||
|
||||
;; Author: Sebastian Wiesner <swiesner@lunaryorn.com>
|
||||
;; Maintainer: Clément Pit-Claudel <clement.pitclaudel@live.com>
|
||||
;; fmdkdd <fmdkdd@gmail.com>
|
||||
;; URL: https://github.com/flycheck/flycheck
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
|
||||
;; 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:
|
||||
|
||||
;; Unit testing library for Flycheck, the modern on-the-fly syntax checking
|
||||
;; extension for GNU Emacs.
|
||||
|
||||
;; Provide various utility functions and unit test helpers to test Flycheck and
|
||||
;; Flycheck extensions.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'flycheck)
|
||||
(require 'ert)
|
||||
(require 'macroexp) ; For macro utilities
|
||||
|
||||
|
||||
;;; Internal variables
|
||||
|
||||
(defvar flycheck-ert--resource-directory nil
|
||||
"The directory to get resources from in this test suite.")
|
||||
|
||||
|
||||
;;; Resource management macros
|
||||
|
||||
(defmacro flycheck-ert-with-temp-buffer (&rest body)
|
||||
"Eval BODY within a temporary buffer.
|
||||
|
||||
Like `with-temp-buffer', but resets the modification state of the
|
||||
temporary buffer to make sure that it is properly killed even if
|
||||
it has a backing file and is modified."
|
||||
(declare (indent 0) (debug t))
|
||||
`(with-temp-buffer
|
||||
(unwind-protect
|
||||
,(macroexp-progn body)
|
||||
;; Reset modification state of the buffer, and unlink it from its backing
|
||||
;; file, if any, because Emacs refuses to kill modified buffers with
|
||||
;; backing files, even if they are temporary.
|
||||
(set-buffer-modified-p nil)
|
||||
(set-visited-file-name nil 'no-query))))
|
||||
|
||||
(defmacro flycheck-ert-with-file-buffer (file-name &rest body)
|
||||
"Create a buffer from FILE-NAME and eval BODY.
|
||||
|
||||
BODY is evaluated with `current-buffer' being a buffer with the
|
||||
contents FILE-NAME."
|
||||
(declare (indent 1) (debug t))
|
||||
`(let ((file-name ,file-name))
|
||||
(unless (file-exists-p file-name)
|
||||
(error "%s does not exist" file-name))
|
||||
(flycheck-ert-with-temp-buffer
|
||||
(insert-file-contents file-name 'visit)
|
||||
(set-visited-file-name file-name 'no-query)
|
||||
(cd (file-name-directory file-name))
|
||||
;; Mark the buffer as not modified, because we just loaded the file up to
|
||||
;; now.
|
||||
(set-buffer-modified-p nil)
|
||||
,@body)))
|
||||
|
||||
(defmacro flycheck-ert-with-help-buffer (&rest body)
|
||||
"Execute BODY and kill the help buffer afterwards.
|
||||
|
||||
Use this macro to test functions that create a Help buffer."
|
||||
(declare (indent 0))
|
||||
`(unwind-protect
|
||||
,(macroexp-progn body)
|
||||
(when (buffer-live-p (get-buffer (help-buffer)))
|
||||
(kill-buffer (help-buffer)))))
|
||||
|
||||
(defmacro flycheck-ert-with-global-mode (&rest body)
|
||||
"Execute BODY with Global Flycheck Mode enabled.
|
||||
|
||||
After BODY, restore the old state of Global Flycheck Mode."
|
||||
(declare (indent 0))
|
||||
`(let ((old-state global-flycheck-mode))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(global-flycheck-mode 1)
|
||||
,@body)
|
||||
(global-flycheck-mode (if old-state 1 -1)))))
|
||||
|
||||
(defmacro flycheck-ert-with-env (env &rest body)
|
||||
"Add ENV to `process-environment' in BODY.
|
||||
|
||||
Execute BODY with a `process-environment' which contains all
|
||||
variables from ENV added.
|
||||
|
||||
ENV is an alist, where each cons cell `(VAR . VALUE)' is a
|
||||
environment variable VAR to be added to `process-environment'
|
||||
with VALUE."
|
||||
(declare (indent 1))
|
||||
`(let ((process-environment (copy-sequence process-environment)))
|
||||
(pcase-dolist (`(,var . ,value) ,env)
|
||||
(setenv var value))
|
||||
,@body))
|
||||
|
||||
|
||||
;;; Test resources
|
||||
(defun flycheck-ert-resource-filename (resource-file)
|
||||
"Determine the absolute file name of a RESOURCE-FILE.
|
||||
|
||||
Relative file names are expanded against
|
||||
`flycheck-ert--resource-directory'."
|
||||
(expand-file-name resource-file flycheck-ert--resource-directory))
|
||||
|
||||
(defmacro flycheck-ert-with-resource-buffer (resource-file &rest body)
|
||||
"Create a temp buffer from a RESOURCE-FILE and execute BODY.
|
||||
|
||||
The absolute file name of RESOURCE-FILE is determined with
|
||||
`flycheck-ert-resource-filename'."
|
||||
(declare (indent 1))
|
||||
`(flycheck-ert-with-file-buffer
|
||||
(flycheck-ert-resource-filename ,resource-file)
|
||||
,@body))
|
||||
|
||||
|
||||
;;; Test suite initialization
|
||||
|
||||
(defun flycheck-ert-initialize (resource-dir)
|
||||
"Initialize a test suite with RESOURCE-DIR.
|
||||
|
||||
RESOURCE-DIR is the directory, `flycheck-ert-resource-filename'
|
||||
should use to lookup resource files."
|
||||
(when flycheck-ert--resource-directory
|
||||
(error "Test suite already initialized"))
|
||||
(let ((tests (ert-select-tests t t)))
|
||||
;; Select all tests
|
||||
(unless tests
|
||||
(error "No tests defined. \
|
||||
Call `flycheck-ert-initialize' after defining all tests!"))
|
||||
|
||||
(setq flycheck-ert--resource-directory resource-dir)))
|
||||
|
||||
|
||||
;;; Test case definitions
|
||||
(defmacro flycheck-ert-def-checker-test (checker language name
|
||||
&rest keys-and-body)
|
||||
"Define a test case for a syntax CHECKER for LANGUAGE.
|
||||
|
||||
CHECKER is a symbol or a list of symbols denoting syntax checkers
|
||||
being tested by the test. The test case is skipped, if any of
|
||||
these checkers cannot be used. LANGUAGE is a symbol or a list of
|
||||
symbols denoting the programming languages supported by the
|
||||
syntax checkers. This is currently only used for tagging the
|
||||
test appropriately.
|
||||
|
||||
NAME is a symbol denoting the local name of the test. The test
|
||||
itself is ultimately named
|
||||
`flycheck-define-checker/CHECKER/NAME'. If CHECKER is a list,
|
||||
the first checker in the list is used for naming the test.
|
||||
|
||||
Optionally, the keyword arguments `:tags' and `:expected-result'
|
||||
may be given. They have the same meaning as in `ert-deftest.',
|
||||
and are added to the tags and result expectations set up by this
|
||||
macro.
|
||||
|
||||
The remaining forms KEYS-AND-BODY denote the body of the test
|
||||
case, including assertions and setup code."
|
||||
(declare (indent 3))
|
||||
(unless checker
|
||||
(error "No syntax checkers specified"))
|
||||
(unless language
|
||||
(error "No languages specified"))
|
||||
(let* ((checkers (if (symbolp checker) (list checker) checker))
|
||||
(checker (car checkers))
|
||||
(languages (if (symbolp language) (list language) language))
|
||||
(language-tags (mapcar (lambda (l) (intern (format "language-%s" l)))
|
||||
languages))
|
||||
(checker-tags (mapcar (lambda (c) (intern (format "checker-%s" c)))
|
||||
checkers))
|
||||
(local-name (or name 'default))
|
||||
(full-name (intern (format "flycheck-define-checker/%s/%s"
|
||||
checker local-name)))
|
||||
(keys-and-body (ert--parse-keys-and-body keys-and-body))
|
||||
(body (cadr keys-and-body))
|
||||
(keys (car keys-and-body))
|
||||
(default-tags '(syntax-checker external-tool)))
|
||||
`(ert-deftest ,full-name ()
|
||||
:expected-result ,(or (plist-get keys :expected-result) :passed)
|
||||
:tags (append ',(append default-tags language-tags checker-tags)
|
||||
,(plist-get keys :tags))
|
||||
,@(mapcar (lambda (c)
|
||||
`(skip-unless
|
||||
;; Ignore non-command checkers
|
||||
(or (not (flycheck-checker-get ',c 'command))
|
||||
(executable-find (flycheck-checker-executable ',c)))))
|
||||
checkers)
|
||||
,@body)))
|
||||
|
||||
|
||||
;;; Test case results
|
||||
|
||||
(defun flycheck-ert-syntax-check-timed-out-p (result)
|
||||
"Whether RESULT denotes a timed-out test.
|
||||
|
||||
RESULT is an ERT test result object."
|
||||
(and (ert-test-failed-p result)
|
||||
(eq (car (ert-test-failed-condition result))
|
||||
'flycheck-ert-syntax-check-timed-out)))
|
||||
|
||||
|
||||
;;; Syntax checking in tests
|
||||
|
||||
(defvar-local flycheck-ert-syntax-checker-finished nil
|
||||
"Non-nil if the current checker has finished.")
|
||||
|
||||
(add-hook 'flycheck-after-syntax-check-hook
|
||||
(lambda () (setq flycheck-ert-syntax-checker-finished t)))
|
||||
|
||||
(defconst flycheck-ert-checker-wait-time 10
|
||||
"Time to wait until a checker is finished in seconds.
|
||||
|
||||
After this time has elapsed, the checker is considered to have
|
||||
failed, and the test aborted with failure.")
|
||||
|
||||
(define-error 'flycheck-ert-syntax-check-timed-out "Syntax check timed out.")
|
||||
|
||||
(defun flycheck-ert-wait-for-syntax-checker ()
|
||||
"Wait until the syntax check in the current buffer is finished."
|
||||
(let ((starttime (float-time)))
|
||||
(while (and (not flycheck-ert-syntax-checker-finished)
|
||||
(< (- (float-time) starttime) flycheck-ert-checker-wait-time))
|
||||
(accept-process-output nil 0.02))
|
||||
(unless (< (- (float-time) starttime) flycheck-ert-checker-wait-time)
|
||||
(flycheck-stop)
|
||||
(signal 'flycheck-ert-syntax-check-timed-out nil)))
|
||||
(setq flycheck-ert-syntax-checker-finished nil))
|
||||
|
||||
(defun flycheck-ert-buffer-sync ()
|
||||
"Like `flycheck-buffer', but synchronously."
|
||||
(setq flycheck-ert-syntax-checker-finished nil)
|
||||
(should (not (flycheck-running-p)))
|
||||
(flycheck-mode) ;; This will only start a deferred check,
|
||||
(should (flycheck-get-checker-for-buffer))
|
||||
(flycheck-buffer) ;; …so we need an explicit manual check
|
||||
;; After starting the check, the checker should either be running now, or
|
||||
;; already be finished (if it was fast).
|
||||
(should (or flycheck-current-syntax-check
|
||||
flycheck-ert-syntax-checker-finished))
|
||||
;; Also there should be no deferred check pending anymore
|
||||
(should-not (flycheck-deferred-check-p))
|
||||
(flycheck-ert-wait-for-syntax-checker))
|
||||
|
||||
(defun flycheck-ert-ensure-clear ()
|
||||
"Clear the current buffer.
|
||||
|
||||
Raise an assertion error if the buffer is not clear afterwards."
|
||||
(flycheck-clear)
|
||||
(should (not flycheck-current-errors))
|
||||
(should (not (seq-find (lambda (ov) (overlay-get ov 'flycheck-overlay))
|
||||
(overlays-in (point-min) (point-max))))))
|
||||
|
||||
|
||||
;;; Test assertions
|
||||
|
||||
(defun flycheck-error-without-group (err)
|
||||
"Return a copy ERR with the `group' property set to nil."
|
||||
(let ((copy (copy-flycheck-error err)))
|
||||
(setf (flycheck-error-group copy) nil)
|
||||
copy))
|
||||
|
||||
(defun flycheck-ert-should-overlay (error)
|
||||
"Test that ERROR has a proper overlay in the current buffer.
|
||||
|
||||
ERROR is a Flycheck error object."
|
||||
(let* ((overlay (seq-find (lambda (ov)
|
||||
(equal (flycheck-error-without-group
|
||||
(overlay-get ov 'flycheck-error))
|
||||
(flycheck-error-without-group error)))
|
||||
(flycheck-overlays-in 0 (+ 1 (buffer-size)))))
|
||||
(region
|
||||
;; Overlays of errors from other files are on the first line
|
||||
(if (flycheck-relevant-error-other-file-p error)
|
||||
(cons (point-min)
|
||||
(save-excursion (goto-char (point-min))
|
||||
(line-end-position)))
|
||||
(flycheck-error-region-for-mode error 'symbols)))
|
||||
(level (flycheck-error-level error))
|
||||
(category (flycheck-error-level-overlay-category level))
|
||||
(face (get category 'face))
|
||||
(fringe-bitmap (flycheck-error-level-fringe-bitmap level))
|
||||
(fringe-face (flycheck-error-level-fringe-face level))
|
||||
(fringe-icon (list 'left-fringe fringe-bitmap fringe-face)))
|
||||
(should overlay)
|
||||
(should (overlay-get overlay 'flycheck-overlay))
|
||||
(should (= (overlay-start overlay) (car region)))
|
||||
(should (= (overlay-end overlay) (cdr region)))
|
||||
(should (eq (overlay-get overlay 'face) face))
|
||||
(should (equal (get-char-property 0 'display
|
||||
(overlay-get overlay 'before-string))
|
||||
fringe-icon))
|
||||
(should (eq (overlay-get overlay 'category) category))
|
||||
(should (equal (flycheck-error-without-group (overlay-get overlay
|
||||
'flycheck-error))
|
||||
(flycheck-error-without-group error)))))
|
||||
|
||||
(defun flycheck-ert-sort-errors (errors)
|
||||
"Sort ERRORS by `flycheck-error-<'."
|
||||
(seq-sort #'flycheck-error-< errors))
|
||||
|
||||
(defun flycheck-ert-should-errors (&rest errors)
|
||||
"Test that the current buffers has ERRORS.
|
||||
|
||||
ERRORS is a list of errors expected to be present in the current
|
||||
buffer. Each error is given as a list of arguments to
|
||||
`flycheck-error-new-at'.
|
||||
|
||||
If ERRORS are omitted, test that there are no errors at all in
|
||||
the current buffer.
|
||||
|
||||
With ERRORS, test that each error in ERRORS is present in the
|
||||
current buffer, and that the number of errors in the current
|
||||
buffer is equal to the number of given ERRORS. In other words,
|
||||
check that the buffer has all ERRORS, and no other errors."
|
||||
(let ((expected (flycheck-ert-sort-errors
|
||||
(mapcar (apply-partially #'apply #'flycheck-error-new-at)
|
||||
errors)))
|
||||
(current (flycheck-ert-sort-errors flycheck-current-errors)))
|
||||
(should (equal (mapcar #'flycheck-error-without-group expected)
|
||||
(mapcar #'flycheck-error-without-group current)))
|
||||
;; Check that related errors are the same
|
||||
(cl-mapcar
|
||||
(lambda (err1 err2)
|
||||
(should (equal (flycheck-ert-sort-errors
|
||||
(mapcar #'flycheck-error-without-group
|
||||
(flycheck-related-errors err1 expected)))
|
||||
(flycheck-ert-sort-errors
|
||||
(mapcar #'flycheck-error-without-group
|
||||
(flycheck-related-errors err2))))))
|
||||
expected current)
|
||||
(mapc #'flycheck-ert-should-overlay expected))
|
||||
(should (= (length errors)
|
||||
(length (flycheck-overlays-in (point-min) (point-max))))))
|
||||
|
||||
(define-error 'flycheck-ert-suspicious-checker "Suspicious state from checker")
|
||||
|
||||
(defun flycheck-ert-should-syntax-check-in-buffer (&rest errors)
|
||||
"Test a syntax check in BUFFER, expecting ERRORS.
|
||||
|
||||
This is like `flycheck-ert-should-syntax-check', but with a
|
||||
buffer in the right mode instead of a file."
|
||||
;; Load safe file-local variables because some tests depend on them
|
||||
(let ((enable-local-variables :safe)
|
||||
;; Disable all hooks at this place, to prevent 3rd party packages
|
||||
;; from interfering
|
||||
(hack-local-variables-hook))
|
||||
(hack-local-variables))
|
||||
;; Configure config file locating for unit tests
|
||||
(let ((process-hook-called 0)
|
||||
(suspicious nil))
|
||||
(add-hook 'flycheck-process-error-functions
|
||||
(lambda (_err)
|
||||
(setq process-hook-called (1+ process-hook-called))
|
||||
nil)
|
||||
nil :local)
|
||||
(add-hook 'flycheck-status-changed-functions
|
||||
(lambda (status)
|
||||
(when (eq status 'suspicious)
|
||||
(setq suspicious t)))
|
||||
nil :local)
|
||||
(flycheck-ert-buffer-sync)
|
||||
(when suspicious
|
||||
(signal 'flycheck-ert-suspicious-checker nil))
|
||||
(apply #'flycheck-ert-should-errors errors)
|
||||
(should (= process-hook-called (length errors))))
|
||||
(flycheck-ert-ensure-clear))
|
||||
|
||||
(defun flycheck-ert-should-syntax-check (resource-file modes &rest errors)
|
||||
"Test a syntax check in RESOURCE-FILE with MODES.
|
||||
|
||||
RESOURCE-FILE is the file to check. MODES is a single major mode
|
||||
symbol or a list thereof, specifying the major modes to syntax
|
||||
check with. If more than one major mode is specified, the test
|
||||
is run for each mode separately, so if you give three major
|
||||
modes, the entire test will run three times. ERRORS is the list
|
||||
of expected errors, as in `flycheck-ert-should-errors'. If
|
||||
omitted, the syntax check must not emit any errors. The errors
|
||||
are cleared after each test.
|
||||
|
||||
The syntax checker is selected via standard syntax checker
|
||||
selection. To test a specific checker, you need to set
|
||||
`flycheck-checker' or `flycheck-disabled-checkers' accordingly
|
||||
before using this predicate, depending on whether you want to use
|
||||
manual or automatic checker selection.
|
||||
|
||||
During the syntax check, configuration files of syntax checkers
|
||||
are also searched in the `config-files' sub-directory of the
|
||||
resource directory."
|
||||
(when (symbolp modes)
|
||||
(setq modes (list modes)))
|
||||
(dolist (mode modes)
|
||||
(unless (fboundp mode)
|
||||
(ert-skip (format "%S missing" mode)))
|
||||
(flycheck-ert-with-resource-buffer resource-file
|
||||
(funcall mode)
|
||||
(apply #'flycheck-ert-should-syntax-check-in-buffer errors))))
|
||||
|
||||
(defun flycheck-ert-at-nth-error (n)
|
||||
"Determine whether point is at the N'th Flycheck error.
|
||||
|
||||
Return non-nil if the point is at the N'th Flycheck error in the
|
||||
current buffer. Otherwise return nil."
|
||||
(let* ((error (nth (1- n) flycheck-current-errors))
|
||||
(mode flycheck-highlighting-mode)
|
||||
(region (flycheck-error-region-for-mode error mode)))
|
||||
(and (member error (flycheck-overlay-errors-at (point)))
|
||||
(= (point) (car region)))))
|
||||
|
||||
(defun flycheck-ert-explain--at-nth-error (n)
|
||||
"Explain a failed at-nth-error predicate at N."
|
||||
(let ((errors (flycheck-overlay-errors-at (point))))
|
||||
(if (null errors)
|
||||
(format "Expected to be at error %s, but no error at point %s"
|
||||
n (point))
|
||||
(let ((pos (cl-position (car errors) flycheck-current-errors)))
|
||||
(format "Expected to be at point %s and error %s, \
|
||||
but point %s is at error %s"
|
||||
(car (flycheck-error-region-for-mode
|
||||
(nth (1- n) flycheck-current-errors)
|
||||
flycheck-highlighting-mode))
|
||||
n (point) (1+ pos))))))
|
||||
|
||||
(put 'flycheck-ert-at-nth-error 'ert-explainer
|
||||
'flycheck-ert-explain--at-nth-error)
|
||||
|
||||
(provide 'flycheck-ert)
|
||||
|
||||
;;; flycheck-ert.el ends here
|
||||
@@ -1,11 +1,11 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "flycheck" "20251128.1706"
|
||||
(define-package "flycheck" "20260320.1715"
|
||||
"On-the-fly syntax checking."
|
||||
'((emacs "27.1")
|
||||
(seq "2.24"))
|
||||
:url "https://www.flycheck.org"
|
||||
:commit "62570fafbedb8fa3f7d75a50a9364feca3b294ef"
|
||||
:revdesc "62570fafbedb"
|
||||
:url "https://github.com/flycheck/flycheck"
|
||||
:commit "0e5eb8300d32fd562724216c19eaf199ee1451ab"
|
||||
:revdesc "0e5eb8300d32"
|
||||
:keywords '("convenience" "languages" "tools")
|
||||
:authors '(("Sebastian Wiesner" . "swiesner@lunaryorn.com"))
|
||||
:maintainers '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com")
|
||||
|
||||
+626
-1033
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "flyspell-correct-ivy" "20220520.630"
|
||||
(define-package "flyspell-correct-ivy" "20260106.955"
|
||||
"Correcting words with flyspell via ivy interface."
|
||||
'((flyspell-correct "0.6.1")
|
||||
'((flyspell-correct "1.0.0")
|
||||
(ivy "0.8.0")
|
||||
(emacs "24.4"))
|
||||
(emacs "29.1"))
|
||||
:url "https://github.com/d12frosted/flyspell-correct"
|
||||
:commit "7d7b6b01188bd28e20a13736ac9f36c3367bd16e"
|
||||
:revdesc "7d7b6b01188b"
|
||||
:commit "a5a41c0f3a7881bd3eba07bee424ecb7c7d5061e"
|
||||
:revdesc "a5a41c0f3a78"
|
||||
:authors '(("Boris Buliga" . "boris@d12frosted.io"))
|
||||
:maintainers '(("Boris Buliga" . "boris@d12frosted.io")))
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
;;; flyspell-correct-ivy.el --- Correcting words with flyspell via ivy interface -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (c) 2016-2022 Boris Buliga
|
||||
;; Copyright (c) 2016-2026 Boris Buliga
|
||||
;;
|
||||
;; Author: Boris Buliga <boris@d12frosted.io>
|
||||
;; URL: https://github.com/d12frosted/flyspell-correct
|
||||
;; Package-Version: 20220520.630
|
||||
;; Package-Revision: 7d7b6b01188b
|
||||
;; Package-Requires: ((flyspell-correct "0.6.1") (ivy "0.8.0") (emacs "24.4"))
|
||||
;; Package-Version: 20260106.955
|
||||
;; Package-Revision: a5a41c0f3a78
|
||||
;; Package-Requires: ((flyspell-correct "1.0.0") (ivy "0.8.0") (emacs "29.1"))
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
;;; flyspell-correct-ido.el --- Correcting words with flyspell via ido interface -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (c) 2016-2022 Boris Buliga
|
||||
;; Copyright (c) 2016-2026 Boris Buliga
|
||||
;;
|
||||
;; Author: Boris Buliga <boris@d12frosted.io>
|
||||
;; URL: https://github.com/d12frosted/flyspell-correct
|
||||
;; Package-Requires: ((flyspell-correct "0.6.1") (emacs "24.1"))
|
||||
;; Package-Requires: ((flyspell-correct "1.0.0") (emacs "29.1"))
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "flyspell-correct" "20220520.630"
|
||||
(define-package "flyspell-correct" "20260106.955"
|
||||
"Correcting words with flyspell via custom interface."
|
||||
'((emacs "24"))
|
||||
'((emacs "29.1"))
|
||||
:url "https://github.com/d12frosted/flyspell-correct"
|
||||
:commit "7d7b6b01188bd28e20a13736ac9f36c3367bd16e"
|
||||
:revdesc "7d7b6b01188b"
|
||||
:commit "a5a41c0f3a7881bd3eba07bee424ecb7c7d5061e"
|
||||
:revdesc "a5a41c0f3a78"
|
||||
:authors '(("Boris Buliga" . "boris@d12frosted.io"))
|
||||
:maintainers '(("Boris Buliga" . "boris@d12frosted.io")))
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
;;; flyspell-correct.el --- Correcting words with flyspell via custom interface -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (c) 2016-2022 Boris Buliga
|
||||
;; Copyright (c) 2016-2026 Boris Buliga
|
||||
;;
|
||||
;; Author: Boris Buliga <boris@d12frosted.io>
|
||||
;; URL: https://github.com/d12frosted/flyspell-correct
|
||||
;; Package-Version: 20220520.630
|
||||
;; Package-Revision: 7d7b6b01188b
|
||||
;; Package-Requires: ((emacs "24"))
|
||||
;; Package-Version: 20260106.955
|
||||
;; Package-Revision: a5a41c0f3a78
|
||||
;; Package-Requires: ((emacs "29.1"))
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
@@ -63,31 +63,22 @@
|
||||
|
||||
(defcustom flyspell-correct-interface #'flyspell-correct-completing-read
|
||||
"Interface for `flyspell-correct-at-point'.
|
||||
|
||||
`flyspell-correct-interface' is a function accepting two arguments:
|
||||
|
||||
- candidates for correction (list of strings)
|
||||
- misspelled word (string)
|
||||
|
||||
Result must be either a string (replacement word) or a cons of a
|
||||
command and a string (replacement word), where the command is one
|
||||
of the following:
|
||||
|
||||
- skip - do nothing to misspelled word, in rapid mode used for
|
||||
jumping to the next (or previous) misspelled word
|
||||
|
||||
- break - do nothing to misspelled word, break from rapid mode
|
||||
|
||||
- stop - do nothing to misspelled word, break from rapid
|
||||
mode (if enabled) and leave the point at the misspelled word
|
||||
|
||||
- save - replace misspelled word with replacement word and save
|
||||
it to the personal dictionary
|
||||
|
||||
- session - replace misspelled word with replacement word and
|
||||
save it to the session dictionary (correction will be
|
||||
discarded upon quitting Emacs)
|
||||
|
||||
- buffer - replace misspelled word with replacement word and
|
||||
save it to the buffer dictionary (added to the bottom of
|
||||
buffer)"
|
||||
@@ -96,12 +87,27 @@ of the following:
|
||||
|
||||
(defcustom flyspell-correct-highlight t
|
||||
"When non-nil highlight the word while correcting.
|
||||
|
||||
The face `flyspell-correct-highlight-face' is used for
|
||||
highlighting."
|
||||
:group 'flyspell-correct
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom flyspell-correct-default-direction 'backward
|
||||
"Default direction for `flyspell-correct-wrapper'.
|
||||
When set to `backward' (the default), search for misspelled words
|
||||
before point. When set to `forward', search for misspelled words
|
||||
after point."
|
||||
:group 'flyspell-correct
|
||||
:type '(choice (const :tag "Backward" backward)
|
||||
(const :tag "Forward" forward)))
|
||||
|
||||
(defcustom flyspell-correct-abort-on-quit t
|
||||
"When non-nil, restore point when quitting correction.
|
||||
When set to nil, leave point at the misspelled word when quitting
|
||||
with \\[keyboard-quit] (similar to the `stop' action)."
|
||||
:group 'flyspell-correct
|
||||
:type 'boolean)
|
||||
|
||||
(defface flyspell-correct-highlight-face
|
||||
'((t (:inherit isearch)))
|
||||
"Face used for highlighting the word while correcting."
|
||||
@@ -125,7 +131,6 @@ highlighting."
|
||||
|
||||
(defun flyspell-correct--cr-index (n)
|
||||
"Generate a short unique index string for N.
|
||||
|
||||
The index string is used to prefix suggestion candidates. The digits 12345
|
||||
encode (mod n 5) and occur as suffix of the index string. If one of the keys
|
||||
12345 is pressed, the selected candidate is automatically submitted. The
|
||||
@@ -141,9 +146,7 @@ prefix of the index string."
|
||||
|
||||
(defun flyspell-correct-completing-read (candidates word)
|
||||
"Run `completing-read' for the given CANDIDATES.
|
||||
|
||||
List of CANDIDATES is given by flyspell for the WORD.
|
||||
|
||||
Return a selected word to use as a replacement or a tuple
|
||||
of (command, word) to be used by `flyspell-do-correct'."
|
||||
(let* ((idx 0)
|
||||
@@ -212,7 +215,7 @@ of (command, word) to be used by `flyspell-do-correct'."
|
||||
(define-obsolete-function-alias
|
||||
'flyspell-correct-dummy
|
||||
'flyspell-correct-completing-read
|
||||
"0.6.1")
|
||||
"1.0.0")
|
||||
|
||||
;;; On point word correction
|
||||
;;
|
||||
@@ -225,7 +228,9 @@ Adapted from `flyspell-correct-word-before-point'."
|
||||
(unless flyspell-correct-interface
|
||||
(error "Could not correct word because `flyspell-correct-interface' is not set"))
|
||||
(let ((res))
|
||||
;; use the correct dictionary
|
||||
;; Initialize spell checker and use the correct dictionary.
|
||||
;; This allows flyspell-correct-at-point to work without flyspell-mode.
|
||||
(ispell-set-spellchecker-params)
|
||||
(flyspell-accept-buffer-local-defs)
|
||||
(flyspell-correct--highlight-add)
|
||||
(unwind-protect
|
||||
@@ -293,10 +298,9 @@ Adapted from `flyspell-correct-word-before-point'."
|
||||
(defun flyspell-correct-previous (position)
|
||||
"Correct the first misspelled word that occurs before POSITION.
|
||||
But don't look beyond what's visible on the screen.
|
||||
|
||||
Uses `flyspell-correct-at-point' function for correction.
|
||||
|
||||
With a prefix argument, automatically continues to all prior misspelled words in the buffer."
|
||||
With a prefix argument, automatically continues to all prior
|
||||
misspelled words in the buffer."
|
||||
(interactive "d")
|
||||
(flyspell-correct-move position nil current-prefix-arg))
|
||||
|
||||
@@ -306,9 +310,7 @@ With a prefix argument, automatically continues to all prior misspelled words in
|
||||
;;;###autoload
|
||||
(defun flyspell-correct-next (position)
|
||||
"Correct the first misspelled word that occurs after POSITION.
|
||||
|
||||
Uses `flyspell-correct-at-point' function for correction.
|
||||
|
||||
With a prefix argument, automatically continues to all further
|
||||
misspelled words in the buffer."
|
||||
(interactive "d")
|
||||
@@ -320,48 +322,84 @@ misspelled words in the buffer."
|
||||
;;;###autoload
|
||||
(defun flyspell-correct-wrapper ()
|
||||
"Correct spelling error in a dwim fashion based on universal argument.
|
||||
|
||||
- One \\[universal-argument] enables rapid mode.
|
||||
- Two \\[universal-argument]'s changes direction of spelling
|
||||
errors search.
|
||||
- Three \\[universal-argument]'s changes direction of spelling
|
||||
errors search and enables rapid mode."
|
||||
errors search and enables rapid mode.
|
||||
|
||||
The default direction is controlled by `flyspell-correct-default-direction'."
|
||||
(interactive)
|
||||
(let ((forward-direction nil)
|
||||
(let ((forward-direction (eq flyspell-correct-default-direction 'forward))
|
||||
(rapid nil))
|
||||
(cond
|
||||
((equal current-prefix-arg '(4)) ; C-u = rapid
|
||||
(setq rapid t))
|
||||
((equal current-prefix-arg '(16)) ; C-u C-u = change direction
|
||||
(setq forward-direction t))
|
||||
(setq forward-direction (not forward-direction)))
|
||||
((equal current-prefix-arg '(64)) ; C-u C-u C-u = do both
|
||||
(setq rapid t)
|
||||
(setq forward-direction t)))
|
||||
(setq forward-direction (not forward-direction))))
|
||||
|
||||
(flyspell-correct-move (point) forward-direction rapid)))
|
||||
|
||||
;;;###autoload
|
||||
(defun flyspell-correct-region (beg end)
|
||||
"Correct all misspelled words in region between BEG and END.
|
||||
Runs `flyspell-region' first to find misspelled words, then
|
||||
corrects them one by one using `flyspell-correct-at-point'.
|
||||
|
||||
This is useful for spell-checking a specific portion of the buffer
|
||||
without affecting the rest."
|
||||
(interactive "r")
|
||||
(flyspell-region beg end)
|
||||
(let ((overlay-list (seq-filter
|
||||
#'flyspell-overlay-p
|
||||
(overlays-in beg end))))
|
||||
;; Sort by position
|
||||
(setq overlay-list (sort overlay-list
|
||||
(lambda (o1 o2)
|
||||
(< (overlay-start o1)
|
||||
(overlay-start o2)))))
|
||||
(when (or (not (mark t))
|
||||
(/= (mark t) (point)))
|
||||
(push-mark (point) t))
|
||||
(unwind-protect
|
||||
(save-excursion
|
||||
(catch 'break
|
||||
(dolist (overlay overlay-list)
|
||||
(when (flyspell-overlay-p overlay) ; Check again, might be deleted
|
||||
(goto-char (overlay-start overlay))
|
||||
(let ((scroll (> (point) (window-end))))
|
||||
(when scroll (ignore-errors (recenter))))
|
||||
(let ((res (condition-case nil
|
||||
(flyspell-correct-at-point)
|
||||
(quit 'break))))
|
||||
(when (or (eq res 'break)
|
||||
(eq (car-safe res) 'break)
|
||||
(eq (car-safe res) 'stop))
|
||||
(throw 'break nil)))))))
|
||||
(goto-char (mark t)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun flyspell-correct-move (position &optional forward rapid)
|
||||
"Correct the first misspelled word that occurs before POSITION.
|
||||
|
||||
Uses `flyspell-correct-at-point' function for correction.
|
||||
|
||||
With FORWARD set non-nil, check forward instead of backward.
|
||||
|
||||
With RAPID set non-nil, automatically continues in direction
|
||||
until all errors in buffer have been addressed."
|
||||
;; NOTE: The way I may be pushing the mark may possibly be more
|
||||
;; idiomatically done using the opoint arg of
|
||||
;; `flyspell-correct-word-before-point'.
|
||||
(interactive "d")
|
||||
;; push mark when starting
|
||||
(when (or (not (mark t))
|
||||
(/= (mark t) (point)))
|
||||
(push-mark (point) t))
|
||||
(let ((original-pos (point))
|
||||
(target-pos (point))
|
||||
(hard-move-point)
|
||||
(mark-opos))
|
||||
(original-mark-ring mark-ring)
|
||||
(preserve-mark))
|
||||
(when (or (not (mark t))
|
||||
(/= (mark t) (point)))
|
||||
(push-mark (point) t))
|
||||
(unwind-protect
|
||||
(save-excursion
|
||||
(let ((incorrect-word-pos))
|
||||
@@ -403,13 +441,19 @@ until all errors in buffer have been addressed."
|
||||
(<= original-pos (overlay-end overlay))))
|
||||
|
||||
;; Correct a word using `flyspell-correct-at-point'.
|
||||
(let ((res (flyspell-correct-at-point)))
|
||||
(let ((res (condition-case nil
|
||||
(flyspell-correct-at-point)
|
||||
(quit
|
||||
;; Handle C-g based on configuration
|
||||
(if flyspell-correct-abort-on-quit
|
||||
'break
|
||||
'stop)))))
|
||||
(when res
|
||||
;; stop at misspelled word
|
||||
(when (eq (car-safe res) 'stop)
|
||||
(setq target-pos incorrect-word-pos
|
||||
hard-move-point t
|
||||
mark-opos t))
|
||||
(setq target-pos incorrect-word-pos)
|
||||
(setq hard-move-point t)
|
||||
(setq preserve-mark t))
|
||||
|
||||
;; break from rapid mode
|
||||
(when (or
|
||||
@@ -420,23 +464,15 @@ until all errors in buffer have been addressed."
|
||||
;; explicit rapid mode disablers
|
||||
(eq (car-safe res) 'break)
|
||||
(eq (car-safe res) 'stop))
|
||||
(setq overlay nil))
|
||||
(setq overlay nil)))))))))
|
||||
|
||||
(when (and
|
||||
;; don't push mark if there is no change
|
||||
(not (memq (car-safe res) '(stop break skip)))
|
||||
(/= (mark t) (point)))
|
||||
;; `flyspell-correct-at-point' may move point, use
|
||||
;; original `incorrect-word-pos' instead
|
||||
(push-mark incorrect-word-pos t)))))))))
|
||||
|
||||
(when hard-move-point
|
||||
(when mark-opos
|
||||
(push-mark (point) t))
|
||||
(goto-char target-pos))
|
||||
(if hard-move-point
|
||||
(goto-char target-pos)
|
||||
(goto-char (mark t)))
|
||||
;; We pushed the mark when starting, but if the operation is canceled
|
||||
;; without any change that mark is redundant and needs to be cleaned-up.
|
||||
(when (= (mark t) (point)) (pop-mark)))))
|
||||
(unless preserve-mark
|
||||
(setq mark-ring original-mark-ring)))))
|
||||
|
||||
;;; Overlays
|
||||
|
||||
@@ -461,7 +497,6 @@ until all errors in buffer have been addressed."
|
||||
|
||||
(defun flyspell-correct--overlay-loc ()
|
||||
"Return `cons' with start and end of `flyspell' overlay at point.
|
||||
|
||||
Returns nil if no overlay is found."
|
||||
(let ((ovs (overlays-at (point)))
|
||||
ov)
|
||||
@@ -488,12 +523,11 @@ Use floating point numbers to express fractions of seconds."
|
||||
"Interface to use in `flyspell-correct-auto-mode'.
|
||||
When set to nil `flyspell-correct-interface' is used.")
|
||||
|
||||
(defvar flyspell-correct--auto-timer nil
|
||||
(defvar-local flyspell-correct--auto-timer nil
|
||||
"Timer to automatically call `flyspell-correct-previous'.")
|
||||
(make-variable-buffer-local 'flyspell-correct--auto-timer)
|
||||
|
||||
(defvar flyspell-correct--auto-active-p nil)
|
||||
(make-variable-buffer-local 'flyspell-correct--auto-active-p)
|
||||
(defvar-local flyspell-correct--auto-active-p nil
|
||||
"Non-nil when auto-correction is active.")
|
||||
|
||||
(defun flyspell-correct-auto-cancel-timer ()
|
||||
"Cancel auto correct timer."
|
||||
@@ -527,12 +561,10 @@ When set to nil `flyspell-correct-interface' is used.")
|
||||
;;;###autoload
|
||||
(define-minor-mode flyspell-correct-auto-mode
|
||||
"Minor mode for automatically correcting word at point.
|
||||
|
||||
Take my advice and don't use this functionality unless you find
|
||||
`flyspell-correct-previous' function useless for your purposes.
|
||||
Seriously, just try named function for completion. You can find
|
||||
more info in comment[1].
|
||||
|
||||
[1]:
|
||||
https://github.com/syl20bnr/spacemacs/issues/6209#issuecomment-274320376"
|
||||
:group 'flyspell
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"Dim the font color of text in surrounding sections."
|
||||
'((emacs "24.3")
|
||||
(cl-lib "0.5"))
|
||||
:url "http://github.com/larstvei/Focus"
|
||||
:url "https://github.com/larstvei/Focus"
|
||||
:commit "29b412b209c3542a7932c201f0166e48c9fd7fee"
|
||||
:revdesc "29b412b209c3"
|
||||
:authors '(("Lars Tveito" . "larstvei@ifi.uio.no"))
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
;; Author: Jon Oddie <jonxfield@gmail.com>
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
|
||||
;; 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
|
||||
@@ -472,7 +470,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME."
|
||||
|
||||
(t ; two patterns
|
||||
(let* ((pat1 (cadr pat))
|
||||
(pat2 (cl-caddr pat))
|
||||
(pat2 (caddr pat))
|
||||
(pat1-c (gnuplot-context--compile-pattern pat1))
|
||||
(pat2-c (gnuplot-context--compile-pattern pat2))
|
||||
(pat1-l (length pat1-c))
|
||||
@@ -509,7 +507,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME."
|
||||
;; Syntactic sugar for delimited lists
|
||||
((delimited-list)
|
||||
(let* ((item (cadr pat))
|
||||
(sep (cl-caddr pat)))
|
||||
(sep (caddr pat)))
|
||||
(gnuplot-context--compile-pattern
|
||||
`(sequence ,item (many (sequence ,sep ,item))))))
|
||||
|
||||
@@ -1799,7 +1797,7 @@ there."
|
||||
;; (literal LITERAL NO-COMPLETE)
|
||||
((literal)
|
||||
(let ((expect (cadr inst))
|
||||
(no-complete (cl-caddr inst)))
|
||||
(no-complete (caddr inst)))
|
||||
(cond (end-of-tokens
|
||||
(unless no-complete
|
||||
(gnuplot-context--trace "\tpushing \"%s\" to completions\n" expect)
|
||||
@@ -1824,7 +1822,7 @@ there."
|
||||
;; regexp-matches REGEXP, use NAME for completions
|
||||
((keyword)
|
||||
(let ((regexp (cadr inst))
|
||||
(name (cl-caddr inst)))
|
||||
(name (caddr inst)))
|
||||
(cond (end-of-tokens
|
||||
(gnuplot-context--trace "\tpushing \"%s\" to completions\n" name)
|
||||
(push name gnuplot-context--completions)
|
||||
@@ -1901,7 +1899,7 @@ there."
|
||||
;; onto the stack
|
||||
((push)
|
||||
(let* ((type (cadr inst))
|
||||
(value (cl-caddr inst)))
|
||||
(value (caddr inst)))
|
||||
(push `(,type ,value ,tokens) stack)))
|
||||
|
||||
;; (pop TYPE): pop something off the stack
|
||||
@@ -1925,7 +1923,7 @@ there."
|
||||
(record (assoc name gnuplot-context--captures)))
|
||||
(if (not record)
|
||||
(error "Gnuplot-match-tokens: no open capture group named %s" name)
|
||||
(setf (cl-caddr record) tokens)
|
||||
(setf (caddr record) tokens)
|
||||
(gnuplot-context--debug (gnuplot-dump-captures)))))
|
||||
|
||||
;; (check-progress): make sure not stuck in an infinite loop
|
||||
@@ -1975,7 +1973,7 @@ there."
|
||||
(not (and gnuplot-context--info-at-point gnuplot-context--eldoc)))
|
||||
(let* ((item (car stack))
|
||||
(type (car item))
|
||||
(position (cl-caddr item))) ; must progress by at least one token
|
||||
(position (caddr item))) ; must progress by at least one token
|
||||
(if (and (memq type '(info eldoc no-scan))
|
||||
(not (eq position tokens)))
|
||||
(cl-case type
|
||||
@@ -2013,7 +2011,7 @@ there."
|
||||
(let ((record (assoc name gnuplot-context--captures)))
|
||||
(if (not record) nil
|
||||
(let ((begin (cadr record))
|
||||
(end (cl-caddr record))
|
||||
(end (caddr record))
|
||||
(accum '()))
|
||||
(while (and begin (not (eq begin end)))
|
||||
(push (pop begin) accum))
|
||||
|
||||
+23
-27
@@ -4,8 +4,6 @@
|
||||
|
||||
;; Author: Bruce Ravel <ravel@phys.washington.edu>
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
|
||||
;; 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
|
||||
@@ -872,16 +870,14 @@ Note that \"cntrparam\" is not currently supported."
|
||||
(old-top (gnuplot-gui-get-frame-param 'top)))
|
||||
(when (or
|
||||
(and (equal gnuplot-gui-plot-splot-fit-style 'complete)
|
||||
(cl-member word '("plot" "splot" "fit")
|
||||
:test 'equal))
|
||||
(member word '("plot" "splot" "fit")))
|
||||
(equal word "test"))
|
||||
(gnuplot-gui-set-frame-param 'height 32)
|
||||
(gnuplot-gui-set-frame-param 'top 50))
|
||||
(gnuplot-gui-prompt-for-frame word)
|
||||
(when (or
|
||||
(and (equal gnuplot-gui-plot-splot-fit-style 'complete)
|
||||
(cl-member word '("plot" "splot" "fit")
|
||||
:test 'equal))
|
||||
(member word '("plot" "splot" "fit")))
|
||||
(equal word "test"))
|
||||
(gnuplot-gui-set-frame-param 'height old-height)
|
||||
(gnuplot-gui-set-frame-param 'top old-top)) ))
|
||||
@@ -946,8 +942,8 @@ argument, for example an axis label or a font name. It also replaces
|
||||
bounding single quotes with double quotes, since double quotes are
|
||||
used in `gnuplot-gui-all-types'."
|
||||
(let (fixed-list quote quoted) ; remove blanks
|
||||
(setq list (cl-remove "\\s-+" list :test 'string-match)
|
||||
list (cl-remove "" list :test 'equal))
|
||||
(setq list (cl-remove "\\s-+" list :test #'string-match)
|
||||
list (remove "" list))
|
||||
(while list ; concatinate parts of quoted string
|
||||
(if (not (string-match "^\\([\]\[()'\"]\\)" (car list)))
|
||||
(setq fixed-list (append fixed-list (list (car list))))
|
||||
@@ -998,15 +994,15 @@ arguments."
|
||||
(while temp-list
|
||||
(cond
|
||||
;; ---------------------------- list
|
||||
((cl-member symbol '(list list*) :test 'equal)
|
||||
((memq symbol '(list list*))
|
||||
(let* ((case-fold-search nil)
|
||||
(match-cons (cl-member (concat "^" (car temp-list))
|
||||
values :test 'string-match)))
|
||||
values :test #'string-match)))
|
||||
(if (and (car match-cons) ; " " may be first elem. of list
|
||||
(not (equal " " (car match-cons))))
|
||||
(setq this-cons (cons tag (car match-cons))
|
||||
arg-list (cl-remove (car temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
temp-list nil)
|
||||
(setq temp-list (cdr temp-list)))))
|
||||
;; ---------------------------- tag (first number in list)
|
||||
@@ -1027,16 +1023,16 @@ arguments."
|
||||
(string-match "^[-0-9.]+$" (cadr temp-list)))
|
||||
(setq this-cons (cons tag (cadr temp-list))
|
||||
arg-list (cl-remove (car temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
arg-list (cl-remove (cadr temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
temp-list nil))
|
||||
;; --------------------- number without prefix
|
||||
((and (not prefix)
|
||||
(string-match "^[-0-9.]+$" (car temp-list)))
|
||||
(setq this-cons (cons tag (car temp-list))
|
||||
arg-list (cl-remove (car temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
temp-list nil))
|
||||
(t
|
||||
(setq temp-list (cdr temp-list)))))
|
||||
@@ -1045,8 +1041,8 @@ arguments."
|
||||
(if (and (equal prefix (car temp-list))
|
||||
(string-match "^[-0-9.]+$" (cadr temp-list)))
|
||||
(let ((this-car (cadr temp-list))
|
||||
(this-cdr (if (string-match "^[-0-9.]+$" (cl-caddr temp-list))
|
||||
(cl-caddr temp-list) "")))
|
||||
(this-cdr (if (string-match "^[-0-9.]+$" (caddr temp-list))
|
||||
(caddr temp-list) "")))
|
||||
(setq this-cons (cons tag (cons this-car this-cdr))
|
||||
temp-list nil))
|
||||
(setq temp-list (cdr temp-list))))
|
||||
@@ -1062,7 +1058,7 @@ arguments."
|
||||
(cons tag (cons (match-string 1 (car temp-list))
|
||||
(match-string 2 (car temp-list))))
|
||||
arg-list (cl-remove (car temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
temp-list nil)
|
||||
(setq temp-list (cdr temp-list)) ))
|
||||
;; ---------------------------- labels
|
||||
@@ -1072,7 +1068,7 @@ arguments."
|
||||
")") ; closing paren
|
||||
(car temp-list))
|
||||
(let* ((list (split-string (car temp-list) "[ \t(),]+"))
|
||||
(list (cl-remove "" list :test 'equal))
|
||||
(list (remove "" list))
|
||||
(return ()))
|
||||
(while list
|
||||
(if (string-match "['\"]\\([^'\"]*\\)['\"]" (car list))
|
||||
@@ -1084,18 +1080,18 @@ arguments."
|
||||
(setq list (cdr list)) )
|
||||
(setq this-cons (cons tag return)
|
||||
arg-list (cl-remove (car temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
temp-list nil))
|
||||
(setq temp-list (cdr temp-list))) )
|
||||
;; ---------------------------- string, file, format
|
||||
((cl-member symbol '(string file format) :test 'equal)
|
||||
((memq symbol '(string file format))
|
||||
(if (string-match (concat "['\"]" ; opening quote
|
||||
"\\([^'\"]*\\)" ; string
|
||||
"['\"]") ; closing quote
|
||||
(car temp-list))
|
||||
(setq this-cons (cons tag (match-string 0 (car temp-list)))
|
||||
arg-list (cl-remove (car temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
temp-list nil)
|
||||
(setq temp-list (cdr temp-list)) ))
|
||||
;; ---------------------------- string*
|
||||
@@ -1103,9 +1099,9 @@ arguments."
|
||||
(if (equal prefix (car temp-list))
|
||||
(setq this-cons (cons tag (cadr temp-list))
|
||||
arg-list (cl-remove (car temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
arg-list (cl-remove (cadr temp-list) arg-list
|
||||
:test 'equal :count 1)
|
||||
:test #'equal :count 1)
|
||||
temp-list nil)
|
||||
(setq temp-list (cdr temp-list)) ) )
|
||||
;; ---------------------------- other or unknown
|
||||
@@ -1237,19 +1233,19 @@ SAVE-FRAME is non-nil when the widgets are being reset."
|
||||
(widget-insert "\t") ; insert the appropriate widget
|
||||
(cond
|
||||
;;------------------------------ list, list* ------------
|
||||
((cl-member (eval wtype) '(list list*) :test 'equal)
|
||||
((memq (eval wtype) '(list list*))
|
||||
(let ((starred (if (equal (eval wtype) 'list*) t nil)))
|
||||
(gnuplot-gui-menu-choice tag default list starred)))
|
||||
;;------------------------------ number, tag, fontsize --
|
||||
((cl-member (eval wtype) '(number tag fontsize) :test 'equal)
|
||||
((memq (eval wtype) '(number tag fontsize))
|
||||
(gnuplot-gui-number tag default prefix))
|
||||
;;------------------------------ position ---------------
|
||||
;;------------------------------ range, pair ------------
|
||||
((cl-member (eval wtype) '(range pair) :test 'equal)
|
||||
((memq (eval wtype) '(range pair))
|
||||
(let ((is-range (equal (eval wtype) 'range)))
|
||||
(gnuplot-gui-range tag default prefix is-range)))
|
||||
;;------------------------------ string, string* --------
|
||||
((cl-member (eval wtype) '(string string*) :test 'equal)
|
||||
((memq (eval wtype) '(string string*))
|
||||
(let ((starred (if (equal (eval wtype) 'string) nil t)))
|
||||
(gnuplot-gui-string tag default prefix starred)))
|
||||
;;------------------------------ format -----------------
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "gnuplot" "20250724.1531"
|
||||
(define-package "gnuplot" "20260322.20"
|
||||
"Major-mode and interactive frontend for gnuplot."
|
||||
'((emacs "28.1")
|
||||
(compat "30"))
|
||||
:url "https://github.com/emacs-gnuplot/gnuplot"
|
||||
:commit "43e9674b869475b1c2a32f045c167673eb2faae0"
|
||||
:revdesc "43e9674b8694"
|
||||
:commit "39ba1dec5e8e227ba093a30ca07b20d8eb038f29"
|
||||
:revdesc "39ba1dec5e8e"
|
||||
:keywords '("data" "gnuplot" "plotting")
|
||||
:maintainers '(("Maxime Tréca" . "maxime@gmail.com")
|
||||
("Daniel Mendler" . "mail@daniel-mendler.de")))
|
||||
|
||||
@@ -5,14 +5,12 @@
|
||||
;; Author: Jon Oddie, Bruce Ravel, Phil Type
|
||||
;; Maintainer: Maxime Tréca <maxime@gmail.com>, Daniel Mendler <mail@daniel-mendler.de>
|
||||
;; Created: 1998
|
||||
;; Package-Version: 20250724.1531
|
||||
;; Package-Revision: 43e9674b8694
|
||||
;; Package-Version: 20260322.20
|
||||
;; Package-Revision: 39ba1dec5e8e
|
||||
;; Keywords: data gnuplot plotting
|
||||
;; URL: https://github.com/emacs-gnuplot/gnuplot
|
||||
;; Package-Requires: ((emacs "28.1") (compat "30"))
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
|
||||
;; 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
This is gnuplot.info, produced by makeinfo version 7.2 from
|
||||
This is gnuplot.info, produced by makeinfo version 7.3 from
|
||||
gnuplot.texi.
|
||||
|
||||
INFO-DIR-SECTION Math
|
||||
@@ -23499,7 +23499,7 @@ Concept Index
|
||||
* ? <3>: gamma. (line 9)
|
||||
* ? <4>: inverf. (line 7)
|
||||
* ? <5>: imag. (line 7)
|
||||
* ? <6>: invnorm. (line 10)
|
||||
* ? <6>: invnorm. (line 9)
|
||||
* ? <7>: invnorm. (line 9)
|
||||
* ? <8>: real. (line 6)
|
||||
* ? <9>: sqrt. (line 8)
|
||||
@@ -23519,13 +23519,13 @@ Concept Index
|
||||
* ? <23>: words. (line 33)
|
||||
* ? <24>: words. (line 35)
|
||||
* ? <25>: words. (line 38)
|
||||
* ? <26>: words. (line 40)
|
||||
* ? <27>: words. (line 40)
|
||||
* ? <28>: words. (line 40)
|
||||
* ? <26>: words. (line 39)
|
||||
* ? <27>: words. (line 39)
|
||||
* ? <28>: words. (line 39)
|
||||
* ? <29>: words. (line 39)
|
||||
* ? <30>: hsv2rgb. (line 7)
|
||||
* ? <31>: rgbcolor. (line 11)
|
||||
* ? <32>: rgbcolor. (line 13)
|
||||
* ? <32>: rgbcolor. (line 12)
|
||||
* ? <33>: rgbcolor. (line 12)
|
||||
* .gnuplot: Start-up_(initialization).
|
||||
(line 6)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "indent-guide" "20210115.400"
|
||||
(define-package "indent-guide" "20260211.1005"
|
||||
"Show vertical lines to guide indentation."
|
||||
()
|
||||
:url "http://hins11.yu-yake.com/"
|
||||
:commit "d388c3387781a370ca13233ff445d03f3c5cf12f"
|
||||
:revdesc "d388c3387781")
|
||||
:commit "f3455c6c798b568a6ea1013b7eea1153d2e092be"
|
||||
:revdesc "f3455c6c798b")
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
;; Author: zk_phi
|
||||
;; URL: http://hins11.yu-yake.com/
|
||||
;; Package-Version: 20210115.400
|
||||
;; Package-Revision: d388c3387781
|
||||
;; Package-Version: 20260211.1005
|
||||
;; Package-Revision: f3455c6c798b
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
(require 'cl-lib)
|
||||
|
||||
(defconst indent-guide-version "2.3.1")
|
||||
(defconst indent-guide-version "2.4")
|
||||
|
||||
;; * customs
|
||||
|
||||
@@ -85,7 +85,17 @@
|
||||
:group 'environment)
|
||||
|
||||
(defcustom indent-guide-char "|"
|
||||
"Character used as vertical line."
|
||||
"Character used for the guide line."
|
||||
:type 'string
|
||||
:group 'indent-guide)
|
||||
|
||||
(defcustom indent-guide-char-top nil
|
||||
"when non-nil, character used for the top of the guide line."
|
||||
:type 'string
|
||||
:group 'indent-guide)
|
||||
|
||||
(defcustom indent-guide-char-bottom nil
|
||||
"when non-nil, character used for the bottom of the guide line."
|
||||
:type 'string
|
||||
:group 'indent-guide)
|
||||
|
||||
@@ -178,9 +188,21 @@ the point. When no such points are found, just return nil."
|
||||
(and (search-backward-regexp regex nil t)
|
||||
(goto-char (match-end 1))))))
|
||||
|
||||
;;; NOTE(arka): custom fn for decorated guide line
|
||||
(defun indent-guide--choose-char (line line-start line-end)
|
||||
"Return the appropriate guide character for LINE."
|
||||
(if (= line-start line-end)
|
||||
indent-guide-char
|
||||
(cond
|
||||
((= line line-start) (or indent-guide-char-top indent-guide-char))
|
||||
((= line line-end) (or indent-guide-char-bottom indent-guide-char))
|
||||
(t indent-guide-char)))
|
||||
)
|
||||
|
||||
;; * generate guides
|
||||
|
||||
(defun indent-guide--make-overlay (line col)
|
||||
;;; NOTE(arka): extra `line-start` and `line-end` are parameters added for decorated guide line
|
||||
(defun indent-guide--make-overlay (line col line-start line-end)
|
||||
"draw line at (line, col)"
|
||||
(let (diff string ov prop)
|
||||
(save-excursion
|
||||
@@ -204,10 +226,14 @@ the point. When no such points are found, just return nil."
|
||||
(setq string (let ((str (overlay-get ov 'before-string)))
|
||||
(concat str
|
||||
(make-string (- diff (length str)) ?\s)
|
||||
(propertize indent-guide-char 'face 'indent-guide-face)))
|
||||
;;; NOTE(arka): automatic indentaiton guide character selection
|
||||
;;; based on line number count.
|
||||
(propertize (indent-guide--choose-char line line-start line-end)
|
||||
'face 'indent-guide-face)))
|
||||
prop 'before-string)
|
||||
(setq string (concat (make-string diff ?\s)
|
||||
(propertize indent-guide-char 'face 'indent-guide-face))
|
||||
(propertize (indent-guide--choose-char line line-start line-end)
|
||||
'face 'indent-guide-face))
|
||||
prop 'before-string
|
||||
ov (make-overlay (point) (point)))))
|
||||
((< diff 0) ; the column is inside a tab
|
||||
@@ -226,19 +252,22 @@ the point. When no such points are found, just return nil."
|
||||
str)
|
||||
prop 'display)
|
||||
(setq string (concat (make-string (+ tab-width diff) ?\s)
|
||||
(propertize indent-guide-char 'face 'indent-guide-face)
|
||||
(propertize (indent-guide--choose-char line line-start line-end)
|
||||
'face 'indent-guide-face)
|
||||
(make-string (1- (- diff)) ?\s))
|
||||
prop 'display
|
||||
ov (make-overlay (point) (1- (point))))))
|
||||
((looking-at "\t") ; okay but looking at tab
|
||||
;; <-tab-width->
|
||||
;; [|]
|
||||
(setq string (concat (propertize indent-guide-char 'face 'indent-guide-face)
|
||||
(setq string (concat (propertize (indent-guide--choose-char line line-start line-end)
|
||||
'face 'indent-guide-face)
|
||||
(make-string (1- tab-width) ?\s))
|
||||
prop 'display
|
||||
ov (make-overlay (point) (1+ (point)))))
|
||||
(t ; okay and looking at a space
|
||||
(setq string (propertize indent-guide-char 'face 'indent-guide-face)
|
||||
(setq string (propertize (indent-guide--choose-char line line-start line-end)
|
||||
'face 'indent-guide-face)
|
||||
prop 'display
|
||||
ov (make-overlay (point) (1+ (point))))))
|
||||
(when ov
|
||||
@@ -247,8 +276,10 @@ the point. When no such points are found, just return nil."
|
||||
|
||||
(defun indent-guide-show ()
|
||||
(interactive)
|
||||
(unless (or (indent-guide--active-overlays)
|
||||
(active-minibuffer-window))
|
||||
;;; NOTE(arka): redraw only when needed
|
||||
(unless (active-minibuffer-window)
|
||||
(indent-guide-remove)
|
||||
|
||||
(let ((win-start (window-start))
|
||||
(win-end (window-end nil t))
|
||||
line-col line-start line-end)
|
||||
@@ -279,7 +310,7 @@ the point. When no such points are found, just return nil."
|
||||
(setq line-end (line-number-at-pos)))))
|
||||
;; draw line
|
||||
(dotimes (tmp (- (1+ line-end) line-start))
|
||||
(indent-guide--make-overlay (+ line-start tmp) line-col))
|
||||
(indent-guide--make-overlay (+ line-start tmp) line-col line-start line-end))
|
||||
(remove-overlays (point) (point) 'category 'indent-guide)))))
|
||||
|
||||
(defun indent-guide-remove ()
|
||||
@@ -298,10 +329,16 @@ the point. When no such points are found, just return nil."
|
||||
(indent-guide-show)
|
||||
(setq indent-guide--timer-object nil)))))))
|
||||
|
||||
(defun indent-guide-pre-command-hook ()
|
||||
;; some commands' behavior may affected by indent-guide overlays, so
|
||||
;; remove all overlays in pre-command-hook.
|
||||
(indent-guide-remove))
|
||||
;;; NOTE(arka): root cause of flickering effect. we don't actually need
|
||||
;;; pre-hook to redraw guides on each command.
|
||||
;; (defun indent-guide-pre-command-hook ()
|
||||
;; ;; some commands' behavior may affected by indent-guide overlays, so
|
||||
;; ;; remove all overlays in pre-command-hook.
|
||||
;; (indent-guide-remove))
|
||||
|
||||
;;; NOTE(arka): fn to fix flickering effect when scrolling.
|
||||
(defun indent-guide--window-scroll-hook (&rest _)
|
||||
(indent-guide-show))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode indent-guide-mode
|
||||
@@ -311,10 +348,11 @@ the point. When no such points are found, just return nil."
|
||||
:global nil
|
||||
(if indent-guide-mode
|
||||
(progn
|
||||
(add-hook 'pre-command-hook 'indent-guide-pre-command-hook nil t)
|
||||
(add-hook 'post-command-hook 'indent-guide-post-command-hook nil t))
|
||||
(remove-hook 'pre-command-hook 'indent-guide-pre-command-hook t)
|
||||
(remove-hook 'post-command-hook 'indent-guide-post-command-hook t)))
|
||||
;;; NOTE(arka): only use post-hook. pre-hook is now depricated
|
||||
(add-hook 'post-command-hook 'indent-guide-post-command-hook nil t)
|
||||
(add-hook 'window-scroll-functions 'indent-guide--window-scroll-hook nil t))
|
||||
(remove-hook 'post-command-hook 'indent-guide-post-command-hook t)
|
||||
(remove-hook 'window-scroll-functions 'indent-guide--window-scroll-hook t)))
|
||||
|
||||
;;;###autoload
|
||||
(define-globalized-minor-mode indent-guide-global-mode
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
;;; colir.el --- Color blending library -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2015-2025 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2015-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Oleh Krehel <ohwoeowho@gmail.com>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; ivy-faces.el --- Faces for Ivy -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2020-2025 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2020-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Oleh Krehel <ohwoeowho@gmail.com>
|
||||
;; Keywords: convenience
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; ivy-overlay.el --- Overlay display functions for Ivy -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2016-2025 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2016-2026 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Oleh Krehel <ohwoeowho@gmail.com>
|
||||
;; Keywords: convenience
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "ivy" "20251123.1023"
|
||||
(define-package "ivy" "20260318.1355"
|
||||
"Incremental Vertical completYon."
|
||||
'((emacs "24.5"))
|
||||
:url "https://github.com/abo-abo/swiper"
|
||||
:commit "ec9421340c88ebe08f05680e22308ed57ed68a3d"
|
||||
:revdesc "ec9421340c88"
|
||||
:commit "1005bff8a700b92dc464f770aff8a0db5b4a1c0b"
|
||||
:revdesc "1005bff8a700"
|
||||
:keywords '("matching")
|
||||
:authors '(("Oleh Krehel" . "ohwoeowho@gmail.com"))
|
||||
:maintainers '(("Basil L. Contovounesios" . "basil@contovou.net")))
|
||||
|
||||
+365
-217
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,4 +1,4 @@
|
||||
This is ivy.info, produced by makeinfo version 7.2 from ivy.texi.
|
||||
This is ivy.info, produced by makeinfo version 7.3 from ivy.texi.
|
||||
|
||||
Ivy manual, version 0.15.1
|
||||
|
||||
@@ -11,7 +11,7 @@ available choices while previewing in the minibuffer. Selecting the
|
||||
final candidate is either through simple keyboard character inputs or
|
||||
through powerful regular expressions.
|
||||
|
||||
Copyright (C) 2015-2025 Free Software Foundation, Inc.
|
||||
Copyright (C) 2015-2026 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU Free Documentation License,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
This is ledger-mode.info, produced by makeinfo version 7.2 from
|
||||
This is ledger-mode.info, produced by makeinfo version 7.3 from
|
||||
ledger-mode.texi.
|
||||
|
||||
Copyright © 2013, Craig Earls. All rights reserved.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
((nil
|
||||
(indent-tabs-mode . nil))
|
||||
(emacs-lisp-mode
|
||||
(lisp-indent-local-overrides . ((cond . 0) (interactive . 0))))
|
||||
(makefile-mode
|
||||
(indent-tabs-mode . t))
|
||||
(git-commit-mode
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "llama" "20251101.2002"
|
||||
(define-package "llama" "20260301.1253"
|
||||
"Compact syntax for short lambda."
|
||||
'((emacs "26.1")
|
||||
(compat "30.1"))
|
||||
:url "https://github.com/tarsius/llama"
|
||||
:commit "e4803de8ab85991b6a944430bb4f543ea338636d"
|
||||
:revdesc "e4803de8ab85"
|
||||
:commit "d430d48e0b5afd2a34b5531f103dcb110c3539c4"
|
||||
:revdesc "d430d48e0b5a"
|
||||
:keywords '("extensions"))
|
||||
|
||||
+5
-4
@@ -1,13 +1,13 @@
|
||||
;;; llama.el --- Compact syntax for short lambda -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2020-2025 Jonas Bernoulli
|
||||
;; Copyright (C) 2020-2026 Jonas Bernoulli
|
||||
|
||||
;; Authors: Jonas Bernoulli <emacs.llama@jonas.bernoulli.dev>
|
||||
;; Homepage: https://github.com/tarsius/llama
|
||||
;; Keywords: extensions
|
||||
|
||||
;; Package-Version: 20251101.2002
|
||||
;; Package-Revision: e4803de8ab85
|
||||
;; Package-Version: 20260301.1253
|
||||
;; Package-Revision: d430d48e0b5a
|
||||
;; Package-Requires: (
|
||||
;; (emacs "26.1")
|
||||
;; (compat "30.1"))
|
||||
@@ -355,7 +355,8 @@ expansion, and the looks of this face should hint at that.")
|
||||
(prog1 t
|
||||
(save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
(when-let ((_(save-match-data (not (nth 8 (syntax-ppss)))))
|
||||
(when-let*
|
||||
((_(save-match-data (not (nth 8 (syntax-ppss)))))
|
||||
(expr (ignore-errors
|
||||
(read-positioning-symbols (current-buffer)))))
|
||||
(put-text-property (match-beginning 0) (point)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
;; -*- no-byte-compile: t; lexical-binding: nil -*-
|
||||
(define-package "magit-section" "20251220.917"
|
||||
(define-package "magit-section" "20260330.1102"
|
||||
"Sections for read-only buffers."
|
||||
'((emacs "28.1")
|
||||
(compat "30.1")
|
||||
(cond-let "0.1")
|
||||
(cond-let "0.2")
|
||||
(llama "1.0")
|
||||
(seq "2.24"))
|
||||
:url "https://github.com/magit/magit"
|
||||
:commit "649b4c972151c0ee495876c0d4c8c13787614886"
|
||||
:revdesc "649b4c972151"
|
||||
:commit "89a51310bd8f8087c44f7ac5c902cc82dddbbe2a"
|
||||
:revdesc "89a51310bd8f"
|
||||
:keywords '("tools")
|
||||
:authors '(("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev"))
|
||||
:maintainers '(("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev")))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-section.el --- Sections for read-only buffers -*- lexical-binding:t; coding:utf-8 -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -8,12 +8,12 @@
|
||||
;; Homepage: https://github.com/magit/magit
|
||||
;; Keywords: tools
|
||||
|
||||
;; Package-Version: 20251220.917
|
||||
;; Package-Revision: 649b4c972151
|
||||
;; Package-Version: 20260330.1102
|
||||
;; Package-Revision: 89a51310bd8f
|
||||
;; Package-Requires: (
|
||||
;; (emacs "28.1")
|
||||
;; (compat "30.1")
|
||||
;; (cond-let "0.1")
|
||||
;; (cond-let "0.2")
|
||||
;; (llama "1.0")
|
||||
;; (seq "2.24"))
|
||||
|
||||
@@ -106,7 +106,8 @@ similar defect.")
|
||||
'magit-section-keep-region-overlay "Magit-Section 4.0.0")
|
||||
|
||||
(make-obsolete-variable 'magit-section-visibility-indicator
|
||||
'magit-section-visibility-indicators "Magit-Section 4.5.0")
|
||||
'magit-section-visibility-indicators
|
||||
"Magit-Section 4.5.0")
|
||||
|
||||
;;; Hooks
|
||||
|
||||
@@ -885,10 +886,10 @@ If there is no previous sibling section, then move to the parent."
|
||||
(defun magit-section-goto (arg)
|
||||
"Run `magit-section-movement-hook'.
|
||||
See info node `(magit)Section Movement'."
|
||||
(if (integerp arg)
|
||||
(progn (forward-line arg)
|
||||
(cond ((integerp arg)
|
||||
(forward-line arg)
|
||||
(setq arg (magit-current-section)))
|
||||
(goto-char (oref arg start)))
|
||||
((goto-char (oref arg start))))
|
||||
(run-hook-with-args 'magit-section-movement-hook arg))
|
||||
|
||||
(defun magit-section-set-window-start (section)
|
||||
@@ -936,8 +937,8 @@ With a prefix argument also expand it." heading)
|
||||
(oset section hidden nil)
|
||||
(magit-section--opportunistic-wash section)
|
||||
(magit-section--opportunistic-paint section)
|
||||
(when-let ((beg (oref section content)))
|
||||
(remove-overlays beg (oref section end) 'invisible t))
|
||||
(when$ (oref section content)
|
||||
(remove-overlays $ (oref section end) 'invisible t))
|
||||
(magit-section-maybe-update-visibility-indicator section)
|
||||
(magit-section-maybe-cache-visibility section)
|
||||
(dolist (child (oref section children))
|
||||
@@ -2677,6 +2678,7 @@ with the variables' values as arguments, which were recorded by
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
This is magit-section.info, produced by makeinfo version 7.2 from
|
||||
This is magit-section.info, produced by makeinfo version 7.3 from
|
||||
magit-section.texi.
|
||||
|
||||
Copyright (C) 2015-2025 Jonas Bernoulli
|
||||
Copyright (C) 2015-2026 Jonas Bernoulli
|
||||
<emacs.magit@jonas.bernoulli.dev>
|
||||
|
||||
You can redistribute this document and/or modify it under the terms
|
||||
@@ -34,9 +34,9 @@ packages that have nothing to do with Magit or Git.
|
||||
and user options see *note (magit)Sections::. This manual documents how
|
||||
you can use sections in your own packages.
|
||||
|
||||
This manual is for Magit-Section version 4.4.2.
|
||||
This manual is for Magit-Section version 4.5.0.
|
||||
|
||||
Copyright (C) 2015-2025 Jonas Bernoulli
|
||||
Copyright (C) 2015-2026 Jonas Bernoulli
|
||||
<emacs.magit@jonas.bernoulli.dev>
|
||||
|
||||
You can redistribute this document and/or modify it under the terms
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
((nil
|
||||
(indent-tabs-mode . nil))
|
||||
(emacs-lisp-mode
|
||||
(checkdoc-allow-quoting-nil-and-t . t)
|
||||
(lisp-indent-local-overrides . ((cond . 0) (interactive . 0))))
|
||||
(makefile-mode
|
||||
(indent-tabs-mode . t)
|
||||
(outline-regexp . "#\\(#+\\)")
|
||||
(mode . outline-minor))
|
||||
(emacs-lisp-mode
|
||||
(checkdoc-allow-quoting-nil-and-t . t))
|
||||
(mode . outline-minor)
|
||||
(outline-regexp . "#\\(#+\\)"))
|
||||
(git-commit-mode
|
||||
(git-commit-major-mode . git-commit-elisp-text-mode))
|
||||
(".github/PULL_REQUEST_TEMPLATE"
|
||||
|
||||
@@ -49,6 +49,7 @@ All Contributors
|
||||
- Alex Kreisher
|
||||
- Alex Ott
|
||||
- Allen Li
|
||||
- Andrea Alberti
|
||||
- Andreas Fuchs
|
||||
- Andreas Liljeqvist
|
||||
- Andreas Rottmann
|
||||
@@ -230,6 +231,7 @@ All Contributors
|
||||
- Lele Gaifax
|
||||
- Lénaïc Huard
|
||||
- Leo Liu
|
||||
- Leonard Lausen
|
||||
- Leonardo Etcheverry
|
||||
- Leo Vivier
|
||||
- Li Chen
|
||||
|
||||
+187
-58
@@ -1,6 +1,6 @@
|
||||
;;; git-commit.el --- Edit Git commit messages -*- lexical-binding:t; coding:utf-8 -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Sebastian Wiesner <lunaryorn@gmail.com>
|
||||
@@ -110,6 +110,7 @@
|
||||
(require 'transient)
|
||||
(require 'with-editor)
|
||||
|
||||
(defvar dabbrev--abbrev-char-regexp)
|
||||
(defvar diff-default-read-only)
|
||||
(defvar flyspell-generic-check-word-predicate)
|
||||
(defvar font-lock-beg)
|
||||
@@ -118,6 +119,12 @@
|
||||
|
||||
(defvar git-commit-need-summary-line)
|
||||
|
||||
(declare-function dabbrev--reset-global-variables "dabbrev" ())
|
||||
(declare-function dabbrev-capf "dabbrev" ())
|
||||
(declare-function magit-commit-diff--args "magit-commit" ())
|
||||
(declare-function magit-diff--modified-defuns "magit-diff" ())
|
||||
(declare-function magit-diff-arguments "magit-diff" (&optional mode))
|
||||
|
||||
(define-obsolete-variable-alias
|
||||
'git-commit-known-pseudo-headers
|
||||
'git-commit-trailers
|
||||
@@ -132,42 +139,6 @@
|
||||
:link '(info-link "(magit)Editing Commit Messages")
|
||||
:group 'tools)
|
||||
|
||||
(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.
|
||||
|
||||
Loading the library `git-commit' by default enables this mode,
|
||||
but the library is not automatically loaded because doing that
|
||||
would pull in many dependencies and increase startup time too
|
||||
much. You can either rely on `magit' loading this library or
|
||||
you can load it explicitly. Autoloading is not an alternative
|
||||
because in this case autoloading would immediately trigger
|
||||
full loading."
|
||||
: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)
|
||||
(remove-hook 'after-change-major-mode-hook
|
||||
#'git-commit-setup-font-lock-in-buffer)))
|
||||
(cond
|
||||
(global-git-commit-mode
|
||||
(add-hook 'find-file-hook #'git-commit-setup-check-buffer)
|
||||
(add-hook 'after-change-major-mode-hook
|
||||
#'git-commit-setup-font-lock-in-buffer))
|
||||
(t
|
||||
(remove-hook 'find-file-hook #'git-commit-setup-check-buffer)
|
||||
(remove-hook 'after-change-major-mode-hook
|
||||
#'git-commit-setup-font-lock-in-buffer))))
|
||||
|
||||
(defcustom git-commit-major-mode #'text-mode
|
||||
"Major mode used to edit Git commit messages.
|
||||
|
||||
@@ -198,9 +169,11 @@ Also note that `git-commit-mode' (which see) is not a major-mode.")
|
||||
(defcustom git-commit-setup-hook
|
||||
(list #'git-commit-ensure-comment-gap
|
||||
#'git-commit-save-message
|
||||
#'git-commit-setup-capf
|
||||
#'git-commit-setup-changelog-support
|
||||
#'git-commit-turn-on-auto-fill
|
||||
#'git-commit-setup-auto-fill
|
||||
#'git-commit-propertize-diff
|
||||
#'git-commit-collapse-diff
|
||||
#'bug-reference-mode)
|
||||
"Hook run at the end of `git-commit-setup'."
|
||||
:group 'git-commit
|
||||
@@ -208,12 +181,14 @@ Also note that `git-commit-mode' (which see) is not a major-mode.")
|
||||
:get #'magit-hook-custom-get
|
||||
:options '(git-commit-ensure-comment-gap
|
||||
git-commit-save-message
|
||||
git-commit-setup-capf
|
||||
git-commit-setup-changelog-support
|
||||
magit-generate-changelog
|
||||
git-commit-turn-on-auto-fill
|
||||
git-commit-turn-on-orglink
|
||||
git-commit-turn-on-flyspell
|
||||
git-commit-setup-auto-fill
|
||||
git-commit-setup-orglink
|
||||
git-commit-setup-flyspell
|
||||
git-commit-propertize-diff
|
||||
git-commit-collapse-diff
|
||||
bug-reference-mode))
|
||||
|
||||
(defcustom git-commit-finish-query-functions
|
||||
@@ -363,6 +338,11 @@ In this context a \"keyword\" is text surrounded by brackets."
|
||||
"Face used for headings in commit message comments."
|
||||
:group 'git-commit-faces)
|
||||
|
||||
(defface git-commit-comment-button
|
||||
'((t :inherit git-commit-comment-heading :underline t))
|
||||
"Face used for buttons in commit message comments."
|
||||
:group 'git-commit-faces)
|
||||
|
||||
(defface git-commit-comment-file
|
||||
'((t :inherit git-commit-trailer-value))
|
||||
"Face used for file names in commit message comments."
|
||||
@@ -437,7 +417,43 @@ the redundant bindings, then set this to nil, before loading
|
||||
["Cancel" with-editor-cancel t]
|
||||
["Commit" with-editor-finish t]))
|
||||
|
||||
;;; Hooks
|
||||
;;; Global Mode
|
||||
|
||||
(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.
|
||||
|
||||
Loading the library `git-commit' by default enables this mode,
|
||||
but the library is not automatically loaded because doing that
|
||||
would pull in many dependencies and increase startup time too
|
||||
much. You can either rely on `magit' loading this library or
|
||||
you can load it explicitly. Autoloading is not an alternative
|
||||
because in this case autoloading would immediately trigger
|
||||
full loading."
|
||||
: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)
|
||||
(remove-hook 'after-change-major-mode-hook
|
||||
#'git-commit-setup-font-lock-in-buffer)))
|
||||
(cond
|
||||
(global-git-commit-mode
|
||||
(add-hook 'find-file-hook #'git-commit-setup-check-buffer)
|
||||
(add-hook 'after-change-major-mode-hook
|
||||
#'git-commit-setup-font-lock-in-buffer))
|
||||
(t
|
||||
(remove-hook 'find-file-hook #'git-commit-setup-check-buffer)
|
||||
(remove-hook 'after-change-major-mode-hook
|
||||
#'git-commit-setup-font-lock-in-buffer))))
|
||||
|
||||
(defconst git-commit-filename-regexp "/\\(\
|
||||
\\(\\(COMMIT\\|NOTES\\|PULLREQ\\|MERGEREQ\\|TAG\\)_EDIT\\|MERGE_\\|\\)MSG\
|
||||
@@ -458,8 +474,6 @@ the redundant bindings, then set this to nil, before loading
|
||||
(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.
|
||||
@@ -480,6 +494,10 @@ the redundant bindings, then set this to nil, before loading
|
||||
(when (eq system-type 'windows-nt)
|
||||
(add-hook 'find-file-not-found-functions #'git-commit-file-not-found))
|
||||
|
||||
;;; Local Mode
|
||||
|
||||
(defvar git-commit-mode)
|
||||
|
||||
(defconst git-commit-default-usage-message "\
|
||||
Type \\[with-editor-finish] to finish, \
|
||||
\\[with-editor-cancel] to cancel, and \
|
||||
@@ -504,6 +522,12 @@ Used as the local value of `header-line-format', in buffer using
|
||||
(setq git-commit-usage-message nil) ; show a shorter message")
|
||||
|
||||
(defun git-commit-setup ()
|
||||
;; If an error occurs when `emacsclient' is used, and it turns out
|
||||
;; to not be triggered by something in this function, then another
|
||||
;; likely source are functions on `server-switch-hook'. Debugging
|
||||
;; is suppressed while running that hook, so it may be necessary to
|
||||
;; force debugging by modifying those functions directly. Enabling
|
||||
;; `magit-process-record-invocations' may also help.
|
||||
(let ((gitdir default-directory)
|
||||
(cd (and git-commit-cd-to-toplevel
|
||||
(or (car (rassoc default-directory magit--separated-gitdirs))
|
||||
@@ -568,9 +592,9 @@ Used as the local value of `header-line-format', in buffer using
|
||||
(with-demoted-errors "Error running git-commit-setup-hook: %S"
|
||||
(run-hooks 'git-commit-setup-hook))
|
||||
(set-buffer-modified-p nil)
|
||||
(when-let ((format git-commit-header-line-format))
|
||||
(when$ git-commit-header-line-format
|
||||
(setq header-line-format
|
||||
(if (stringp format) (substitute-command-keys format) format)))
|
||||
(if (stringp $) (substitute-command-keys $) $)))
|
||||
(when git-commit-usage-message
|
||||
(setq with-editor-usage-message git-commit-usage-message))
|
||||
(with-editor-usage-message))
|
||||
@@ -585,6 +609,8 @@ used."
|
||||
|
||||
(put 'git-commit-mode 'permanent-local t)
|
||||
|
||||
;;; Setup
|
||||
|
||||
(defun git-commit-ensure-comment-gap ()
|
||||
"Separate initial empty line from initial comment.
|
||||
If the buffer begins with an empty line followed by a comment, insert
|
||||
@@ -595,25 +621,36 @@ the input isn't tacked to the comment."
|
||||
(when (looking-at (format "\\`\n%s" comment-start))
|
||||
(open-line 1))))
|
||||
|
||||
(defun git-commit-setup-capf ()
|
||||
"Teach `complete-symbol' about `dabbrev-capf'.
|
||||
When \"git commit\"'s \"--verbose\" argument is used, this allows
|
||||
completing modified symbols and other text appearing in the diff."
|
||||
(require 'dabbrev)
|
||||
(unless dabbrev--abbrev-char-regexp
|
||||
;; Initialize (not "reset") variables. See #5545.
|
||||
(dabbrev--reset-global-variables))
|
||||
(add-hook 'completion-at-point-functions #'dabbrev-capf -90 t))
|
||||
|
||||
(defun git-commit-setup-changelog-support ()
|
||||
"Treat ChangeLog entries as unindented paragraphs."
|
||||
(setq-local fill-paragraph-function #'log-edit-fill-entry)
|
||||
(setq-local fill-indent-according-to-mode t)
|
||||
(setq-local paragraph-start (concat paragraph-start "\\|\\*\\|(")))
|
||||
|
||||
(defun git-commit-turn-on-auto-fill ()
|
||||
(defun git-commit-setup-auto-fill ()
|
||||
"Unconditionally turn on Auto Fill mode.
|
||||
Ensure auto filling happens everywhere, except in the summary line."
|
||||
(auto-fill-mode 1)
|
||||
(setq-local comment-auto-fill-only-comments nil)
|
||||
(when git-commit-need-summary-line
|
||||
(setq-local auto-fill-function #'git-commit-auto-fill-except-summary)))
|
||||
(setq-local auto-fill-function #'git-commit--auto-fill-except-summary)))
|
||||
|
||||
(defun git-commit-auto-fill-except-summary ()
|
||||
(defun git-commit--auto-fill-except-summary ()
|
||||
"Do not fill summary line."
|
||||
(unless (eq (line-beginning-position) 1)
|
||||
(do-auto-fill)))
|
||||
|
||||
(defun git-commit-turn-on-orglink ()
|
||||
(defun git-commit-setup-orglink ()
|
||||
"Turn on Orglink mode if it is available.
|
||||
If `git-commit-major-mode' is `org-mode', then silently forgo
|
||||
turning on `orglink-mode'."
|
||||
@@ -623,15 +660,14 @@ turning on `orglink-mode'."
|
||||
(setq-local orglink-match-anywhere t)
|
||||
(orglink-mode 1)))
|
||||
|
||||
(defun git-commit-turn-on-flyspell ()
|
||||
(defun git-commit-setup-flyspell ()
|
||||
"Unconditionally turn on Flyspell mode.
|
||||
Also check text that is already in the buffer, while avoiding to check
|
||||
most text that Git will strip from the final message, such as the last
|
||||
comment and anything below the cut line (\"--- >8 ---\")."
|
||||
(require 'flyspell)
|
||||
(flyspell-mode 1)
|
||||
(setq flyspell-generic-check-word-predicate
|
||||
#'git-commit-flyspell-verify)
|
||||
(setq flyspell-generic-check-word-predicate #'git-commit--flyspell-verify)
|
||||
(let ((end nil)
|
||||
;; The "cut line" is defined in "git/wt-status.c". It appears
|
||||
;; in the commit message when `commit.verbose' is set to true.
|
||||
@@ -647,10 +683,37 @@ comment and anything below the cut line (\"--- >8 ---\")."
|
||||
(setq end (point)))
|
||||
(flyspell-region (point-min) end)))
|
||||
|
||||
(defun git-commit-flyspell-verify ()
|
||||
(defun git-commit--flyspell-verify ()
|
||||
"Do not check spelling in comments."
|
||||
(not (= (char-after (line-beginning-position))
|
||||
(aref comment-start 0))))
|
||||
|
||||
(defun git-commit-collapse-diff ()
|
||||
"Collapse inline diff and add button to allow expanding it."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward (format "%s -+ >8 -+" comment-start) nil t)
|
||||
(let ((elt '(git-commit-diff t)))
|
||||
(add-to-invisibility-spec elt)
|
||||
(make-button (line-beginning-position) (point)
|
||||
'face 'git-commit-comment-button
|
||||
'keymap (define-keymap :parent button-map
|
||||
"<return>" #'push-button
|
||||
"<tab>" #'push-button)
|
||||
'action (lambda (_)
|
||||
(if (memq elt buffer-invisibility-spec)
|
||||
(remove-from-invisibility-spec elt)
|
||||
(add-to-invisibility-spec elt))
|
||||
;; KLUDGE Force "redisplay".
|
||||
(when-let ((w1 (selected-window))
|
||||
(w2 (next-window)))
|
||||
(select-window w2)
|
||||
(select-window w1)))))
|
||||
(let ((ov (make-overlay (point) (point-max))))
|
||||
(overlay-put ov 'invisible 'git-commit-diff)))))
|
||||
|
||||
;;; Finish
|
||||
|
||||
(defun git-commit-finish-query-functions (force)
|
||||
(run-hook-with-args-until-failure
|
||||
'git-commit-finish-query-functions force))
|
||||
@@ -784,6 +847,55 @@ Save current message first."
|
||||
(setq str (replace-match "\n" t t str)))
|
||||
str))))
|
||||
|
||||
;;; Changelog
|
||||
|
||||
(defun git-commit--modified-defuns ()
|
||||
(if (save-excursion
|
||||
(goto-char (point-min))
|
||||
(re-search-forward "^diff --git" nil t))
|
||||
(magit-diff--modified-defuns)
|
||||
(with-temp-buffer
|
||||
(pcase-let ((`(,rev ,arg) (magit-commit-diff--args)))
|
||||
(save-excursion
|
||||
(magit-git-insert "diff" "-p" arg (car (magit-diff-arguments)) rev)))
|
||||
(magit-diff--modified-defuns))))
|
||||
|
||||
;;;###autoload
|
||||
(defun git-commit-insert-changelog-gnu ()
|
||||
"Insert a GNU-style changelog at point while authorig a commit message.
|
||||
|
||||
The modified definitions are extracted from the diff in the message
|
||||
buffer, which is only available if \"git commit\" was invoked with
|
||||
\"--verbose\"."
|
||||
(interactive)
|
||||
(unless git-commit-mode
|
||||
(user-error "Not in a commit message buffer"))
|
||||
;; Like `change-log-insert-entries'.
|
||||
(pcase-dolist (`(,file . ,defuns) (git-commit--modified-defuns))
|
||||
(if (not defuns)
|
||||
(insert "* " file ":\n")
|
||||
(insert "* " file " ")
|
||||
(dolist (def defuns)
|
||||
(insert "(" def "):\n")))))
|
||||
|
||||
;;;###autoload
|
||||
(defun git-commit-insert-changelog-plain ()
|
||||
"Insert a simple changelog at point while authorig a commit message.
|
||||
|
||||
Defuns are slightly indented and quoted like in elisp docstrings.
|
||||
The exact format is still subject to change.
|
||||
|
||||
The modified definitions are extracted from the diff in the message
|
||||
buffer, which is only available if \"git commit\" was invoked with
|
||||
\"--verbose\"."
|
||||
(interactive)
|
||||
(unless git-commit-mode
|
||||
(user-error "Not in a commit message buffer"))
|
||||
(pcase-dolist (`(,file . ,defuns) (git-commit--modified-defuns))
|
||||
(insert file ":\n")
|
||||
(dolist (def defuns)
|
||||
(insert " `" def "'\n"))))
|
||||
|
||||
;;; Trailers
|
||||
|
||||
(transient-define-prefix git-commit-insert-trailer ()
|
||||
@@ -793,19 +905,22 @@ See also manpage git-interpret-trailer(1). This command does
|
||||
not use that Git command, but the initial description still
|
||||
serves as a good introduction."
|
||||
[[:description (##cond (prefix-arg
|
||||
"Insert ... by someone ")
|
||||
("Insert ... by yourself"))
|
||||
"Insert trailer ... by someone ")
|
||||
("Insert trailer ... by yourself"))
|
||||
("a" "Ack" git-commit-ack)
|
||||
("m" "Modified" git-commit-modified)
|
||||
("r" "Reviewed" git-commit-review)
|
||||
("s" "Signed-off" git-commit-signoff)
|
||||
("t" "Tested" git-commit-test)]
|
||||
["Insert ... by someone"
|
||||
["Insert trailer ... by someone"
|
||||
("C-c" "Cc" git-commit-cc)
|
||||
("C-r" "Reported" git-commit-reported)
|
||||
("C-i" "Suggested" git-commit-suggested)
|
||||
("C-a" "Co-authored" git-commit-co-authored)
|
||||
("C-d" "Co-developed" git-commit-co-developed)]])
|
||||
("C-d" "Co-developed" git-commit-co-developed)]]
|
||||
["Insert changelog"
|
||||
("l g" "GNU-style" git-commit-insert-changelog-gnu)
|
||||
("l p" "plain" git-commit-insert-changelog-plain)])
|
||||
|
||||
(defun git-commit-ack (name mail)
|
||||
"Insert a trailer acknowledging that you have looked at the commit."
|
||||
@@ -1225,6 +1340,19 @@ commit, then the hook is not run at all."
|
||||
'git-commit-trailer-token
|
||||
"git-commit 4.0.0")
|
||||
|
||||
(define-obsolete-function-alias
|
||||
'git-commit-turn-on-auto-fill
|
||||
'git-commit-setup-auto-fill
|
||||
"git-commit 4.6.0")
|
||||
(define-obsolete-function-alias
|
||||
'git-commit-turn-on-flyspell
|
||||
'git-commit-setup-flyspell
|
||||
"git-commit 4.6.0")
|
||||
(define-obsolete-function-alias
|
||||
'git-commit-turn-on-orglink
|
||||
'git-commit-setup-orglink
|
||||
"git-commit 4.6.0")
|
||||
|
||||
(provide 'git-commit)
|
||||
;; Local Variables:
|
||||
;; read-symbol-shorthands: (
|
||||
@@ -1232,6 +1360,7 @@ commit, then the hook is not run at all."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; git-rebase.el --- Edit Git rebase files -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Phil Jackson <phil@shellarchive.co.uk>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -948,6 +948,7 @@ is used as a value for `imenu-extract-index-name-function'."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+29
-28
@@ -1,6 +1,6 @@
|
||||
;;; magit-apply.el --- Apply Git diffs -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -115,19 +115,19 @@ is a member of `magit-post-unstage-hook-commands'."
|
||||
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 ((s (magit-apply--get-selection)))
|
||||
(when$ (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 s args))
|
||||
(`(,_ hunk) (magit-apply-hunk s args))
|
||||
(`(,_ hunks) (magit-apply-hunks s args))
|
||||
(`(,_ region) (magit-apply-region $ args))
|
||||
(`(,_ hunk) (magit-apply-hunk $ args))
|
||||
(`(,_ hunks) (magit-apply-hunks $ args))
|
||||
(`(rebase-sequence file)
|
||||
(call-interactively #'magit-patch-apply))
|
||||
(`(,_ file) (magit-apply-diff s args))
|
||||
(`(,_ files) (magit-apply-diffs s args)))))
|
||||
(`(,_ file) (magit-apply-diff $ args))
|
||||
(`(,_ files) (magit-apply-diffs $ args)))))
|
||||
|
||||
(defun magit-apply--section-content (section)
|
||||
(buffer-substring-no-properties (if (magit-hunk-section-p section)
|
||||
@@ -488,17 +488,17 @@ On a hunk or file with unresolved conflicts prompt which side to
|
||||
keep (while discarding the other). If point is within the text
|
||||
of a side, then keep that side without prompting."
|
||||
(interactive)
|
||||
(when-let ((s (magit-apply--get-selection)))
|
||||
(when$ (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"))
|
||||
(`(untracked list) (magit-discard-untracked))
|
||||
(`(,_ region) (magit-discard-region s))
|
||||
(`(,_ hunk) (magit-discard-hunk s))
|
||||
(`(,_ hunks) (magit-discard-hunks s))
|
||||
(`(,_ file) (magit-discard-file s))
|
||||
(`(,_ files) (magit-discard-files s))
|
||||
(`(,_ list) (magit-discard-files s)))))
|
||||
(`(,_ region) (magit-discard-region $))
|
||||
(`(,_ hunk) (magit-discard-hunk $))
|
||||
(`(,_ hunks) (magit-discard-hunks $))
|
||||
(`(,_ file) (magit-discard-file $))
|
||||
(`(,_ files) (magit-discard-files $))
|
||||
(`(,_ list) (magit-discard-files $)))))
|
||||
|
||||
(defun magit-discard-untracked ()
|
||||
(magit-discard-files--delete
|
||||
@@ -642,13 +642,13 @@ of a side, then keep that side without prompting."
|
||||
files))
|
||||
(dolist (file files)
|
||||
(let ((orig (cadr (assoc file status))))
|
||||
(if (file-exists-p file)
|
||||
(progn
|
||||
(when-let ((path (file-name-directory orig)))
|
||||
(make-directory path t))
|
||||
(cond ((file-exists-p file)
|
||||
(when$ (file-name-directory orig)
|
||||
(make-directory $ t))
|
||||
(magit-call-git "mv" file orig))
|
||||
(t
|
||||
(magit-call-git "rm" "--cached" "--" file)
|
||||
(magit-call-git "reset" "--" orig)))))
|
||||
(magit-call-git "reset" "--" orig))))))
|
||||
|
||||
(defun magit-discard-files--discard (sections new-files)
|
||||
(let ((files (mapcar (##oref % value) sections)))
|
||||
@@ -684,16 +684,16 @@ of a side, then keep that side without prompting."
|
||||
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 ((s (magit-apply--get-selection)))
|
||||
(when$ (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 s args))
|
||||
(`(,_ hunk) (magit-reverse-hunk s args))
|
||||
(`(,_ hunks) (magit-reverse-hunks s args))
|
||||
(`(,_ file) (magit-reverse-file s args))
|
||||
(`(,_ files) (magit-reverse-files s args))
|
||||
(`(,_ list) (magit-reverse-files s args)))))
|
||||
(`(,_ region) (magit-reverse-region $ args))
|
||||
(`(,_ hunk) (magit-reverse-hunk $ args))
|
||||
(`(,_ hunks) (magit-reverse-hunks $ args))
|
||||
(`(,_ file) (magit-reverse-file $ args))
|
||||
(`(,_ files) (magit-reverse-files $ args))
|
||||
(`(,_ list) (magit-reverse-files $ args)))))
|
||||
|
||||
(defun magit-reverse-region (section args)
|
||||
(magit-confirm 'reverse "Reverse region")
|
||||
@@ -717,9 +717,9 @@ so causes the change to be applied to the index as well."
|
||||
(pcase-let ((`(,binaries ,sections)
|
||||
(let ((bs (magit-binary-files
|
||||
(cond ((derived-mode-p 'magit-revision-mode)
|
||||
magit-buffer-range)
|
||||
magit-buffer-diff-range)
|
||||
((derived-mode-p 'magit-diff-mode)
|
||||
magit-buffer-range)
|
||||
magit-buffer-diff-range)
|
||||
("--cached")))))
|
||||
(magit--separate (##member (oref % value) bs)
|
||||
sections))))
|
||||
@@ -822,6 +822,7 @@ a separate commit. A typical workflow would be:
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-autorevert.el --- Revert buffers when files in repository change -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-base.el --- Early birds -*- lexical-binding:t; coding:utf-8 -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -494,7 +494,7 @@ and delay of your graphical environment or operating system."
|
||||
(defclass magit-hunk-section (magit-diff-section)
|
||||
((keymap :initform 'magit-hunk-section-map)
|
||||
(painted :initform nil)
|
||||
(fontified :initform nil) ;TODO
|
||||
(fontified :initform nil)
|
||||
(refined :initform nil)
|
||||
(combined :initform nil :initarg :combined)
|
||||
(from-range :initform nil :initarg :from-range)
|
||||
@@ -824,7 +824,7 @@ ACTION is a member of option `magit-slow-confirm'."
|
||||
(or (cond ((and (not (eq action t))
|
||||
(or (eq magit-no-confirm t)
|
||||
(memq action magit-no-confirm)
|
||||
(cl-member-if (pcase-lambda (`(,key ,var . ,sub))
|
||||
(magit--any (pcase-lambda (`(,key ,var . ,sub))
|
||||
(and (memq key magit-no-confirm)
|
||||
(memq action sub)
|
||||
(or (not var)
|
||||
@@ -1013,6 +1013,24 @@ This function should be named `version>' and be part of Emacs."
|
||||
This function should be named `version>=' and be part of Emacs."
|
||||
(version-list-<= (version-to-list v2) (version-to-list v1)))
|
||||
|
||||
(defun magit--delete-text-properties (string &optional props)
|
||||
"Delete text properties PROPS from STRING and return it.
|
||||
If PROPS is nil, remove all properties. To leave STRING unchanged
|
||||
and return a new string, instead use `magit--remove-text-properties'."
|
||||
(set-text-properties 0 (length string) props string)
|
||||
string)
|
||||
|
||||
(defun magit--remove-text-properties (string &optional props)
|
||||
"Return a copy of STRING with text properties PROPS removed.
|
||||
If PROPS is nil, remove all properties."
|
||||
(magit--delete-text-properties (copy-sequence string) props))
|
||||
|
||||
;;; Emacs Compatibility
|
||||
|
||||
(static-if (fboundp 'member-if) ; Emacs 31.1
|
||||
(defalias 'magit--any 'member-if)
|
||||
(defalias 'magit--any 'cl-member-if))
|
||||
|
||||
;;; Kludges for Emacs Bugs
|
||||
|
||||
(defun magit-which-function ()
|
||||
@@ -1187,6 +1205,16 @@ Like `message', except that `message-log-max' is bound to nil."
|
||||
(push char quoted))
|
||||
(concat (nreverse quoted))))
|
||||
|
||||
(defun magit--find-buffer (&rest plist)
|
||||
"Like `find-buffer' but take multiple VARIABLE-VALUE pairs."
|
||||
(seq-find (lambda (buf)
|
||||
(while (and plist
|
||||
(equal (buffer-local-value (car plist) buf)
|
||||
(cadr plist)))
|
||||
(setq plist (cddr plist)))
|
||||
(not plist))
|
||||
(buffer-list)))
|
||||
|
||||
;;; _
|
||||
(provide 'magit-base)
|
||||
;; Local Variables:
|
||||
@@ -1195,6 +1223,7 @@ Like `message', except that `message-log-max' is bound to nil."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-bisect.el --- Bisect support for Magit -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -321,6 +321,7 @@ bisect run'."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-blame.el --- Blame support for Magit -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -261,7 +261,7 @@ Also see option `magit-blame-styles'."
|
||||
(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))
|
||||
(let ((rev magit-buffer-revision)
|
||||
(file (and (not (derived-mode-p 'dired-mode))
|
||||
(magit-file-relative-name
|
||||
nil (not magit-buffer-file-name))))
|
||||
@@ -418,8 +418,8 @@ modes is toggled, then this mode also gets toggled automatically.
|
||||
(magit-blame-mode 1))
|
||||
(message "Blaming...")
|
||||
(magit-blame-run-process
|
||||
(and$ (or magit-buffer-refname magit-buffer-revision)
|
||||
(and (not (equal $ "{index}")) $))
|
||||
(and (not (equal magit-buffer-revision "{index}"))
|
||||
magit-buffer-revision)
|
||||
(magit-file-relative-name nil (not magit-buffer-file-name))
|
||||
(if (memq magit-blame-type '(final removal))
|
||||
(cons "--reverse" args)
|
||||
@@ -1006,6 +1006,7 @@ instead of the hash, like `kill-ring-save' would."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-bookmark.el --- Bookmarks for Magit buffers -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Inspired by an earlier implementation by Yuri Khan.
|
||||
|
||||
@@ -56,8 +56,8 @@
|
||||
;;;; Diff
|
||||
|
||||
(put 'magit-diff-mode 'magit-bookmark-variables
|
||||
'(magit-buffer-range-hashed
|
||||
magit-buffer-typearg
|
||||
'(magit-buffer-diff-range-oids
|
||||
magit-buffer-diff-typearg
|
||||
magit-buffer-diff-args
|
||||
magit-buffer-diff-files))
|
||||
|
||||
@@ -66,9 +66,10 @@
|
||||
(pcase (magit-diff-type)
|
||||
('staged "staged")
|
||||
('unstaged "unstaged")
|
||||
('committed magit-buffer-range)
|
||||
('committed magit-buffer-diff-range)
|
||||
('undefined
|
||||
(delq nil (list magit-buffer-typearg magit-buffer-range-hashed))))
|
||||
(delq nil
|
||||
(list magit-buffer-diff-typearg magit-buffer-diff-range-oids))))
|
||||
(if magit-buffer-diff-files
|
||||
(concat " -- " (string-join magit-buffer-diff-files " "))
|
||||
"")))
|
||||
@@ -76,7 +77,7 @@
|
||||
;;;; Revision
|
||||
|
||||
(put 'magit-revision-mode 'magit-bookmark-variables
|
||||
'(magit-buffer-revision-hash
|
||||
'(magit-buffer-revision-oid
|
||||
magit-buffer-diff-args
|
||||
magit-buffer-diff-files))
|
||||
|
||||
@@ -90,7 +91,7 @@
|
||||
;;;; Stash
|
||||
|
||||
(put 'magit-stash-mode 'magit-bookmark-variables
|
||||
'(magit-buffer-revision-hash
|
||||
'(magit-buffer-revision-oid
|
||||
magit-buffer-diff-args
|
||||
magit-buffer-diff-files))
|
||||
|
||||
@@ -104,20 +105,20 @@
|
||||
(cl-defmethod magit-bookmark--get-child-value
|
||||
(section &context (major-mode magit-stash-mode))
|
||||
(string-replace magit-buffer-revision
|
||||
magit-buffer-revision-hash
|
||||
magit-buffer-revision-oid
|
||||
(oref section value)))
|
||||
|
||||
;;; Log
|
||||
;;;; Log
|
||||
|
||||
(put 'magit-log-mode 'magit-bookmark-variables
|
||||
'(magit-buffer-revisions
|
||||
'(magit-buffer-log-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)"
|
||||
(string-join magit-buffer-revisions " ")
|
||||
(string-join magit-buffer-log-revisions " ")
|
||||
(if magit-buffer-log-files
|
||||
(concat " -- " (string-join magit-buffer-log-files " "))
|
||||
"")))
|
||||
@@ -126,12 +127,12 @@
|
||||
|
||||
(put 'magit-cherry-mode 'magit-bookmark-variables
|
||||
'(magit-buffer-refname
|
||||
magit-buffer-upstream))
|
||||
magit-buffer-cherry-upstream))
|
||||
|
||||
(cl-defmethod magit-bookmark-name (&context (major-mode magit-cherry-mode))
|
||||
(format "magit-cherry(%s > %s)"
|
||||
magit-buffer-refname
|
||||
magit-buffer-upstream))
|
||||
magit-buffer-cherry-upstream))
|
||||
|
||||
;;;; Reflog
|
||||
|
||||
@@ -146,8 +147,8 @@
|
||||
(put 'magit-status-mode 'magit-bookmark-variables nil)
|
||||
|
||||
(put 'magit-refs-mode 'magit-bookmark-variables
|
||||
'(magit-buffer-upstream
|
||||
magit-buffer-arguments))
|
||||
'(magit-buffer-refs-upstream
|
||||
magit-buffer-refs-args))
|
||||
|
||||
(put 'magit-stashes-mode 'magit-bookmark-variables nil)
|
||||
|
||||
@@ -162,6 +163,7 @@
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+13
-12
@@ -1,6 +1,6 @@
|
||||
;;; magit-branch.el --- Branch support -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -153,11 +153,11 @@ 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" ;???
|
||||
:type '(alist :key-type (string :tag "Use upstream")
|
||||
:value-type (choice :tag "For branches" ;???
|
||||
(regexp :tag "Matching")
|
||||
(repeat :tag "Except"
|
||||
(string :tag "Branch"))))))
|
||||
(string :tag "Branch")))))
|
||||
|
||||
(defcustom magit-branch-rename-push-target t
|
||||
"Whether the push-remote setup is preserved when renaming a branch.
|
||||
@@ -511,8 +511,8 @@ from the source branch's upstream, then an error is raised."
|
||||
(if checkout
|
||||
(magit-call-git "checkout" "-b" branch current)
|
||||
(magit-call-git "branch" branch current)))
|
||||
(when-let ((upstream (magit-get-indirect-upstream-branch current)))
|
||||
(magit-call-git "branch" "--set-upstream-to" upstream branch))
|
||||
(when$ (magit-get-indirect-upstream-branch current)
|
||||
(magit-call-git "branch" "--set-upstream-to" $ branch))
|
||||
(when (and tracked
|
||||
(setq base
|
||||
(if from
|
||||
@@ -560,8 +560,7 @@ that is being reset."
|
||||
(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)
|
||||
(magit-ref-fullname branch)
|
||||
to))
|
||||
(when (and set-upstream (magit-branch-p to))
|
||||
(magit-set-upstream-branch branch to)
|
||||
@@ -639,10 +638,10 @@ prompt is confusing."
|
||||
(magit-rev-parse "--short" ref)))
|
||||
;; Assume the branches actually still exist on the remote.
|
||||
(magit-run-git-async
|
||||
"push"
|
||||
"push" "--delete"
|
||||
(and (or force magit-branch-delete-never-verify) "--no-verify")
|
||||
remote
|
||||
(mapcar (##concat ":" (substring % offset)) branches))
|
||||
(mapcar (##concat "refs/heads/" (substring % offset)) branches))
|
||||
;; If that is not the case, then this deletes the tracking branches.
|
||||
(set-process-sentinel
|
||||
magit-this-process
|
||||
@@ -891,7 +890,8 @@ Also rename the respective reflog file."
|
||||
(magit-run-git-with-editor "branch" "--edit-description" branch))
|
||||
|
||||
(defclass magit--git-branch:upstream (magit--git-variable)
|
||||
((format :initform " %k %m %M\n %r %R")))
|
||||
((format :initform " %k %m %M\n %r %R")
|
||||
(accessible-format :initform "%k %m is %M and %r is %R")))
|
||||
|
||||
(transient-define-infix magit-branch.<branch>.merge/remote ()
|
||||
:class 'magit--git-branch:upstream)
|
||||
@@ -919,7 +919,7 @@ Also rename the respective reflog file."
|
||||
(cl-defmethod transient-format ((obj magit--git-branch:upstream))
|
||||
(let ((branch (transient-scope)))
|
||||
(format-spec
|
||||
(oref obj format)
|
||||
(transient--get-format obj)
|
||||
`((?k . ,(transient-format-key obj))
|
||||
(?r . ,(format "branch.%s.remote" branch))
|
||||
(?m . ,(format "branch.%s.merge" branch))
|
||||
@@ -977,6 +977,7 @@ Also rename the respective reflog file."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-bundle.el --- Bundle support for Magit -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -142,6 +142,7 @@
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-clone.el --- Clone a repository -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -354,6 +354,7 @@ Then show the status buffer for the new repository."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+33
-19
@@ -1,6 +1,6 @@
|
||||
;;; magit-commit.el --- Create Git commits -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -144,6 +144,7 @@ This hook is still experimental.")
|
||||
"Create a new commit or replace an existing commit."
|
||||
:info-manual "(magit)Initiating a Commit"
|
||||
:man-page "git-commit"
|
||||
:value '("--verbose")
|
||||
["Arguments"
|
||||
("-a" "Stage all modified and deleted files" ("-a" "--all"))
|
||||
("-e" "Allow empty commit" "--allow-empty")
|
||||
@@ -548,8 +549,7 @@ is updated:
|
||||
(user-error "There are no modified modules that could be absorbed"))
|
||||
(when commit
|
||||
(setq commit (magit-rebase-interactive-assert commit t)))
|
||||
(if (and commit (eq phase 'run))
|
||||
(progn
|
||||
(cond ((and commit (eq phase 'run))
|
||||
(dolist (module modules)
|
||||
(when-let ((msg (magit-git-string
|
||||
"log" "-1" "--format=%s"
|
||||
@@ -558,10 +558,10 @@ is updated:
|
||||
"--only" "--" module)))
|
||||
(magit-refresh)
|
||||
t)
|
||||
(magit-log-select
|
||||
((magit-log-select
|
||||
(lambda (commit)
|
||||
(magit-commit-absorb-modules 'run commit))
|
||||
nil nil nil nil commit))))
|
||||
nil nil nil nil commit)))))
|
||||
|
||||
;;;###autoload(autoload 'magit-commit-absorb "magit-commit" nil t)
|
||||
(transient-define-prefix magit-commit-absorb (phase commit args)
|
||||
@@ -669,18 +669,25 @@ an alternative implementation."
|
||||
'magit-commit--rebase
|
||||
last-command))
|
||||
(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.
|
||||
(when-let ((diff-buffer
|
||||
;; This signals an error if not inside a Git repository,
|
||||
;; but the user may be visiting COMMIT_EDITMSG using a
|
||||
;; tool other than git, which can be used outside a Git
|
||||
;; repository. See #5527.
|
||||
(ignore-error magit-outside-git-repo
|
||||
(magit-get-mode-buffer 'magit-diff-mode))))
|
||||
;; This window just started displaying the commit message buffer.
|
||||
;; Without unrecording that buffer would immediately be replaced
|
||||
;; with the diff buffer. See #2632.
|
||||
(unrecord-window-buffer nil diff-buffer))
|
||||
(message "Diffing changes to be committed (C-g to abort diffing)")
|
||||
(let ((inhibit-quit nil))
|
||||
(condition-case nil
|
||||
(magit-commit-diff-1)
|
||||
(with-demoted-errors "Error showing commit diff: %S"
|
||||
(magit-commit-diff--show))
|
||||
(quit)))))
|
||||
|
||||
(defun magit-commit-diff-1 ()
|
||||
(defun magit-commit-diff--args ()
|
||||
(let ((rev nil)
|
||||
(arg "--cached")
|
||||
(command (magit-repository-local-get 'this-commit-command))
|
||||
@@ -695,6 +702,9 @@ an alternative implementation."
|
||||
(and (file-exists-p f) (length (magit-file-lines f)))))
|
||||
(noalt nil))
|
||||
(pcase (list staged unstaged command)
|
||||
((guard (not (magit-commit-p "HEAD^")))
|
||||
(setq rev "HEAD")
|
||||
(setq arg nil))
|
||||
((and `(,_ ,_ magit-commit--rebase)
|
||||
(guard (integerp squash)))
|
||||
(setq rev (format "HEAD~%s" squash)))
|
||||
@@ -716,20 +726,23 @@ an alternative implementation."
|
||||
(setq arg nil)))
|
||||
(cond
|
||||
((not
|
||||
(and (eq this-command 'magit-diff-while-committing)
|
||||
(and-let ((buf (magit-get-mode-buffer
|
||||
'magit-diff-mode nil 'selected)))
|
||||
(and (equal rev (buffer-local-value 'magit-buffer-range buf))
|
||||
(equal arg (buffer-local-value 'magit-buffer-typearg buf)))))))
|
||||
(and-let*
|
||||
((_(eq this-command 'magit-diff-while-committing))
|
||||
(buf (magit-get-mode-buffer 'magit-diff-mode nil 'selected))
|
||||
(_(equal rev (buffer-local-value 'magit-buffer-diff-range buf)))
|
||||
(_(equal arg (buffer-local-value 'magit-buffer-diff-typearg buf)))))))
|
||||
((eq command 'magit-commit-amend)
|
||||
(setq rev nil))
|
||||
((or squash
|
||||
(file-exists-p (expand-file-name "rebase-merge/amend" (magit-gitdir))))
|
||||
(setq rev "HEAD^"))
|
||||
(t
|
||||
((setq noalt t)))
|
||||
(list rev arg noalt)))
|
||||
|
||||
(defun magit-commit-diff--show ()
|
||||
(pcase-let ((`(,rev ,arg ,noalt) (magit-commit-diff--args)))
|
||||
(if noalt
|
||||
(message "No alternative diff while committing")
|
||||
(setq noalt t)))
|
||||
(unless noalt
|
||||
(let ((magit-inhibit-save-previous-winconf 'unset)
|
||||
(magit-display-buffer-noselect t)
|
||||
(display-buffer-overriding-action
|
||||
@@ -858,6 +871,7 @@ Also see `git-commit-post-finish-hook'."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-core.el --- Core functionality -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -126,6 +126,7 @@ Each of these options falls into one or more of these categories:
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+538
-209
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
;;; magit-dired.el --- Dired support for Magit -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -116,6 +116,7 @@ Interactively, open the file at point."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+126
-167
@@ -1,6 +1,6 @@
|
||||
;;; magit-ediff.el --- Ediff extension for Magit -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -42,19 +42,17 @@
|
||||
:group 'magit-extensions)
|
||||
|
||||
(defcustom magit-ediff-quit-hook
|
||||
(list #'magit-ediff-cleanup-auxiliary-buffers
|
||||
#'magit-ediff-restore-previous-winconf)
|
||||
(list #'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")
|
||||
:package-version '(magit . "4.6.0")
|
||||
:group 'magit-ediff
|
||||
:type 'hook
|
||||
:get #'magit-hook-custom-get
|
||||
:options (list #'magit-ediff-cleanup-auxiliary-buffers
|
||||
#'magit-ediff-restore-previous-winconf))
|
||||
:options (list #'magit-ediff-restore-previous-winconf))
|
||||
|
||||
(defcustom magit-ediff-dwim-resolve-function #'magit-ediff-resolve-rest
|
||||
"The function `magit-ediff-dwim' uses to resolve conflicts."
|
||||
@@ -115,7 +113,7 @@ recommend you do not further complicate that by enabling this.")
|
||||
|
||||
(defvar magit-ediff-previous-winconf nil)
|
||||
|
||||
;;;###autoload(autoload 'magit-ediff "magit-ediff" nil)
|
||||
;;;###autoload(autoload 'magit-ediff "magit-ediff" nil t)
|
||||
(transient-define-prefix magit-ediff ()
|
||||
"Show differences using the Ediff package."
|
||||
:info-manual "(ediff)"
|
||||
@@ -132,86 +130,8 @@ recommend you do not further complicate that by enabling this.")
|
||||
("r" "Show range" magit-ediff-compare)
|
||||
("z" "Show stash" magit-ediff-show-stash)]])
|
||||
|
||||
(defmacro magit-ediff-buffers (a b &optional c setup quit file)
|
||||
"Run Ediff on two or three buffers.
|
||||
This is a wrapper around `ediff-buffers-internal'.
|
||||
|
||||
A, B and C have the form (GET-BUFFER CREATE-BUFFER). If
|
||||
GET-BUFFER returns a non-nil value, then that buffer is used and
|
||||
it is not killed when exiting Ediff. Otherwise CREATE-BUFFER
|
||||
must return a buffer and that is killed when exiting Ediff.
|
||||
|
||||
If non-nil, SETUP must be a function. It is called without
|
||||
arguments after Ediff is done setting up buffers.
|
||||
|
||||
If non-nil, QUIT must be a function. It is added to
|
||||
`ediff-quit-hook' and is called without arguments.
|
||||
|
||||
If FILE is non-nil, then perform a merge. The merge result
|
||||
is put in FILE."
|
||||
(let (get make kill (char ?A))
|
||||
(dolist (spec (list a b c))
|
||||
(if (not spec)
|
||||
(push nil make)
|
||||
(pcase-let ((`(,g ,m) spec))
|
||||
(let ((b (intern (format "buf%c" char))))
|
||||
(push `(,b ,g) get)
|
||||
;; This is an unfortunate complication that I have added for
|
||||
;; the benefit of one user. Pretend we used this instead:
|
||||
;; (push `(or ,b ,m) make)
|
||||
(push `(if ,b
|
||||
(if magit-ediff-use-indirect-buffers
|
||||
(prog1 (make-indirect-buffer
|
||||
,b
|
||||
(generate-new-buffer-name (buffer-name ,b))
|
||||
t)
|
||||
(setq ,b nil))
|
||||
,b)
|
||||
,m)
|
||||
make)
|
||||
(push `(unless ,b
|
||||
;; For merge jobs Ediff switches buffer names around.
|
||||
;; See (if ediff-merge-job ...) in `ediff-setup'.
|
||||
(let ((var ,(if (and file (= char ?C))
|
||||
'ediff-ancestor-buffer
|
||||
(intern (format "ediff-buffer-%c" char)))))
|
||||
(ediff-kill-buffer-carefully var)))
|
||||
kill))
|
||||
(cl-incf char))))
|
||||
(setq get (nreverse get))
|
||||
(setq make (nreverse make))
|
||||
(setq kill (nreverse kill))
|
||||
(let ((mconf (gensym "conf"))
|
||||
(mfile (gensym "file")))
|
||||
`(magit-with-toplevel
|
||||
(let ((,mconf (current-window-configuration))
|
||||
(,mfile ,file)
|
||||
,@get)
|
||||
(ediff-buffers-internal
|
||||
,@make
|
||||
(list ,@(and setup (list setup))
|
||||
(lambda ()
|
||||
;; We do not want to kill buffers that existed before
|
||||
;; Ediff was invoked, so we cannot use Ediff's default
|
||||
;; quit functions. Ediff splits quitting across two
|
||||
;; hooks for merge jobs but we only ever use one.
|
||||
(setq-local ediff-quit-merge-hook nil)
|
||||
(setq-local ediff-quit-hook
|
||||
(list
|
||||
,@(and quit (list quit))
|
||||
(lambda ()
|
||||
,@kill
|
||||
(let ((magit-ediff-previous-winconf ,mconf))
|
||||
(run-hooks 'magit-ediff-quit-hook)))))))
|
||||
(pcase (list ,(and c t) (and ,mfile t))
|
||||
('(nil nil) 'ediff-buffers)
|
||||
('(nil t) 'ediff-merge-buffers)
|
||||
('(t nil) 'ediff-buffers3)
|
||||
('(t t) 'ediff-merge-buffers-with-ancestor))
|
||||
,mfile))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-resolve-all (file)
|
||||
;;;###autoload(autoload 'magit-ediff-resolve-all "magit-ediff" nil t)
|
||||
(transient-define-suffix magit-ediff-resolve-all (file)
|
||||
"Resolve all conflicts in the FILE at point using Ediff.
|
||||
|
||||
If there is no file at point or if it doesn't have any unmerged
|
||||
@@ -219,16 +139,17 @@ changes, then prompt for a file.
|
||||
|
||||
See info node `(magit) Ediffing' for more information about this
|
||||
and alternative commands."
|
||||
:inapt-if-not #'magit-anything-unmerged-p
|
||||
(interactive (list (magit-read-unmerged-file)))
|
||||
(magit-with-toplevel
|
||||
(let* ((dir (magit-gitdir))
|
||||
(revA (or (magit-name-branch "HEAD")
|
||||
(magit-commit-p "HEAD")))
|
||||
(magit-commit-oid "HEAD")))
|
||||
(revB (cl-find-if (##file-exists-p (expand-file-name % dir))
|
||||
'("MERGE_HEAD" "CHERRY_PICK_HEAD" "REVERT_HEAD")))
|
||||
(revB (or (magit-name-branch revB)
|
||||
(magit-commit-p revB)))
|
||||
(revC (magit-commit-p (magit-git-string "merge-base" revA revB)))
|
||||
(magit-commit-oid revB)))
|
||||
(revC (magit-commit-oid (magit-git-string "merge-base" revA revB)))
|
||||
(fileA (magit--rev-file-name file revA revB))
|
||||
(fileB (magit--rev-file-name file revB revA))
|
||||
(fileC (or (magit--rev-file-name file revC revA)
|
||||
@@ -256,7 +177,7 @@ and alternative commands."
|
||||
,(format ">>>>>>> %s" revB)))))
|
||||
(quit (lambda ()
|
||||
;; For merge jobs Ediff switches buffer names around.
|
||||
;; At this point `ediff-buffer-C' no longer refer to
|
||||
;; At this point `ediff-buffer-C' no longer refers to
|
||||
;; the ancestor buffer but to the merge result buffer.
|
||||
;; See (if ediff-merge-job ...) in `ediff-setup'.
|
||||
(when (buffer-live-p ediff-buffer-C)
|
||||
@@ -266,24 +187,14 @@ and alternative commands."
|
||||
(goto-char (point-min))
|
||||
(unless (re-search-forward "^<<<<<<< " nil t)
|
||||
(magit-stage-files (list file)))))))))
|
||||
(cond (fileC
|
||||
(magit-ediff-buffers
|
||||
((magit-get-revision-buffer revA fileA)
|
||||
(magit-find-file-noselect revA fileA))
|
||||
((magit-get-revision-buffer revB fileB)
|
||||
(magit-find-file-noselect revB fileB))
|
||||
((magit-get-revision-buffer revC fileC)
|
||||
(magit-find-file-noselect revC fileC))
|
||||
setup quit file))
|
||||
((magit-ediff-buffers
|
||||
((magit-get-revision-buffer revA fileA)
|
||||
(magit-find-file-noselect revA fileA))
|
||||
((magit-get-revision-buffer revB fileB)
|
||||
(magit-find-file-noselect revB fileB))
|
||||
nil setup quit file)))))))
|
||||
(magit-ediff--find-file revA fileA)
|
||||
(magit-ediff--find-file revB fileB)
|
||||
(and fileC (magit-ediff--find-file revC fileC))
|
||||
setup quit file)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-resolve-rest (file)
|
||||
;;;###autoload(autoload 'magit-ediff-resolve-rest "magit-ediff" nil t)
|
||||
(transient-define-suffix magit-ediff-resolve-rest (file)
|
||||
"Resolve outstanding conflicts in the FILE at point using Ediff.
|
||||
|
||||
If there is no file at point or if it doesn't have any unmerged
|
||||
@@ -291,6 +202,7 @@ changes, then prompt for a file.
|
||||
|
||||
See info node `(magit) Ediffing' for more information about this
|
||||
and alternative commands."
|
||||
:inapt-if-not #'magit-anything-unmerged-p
|
||||
(interactive (list (magit-read-unmerged-file)))
|
||||
(magit-with-toplevel
|
||||
(with-current-buffer (find-file-noselect file)
|
||||
@@ -314,32 +226,27 @@ and alternative commands."
|
||||
(let ((magit-ediff-previous-winconf smerge-ediff-windows))
|
||||
(run-hooks 'magit-ediff-quit-hook)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-stage (file)
|
||||
;;;###autoload(autoload 'magit-ediff-stage "magit-ediff" nil t)
|
||||
(transient-define-suffix magit-ediff-stage (file)
|
||||
"Stage and unstage changes to FILE using Ediff.
|
||||
FILE has to be relative to the top directory of the repository."
|
||||
:inapt-if-not #'magit-anything-modified-p
|
||||
(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* ((bufA (magit-get-revision-buffer "HEAD" file))
|
||||
(bufB (magit-get-revision-buffer "{index}" file))
|
||||
(lockB (and bufB (buffer-local-value 'buffer-read-only bufB)))
|
||||
(bufC (get-file-buffer file))
|
||||
(let* ((bufC (magit-ediff--find-file "{worktree}" file))
|
||||
;; Use the same encoding for all three buffers or we
|
||||
;; may end up changing the file in an unintended way.
|
||||
(bufC* (or bufC (find-file-noselect file)))
|
||||
(coding-system-for-read
|
||||
(buffer-local-value 'buffer-file-coding-system bufC*))
|
||||
(bufA* (magit-find-file-noselect "HEAD" file t))
|
||||
(bufB* (magit-find-file-index-noselect file t)))
|
||||
(with-current-buffer bufB* (setq buffer-read-only nil))
|
||||
(buffer-local-value 'buffer-file-coding-system bufC))
|
||||
(bufA (magit-ediff--find-file "HEAD" file))
|
||||
(bufB (magit-ediff--find-file "{index}" file))
|
||||
(lockB (buffer-local-value 'buffer-read-only bufB)))
|
||||
(with-current-buffer bufB (setq buffer-read-only nil))
|
||||
(magit-ediff-buffers
|
||||
(bufA bufA*)
|
||||
(bufB bufB*)
|
||||
(bufC bufC*)
|
||||
nil
|
||||
bufA bufB bufC nil
|
||||
(lambda ()
|
||||
(when (buffer-live-p ediff-buffer-B)
|
||||
(when lockB
|
||||
@@ -353,13 +260,12 @@ FILE has to be relative to the top directory of the repository."
|
||||
(when (y-or-n-p (format "Save file %s? " buffer-file-name))
|
||||
(save-buffer)))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-compare (revA revB fileA fileB)
|
||||
;;;###autoload(autoload 'magit-ediff-compare "magit-ediff" nil t)
|
||||
(transient-define-suffix 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.
|
||||
repository.
|
||||
|
||||
If the region is active, use the revisions on the first and last
|
||||
line of the region. With a prefix argument, instead of diffing
|
||||
@@ -372,10 +278,8 @@ range)."
|
||||
(nconc (list revA revB)
|
||||
(magit-ediff-read-files revA revB))))
|
||||
(magit-ediff-buffers
|
||||
((if revA (magit-get-revision-buffer revA fileA) (get-file-buffer fileA))
|
||||
(if revA (magit-find-file-noselect revA fileA) (find-file-noselect fileA)))
|
||||
((if revB (magit-get-revision-buffer revB fileB) (get-file-buffer fileB))
|
||||
(if revB (magit-find-file-noselect revB fileB) (find-file-noselect fileB)))))
|
||||
(magit-ediff--find-file revA fileA)
|
||||
(magit-ediff--find-file revB fileB)))
|
||||
|
||||
(defun magit-ediff-compare--read-revisions (&optional arg mbase)
|
||||
(let ((input (or arg (magit-diff-read-range-or-commit
|
||||
@@ -383,12 +287,14 @@ range)."
|
||||
nil mbase))))
|
||||
(if-let ((range (magit-split-range input)))
|
||||
(list (car range) (cdr range))
|
||||
(list input nil))))
|
||||
(list input "{worktree}"))))
|
||||
|
||||
(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."
|
||||
(when (equal revA "{worktree}") (setq revA nil))
|
||||
(when (equal revB "{worktree}") (setq revB nil))
|
||||
(unless (and fileB (member fileB (magit-revision-files revB)))
|
||||
(setq fileB
|
||||
(or (and fileB
|
||||
@@ -416,8 +322,8 @@ prompting for it."
|
||||
revA revB)))
|
||||
fileB))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-dwim ()
|
||||
;;;###autoload(autoload 'magit-ediff-dwim "magit-ediff" nil t)
|
||||
(transient-define-suffix 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
|
||||
@@ -459,7 +365,7 @@ mind at all, then it asks the user for a command to run."
|
||||
(pcase (magit-diff-type)
|
||||
('committed (pcase-let ((`(,a ,b)
|
||||
(magit-ediff-compare--read-revisions
|
||||
magit-buffer-range)))
|
||||
magit-buffer-diff-range)))
|
||||
(setq revA a)
|
||||
(setq revB b)))
|
||||
((guard (not magit-ediff-dwim-show-on-hunks))
|
||||
@@ -490,55 +396,52 @@ mind at all, then it asks the user for a command to run."
|
||||
(funcall command file))
|
||||
((call-interactively command)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-show-staged (file)
|
||||
;;;###autoload(autoload 'magit-ediff-show-staged "magit-ediff" nil t)
|
||||
(transient-define-suffix 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."
|
||||
:inapt-if-not #'magit-anything-staged-p
|
||||
(interactive
|
||||
(list (magit-read-file-choice "Show staged changes for file"
|
||||
(magit-staged-files)
|
||||
"No staged files")))
|
||||
(magit-ediff-buffers ((magit-get-revision-buffer "HEAD" file)
|
||||
(magit-find-file-noselect "HEAD" file))
|
||||
((get-buffer (concat file ".~{index}~"))
|
||||
(magit-find-file-index-noselect file t))))
|
||||
(magit-ediff-buffers (magit-ediff--find-file "HEAD" file)
|
||||
(magit-ediff--find-file "{index}" file)))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-show-unstaged (file)
|
||||
;;;###autoload(autoload 'magit-ediff-show-unstaged "magit-ediff" nil t)
|
||||
(transient-define-suffix 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."
|
||||
:inapt-if-not #'magit-anything-unstaged-p
|
||||
(interactive
|
||||
(list (magit-read-file-choice "Show unstaged changes for file"
|
||||
(magit-unstaged-files)
|
||||
"No unstaged files")))
|
||||
(magit-ediff-buffers ((get-buffer (concat file ".~{index}~"))
|
||||
(magit-find-file-index-noselect file t))
|
||||
((get-file-buffer file)
|
||||
(find-file-noselect file))))
|
||||
(magit-ediff-buffers (magit-ediff--find-file "{index}" file)
|
||||
(magit-ediff--find-file "{worktree}" file)))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-show-working-tree (file)
|
||||
;;;###autoload(autoload 'magit-ediff-show-working-tree "magit-ediff" nil t)
|
||||
(transient-define-suffix 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."
|
||||
:inapt-if-not #'magit-anything-modified-p
|
||||
(interactive
|
||||
(list (magit-read-file-choice "Show changes in file"
|
||||
(magit-changed-files "HEAD")
|
||||
(magit-modified-files)
|
||||
"No changed files")))
|
||||
(magit-ediff-buffers ((magit-get-revision-buffer "HEAD" file)
|
||||
(magit-find-file-noselect "HEAD" file))
|
||||
((get-file-buffer file)
|
||||
(find-file-noselect file))))
|
||||
(magit-ediff-buffers (magit-ediff--find-file "HEAD" file)
|
||||
(magit-ediff--find-file "{worktree}" file)))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-show-commit (commit)
|
||||
;;;###autoload(autoload 'magit-ediff-show-commit "magit-ediff" nil t)
|
||||
(transient-define-suffix magit-ediff-show-commit (commit)
|
||||
"Show changes introduced by COMMIT using Ediff."
|
||||
(interactive (list (magit-read-branch-or-commit "Revision")))
|
||||
(let ((revA (concat commit "^"))
|
||||
@@ -547,12 +450,13 @@ FILE must be relative to the top directory of the repository."
|
||||
revA revB
|
||||
(magit-ediff-read-files revA revB (magit-current-file)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-ediff-show-stash (stash)
|
||||
;;;###autoload(autoload 'magit-ediff-show-stash "magit-ediff" nil t)
|
||||
(transient-define-suffix 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."
|
||||
`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."
|
||||
:inapt-if-not #'magit-list-stashes
|
||||
(interactive (list (magit-read-stash "Stash")))
|
||||
(pcase-let* ((revA (concat stash "^1"))
|
||||
(revB (concat stash "^2"))
|
||||
@@ -562,15 +466,64 @@ stash that were staged."
|
||||
(if (and magit-ediff-show-stash-with-index
|
||||
(member fileA (magit-changed-files revB revA)))
|
||||
(magit-ediff-buffers
|
||||
((magit-get-revision-buffer revA fileA)
|
||||
(magit-find-file-noselect revA fileA))
|
||||
((magit-get-revision-buffer revB fileB)
|
||||
(magit-find-file-noselect revB fileB))
|
||||
((magit-get-revision-buffer revC fileC)
|
||||
(magit-find-file-noselect revC fileC)))
|
||||
(magit-ediff--find-file revA fileA)
|
||||
(magit-ediff--find-file revB fileB)
|
||||
(magit-ediff--find-file revC fileC))
|
||||
(magit-ediff-compare revA revC fileA fileC))))
|
||||
|
||||
(defun magit-ediff-cleanup-auxiliary-buffers ()
|
||||
;;; Setup
|
||||
|
||||
(defun magit-ediff-buffers (a b &optional c setup quit file)
|
||||
"Run Ediff on two or three buffers A, B and C.
|
||||
|
||||
If optional FILE is non-nil, then perform a merge. The merge result
|
||||
is put in FILE.
|
||||
|
||||
Neutralize the hooks `ediff-quit-hook' and `ediff-quit-merge-hook'
|
||||
because they usually feature functions that do not work for Magit.
|
||||
Instead run optional QUIT (if non-nil), `magit-ediff--cleanup-buffers'
|
||||
and `magit-ediff-quit-hook', with no arguments.
|
||||
|
||||
Optional SETUP, if non-nil, is called with no arguments after Ediff
|
||||
is done setting up buffers."
|
||||
(magit-with-toplevel
|
||||
(ediff-buffers-internal
|
||||
a b c
|
||||
(let ((winconf (current-window-configuration)))
|
||||
(list (lambda ()
|
||||
(when setup
|
||||
(funcall setup))
|
||||
(setq-local ediff-quit-merge-hook nil)
|
||||
(setq-local ediff-quit-hook nil)
|
||||
(when quit
|
||||
(add-hook 'ediff-quit-hook quit nil t))
|
||||
(add-hook 'ediff-quit-hook #'magit-ediff--cleanup-buffers t t)
|
||||
(add-hook 'ediff-quit-hook
|
||||
(lambda ()
|
||||
(let ((magit-ediff-previous-winconf winconf))
|
||||
(run-hooks 'magit-ediff-quit-hook)))
|
||||
t t))))
|
||||
(pcase (list (and c t) (and file t))
|
||||
('(nil nil) 'ediff-buffers)
|
||||
('(nil t) 'ediff-merge-buffers)
|
||||
('(t nil) 'ediff-buffers3)
|
||||
('(t t) 'ediff-merge-buffers-with-ancestor))
|
||||
file)))
|
||||
|
||||
(defun magit-ediff--find-file (rev file)
|
||||
(let ((buffer (magit-find-file-noselect rev file t 'ediff)))
|
||||
(when magit-ediff-use-indirect-buffers
|
||||
(setq buffer (make-indirect-buffer
|
||||
buffer (generate-new-buffer-name (buffer-name buffer)) t)))
|
||||
buffer))
|
||||
|
||||
;;; Quit
|
||||
|
||||
(defun magit-ediff--cleanup-buffers ()
|
||||
(magit-ediff--bury-buffer ediff-buffer-A)
|
||||
(magit-ediff--bury-buffer ediff-buffer-B)
|
||||
(magit-ediff--bury-buffer ediff-buffer-C)
|
||||
(magit-ediff--bury-buffer ediff-ancestor-buffer)
|
||||
(let* ((ctl-buf ediff-control-buffer)
|
||||
(ctl-win (ediff-get-visible-buffer-window ctl-buf))
|
||||
(ctl-frm ediff-control-frame)
|
||||
@@ -596,6 +549,11 @@ stash that were staged."
|
||||
(when (frame-live-p main-frame)
|
||||
(select-frame main-frame))))
|
||||
|
||||
(defun magit-ediff--bury-buffer (buffer)
|
||||
(when (and (ediff-buffer-live-p buffer)
|
||||
(eq (buffer-local-value 'magit-buffer--volatile buffer) 'ediff))
|
||||
(kill-buffer (get-buffer buffer))))
|
||||
|
||||
(defun magit-ediff-restore-previous-winconf ()
|
||||
(set-window-configuration magit-ediff-previous-winconf))
|
||||
|
||||
@@ -607,6 +565,7 @@ stash that were staged."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-extras.el --- Additional functionality for Magit -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -737,9 +737,9 @@ abbreviated revision to the `kill-ring' and the
|
||||
(cl-case major-mode
|
||||
(magit-diff-mode
|
||||
(if (string-match "\\.\\.\\.?\\(.+\\)"
|
||||
magit-buffer-range)
|
||||
(match-str 1 magit-buffer-range)
|
||||
magit-buffer-range))
|
||||
magit-buffer-diff-range)
|
||||
(match-str 1 magit-buffer-diff-range)
|
||||
magit-buffer-diff-range))
|
||||
(magit-status-mode "HEAD")))]
|
||||
[_(magit-commit-p rev)]
|
||||
(setq rev (magit-rev-parse
|
||||
@@ -833,6 +833,7 @@ In Magit diffs, also skip over - and + at the beginning of the line."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-fetch.el --- Download objects and refs -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -188,6 +188,7 @@ with a prefix argument."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+269
-115
@@ -1,6 +1,6 @@
|
||||
;;; magit-files.el --- Finding files -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -31,10 +31,21 @@
|
||||
|
||||
(require 'magit)
|
||||
|
||||
(declare-function ediff-quit "ediff-util" (reverse-default-keep-variants))
|
||||
|
||||
;;; Find Blob
|
||||
|
||||
(defvar magit-find-file-hook nil)
|
||||
(add-hook 'magit-find-file-hook #'magit-blob-mode)
|
||||
(define-obsolete-variable-alias 'magit-find-file-hook
|
||||
'magit-find-blob-hook "Magit 4.6.0")
|
||||
|
||||
(define-obsolete-variable-alias 'magit-find-index-hook
|
||||
'magit-find-blob-hook "Magit 4.6.0")
|
||||
|
||||
(defvar magit-find-blob-hook (list #'magit-blob-mode))
|
||||
|
||||
(defvar-local magit-buffer-blob-oid--init nil)
|
||||
(defvar-local magit-buffer--volatile nil)
|
||||
(put 'magit-buffer--volatile 'permanent-local t)
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-find-file (rev file)
|
||||
@@ -44,7 +55,7 @@ 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))
|
||||
(pop-to-buffer-same-window (magit-find-file-noselect rev file)))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-find-file-other-window (rev file)
|
||||
@@ -54,7 +65,7 @@ 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))
|
||||
(switch-to-buffer-other-window (magit-find-file-noselect rev file)))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-find-file-other-frame (rev file)
|
||||
@@ -64,11 +75,11 @@ 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))
|
||||
(switch-to-buffer-other-frame (magit-find-file-noselect rev file)))
|
||||
|
||||
(defun magit-find-file-read-args (prompt)
|
||||
(let ((pseudo-revs '("{worktree}" "{index}")))
|
||||
(let ((rev (magit-completing-read "Find file from revision"
|
||||
(let* ((pseudo-revs '("{worktree}" "{index}"))
|
||||
(rev (magit-completing-read "Find file from revision"
|
||||
(append pseudo-revs
|
||||
(magit-list-refnames nil t))
|
||||
nil 'any nil 'magit-revision-history
|
||||
@@ -76,128 +87,244 @@ the line and column corresponding to that location."
|
||||
(magit-get-current-branch)))))
|
||||
(list rev
|
||||
(magit-read-file-from-rev (if (member rev pseudo-revs) "HEAD" rev)
|
||||
prompt)))))
|
||||
prompt))))
|
||||
|
||||
(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)))
|
||||
((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 &optional revert)
|
||||
(defun magit-find-file-noselect (rev file &optional no-restore-position volatile)
|
||||
"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}\"."
|
||||
(let* ((topdir (magit-toplevel))
|
||||
(absolute (file-name-absolute-p file))
|
||||
(file-abs (if absolute file (expand-file-name file topdir)))
|
||||
(file-rel (if absolute (file-relative-name file topdir) file))
|
||||
(defdir (file-name-directory file-abs))
|
||||
(rev (magit--abbrev-if-hash rev)))
|
||||
(if (equal rev "{worktree}")
|
||||
REV is a revision or one of \"{worktree}\" or \"{index}\".
|
||||
Non-interactively REV can also be a blob object."
|
||||
(let* ((rev (pcase rev
|
||||
('nil "{worktree}")
|
||||
((and "{index}"
|
||||
(guard (length> (magit--file-index-stages file) 1)))
|
||||
"{worktree}")
|
||||
(rev rev)))
|
||||
(topdir (magit-toplevel))
|
||||
(file (expand-file-name file topdir))
|
||||
(file-relative (file-relative-name file topdir))
|
||||
(buffer
|
||||
(cond-let
|
||||
((equal rev "{worktree}")
|
||||
(let ((revert-without-query
|
||||
(if (and$ (find-buffer-visiting file-abs)
|
||||
(if (and$ (find-buffer-visiting file)
|
||||
(buffer-local-value 'auto-revert-mode $))
|
||||
(cons "." revert-without-query)
|
||||
revert-without-query)))
|
||||
(find-file-noselect file-abs))
|
||||
(with-current-buffer (magit-get-revision-buffer-create rev file-rel)
|
||||
(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 rev)
|
||||
(setq magit-buffer-refname rev)
|
||||
(setq magit-buffer-file-name file-abs)
|
||||
(setq default-directory (if (file-exists-p defdir) defdir 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)))))
|
||||
(find-file-noselect file volatile)))
|
||||
((not topdir)
|
||||
(error "%s is not inside a Git repository" file))
|
||||
([defdir (file-name-directory file)]
|
||||
[rev (magit--abbrev-if-oid rev)]
|
||||
(unless (file-in-directory-p file topdir)
|
||||
(error "%s is not inside Git repository %s" file topdir))
|
||||
(with-current-buffer
|
||||
(magit--get-blob-buffer rev file-relative volatile)
|
||||
(if (magit-blob-p rev)
|
||||
(setq magit-buffer-blob-oid--init (magit-rev-parse rev))
|
||||
(setq magit-buffer-revision rev))
|
||||
(setq magit-buffer-file-name file)
|
||||
(setq default-directory
|
||||
(if (file-exists-p defdir) defdir topdir))
|
||||
(setq-local revert-buffer-function #'magit--revert-blob-buffer)
|
||||
(magit--refresh-blob-buffer)
|
||||
(current-buffer)))
|
||||
((error "Unexpected error")))))
|
||||
(when (and (not no-restore-position)
|
||||
(equal (magit-file-relative-name) file-relative))
|
||||
(let ((pos (magit-find-file--position)))
|
||||
(with-current-buffer buffer
|
||||
(apply #'magit-find-file--restore-position pos))))
|
||||
buffer))
|
||||
|
||||
(defun magit-get-revision-buffer-create (rev file)
|
||||
(magit-get-revision-buffer rev file t))
|
||||
(defun magit--get-blob-buffer (obj file &optional volatile)
|
||||
;; If OBJ is a commit, is assummed to be abbreviated.
|
||||
;; FILE is assumed to be relative to the top-level.
|
||||
(cond-let
|
||||
([buf (if (magit-blob-p obj)
|
||||
(magit--find-buffer 'magit-buffer-blob-oid (magit-rev-parse obj)
|
||||
'magit-buffer-file-name file)
|
||||
(magit--find-buffer 'magit-buffer-revision obj
|
||||
'magit-buffer-file-name file))]
|
||||
(with-current-buffer buf
|
||||
(when (and (not volatile) magit-buffer--volatile)
|
||||
(setq magit-buffer--volatile nil)
|
||||
(rename-buffer (magit--blob-buffer-name obj file))
|
||||
(magit--blob-cache-remove buf)))
|
||||
buf)
|
||||
([buf (get-buffer-create (magit--blob-buffer-name obj file volatile))]
|
||||
(with-current-buffer buf
|
||||
(setq magit-buffer--volatile volatile)
|
||||
(magit--blob-cache-put buf))
|
||||
(buffer-enable-undo buf)
|
||||
buf)))
|
||||
|
||||
(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--blob-buffer-name (obj file &optional volatile)
|
||||
(format "%s%s.~%s~"
|
||||
(if volatile " " "")
|
||||
(or file (and (magit-blob-p obj) "{blob}"))
|
||||
(subst-char-in-string ?/ ?_ obj)))
|
||||
|
||||
(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)))
|
||||
(defun magit--revert-blob-buffer (_ignore-auto _noconfirm)
|
||||
(let ((pos (magit-find-file--position)))
|
||||
(magit--refresh-blob-buffer t)
|
||||
(apply #'magit-find-file--restore-position pos)))
|
||||
|
||||
(defun magit--refresh-blob-buffer (&optional force)
|
||||
(let ((old-blob-oid magit-buffer-blob-oid))
|
||||
(cond
|
||||
(magit-buffer-revision
|
||||
(setq magit-buffer-revision-oid
|
||||
(magit-commit-oid magit-buffer-revision t))
|
||||
(setq magit-buffer-blob-oid
|
||||
(magit-blob-oid magit-buffer-revision magit-buffer-file-name)))
|
||||
(magit-buffer-blob-oid--init
|
||||
(setq magit-buffer-blob-oid magit-buffer-blob-oid--init)
|
||||
(setq magit-buffer-blob-oid--init nil)))
|
||||
(when (or force (not (equal old-blob-oid magit-buffer-blob-oid)))
|
||||
(let ((inhibit-read-only t))
|
||||
(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))
|
||||
(save-excursion
|
||||
(magit--insert-blob-contents magit-buffer-revision
|
||||
(magit-file-relative-name))))
|
||||
(magit--blob-normal-mode))))
|
||||
|
||||
(defun magit--blob-normal-mode ()
|
||||
(let ((buffer-file-name magit-buffer-file-name)
|
||||
(after-change-major-mode-hook
|
||||
;; Inhibit diff-hl and eglot; see bb8a65269d and 234a787b8c.
|
||||
(seq-difference after-change-major-mode-hook
|
||||
'(global-diff-hl-mode-enable-in-buffer ; Emacs >= 30
|
||||
global-diff-hl-mode-enable-in-buffers ; Emacs < 30
|
||||
eglot--maybe-activate-editing-mode)
|
||||
#'eq)))
|
||||
#'eq))
|
||||
(buffer-name (buffer-name)))
|
||||
;; `font-lock-mode' contains a hardcoded condition that prevents it
|
||||
;; from being enabled in hidden buffers. Use a fake `buffer-name'
|
||||
;; to trick it into believing the buffer is not hidden.
|
||||
(if (eq (aref buffer-name 0) ?\s)
|
||||
(letrec ((adv (lambda (fn &optional buffer)
|
||||
(let ((name (funcall fn buffer)))
|
||||
(if (equal name buffer-name)
|
||||
(substring name 1)
|
||||
name)))))
|
||||
(advice-add 'buffer-name :around adv)
|
||||
(unwind-protect
|
||||
(normal-mode (not enable-local-variables))
|
||||
(advice-remove 'buffer-name adv)))
|
||||
;; We want `normal-mode' to respect nil `enable-local-variables'.
|
||||
;; The FIND-FILE argument wasn't designed for our use case, so we
|
||||
;; have to use this strange invocation to achieve that.
|
||||
;; The FIND-FILE argument wasn't designed for our use case,
|
||||
;; so we have to use this strange invocation to achieve that.
|
||||
(normal-mode (not enable-local-variables)))
|
||||
(setq buffer-read-only t)
|
||||
(set-buffer-modified-p nil)
|
||||
(goto-char (point-min))))
|
||||
(run-hooks 'magit-find-blob-hook)))
|
||||
|
||||
(defun magit-find-file--position ()
|
||||
(list (or magit-buffer-revision-oid magit-buffer-revision "{worktree}")
|
||||
magit-buffer-blob-oid
|
||||
(line-number-at-pos)
|
||||
(current-column)))
|
||||
|
||||
(defun magit-find-file--restore-position (before blob line col)
|
||||
(let ((file (magit-file-relative-name))
|
||||
(rev (or magit-buffer-revision-oid magit-buffer-revision "{worktree}")))
|
||||
(goto-char (point-min))
|
||||
(forward-line
|
||||
(1-
|
||||
(pcase (list before rev)
|
||||
((guard (equal magit-buffer-blob-oid blob)) line)
|
||||
('("{worktree}" "{worktree}") line)
|
||||
('("{worktree}" "{index}")
|
||||
(magit-diff-visit--offset line file "-R"))
|
||||
(`("{worktree}" ,_)
|
||||
(magit-diff-visit--offset line file "-R" rev))
|
||||
('("{index}" "{worktree}")
|
||||
(magit-diff-visit--offset line file))
|
||||
('("{index}" "{index}")
|
||||
(magit-diff-visit--offset line (list blob magit-buffer-blob-oid file)))
|
||||
(`("{index}" ,_)
|
||||
(magit-diff-visit--offset line file "-R" "--cached"))
|
||||
(`(,_ "{worktree}")
|
||||
(magit-diff-visit--offset line file before))
|
||||
(`(,_ "{index}")
|
||||
(magit-diff-visit--offset line file "--cached"))
|
||||
(_
|
||||
(magit-diff-visit--offset line file before rev)))))
|
||||
(move-to-column col)))
|
||||
|
||||
(defvar magit--blob-cache-limit 100
|
||||
"Limit number of volatile blob buffers to be kept alive.
|
||||
If nil, only use `magit--blob-cache-timeout'.")
|
||||
(defvar magit--blob-cache-timeout 1800
|
||||
"Limit age, since last access, of volatile blob buffers to be kept alive.
|
||||
Age is tracked in seconds. If nil, only use `magit--blob-cache-limit'.")
|
||||
(defvar magit--blob-cache-interval 600
|
||||
"Seconds between volatile blob buffer pruning runs.")
|
||||
(defvar magit--blob-cache-timer nil)
|
||||
(defvar magit--blob-cache nil)
|
||||
|
||||
(defun magit--blob-cache-put (buffer)
|
||||
(if-let ((elt (assq buffer magit--blob-cache)))
|
||||
(setcdr elt (current-time))
|
||||
(push (cons buffer (current-time)) magit--blob-cache))
|
||||
(magit--blob-cache-start))
|
||||
|
||||
(defun magit--blob-cache-remove (buffer)
|
||||
(and$ (assq buffer magit--blob-cache)
|
||||
(delq $ magit--blob-cache)))
|
||||
|
||||
(defun magit--blob-cache-start ()
|
||||
(when (and magit--blob-cache-interval
|
||||
(not magit--blob-cache-timer))
|
||||
(setq magit--blob-cache-timer
|
||||
(run-with-timer magit--blob-cache-interval nil
|
||||
#'magit--blob-cache-prune))))
|
||||
|
||||
(defun magit--blob-cache-prune ()
|
||||
(when magit--blob-cache-timer
|
||||
(cancel-timer magit--blob-cache-timer))
|
||||
(pcase-let
|
||||
((`(,active ,rest)
|
||||
(magit--separate
|
||||
(pcase-lambda (`(,buffer))
|
||||
(or (get-buffer-window buffer t)
|
||||
(not (eq (buffer-local-value 'magit-buffer--volatile buffer) t))))
|
||||
magit--blob-cache)))
|
||||
(when magit--blob-cache-timeout
|
||||
(setq rest
|
||||
(seq-filter (pcase-lambda (`(,buffer . ,time))
|
||||
(cond
|
||||
((not (buffer-live-p buffer)) nil)
|
||||
((time-less-p (time-subtract (current-time) time)
|
||||
magit--blob-cache-timeout)
|
||||
buffer)
|
||||
(t (kill-buffer buffer) nil)))
|
||||
rest)))
|
||||
(when-let* ((_ magit--blob-cache-limit)
|
||||
(ceiling (- magit--blob-cache-limit (length active)))
|
||||
(_ (length> rest ceiling)))
|
||||
(let ((sorted (static-if (>= emacs-major-version 30)
|
||||
(sort rest :key (##float-time (cdr %))
|
||||
:lessp #'< :reverse t)
|
||||
(cl-sort rest #'> :key (##float-time (cdr %))))))
|
||||
(dolist (kill (nthcdr ceiling sorted))
|
||||
(kill-buffer (car kill)))
|
||||
(setq rest (ntake ceiling sorted))))
|
||||
(setq magit--blob-cache (nconc active rest)))
|
||||
(magit--blob-cache-start))
|
||||
|
||||
(defun magit--blob-cache-zap ()
|
||||
(pcase-dolist (`(,buffer) magit--blob-cache)
|
||||
(kill-buffer buffer))
|
||||
(setq magit--blob-cache nil))
|
||||
|
||||
(define-advice lsp (:around (fn &rest args) magit-find-file)
|
||||
"Do nothing when visiting blob using `magit-find-file' and similar.
|
||||
See also https://github.com/doomemacs/doomemacs/pull/6309."
|
||||
(unless magit-buffer-revision
|
||||
(unless magit-buffer-blob-oid
|
||||
(apply fn args)))
|
||||
|
||||
;;; Find Index
|
||||
|
||||
(defvar magit-find-index-hook nil)
|
||||
(add-hook 'magit-find-index-hook #'magit-blob-mode)
|
||||
|
||||
(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 "{index}" file (or revert 'ask-revert)))
|
||||
;;; Update Index
|
||||
|
||||
(defun magit-update-index ()
|
||||
"Update the index with the contents of the current buffer.
|
||||
@@ -205,7 +332,7 @@ 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}")
|
||||
(unless (equal magit-buffer-revision "{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-name
|
||||
@@ -230,8 +357,8 @@ is done using `magit-find-index-noselect'."
|
||||
(set-buffer-modified-p nil)
|
||||
(magit-run-after-apply-functions file "un-/stage"))
|
||||
(message "Abort")))
|
||||
(when-let ((buffer (magit-get-mode-buffer 'magit-status-mode)))
|
||||
(with-current-buffer buffer
|
||||
(when$ (magit-get-mode-buffer 'magit-status-mode)
|
||||
(with-current-buffer $
|
||||
(magit-refresh)))
|
||||
t)
|
||||
|
||||
@@ -345,6 +472,7 @@ to `magit-dispatch'."
|
||||
|
||||
(defvar-keymap magit-blob-mode-map
|
||||
:doc "Keymap for `magit-blob-mode'."
|
||||
"g" #'revert-buffer
|
||||
"p" #'magit-blob-previous
|
||||
"n" #'magit-blob-next
|
||||
"b" #'magit-blame-addition
|
||||
@@ -360,18 +488,32 @@ Currently this only adds the following key bindings.
|
||||
:package-version '(magit . "2.3.0"))
|
||||
|
||||
(defun magit-bury-buffer (&optional kill-buffer)
|
||||
"Bury the current buffer, or with a prefix argument kill it."
|
||||
"Bury the current buffer, or with a prefix argument kill it.
|
||||
|
||||
If the buffer is used by an Ediff session, refuse to kill or bury just
|
||||
that buffer. That former would break the session and the latter makes
|
||||
little sense in this context. Instead offer to quit the whole session."
|
||||
(interactive "P")
|
||||
(if kill-buffer (kill-buffer) (bury-buffer)))
|
||||
(cond ((bound-and-true-p ediff-this-buffer-ediff-sessions)
|
||||
(ediff-quit nil))
|
||||
(kill-buffer (kill-buffer))
|
||||
((bury-buffer))))
|
||||
|
||||
(defun magit-bury-or-kill-buffer (&optional bury-buffer)
|
||||
"Bury the current buffer if displayed in multiple windows, else kill it.
|
||||
With a prefix argument only bury the buffer even if it is only displayed
|
||||
in a single window."
|
||||
|
||||
With a prefix argument only bury the buffer even if it is only
|
||||
displayed in a single window.
|
||||
|
||||
If the buffer is used by an Ediff session, refuse to kill or bury just
|
||||
that buffer. That former would break the session and the latter makes
|
||||
little sense in this context. Instead offer to quit the whole session."
|
||||
(interactive "P")
|
||||
(if (or bury-buffer (cdr (get-buffer-window-list nil nil t)))
|
||||
(bury-buffer)
|
||||
(kill-buffer)))
|
||||
(cond ((bound-and-true-p ediff-this-buffer-ediff-sessions)
|
||||
(ediff-quit nil))
|
||||
((or bury-buffer (cdr (get-buffer-window-list nil nil t)))
|
||||
(bury-buffer))
|
||||
((kill-buffer))))
|
||||
|
||||
(defun magit-kill-this-buffer ()
|
||||
"Kill the current buffer."
|
||||
@@ -412,7 +554,7 @@ 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)
|
||||
(pop-to-buffer-same-window (magit-find-file-noselect "{worktree}" file))
|
||||
(user-error "Not visiting a blob")))
|
||||
|
||||
(defun magit-blob-visit (rev file)
|
||||
@@ -624,6 +766,17 @@ If DEFAULT is non-nil, use this as the default value instead of
|
||||
(define-obsolete-function-alias 'magit-find-file-noselect-1
|
||||
'magit-find-file-noselect "Magit 4.4.0")
|
||||
|
||||
(defun magit-find-file--internal (rev file display)
|
||||
(declare (obsolete magit-find-file-noselect "Magit 4.6.0"))
|
||||
(let ((buf (magit-find-file-noselect rev file)))
|
||||
(funcall display buf)
|
||||
buf))
|
||||
|
||||
(defun magit-find-file-index-noselect (file)
|
||||
"Read FILE from the index into a buffer and return the buffer."
|
||||
(declare (obsolete magit-find-file-noselect "Magit 4.6.0"))
|
||||
(magit-find-file-noselect "{index}" file t))
|
||||
|
||||
(provide 'magit-files)
|
||||
;; Local Variables:
|
||||
;; read-symbol-shorthands: (
|
||||
@@ -631,6 +784,7 @@ If DEFAULT is non-nil, use this as the default value instead of
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+153
-86
@@ -1,6 +1,6 @@
|
||||
;;; magit-git.el --- Git functionality -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -48,7 +48,6 @@
|
||||
(defvar magit-buffer-file-name)
|
||||
(defvar magit-buffer-log-args)
|
||||
(defvar magit-buffer-log-files)
|
||||
(defvar magit-buffer-refname)
|
||||
(defvar magit-buffer-revision)
|
||||
|
||||
;; From `magit-process'.
|
||||
@@ -72,6 +71,8 @@
|
||||
(cl-pushnew 'orig-rev eieio--known-slot-names)
|
||||
(cl-pushnew 'number eieio--known-slot-names))
|
||||
|
||||
(defvar crm-prompt) ; Emacs 31.1
|
||||
|
||||
;;; Options
|
||||
|
||||
;; For now this is shared between `magit-process' and `magit-git'.
|
||||
@@ -393,7 +394,7 @@ to do the following.
|
||||
|
||||
* Prepend `magit-git-global-arguments' to ARGS.
|
||||
* If ASYNC is non-nil and `magit-overriding-githook-directory' is non-nil
|
||||
and valid, set `core.hooksPath' by adding additional aguments to ARGS.
|
||||
and valid, set `core.hooksPath' by adding additional arguments to ARGS.
|
||||
* Flatten ARGS, removing nil arguments.
|
||||
* If `system-type' is `windows-nt', encode ARGS to `w32-ansi-code-page'."
|
||||
(cond ((not async))
|
||||
@@ -434,22 +435,6 @@ to do the following.
|
||||
"Execute Git with ARGS, returning t if its exit code is 1."
|
||||
(= (magit-git-exit-code args) 1))
|
||||
|
||||
(defun magit-git-string-p (&rest args)
|
||||
"Execute Git with ARGS, returning the first line of its output.
|
||||
If the exit code isn't zero or if there is no output, then return
|
||||
nil. Neither of these results is considered an error; if that is
|
||||
what you want, then use `magit-git-string-ng' instead.
|
||||
|
||||
This is an experimental replacement for `magit-git-string', and
|
||||
still subject to major changes."
|
||||
(magit--with-refresh-cache (cons default-directory args)
|
||||
(magit--with-temp-process-buffer
|
||||
(and (zerop (magit-process-git t args))
|
||||
(not (bobp))
|
||||
(progn
|
||||
(goto-char (point-min))
|
||||
(buffer-substring-no-properties (point) (line-end-position)))))))
|
||||
|
||||
(defun magit-git-string-ng (&rest args)
|
||||
"Execute Git with ARGS, returning the first line of its output.
|
||||
If the exit code isn't zero or if there is no output, then that
|
||||
@@ -459,7 +444,7 @@ buffer (creating it if necessary) and the error message is shown
|
||||
in the status buffer (provided it exists).
|
||||
|
||||
This is an experimental replacement for `magit-git-string', and
|
||||
still subject to major changes. Also see `magit-git-string-p'."
|
||||
still subject to major changes."
|
||||
(magit--with-refresh-cache
|
||||
(list default-directory 'magit-git-string-ng args)
|
||||
(magit--with-temp-process-buffer
|
||||
@@ -526,9 +511,9 @@ signal `magit-invalid-git-boolean'."
|
||||
|
||||
(defun magit-git-config-p (variable &optional default)
|
||||
"Return the boolean value of the Git variable VARIABLE.
|
||||
VARIABLE has to be specified as a string. Return DEFAULT (which
|
||||
defaults to nil) if VARIABLE is unset. If VARIABLE's value isn't
|
||||
a boolean, then raise an error."
|
||||
VARIABLE has to be specified as a string. If VARIABLE is unset,
|
||||
return nil by default, unless DEFAULT is non-nil, in which case
|
||||
return t. Signal an error if VARIABLE is set but not a boolean."
|
||||
(let ((args (list "config" "--bool" "--default" (if default "true" "false")
|
||||
variable)))
|
||||
(magit--with-refresh-cache (cons default-directory args)
|
||||
@@ -577,10 +562,12 @@ insert the run command and stderr into the process buffer."
|
||||
exit log 'magit-section-secondary-heading)
|
||||
exit)))))
|
||||
(cond ((not magit-git-debug))
|
||||
(errmsg (message "%s" errmsg))
|
||||
(errmsg (message "magit--git-insert: %S" errmsg))
|
||||
((zerop exit))
|
||||
((message "Git returned with exit-code %s" exit))))
|
||||
(or errmsg exit))
|
||||
((message "magit--git-insert: %s %s"
|
||||
"Git returned with exit-code" exit))))
|
||||
(or (and return-error errmsg)
|
||||
exit))
|
||||
(ignore-errors (delete-file log))))
|
||||
(magit-process-git (list t nil) args)))
|
||||
|
||||
@@ -591,16 +578,18 @@ insert the run command and stderr into the process buffer."
|
||||
(match-str 1)))
|
||||
|
||||
(defun magit-git-string (&rest args)
|
||||
"Execute Git with ARGS, returning the first line of its output.
|
||||
If there is no output, return nil. If the output begins with a
|
||||
newline, return an empty string."
|
||||
"Execute Git with ARGS, returning the first line of its output (stdout).
|
||||
If the exit code isn't zero or if there is no output, then return nil.
|
||||
Neither of these results is considered an error; if that is what you
|
||||
want, then use `magit-git-string-ng' instead."
|
||||
(setq args (flatten-tree args))
|
||||
(magit--with-refresh-cache (cons default-directory args)
|
||||
(magit--with-temp-process-buffer
|
||||
(apply #'magit-git-insert args)
|
||||
(unless (bobp)
|
||||
(and (zerop (apply #'magit-git-insert args))
|
||||
(not (bobp))
|
||||
(progn
|
||||
(goto-char (point-min))
|
||||
(buffer-substring-no-properties (point) (line-end-position))))))
|
||||
(buffer-substring-no-properties (point) (line-end-position)))))))
|
||||
|
||||
(defun magit-git-lines (&rest args)
|
||||
"Execute Git with ARGS, returning its output as a list of lines.
|
||||
@@ -1019,9 +1008,7 @@ returning the truename."
|
||||
|
||||
(define-error 'magit-outside-git-repo "Not inside Git repository")
|
||||
(define-error 'magit-corrupt-git-config "Corrupt Git configuration")
|
||||
(define-error 'magit-git-executable-not-found
|
||||
(concat "Git executable cannot be found "
|
||||
"(see https://magit.vc/goto/e6a78ed2)"))
|
||||
(define-error 'magit-git-executable-not-found "Git executable cannot be found")
|
||||
|
||||
(defun magit--assert-usable-git ()
|
||||
(if (not (executable-find (magit-git-executable) t))
|
||||
@@ -1121,7 +1108,7 @@ tracked file."
|
||||
(file-relative-name file dir))))
|
||||
|
||||
(defun magit-file-ignored-p (file)
|
||||
(magit-git-string-p "ls-files" "--others" "--ignored" "--exclude-standard"
|
||||
(magit-git-string "ls-files" "--others" "--ignored" "--exclude-standard"
|
||||
"--" (magit-convert-filename-for-git file)))
|
||||
|
||||
(defun magit-file-tracked-p (file)
|
||||
@@ -1145,6 +1132,16 @@ issue."
|
||||
(and (not all) "--exclude-standard")
|
||||
"--" files))
|
||||
|
||||
(defun magit--untracked-files (&optional directory all)
|
||||
(magit-with-toplevel
|
||||
(seq-keep (##and (eq (aref % 0) ??)
|
||||
(substring % 3))
|
||||
(magit-git-items "status" "-z" "--porcelain"
|
||||
(if all
|
||||
"--untracked-files=all"
|
||||
"--untracked-files=normal")
|
||||
"--" directory))))
|
||||
|
||||
(defun magit-list-untracked-files (&optional files)
|
||||
"Return a list of untracked files.
|
||||
|
||||
@@ -1258,13 +1255,12 @@ or if no rename is detected."
|
||||
(y (char-after (1+ pos)))
|
||||
(file (buffer-substring (+ pos 3) (point))))
|
||||
(forward-char)
|
||||
(if (memq x '(?R ?C))
|
||||
(progn
|
||||
(cond ((memq x '(?R ?C))
|
||||
(setq pos (point))
|
||||
(skip-chars-forward "[:print:]")
|
||||
(push (list file (buffer-substring pos (point)) x y) status)
|
||||
(forward-char))
|
||||
(push (list file nil x y) status)))
|
||||
((push (list file nil x y) status))))
|
||||
(setq pos (point)))
|
||||
status)))
|
||||
|
||||
@@ -1279,11 +1275,10 @@ or if no rename is detected."
|
||||
"Failed to parse Cygwin mount: %S" mount)))
|
||||
;; If --exec-path is not a native Windows path,
|
||||
;; then we probably have a cygwin git.
|
||||
(and (not (string-match-p
|
||||
"\\`[a-zA-Z]:"
|
||||
(car (magit--early-process-lines
|
||||
magit-git-executable "--exec-path"))))
|
||||
(magit--early-process-lines "mount")))
|
||||
(and-let ((dirs (magit--early-process-lines
|
||||
magit-git-executable "--exec-path")))
|
||||
(and (not (string-match-p "\\`[a-zA-Z]:" (car dirs)))
|
||||
(magit--early-process-lines "mount"))))
|
||||
#'> :key (pcase-lambda (`(,cyg . ,_win)) (length cyg))))
|
||||
"Alist of (CYGWIN . WIN32) directory names.
|
||||
Sorted from longest to shortest CYGWIN name."
|
||||
@@ -1344,6 +1339,36 @@ Sorted from longest to shortest CYGWIN name."
|
||||
(and (derived-mode-p 'magit-log-mode)
|
||||
(car magit-buffer-log-files))))
|
||||
|
||||
;;; Blobs
|
||||
|
||||
(defun magit-blob-p (obj)
|
||||
(equal (magit-object-type obj) "blob"))
|
||||
|
||||
(defun magit-blob-oid (rev file)
|
||||
(cond-let
|
||||
((equal rev "{index}")
|
||||
(cadr (car (magit--file-index-stages file))))
|
||||
;; --object-only and --format were only added in Git v2.36.0.
|
||||
([out (magit-git-string "ls-tree" "--full-tree" rev "--"
|
||||
(magit-convert-filename-for-git file))]
|
||||
(nth 2 (split-string out "[\s\t]")))))
|
||||
|
||||
(defun magit--file-index-stages (file)
|
||||
(mapcar (##split-string % " ")
|
||||
(magit-git-lines "ls-files" "--stage" "--"
|
||||
(magit-convert-filename-for-git file))))
|
||||
|
||||
(defun magit--insert-blob-contents (obj file)
|
||||
(let ((coding-system-for-read (or coding-system-for-read 'undecided)))
|
||||
(if (magit-blob-p obj)
|
||||
(magit-git-insert "cat-file" "blob" obj)
|
||||
(magit-git-insert "cat-file" "-p"
|
||||
(if (equal obj "{index}")
|
||||
(concat ":" file)
|
||||
(concat obj ":" file))))
|
||||
(setq buffer-file-coding-system last-coding-system-used)
|
||||
nil))
|
||||
|
||||
;;; Predicates
|
||||
|
||||
(defun magit-no-commit-p ()
|
||||
@@ -1441,21 +1466,29 @@ string \"true\", otherwise return nil."
|
||||
(equal (magit-git-str "rev-parse" args) "true"))
|
||||
|
||||
(defun magit-rev-verify (rev)
|
||||
(magit-git-string-p "rev-parse" "--verify" rev))
|
||||
(magit-git-string "rev-parse" "--verify" rev))
|
||||
|
||||
(defun magit-commit-p (rev)
|
||||
"Return full hash for REV if it names an existing commit."
|
||||
"Return non-nil if REV can be dereferences as a commit.
|
||||
Otherwise return nil. Use `magit-commit-oid' if you actually need
|
||||
the oid; eventually this function will return t instead of the oid,
|
||||
as it currently does for backward compatibility."
|
||||
;; TODO Return t instead of the oid.
|
||||
(magit-rev-verify (magit--rev-dereference rev)))
|
||||
|
||||
(defalias 'magit-rev-verify-commit #'magit-commit-p)
|
||||
|
||||
(defalias 'magit-rev-hash #'magit-commit-p)
|
||||
(defun magit-commit-oid (rev &optional noerror)
|
||||
"Return commit oid for REV if it can be dereferences as a commit.
|
||||
Otherwise signal an error, or return nil, if optional NOERROR is non-nil."
|
||||
(cond ((magit-rev-verify (magit--rev-dereference rev)))
|
||||
(noerror nil)
|
||||
((error "%s cannot be dereferenced as a commit" rev))))
|
||||
|
||||
(defun magit--rev-dereference (rev)
|
||||
"Return a rev that forces Git to interpret REV as a commit.
|
||||
If REV is nil or has the form \":/TEXT\", return REV itself."
|
||||
Do so by appending \"^{commit}\"; see \"--verify\" in git-rev-parse(1).
|
||||
However, if REV is nil or has the form \":/TEXT\", return REV itself."
|
||||
(cond ((not rev) nil)
|
||||
((string-match-p "^:/" rev) rev)
|
||||
((string-prefix-p ":/" rev) rev)
|
||||
((concat rev "^{commit}"))))
|
||||
|
||||
(defun magit-rev-equal (a b)
|
||||
@@ -1464,20 +1497,18 @@ If REV is nil or has the form \":/TEXT\", return REV itself."
|
||||
|
||||
(defun magit-rev-eq (a b)
|
||||
"Return t if A and B refer to the same commit."
|
||||
(let ((a (magit-commit-p a))
|
||||
(b (magit-commit-p b)))
|
||||
(and a b (equal a b))))
|
||||
(and-let ((a (magit-commit-oid a t))
|
||||
(b (magit-commit-oid b t)))
|
||||
(equal a b)))
|
||||
|
||||
(defun magit-rev-ancestor-p (a b)
|
||||
"Return non-nil if commit A is an ancestor of commit B."
|
||||
(magit-git-success "merge-base" "--is-ancestor" a b))
|
||||
|
||||
(defun magit-rev-head-p (rev)
|
||||
"Return t if REV can be dereferences as the `HEAD' commit."
|
||||
(or (equal rev "HEAD")
|
||||
(and rev
|
||||
(not (string-search ".." rev))
|
||||
(equal (magit-rev-parse rev)
|
||||
(magit-rev-parse "HEAD")))))
|
||||
(magit-rev-eq rev "HEAD")))
|
||||
|
||||
(defun magit-rev-author-p (rev)
|
||||
"Return t if the user is the author of REV.
|
||||
@@ -1584,9 +1615,9 @@ nil, then use \"heads/\"."
|
||||
A symbolic-ref pointing to some ref, is `equal' to that ref,
|
||||
as are two symbolic-refs pointing to the same ref. Refnames
|
||||
may be abbreviated."
|
||||
(let ((a (magit-ref-fullname a))
|
||||
(and-let ((a (magit-ref-fullname a))
|
||||
(b (magit-ref-fullname b)))
|
||||
(and a b (equal a b))))
|
||||
(equal a b)))
|
||||
|
||||
(defun magit-ref-eq (a b)
|
||||
"Return t if the refnames A and B are `eq'.
|
||||
@@ -1682,7 +1713,7 @@ to, or to some other symbolic-ref that points to the same ref."
|
||||
(magit-current-blame-chunk))))
|
||||
(oref chunk orig-rev))
|
||||
(and magit-buffer-file-name
|
||||
magit-buffer-refname)
|
||||
magit-buffer-revision)
|
||||
(and (derived-mode-p 'magit-stash-mode
|
||||
'magit-merge-preview-mode
|
||||
'magit-revision-mode)
|
||||
@@ -1874,7 +1905,8 @@ according to the branch type."
|
||||
(defun magit-get-push-branch (&optional branch verify)
|
||||
(magit--with-refresh-cache
|
||||
(list default-directory 'magit-get-push-branch branch verify)
|
||||
(and-let* ((branch (or branch (setq branch (magit-get-current-branch))))
|
||||
(and-let*
|
||||
((branch (magit-ref-abbrev (or branch (magit-get-current-branch))))
|
||||
(remote (magit-get-push-remote branch))
|
||||
(target (concat remote "/" branch)))
|
||||
(and (or (not verify)
|
||||
@@ -1882,11 +1914,9 @@ according to the branch type."
|
||||
(magit--propertize-face target 'magit-branch-remote)))))
|
||||
|
||||
(defun magit-get-@{push}-branch (&optional branch)
|
||||
(let ((ref (magit-rev-parse "--symbolic-full-name"
|
||||
(concat branch "@{push}"))))
|
||||
(and ref
|
||||
(string-prefix-p "refs/remotes/" ref)
|
||||
(substring ref 13))))
|
||||
(and-let* ((branch (magit-ref-abbrev (or branch (magit-get-current-branch))))
|
||||
(target (magit-ref-fullname (concat branch "@{push}"))))
|
||||
(magit-ref-abbrev target)))
|
||||
|
||||
(defun magit-get-remote (&optional branch)
|
||||
(and (or branch (setq branch (magit-get-current-branch)))
|
||||
@@ -2232,11 +2262,11 @@ specified using `core.worktree'."
|
||||
(let* ((default-directory (car worktree))
|
||||
(wt (and (not (magit-get-boolean "core.bare"))
|
||||
(magit-get "core.worktree"))))
|
||||
(if (and wt (file-exists-p (expand-file-name wt)))
|
||||
(progn (setf (nth 0 worktree) (expand-file-name wt))
|
||||
(cond ((and wt (file-exists-p (expand-file-name wt)))
|
||||
(setf (nth 0 worktree) (expand-file-name wt))
|
||||
(setf (nth 2 worktree) (magit-rev-parse "HEAD"))
|
||||
(setf (nth 3 worktree) (magit-get-current-branch)))
|
||||
(setf (nth 3 worktree) t))))
|
||||
((setf (nth 3 worktree) t)))))
|
||||
((string-equal line "detached")
|
||||
(setf (nth 4 worktree) t))
|
||||
((string-prefix-p line "locked")
|
||||
@@ -2271,8 +2301,8 @@ specified using `core.worktree'."
|
||||
'magit-branch-local
|
||||
'magit-branch-remote)))
|
||||
|
||||
(defun magit-tag-p (rev)
|
||||
(car (member rev (magit-list-tags))))
|
||||
(defun magit-tag-p (obj)
|
||||
(equal (magit-object-type obj) "tag"))
|
||||
|
||||
(defun magit-remote-p (string)
|
||||
(car (member string (magit-list-remotes))))
|
||||
@@ -2342,10 +2372,10 @@ If `first-parent' is set, traverse only first parents."
|
||||
(defun magit-rev-abbrev (rev)
|
||||
(magit-rev-parse (magit-abbrev-arg "short") rev))
|
||||
|
||||
(defun magit--abbrev-if-hash (rev)
|
||||
(cond ((or (magit-ref-p rev) (member rev '("{index}" "{worktree}"))) rev)
|
||||
((magit-rev-parse (magit-abbrev-arg "short") rev))
|
||||
(rev)))
|
||||
(defun magit--abbrev-if-oid (obj)
|
||||
(cond ((or (magit-ref-p obj) (member obj '("{index}" "{worktree}"))) obj)
|
||||
((magit-rev-parse (magit-abbrev-arg "short") obj))
|
||||
(obj)))
|
||||
|
||||
(defun magit-commit-children (rev &optional args)
|
||||
(seq-keep (lambda (line)
|
||||
@@ -2568,8 +2598,8 @@ and this option only controls what face is used.")
|
||||
(beg (or beg "HEAD"))
|
||||
(end (or end "HEAD")))
|
||||
(when abbrev
|
||||
(setq beg (magit--abbrev-if-hash beg))
|
||||
(setq end (magit--abbrev-if-hash end)))
|
||||
(setq beg (magit--abbrev-if-oid beg))
|
||||
(setq end (magit--abbrev-if-oid end)))
|
||||
(pcase sep
|
||||
(".." (cons beg end))
|
||||
("..." (and$ (magit-git-string "merge-base" beg end)
|
||||
@@ -2583,15 +2613,18 @@ and this option only controls what face is used.")
|
||||
(list beg end sep)))))
|
||||
|
||||
(defun magit-hash-range (range)
|
||||
"Return a string with the revisions in RANGE replaced with commit oids.
|
||||
Either side of RANGE may be omitted, and RANGE may be just a revision.
|
||||
If either revision cannot be dereferenced as a commit, signal an error."
|
||||
(if (string-match magit-range-re range)
|
||||
(magit-bind-match-strings (beg sep end) range
|
||||
(and (or beg end)
|
||||
(let ((beg-hash (and beg (magit-rev-hash beg)))
|
||||
(end-hash (and end (magit-rev-hash end))))
|
||||
(and (or (not beg) beg-hash)
|
||||
(or (not end) end-hash)
|
||||
(concat beg-hash sep end-hash)))))
|
||||
(magit-rev-hash range)))
|
||||
(let ((beg-oid (and beg (magit-commit-oid beg)))
|
||||
(end-oid (and end (magit-commit-oid end))))
|
||||
(and (or (not beg) beg-oid)
|
||||
(or (not end) end-oid)
|
||||
(concat beg-oid sep end-oid)))))
|
||||
(magit-commit-oid range)))
|
||||
|
||||
(defvar magit-revision-faces
|
||||
'(magit-hash
|
||||
@@ -2645,7 +2678,7 @@ and this option only controls what face is used.")
|
||||
(and (not (equal string "@"))
|
||||
(or (and (>= (length string) 7)
|
||||
(string-match-p "[a-z]" string)
|
||||
(magit-commit-p string))
|
||||
(magit-commit-oid string t))
|
||||
(and (magit-ref-p string)
|
||||
(member (get-text-property (point) 'face)
|
||||
magit-revision-faces)))
|
||||
@@ -2729,10 +2762,11 @@ and this option only controls what face is used.")
|
||||
(lambda ()
|
||||
(magit--minibuf-default-add-commit)
|
||||
(setq-local crm-separator "\\.\\.\\.?"))
|
||||
(let ((crm-prompt "%p"))
|
||||
(magit-completing-read-multiple
|
||||
(concat prompt ": ")
|
||||
(magit-list-refnames)
|
||||
nil 'any nil 'magit-revision-history default nil t)))
|
||||
nil 'any nil 'magit-revision-history default nil t))))
|
||||
|
||||
(defun magit-read-remote-branch
|
||||
(prompt &optional remote default local-branch require-match)
|
||||
@@ -2812,6 +2846,23 @@ and this option only controls what face is used.")
|
||||
(magit-completing-read prompt (delete exclude (magit-list-refnames))
|
||||
nil 'any nil 'magit-revision-history default))))
|
||||
|
||||
(defun magit-read-other-branches-or-commits
|
||||
(prompt &optional exclude secondary-default)
|
||||
(let* ((current (magit-get-current-branch))
|
||||
(atpoint (magit-branch-or-commit-at-point))
|
||||
(exclude (or exclude current))
|
||||
(default (or (and (not (equal atpoint exclude))
|
||||
(not (and (not current)
|
||||
(magit-rev-equal atpoint "HEAD")))
|
||||
atpoint)
|
||||
(and (not (equal current exclude)) current)
|
||||
secondary-default
|
||||
(magit-get-previous-branch))))
|
||||
(minibuffer-with-setup-hook #'magit--minibuf-default-add-commit
|
||||
(magit-completing-read-multiple
|
||||
prompt (delete exclude (magit-list-refnames))
|
||||
nil 'any nil 'magit-revision-history default))))
|
||||
|
||||
(defun magit-read-other-local-branch
|
||||
(prompt &optional exclude secondary-default)
|
||||
(let* ((current (magit-get-current-branch))
|
||||
@@ -2993,6 +3044,21 @@ out. Only existing branches can be selected."
|
||||
(server-send-string client msg))))
|
||||
|
||||
;;; _
|
||||
|
||||
(define-obsolete-function-alias 'magit-git-string-p
|
||||
#'magit-git-string "Magit 4.6.0")
|
||||
|
||||
(define-obsolete-function-alias 'magit-rev-verify-commit
|
||||
#'magit-commit-p "Magit 4.6.0")
|
||||
|
||||
(define-obsolete-function-alias 'magit-rev-hash
|
||||
#'magit-commit-p "Magit 4.6.0"
|
||||
"Return oid for REV if it names an existing commit, nil otherwise.
|
||||
Instead use `magit-commit-p' or `magit-commit-oid'.")
|
||||
|
||||
(define-obsolete-function-alias 'magit--abbrev-if-hash
|
||||
#'magit--abbrev-if-oid "Magit 4.6.0")
|
||||
|
||||
(provide 'magit-git)
|
||||
;; Local Variables:
|
||||
;; read-symbol-shorthands: (
|
||||
@@ -3000,6 +3066,7 @@ out. Only existing branches can be selected."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-gitignore.el --- Intentionally untracked files -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -35,16 +35,10 @@
|
||||
"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 (##magit-get "core.excludesfile")
|
||||
:description (##format "privately for all repositories (%s)"
|
||||
(magit-get "core.excludesfile")))]
|
||||
("t" magit-gitignore-in-topdir)
|
||||
("s" magit-gitignore-in-subdir)
|
||||
("p" magit-gitignore-in-gitdir)
|
||||
("g" magit-gitignore-on-system)]
|
||||
["Skip worktree"
|
||||
(7 "w" "do skip worktree" magit-skip-worktree)
|
||||
(7 "W" "do not skip worktree" magit-no-skip-worktree)]
|
||||
@@ -54,51 +48,56 @@
|
||||
|
||||
;;; Gitignore Commands
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-gitignore-in-topdir (rule)
|
||||
;;;###autoload(autoload 'magit-gitignore-in-topdir "magit-gitignore" nil t)
|
||||
(transient-define-suffix 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."
|
||||
:description "shared at toplevel (.gitignore)"
|
||||
(interactive (list (magit-gitignore-read-pattern)))
|
||||
(magit-with-toplevel
|
||||
(magit--gitignore rule ".gitignore")
|
||||
(magit-run-git "add" ".gitignore")))
|
||||
(magit--gitignore rule (expand-file-name ".gitignore" (magit-toplevel)) t))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-gitignore-in-subdir (rule directory)
|
||||
;;;###autoload(autoload 'magit-gitignore-in-subdir "magit-gitignore" nil t)
|
||||
(transient-define-suffix magit-gitignore-in-subdir (rule directory)
|
||||
"Add the Git ignore RULE to a \".gitignore\" file in DIRECTORY.
|
||||
Prompt 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" (magit-convert-filename-for-git file)))))
|
||||
:description "shared in subdirectory (path/to/.gitignore)"
|
||||
(interactive (let ((dir (expand-file-name
|
||||
(read-directory-name
|
||||
"Limit rule to files in: "
|
||||
(and$ (magit-current-file)
|
||||
(file-name-directory
|
||||
(expand-file-name $ (magit-toplevel))))))))
|
||||
(list (magit-gitignore-read-pattern dir) dir)))
|
||||
(magit--gitignore rule (expand-file-name ".gitignore" directory) t))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-gitignore-in-gitdir (rule)
|
||||
;;;###autoload(autoload 'magit-gitignore-in-gitdir "magit-gitignore" nil t)
|
||||
(transient-define-suffix 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."
|
||||
:description "privately (.git/info/exclude)"
|
||||
(interactive (list (magit-gitignore-read-pattern)))
|
||||
(magit--gitignore rule (expand-file-name "info/exclude" (magit-gitdir)))
|
||||
(magit-refresh))
|
||||
(magit--gitignore rule (expand-file-name "info/exclude" (magit-gitdir))))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-gitignore-on-system (rule)
|
||||
;;;###autoload(autoload 'magit-gitignore-on-system "magit-gitignore" nil t)
|
||||
(transient-define-suffix 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."
|
||||
:inapt-if-not (##magit-get "core.excludesfile")
|
||||
:description (##format "privately for all repositories (%s)"
|
||||
(or (magit-get "core.excludesfile")
|
||||
"core.excludesfile is not set"))
|
||||
(interactive (list (magit-gitignore-read-pattern)))
|
||||
(magit--gitignore rule
|
||||
(or (magit-get "core.excludesFile")
|
||||
(if-let ((file (magit-get "core.excludesFile")))
|
||||
(magit--gitignore rule file)
|
||||
(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))
|
||||
(defun magit--gitignore (rule file &optional stage)
|
||||
(when$ (file-name-directory file)
|
||||
(make-directory $ t))
|
||||
(with-temp-buffer
|
||||
(when (file-exists-p file)
|
||||
(insert-file-contents file))
|
||||
@@ -107,31 +106,21 @@ Rules that are defined in that file affect all local repositories."
|
||||
(insert "\n"))
|
||||
(insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" rule))
|
||||
(insert "\n")
|
||||
(write-region nil nil file)))
|
||||
(write-region nil nil file))
|
||||
(if stage
|
||||
(magit-with-toplevel
|
||||
(magit-run-git "add" (magit-convert-filename-for-git file)))
|
||||
(magit-refresh)))
|
||||
|
||||
(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
|
||||
(mapcan
|
||||
(lambda (file)
|
||||
(cons (concat "/" file)
|
||||
(and$ (file-name-extension file)
|
||||
(list (concat "/" (file-name-directory file) "*." $)
|
||||
(concat "*." $)))))
|
||||
(sort (nconc
|
||||
(magit-untracked-files nil base)
|
||||
;; The untracked section of the status buffer lists
|
||||
;; directories containing only untracked files.
|
||||
;; Add those as candidates.
|
||||
(seq-filter #'directory-name-p
|
||||
(magit-list-files
|
||||
"--other" "--exclude-standard" "--directory"
|
||||
"--no-empty-directory" "--" base)))
|
||||
#'string-lessp)))))
|
||||
(defun magit-gitignore-read-pattern (&optional directory)
|
||||
(let ((choices (magit--gitignore-patterns directory))
|
||||
(default (magit-current-file)))
|
||||
(when default
|
||||
(when directory
|
||||
(setq default
|
||||
(substring default
|
||||
(length
|
||||
(file-relative-name directory (magit-toplevel))))))
|
||||
(setq default (concat "/" default))
|
||||
(unless (member default choices)
|
||||
(setq default (concat "*." (file-name-extension default)))
|
||||
@@ -140,6 +129,28 @@ Rules that are defined in that file affect all local repositories."
|
||||
(magit-completing-read "File or pattern to ignore"
|
||||
choices nil 'any nil nil default)))
|
||||
|
||||
(defun magit--gitignore-patterns (&optional directory)
|
||||
(let* ((topdir (magit-toplevel))
|
||||
(default-directory (or directory topdir))
|
||||
(files (magit--untracked-files directory t))
|
||||
;; Include directories that contain only untracked files.
|
||||
(dirs (seq-filter (##equal (substring % -1) "/")
|
||||
(magit--untracked-files directory)))
|
||||
(globs nil)
|
||||
(dirglobs nil))
|
||||
(when directory
|
||||
(let ((beg (length (file-relative-name directory topdir))))
|
||||
(setq files (mapcar (##substring % beg) files))
|
||||
(setq dirs (mapcar (##substring % beg) dirs))))
|
||||
(dolist (file files)
|
||||
(when-let ((ext (file-name-extension file)))
|
||||
(cl-pushnew (concat "*." ext) globs :test #'equal)
|
||||
(when-let ((dir (file-name-directory file)))
|
||||
(cl-pushnew (concat dir "*." ext) dirglobs :test #'equal))))
|
||||
(sort (nconc globs
|
||||
(mapcar (##concat "/" %) (nconc files dirs dirglobs)))
|
||||
#'string<)))
|
||||
|
||||
;;; Skip Worktree Commands
|
||||
|
||||
;;;###autoload
|
||||
@@ -198,6 +209,7 @@ Rules that are defined in that file affect all local repositories."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+33
-22
@@ -1,6 +1,6 @@
|
||||
;;; magit-log.el --- Inspect Git history -*- lexical-binding:t; coding:utf-8 -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -374,6 +374,12 @@ commits before and half after."
|
||||
:group 'magit-log
|
||||
:type 'integer)
|
||||
|
||||
;;; Variables
|
||||
|
||||
(defvar-local magit-buffer-log-revisions nil)
|
||||
(defvar-local magit-buffer-log-args nil)
|
||||
(defvar-local magit-buffer-log-files nil)
|
||||
|
||||
;;; Arguments
|
||||
;;;; Prefix Classes
|
||||
|
||||
@@ -779,7 +785,7 @@ restrict the log to the lines that the region touches."
|
||||
(require 'magit)
|
||||
(if-let ((file (magit-file-relative-name)))
|
||||
(magit-log-setup-buffer
|
||||
(list (or magit-buffer-refname
|
||||
(list (or magit-buffer-revision
|
||||
(magit-get-current-branch)
|
||||
"HEAD"))
|
||||
(let ((args (car (magit-log-arguments))))
|
||||
@@ -802,7 +808,7 @@ restrict the log to the lines that the region touches."
|
||||
(user-error "Buffer isn't visiting a file"))
|
||||
(or (funcall magit-log-trace-definition-function)
|
||||
(user-error "No function at point found"))
|
||||
(or magit-buffer-refname
|
||||
(or magit-buffer-revision
|
||||
(magit-get-current-branch)
|
||||
"HEAD")))
|
||||
(require 'magit)
|
||||
@@ -872,7 +878,7 @@ https://github.com/mhagger/git-when-merged."
|
||||
(to (if (<= to 0)
|
||||
branch
|
||||
(format "%s~%s" branch to))))
|
||||
(unless (magit-rev-verify-commit from)
|
||||
(unless (magit-commit-p from)
|
||||
(setq from (magit-git-string "rev-list" "--max-parents=0"
|
||||
commit)))
|
||||
(magit-log-setup-buffer (list (concat from ".." to))
|
||||
@@ -1131,7 +1137,7 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
|
||||
(require 'magit)
|
||||
(with-current-buffer
|
||||
(magit-setup-buffer #'magit-log-mode locked
|
||||
(magit-buffer-revisions revs)
|
||||
(magit-buffer-log-revisions revs)
|
||||
(magit-buffer-log-args args)
|
||||
(magit-buffer-log-files files))
|
||||
(when (if focus
|
||||
@@ -1141,7 +1147,7 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
|
||||
(current-buffer)))
|
||||
|
||||
(defun magit-log-refresh-buffer ()
|
||||
(let ((revs magit-buffer-revisions)
|
||||
(let ((revs magit-buffer-log-revisions)
|
||||
(args magit-buffer-log-args)
|
||||
(files magit-buffer-log-files)
|
||||
(limit (magit-log-get-commit-limit)))
|
||||
@@ -1181,8 +1187,9 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
|
||||
(defvar-local magit-log--color-graph nil)
|
||||
|
||||
(defun magit-log--maybe-drop-color-graph (args limit)
|
||||
(if (member "--color" args)
|
||||
(if (cond ((not (member "--graph" args)))
|
||||
(cond ((not (member "--color" args))
|
||||
(setq magit-log--color-graph nil))
|
||||
((cond ((not (member "--graph" args)) t)
|
||||
((not magit-log-color-graph-limit) nil)
|
||||
((not limit)
|
||||
(message "Dropping --color because -n isn't set (see %s)"
|
||||
@@ -1190,15 +1197,14 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
|
||||
((> limit magit-log-color-graph-limit)
|
||||
(message "Dropping --color because -n is larger than %s"
|
||||
'magit-log-color-graph-limit)))
|
||||
(progn (setq args (remove "--color" args))
|
||||
(setq magit-log--color-graph nil))
|
||||
(setq magit-log--color-graph t))
|
||||
(setq args (remove "--color" args))
|
||||
(setq magit-log--color-graph nil))
|
||||
((setq magit-log--color-graph t)))
|
||||
args)
|
||||
|
||||
(cl-defmethod magit-buffer-value (&context (major-mode magit-log-mode))
|
||||
(append magit-buffer-revisions
|
||||
(if (and magit-buffer-revisions magit-buffer-log-files)
|
||||
(append magit-buffer-log-revisions
|
||||
(if (and magit-buffer-log-revisions magit-buffer-log-files)
|
||||
(cons "--" magit-buffer-log-files)
|
||||
magit-buffer-log-files)))
|
||||
|
||||
@@ -1779,20 +1785,20 @@ Type \\[magit-log-select-quit] to abort without selecting a commit."
|
||||
|
||||
(defun magit-log-select-setup-buffer (revs args)
|
||||
(magit-setup-buffer #'magit-log-select-mode nil
|
||||
(magit-buffer-revisions revs)
|
||||
(magit-buffer-log-revisions revs)
|
||||
(magit-buffer-log-args args)))
|
||||
|
||||
(defun magit-log-select-refresh-buffer ()
|
||||
(setq magit-section-inhibit-markers t)
|
||||
(setq magit-section-insert-in-reverse t)
|
||||
(magit-insert-section (logbuf)
|
||||
(magit--insert-log t magit-buffer-revisions
|
||||
(magit--insert-log t magit-buffer-log-revisions
|
||||
(magit-log--maybe-drop-color-graph
|
||||
magit-buffer-log-args
|
||||
(magit-log-get-commit-limit)))))
|
||||
|
||||
(cl-defmethod magit-buffer-value (&context (major-mode magit-log-select-mode))
|
||||
magit-buffer-revisions)
|
||||
magit-buffer-log-revisions)
|
||||
|
||||
(defvar-local magit-log-select-pick-function nil)
|
||||
(defvar-local magit-log-select-quit-function nil)
|
||||
@@ -1881,11 +1887,14 @@ Type \\[magit-cherry-pick] to apply the commit at point.
|
||||
(magit-hack-dir-local-variables)
|
||||
(setq magit--imenu-group-types 'cherries))
|
||||
|
||||
(defvar-local magit-buffer-cherry-upstream nil)
|
||||
(defvar-local magit-buffer-cherry-range nil)
|
||||
|
||||
(defun magit-cherry-setup-buffer (head upstream)
|
||||
(magit-setup-buffer #'magit-cherry-mode nil
|
||||
(magit-buffer-refname head)
|
||||
(magit-buffer-upstream upstream)
|
||||
(magit-buffer-range (concat upstream ".." head))))
|
||||
(magit-buffer-cherry-upstream upstream)
|
||||
(magit-buffer-cherry-range (concat upstream ".." head))))
|
||||
|
||||
(defun magit-cherry-refresh-buffer ()
|
||||
(setq magit-section-insert-in-reverse t)
|
||||
@@ -1893,7 +1902,7 @@ Type \\[magit-cherry-pick] to apply the commit at point.
|
||||
(magit-run-section-hook 'magit-cherry-sections-hook)))
|
||||
|
||||
(cl-defmethod magit-buffer-value (&context (major-mode magit-cherry-mode))
|
||||
magit-buffer-range)
|
||||
magit-buffer-cherry-range)
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-cherry (head upstream)
|
||||
@@ -1909,8 +1918,9 @@ Type \\[magit-cherry-pick] to apply the commit at point.
|
||||
"Insert headers appropriate for `magit-cherry-mode' buffers."
|
||||
(let ((branch (propertize magit-buffer-refname
|
||||
'font-lock-face 'magit-branch-local))
|
||||
(upstream (propertize magit-buffer-upstream 'font-lock-face
|
||||
(if (magit-local-branch-p magit-buffer-upstream)
|
||||
(upstream (propertize
|
||||
magit-buffer-cherry-upstream 'font-lock-face
|
||||
(if (magit-local-branch-p magit-buffer-cherry-upstream)
|
||||
'magit-branch-local
|
||||
'magit-branch-remote))))
|
||||
(magit-insert-head-branch-header branch)
|
||||
@@ -1923,7 +1933,7 @@ Type \\[magit-cherry-pick] to apply the commit at point.
|
||||
(magit-insert-heading t "Cherry commits")
|
||||
(magit-git-wash (apply-partially #'magit-log-wash-log 'cherry)
|
||||
"cherry" "-v" "--abbrev"
|
||||
magit-buffer-upstream
|
||||
magit-buffer-cherry-upstream
|
||||
magit-buffer-refname)))
|
||||
|
||||
;;; Log Sections
|
||||
@@ -2114,6 +2124,7 @@ all others with \"-\"."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-margin.el --- Margins in Magit buffers -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -263,6 +263,7 @@ English.")
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-merge.el --- Merge functionality -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -95,8 +95,10 @@ the user inspect the result. With a prefix argument pretend the
|
||||
merge failed to give the user the opportunity to inspect the
|
||||
merge.
|
||||
|
||||
To create an octopus-merge, separate branches with commas.
|
||||
|
||||
\(git merge --no-edit|--no-commit [ARGS] REV)"
|
||||
(interactive (list (magit-read-other-branch-or-commit "Merge")
|
||||
(interactive (list (magit-read-other-branches-or-commits "Merge")
|
||||
(magit-merge-arguments)
|
||||
current-prefix-arg))
|
||||
(magit-merge-assert)
|
||||
@@ -105,24 +107,30 @@ merge.
|
||||
;;;###autoload
|
||||
(defun magit-merge-editmsg (rev &optional args)
|
||||
"Merge commit REV into the current branch; and edit message.
|
||||
|
||||
Perform the merge and prepare a commit message but let the user
|
||||
edit it.
|
||||
\n(git merge --edit --no-ff [ARGS] REV)"
|
||||
(interactive (list (magit-read-other-branch-or-commit "Merge")
|
||||
|
||||
To create an octopus-merge, separate branches with commas.
|
||||
|
||||
\(git merge --edit --no-ff [ARGS] REV)"
|
||||
(interactive (list (magit-read-other-branches-or-commits "Merge")
|
||||
(magit-merge-arguments)))
|
||||
(magit-merge-assert)
|
||||
(cl-pushnew "--no-ff" args :test #'equal)
|
||||
(apply #'magit-run-git-with-editor "merge" "--edit"
|
||||
(append (delete "--ff-only" args)
|
||||
(list rev))))
|
||||
(magit-run-git-with-editor "merge" "--edit" (delete "--ff-only" args) rev))
|
||||
|
||||
;;;###autoload
|
||||
(defun magit-merge-nocommit (rev &optional args)
|
||||
"Merge commit REV into the current branch; pretending it failed.
|
||||
|
||||
Pretend the merge failed to give the user the opportunity to
|
||||
inspect the merge and change the commit message.
|
||||
\n(git merge --no-commit --no-ff [ARGS] REV)"
|
||||
(interactive (list (magit-read-other-branch-or-commit "Merge")
|
||||
|
||||
To create an octopus-merge, separate branches with commas.
|
||||
|
||||
\(git merge --no-commit --no-ff [ARGS] REV)"
|
||||
(interactive (list (magit-read-other-branches-or-commits "Merge")
|
||||
(magit-merge-arguments)))
|
||||
(magit-merge-assert)
|
||||
(cl-pushnew "--no-ff" args :test #'equal)
|
||||
@@ -317,6 +325,7 @@ If no merge is in progress, do nothing."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
+56
-31
@@ -1,6 +1,6 @@
|
||||
;;; magit-mode.el --- Create and refresh Magit buffers -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -51,6 +51,8 @@
|
||||
(declare-function magit-wip-get-ref "magit-wip" ())
|
||||
(declare-function magit-wip-commit-worktree "magit-wip" (ref files msg))
|
||||
|
||||
(declare-function magit--blob-cache-zap "magit-files" ())
|
||||
|
||||
;;; Options
|
||||
|
||||
(defcustom magit-mode-hook nil
|
||||
@@ -578,35 +580,41 @@ Magit is documented in info node `(magit)'."
|
||||
|
||||
;;; Local Variables
|
||||
|
||||
(defvar-local magit-buffer-arguments nil)
|
||||
(defvar-local magit-buffer-diff-type nil)
|
||||
(defvar-local magit-buffer-diff-args nil)
|
||||
(defvar-local magit-buffer-diff-files nil)
|
||||
(defvar-local magit-buffer-diff-files-suspended nil)
|
||||
(defvar-local magit-buffer-file-name nil)
|
||||
(defvar-local magit-buffer-files nil)
|
||||
(defvar-local magit-buffer-log-args nil)
|
||||
(defvar-local magit-buffer-log-files nil)
|
||||
(defvar-local magit-buffer-range nil)
|
||||
(defvar-local magit-buffer-range-hashed nil)
|
||||
(defvar-local magit-buffer-refname nil)
|
||||
(defvaralias 'magit-buffer-refname 'magit-buffer-revision)
|
||||
(defvar-local magit-buffer-revision nil)
|
||||
(defvar-local magit-buffer-revision-hash nil)
|
||||
(defvar-local magit-buffer-revisions nil)
|
||||
(defvar-local magit-buffer-typearg nil)
|
||||
(defvar-local magit-buffer-upstream nil)
|
||||
(defvar-local magit-buffer-revision-oid nil)
|
||||
(defvar-local magit-buffer-blob-oid nil)
|
||||
(defvar-local magit-buffer-file-name nil)
|
||||
|
||||
;; These variables are also used in file-visiting buffers.
|
||||
;; Because the user may change the major-mode, they have
|
||||
;; to be permanent buffer-local.
|
||||
(put 'magit-buffer-file-name 'permanent-local t)
|
||||
(put 'magit-buffer-refname 'permanent-local t)
|
||||
;; Preserve when major-mode is changed in file-visiting buffers.
|
||||
(put 'magit-buffer-revision 'permanent-local t)
|
||||
(put 'magit-buffer-revision-hash 'permanent-local t)
|
||||
(put 'magit-buffer-revision-oid 'permanent-local t)
|
||||
(put 'magit-buffer-blob-oid 'permanent-local t)
|
||||
(put 'magit-buffer-file-name 'permanent-local t)
|
||||
|
||||
;; `magit-status' re-enables mode function but its refresher
|
||||
;; function does not reinstate this.
|
||||
(put 'magit-buffer-diff-files-suspended 'permanent-local t)
|
||||
(eval-and-compile
|
||||
(defvar magit-define-aliases-for:magit-buffer-* t)
|
||||
(when magit-define-aliases-for:magit-buffer-*
|
||||
;; Unfortunately defvar-local can only be used at top-level,
|
||||
;; so instead we have to use make-variable-buffer-local below.
|
||||
(defvar magit-buffer-arguments nil)
|
||||
(make-obsolete-variable 'magit-buffer-arguments
|
||||
"use a mode- or package-specific `magit-buffer-{*}-args' instead"
|
||||
"magit 4.6.0")
|
||||
(defvar magit-buffer-upstream nil)
|
||||
(make-obsolete-variable 'magit-buffer-upstream
|
||||
"use a mode- or package-specific `magit-buffer-{*}-upstream' instead"
|
||||
"magit 4.6.0")
|
||||
(define-obsolete-variable-alias 'magit-buffer-range-hashed
|
||||
'magit-buffer-diff-range-oids "magit 4.6.0")
|
||||
(define-obsolete-variable-alias 'magit-buffer-revisions
|
||||
'magit-buffer-log-revisions "magit 4.6.0")
|
||||
(define-obsolete-variable-alias 'magit-buffer-revision-hash
|
||||
'magit-buffer-revision-oid "magit 4.6.0")
|
||||
(define-obsolete-variable-alias 'magit-buffer-typearg
|
||||
'magit-buffer-diff-typearg "magit 4.6.0")))
|
||||
(make-variable-buffer-local 'magit-buffer-arguments)
|
||||
(make-variable-buffer-local 'magit-buffer-upstream)
|
||||
|
||||
(defun magit-buffer-file-name ()
|
||||
"Return `magit-buffer-file-name' or if that is nil `buffer-file-name'.
|
||||
@@ -617,6 +625,7 @@ In an indirect buffer get the value for its base buffer."
|
||||
(defun magit-buffer-revision ()
|
||||
"Return `magit-buffer-revision' or if that is nil \"{worktree}\".
|
||||
If not visiting a blob or file, or the file isn't being tracked,
|
||||
return nil. If visiting a blob but `magit-buffer-revision' is nil,
|
||||
return nil."
|
||||
(or magit-buffer-revision
|
||||
(and buffer-file-name
|
||||
@@ -1179,7 +1188,21 @@ The arguments are for internal use."
|
||||
;; for the wrong buffer. Originally reported in #4196 and
|
||||
;; fixed with 482c25a3204468a4f6c2fe12ff061666b61f5f4d.
|
||||
(let ((magit-section-movement-hook nil))
|
||||
(magit-section-goto-successor section line char)))))
|
||||
(magit-section-goto-successor section line char)
|
||||
;; To store the point value for the selected window, it isn't
|
||||
;; enough for it to be current, the window has to "display" it.
|
||||
;; The effect of `goto-char', used by the above function, is not
|
||||
;; preserved, and using just `set-window-point' would affect the
|
||||
;; wrong buffer.
|
||||
(unless (eq (window-dedicated-p) t)
|
||||
(let ((restore (window-buffer))
|
||||
(window-scroll-functions nil)
|
||||
(window-configuration-change-hook nil))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(set-window-buffer nil (current-buffer) t)
|
||||
(set-window-point nil (point)))
|
||||
(set-window-buffer nil restore t))))))))
|
||||
|
||||
(defun magit-revert-buffer (_ignore-auto _noconfirm)
|
||||
"Wrapper around `magit-refresh-buffer' suitable as `revert-buffer-function'."
|
||||
@@ -1539,13 +1562,14 @@ repositories."
|
||||
"Zap caches for the current repository.
|
||||
|
||||
Remove the repository's entry from `magit-repository-local-cache',
|
||||
remove the host's entry from `magit--host-git-version-cache', and
|
||||
set `magit-section-visibility-cache' to nil for all Magit buffers
|
||||
of the repository.
|
||||
remove the host's entry from `magit--host-git-version-cache', set
|
||||
`magit-section-visibility-cache' to nil for all Magit buffers of
|
||||
the repository, and empty the `magit--blob-cache'.
|
||||
|
||||
With a prefix argument or if optional ALL is non-nil, discard the
|
||||
mentioned caches completely."
|
||||
(interactive)
|
||||
(magit--blob-cache-zap)
|
||||
(cond (all
|
||||
(setq magit-repository-local-cache nil)
|
||||
(setq magit--host-git-version-cache nil)
|
||||
@@ -1594,7 +1618,7 @@ The additional output can be found in the *Messages* buffer."
|
||||
(defun magit-file-region-line-numbers ()
|
||||
"Return the bounds of the region as line numbers.
|
||||
The returned value has the form (BEGINNING-LINE END-LINE). If
|
||||
the region end at the beginning of a line, do not include that
|
||||
the region ends at the beginning of a line, do not include that
|
||||
line. Avoid including the line after the end of the file."
|
||||
(and (magit-buffer-file-name)
|
||||
(region-active-p)
|
||||
@@ -1615,6 +1639,7 @@ line. Avoid including the line after the end of the file."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; magit-notes.el --- Notes support -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 2008-2025 The Magit Project Contributors
|
||||
;; Copyright (C) 2008-2026 The Magit Project Contributors
|
||||
|
||||
;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
|
||||
@@ -204,6 +204,7 @@ Also see `magit-notes-merge'."
|
||||
;; ("and>" . "cond-let--and>")
|
||||
;; ("and-let" . "cond-let--and-let")
|
||||
;; ("if-let" . "cond-let--if-let")
|
||||
;; ("when$" . "cond-let--when$")
|
||||
;; ("when-let" . "cond-let--when-let")
|
||||
;; ("while-let" . "cond-let--while-let")
|
||||
;; ("match-string" . "match-string")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user