From ff160687915804b109fe626a5c7fbe949f227106 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Wed, 10 Jan 2024 21:49:17 +0100 Subject: Update markdown-mode and yasnippet. Add some new Python snippets --- .emacs.d/lisp/markdown-mode.el | 178 ++++++++++++++- .emacs.d/lisp/yasnippet.el | 253 +++++++++++---------- .emacs.d/snippets/c-mode/.yas-parents | 1 + .../snippets/python-mode.statnett/.yas-setup.el | 31 ++- .emacs.d/snippets/python-mode.statnett/__call__ | 7 + .emacs.d/snippets/python-mode.statnett/__repr__ | 7 + .emacs.d/snippets/python-mode.statnett/__str__ | 7 + .emacs.d/snippets/python-mode.statnett/script | 3 +- .emacs.d/snippets/python-mode.statnett/with-open | 6 + .emacs.d/snippets/python-mode/.yas-setup.el | 31 ++- .emacs.d/snippets/python-mode/__call__ | 7 + .emacs.d/snippets/python-mode/__repr__ | 7 + .emacs.d/snippets/python-mode/__str__ | 7 + .emacs.d/snippets/python-mode/script | 1 - .emacs.d/snippets/python-mode/with-open | 6 + 15 files changed, 401 insertions(+), 151 deletions(-) create mode 100644 .emacs.d/snippets/python-mode.statnett/__call__ create mode 100644 .emacs.d/snippets/python-mode.statnett/__repr__ create mode 100644 .emacs.d/snippets/python-mode.statnett/__str__ create mode 100644 .emacs.d/snippets/python-mode.statnett/with-open create mode 100644 .emacs.d/snippets/python-mode/__call__ create mode 100644 .emacs.d/snippets/python-mode/__repr__ create mode 100644 .emacs.d/snippets/python-mode/__str__ create mode 100644 .emacs.d/snippets/python-mode/with-open diff --git a/.emacs.d/lisp/markdown-mode.el b/.emacs.d/lisp/markdown-mode.el index f1aee9d..8094e02 100644 --- a/.emacs.d/lisp/markdown-mode.el +++ b/.emacs.d/lisp/markdown-mode.el @@ -659,6 +659,44 @@ markdown-header-face-* faces." :safe 'booleanp :package-version '(markdown-mode . "2.5")) +(defcustom markdown-special-ctrl-a/e nil + "Non-nil means `C-a' and `C-e' behave specially in headlines and items. + +When t, `C-a' will bring back the cursor to the beginning of the +headline text. In an item, this will be the position after bullet +and check-box, if any. When the cursor is already at that +position, another `C-a' will bring it to the beginning of the +line. + +`C-e' will jump to the end of the headline, ignoring the presence +of closing tags in the headline. A second `C-e' will then jump to +the true end of the line, after closing tags. This also means +that, when this variable is non-nil, `C-e' also will never jump +beyond the end of the heading of a folded section, i.e. not after +the ellipses. + +When set to the symbol `reversed', the first `C-a' or `C-e' works +normally, going to the true line boundary first. Only a directly +following, identical keypress will bring the cursor to the +special positions. + +This may also be a cons cell where the behavior for `C-a' and +`C-e' is set separately." + :group 'markdown + :type '(choice + (const :tag "off" nil) + (const :tag "on: after hashes/bullet and before closing tags first" t) + (const :tag "reversed: true line boundary first" reversed) + (cons :tag "Set C-a and C-e separately" + (choice :tag "Special C-a" + (const :tag "off" nil) + (const :tag "on: after hashes/bullet first" t) + (const :tag "reversed: before hashes/bullet first" reversed)) + (choice :tag "Special C-e" + (const :tag "off" nil) + (const :tag "on: before closing tags first" t) + (const :tag "reversed: after closing tags first" reversed)))) + :package-version '(markdown-mode . "2.7")) ;;; Markdown-Specific `rx' Macro ============================================== @@ -5531,6 +5569,9 @@ Assumes match data is available for `markdown-regex-italic'." (define-key map (kbd "C-x n s") 'markdown-narrow-to-subtree) (define-key map (kbd "M-RET") 'markdown-insert-list-item) (define-key map (kbd "C-c C-j") 'markdown-insert-list-item) + ;; Lines + (define-key map [remap move-beginning-of-line] 'markdown-beginning-of-line) + (define-key map [remap move-end-of-line] 'markdown-end-of-line) ;; Paragraphs (Markdown context aware) (define-key map [remap backward-paragraph] 'markdown-backward-paragraph) (define-key map [remap forward-paragraph] 'markdown-forward-paragraph) @@ -6474,6 +6515,130 @@ a list." ;;; Movement ================================================================== +;; This function was originally derived from `org-beginning-of-line' from org.el. +(defun markdown-beginning-of-line (&optional n) + "Go to the beginning of the current visible line. + +If this is a headline, and `markdown-special-ctrl-a/e' is not nil +or symbol `reversed', on the first attempt move to where the +headline text hashes, and only move to beginning of line when the +cursor is already before the hashes of the text of the headline. + +If `markdown-special-ctrl-a/e' is symbol `reversed' then go to +the hashes of the text on the second attempt. + +With argument N not nil or 1, move forward N - 1 lines first." + (interactive "^p") + (let ((origin (point)) + (special (pcase markdown-special-ctrl-a/e + (`(,C-a . ,_) C-a) (_ markdown-special-ctrl-a/e))) + deactivate-mark) + ;; First move to a visible line. + (if visual-line-mode + (beginning-of-visual-line n) + (move-beginning-of-line n) + ;; `move-beginning-of-line' may leave point after invisible + ;; characters if line starts with such of these (e.g., with + ;; a link at column 0). Really move to the beginning of the + ;; current visible line. + (forward-line 0)) + (cond + ;; No special behavior. Point is already at the beginning of + ;; a line, logical or visual. + ((not special)) + ;; `beginning-of-visual-line' left point before logical beginning + ;; of line: point is at the beginning of a visual line. Bail + ;; out. + ((and visual-line-mode (not (bolp)))) + ((looking-at markdown-regex-header-atx) + ;; At a header, special position is before the title. + (let ((refpos (match-beginning 2)) + (bol (point))) + (if (eq special 'reversed) + (when (and (= origin bol) (eq last-command this-command)) + (goto-char refpos)) + (when (or (> origin refpos) (<= origin bol)) + (goto-char refpos))) + ;; Prevent automatic cursor movement caused by the command loop. + ;; Enable disable-point-adjustment to avoid unintended cursor repositioning. + (when (and markdown-hide-markup + (equal (get-char-property (point) 'display) "")) + (setq disable-point-adjustment t)))) + ((looking-at markdown-regex-list) + ;; At a list item, special position is after the list marker or checkbox. + (let ((refpos (or (match-end 4) (match-end 3)))) + (if (eq special 'reversed) + (when (and (= (point) origin) (eq last-command this-command)) + (goto-char refpos)) + (when (or (> origin refpos) (<= origin (line-beginning-position))) + (goto-char refpos))))) + ;; No special case, already at beginning of line. + (t nil)))) + +;; This function was originally derived from `org-end-of-line' from org.el. +(defun markdown-end-of-line (&optional n) + "Go to the end of the line, but before ellipsis, if any. + +If this is a headline, and `markdown-special-ctrl-a/e' is not nil +or symbol `reversed', ignore closing tags on the first attempt, +and only move to after the closing tags when the cursor is +already beyond the end of the headline. + +If `markdown-special-ctrl-a/e' is symbol `reversed' then ignore +closing tags on the second attempt. + +With argument N not nil or 1, move forward N - 1 lines first." + (interactive "^p") + (let ((origin (point)) + (special (pcase markdown-special-ctrl-a/e + (`(,_ . ,C-e) C-e) (_ markdown-special-ctrl-a/e))) + deactivate-mark) + ;; First move to a visible line. + (if visual-line-mode + (beginning-of-visual-line n) + (move-beginning-of-line n)) + (cond + ;; At a headline, with closing tags. + ((save-excursion + (forward-line 0) + (and (looking-at markdown-regex-header-atx) (match-end 3))) + (let ((refpos (match-end 2)) + (visual-end (and visual-line-mode + (save-excursion + (end-of-visual-line) + (point))))) + ;; If `end-of-visual-line' brings us before end of line or even closing + ;; tags, i.e., the headline spans over multiple visual lines, move + ;; there. + (cond ((and visual-end + (< visual-end refpos) + (<= origin visual-end)) + (goto-char visual-end)) + ((not special) (end-of-line)) + ((eq special 'reversed) + (if (and (= origin (line-end-position)) + (eq this-command last-command)) + (goto-char refpos) + (end-of-line))) + (t + (if (or (< origin refpos) (>= origin (line-end-position))) + (goto-char refpos) + (end-of-line)))) + ;; Prevent automatic cursor movement caused by the command loop. + ;; Enable disable-point-adjustment to avoid unintended cursor repositioning. + (when (and markdown-hide-markup + (equal (get-char-property (point) 'display) "")) + (setq disable-point-adjustment t)))) + (visual-line-mode + (let ((bol (line-beginning-position))) + (end-of-visual-line) + ;; If `end-of-visual-line' gets us past the ellipsis at the + ;; end of a line, backtrack and use `end-of-line' instead. + (when (/= bol (line-beginning-position)) + (goto-char bol) + (end-of-line)))) + (t (end-of-line))))) + (defun markdown-beginning-of-defun (&optional arg) "`beginning-of-defun-function' for Markdown. This is used to find the beginning of the defun and should behave @@ -10042,7 +10207,18 @@ rows and columns and the column alignment." ;; add live preview export hook (add-hook 'after-save-hook #'markdown-live-preview-if-markdown t t) - (add-hook 'kill-buffer-hook #'markdown-live-preview-remove-on-kill t t)) + (add-hook 'kill-buffer-hook #'markdown-live-preview-remove-on-kill t t) + + ;; Add a custom keymap for `visual-line-mode' so that activating + ;; this minor mode does not override markdown-mode's keybindings. + ;; FIXME: Probably `visual-line-mode' should take care of this. + (let ((oldmap (cdr (assoc 'visual-line-mode minor-mode-map-alist))) + (newmap (make-sparse-keymap))) + (set-keymap-parent newmap oldmap) + (define-key newmap [remap move-beginning-of-line] nil) + (define-key newmap [remap move-end-of-line] nil) + (make-local-variable 'minor-mode-overriding-map-alist) + (push `(visual-line-mode . ,newmap) minor-mode-overriding-map-alist))) ;;;###autoload (add-to-list 'auto-mode-alist diff --git a/.emacs.d/lisp/yasnippet.el b/.emacs.d/lisp/yasnippet.el index c4f8ae4..f5210d5 100644 --- a/.emacs.d/lisp/yasnippet.el +++ b/.emacs.d/lisp/yasnippet.el @@ -1,6 +1,6 @@ ;;; yasnippet.el --- Yet another snippet extension for Emacs -*- lexical-binding: t; -*- -;; Copyright (C) 2008-2023 Free Software Foundation, Inc. +;; Copyright (C) 2008-2024 Free Software Foundation, Inc. ;; Authors: pluskid , ;; João Távora , ;; Noam Postavsky @@ -132,8 +132,7 @@ ;;; Code: (require 'cl-lib) -(require 'eldoc) ; Needed for 24. -(declare-function cl-progv-after "cl-extra") ; Needed for 23.4. +(require 'eldoc) ; Needed for Emacs<25. (require 'easymenu) (require 'help-mode) @@ -342,8 +341,8 @@ If non-nil insert region contents. This can be overridden on a per-snippet basis. A value of `cua' is considered equivalent to `?0' for backwards compatibility." :type '(choice (character :tag "Insert from register") - (const t :tag "Insert region contents") - (const nil :tag "Don't insert anything") + (const :tag "Insert region contents" t) + (const :tag "Don't insert anything" nil) (const cua))) ; backwards compat (defcustom yas-good-grace t @@ -763,7 +762,7 @@ expanded.") :help "Display some information about YASnippet"])) (define-obsolete-variable-alias 'yas-extra-modes 'yas--extra-modes "0.9.1") -(defvar yas--extra-modes nil +(defvar yas--extra-modes nil ;FIXME: Use `defvar-local'? "An internal list of modes for which to also lookup snippets. This variable probably makes more sense as buffer-local, so @@ -773,7 +772,7 @@ ensure your use `make-local-variable' when you set it.") "A hash table of mode symbols to `yas--table' objects.") (defvar yas--parents (make-hash-table) - "A hash table of mode symbols do lists of direct parent mode symbols. + "A hash table of mode symbols to lists of direct parent mode symbols. This list is populated when reading the \".yas-parents\" files found when traversing snippet directories with @@ -805,29 +804,59 @@ which decides on the snippet to expand.") yas--direct-keymaps)) yas--tables)) +(defalias 'yas--merge-ordered-lists + (if (fboundp 'merge-ordered-lists) ;Emacs≥30. + #'merge-ordered-lists + (lambda (lists) + (setq lists (delq nil lists)) + (if (null (cdr lists)) (car lists) ;Common case. + (delete-dups (apply #'append + ;; Prevent sharing the tail. + (append lists '(()) ))))))) + +(defun yas--all-parents (mode) + "Like `derived-mode-all-parents' but obeying `yas--parents'." + (or (get mode 'yas--all-parents) ;; FIXME: Use `with-memoization'? + (progn + (put mode 'yas--all-parents (list mode)) ;; Stop inf-loop with cycles. + (put mode 'yas--all-parents + (if (fboundp 'derived-mode-all-parents) + (let* ((ap (derived-mode-all-parents mode)) + (extras + (mapcar (lambda (parent) + (yas--merge-ordered-lists + (mapcar #'yas--all-parents + (gethash parent yas--parents)))) + ap))) + (yas--merge-ordered-lists + (cons (append ap '(fundamental-mode)) extras))) + (cons mode + (yas--merge-ordered-lists + (mapcar #'yas--all-parents + (remq nil + `(,(or (get mode 'derived-mode-parent) + ;; Consider `fundamental-mode' + ;; as ultimate ancestor. + 'fundamental-mode) + ,(let ((alias (symbol-function mode))) + (when (symbolp alias) alias)) + ,@(gethash mode yas--parents))))))))))) + (defun yas--modes-to-activate (&optional mode) "Compute list of mode symbols that are active for `yas-expand' and friends." - (defvar yas--dfs) ;We rely on dynbind. We could use `letrec' instead! - (let* ((explored (if mode (list mode) ; Building up list in reverse. - (cons major-mode (reverse yas--extra-modes)))) - (yas--dfs - (lambda (mode) - (cl-loop for neighbour - in (cl-list* (or (get mode 'derived-mode-parent) - ;; Consider `fundamental-mode' - ;; as ultimate ancestor. - 'fundamental-mode) - ;; NOTE: `fboundp' check is redundant - ;; since Emacs 24.4. - (and (fboundp mode) (symbol-function mode)) - (gethash mode yas--parents)) - when (and neighbour - (not (memq neighbour explored)) - (symbolp neighbour)) - do (push neighbour explored) - (funcall yas--dfs neighbour))))) - (mapc yas--dfs explored) - (nreverse explored))) + (let* ((modes + (delete-dups + (remq nil `(,(or mode major-mode) + ;; FIXME: Alternative major modes should use + ;; `derived-mode-add-parents', but until that + ;; becomes common, use `major-mode-remap-alist' + ;; as a crutch to supplement the mode hierarchy. + ,(and (boundp 'major-mode-remap-alist) + (car (rassq (or mode major-mode) + major-mode-remap-alist))) + ,@(unless mode (reverse yas--extra-modes))))))) + (yas--merge-ordered-lists + (mapcar #'yas--all-parents modes)))) (defvar yas-minor-mode-hook nil "Hook run when `yas-minor-mode' is turned on.") @@ -889,13 +918,8 @@ Key bindings: The function can be called in the hook of a minor mode to activate snippets associated with that mode." (interactive - (let (modes - symbol) - (maphash (lambda (k _) - (setq modes (cons (list k) modes))) - yas--parents) - (setq symbol (completing-read - "Activate mode: " modes nil t)) + (let ((symbol (completing-read + "Activate mode: " yas--parents nil t))) (list (when (not (string= "" symbol)) (intern symbol))))) @@ -909,9 +933,8 @@ activate snippets associated with that mode." (list (intern (completing-read "Deactivate mode: " (mapcar #'list yas--extra-modes) nil t)))) - (set (make-local-variable 'yas--extra-modes) - (remove mode - yas--extra-modes))) + (setq-local yas--extra-modes + (remove mode yas--extra-modes))) (defun yas-temp-buffer-p (&optional buffer) (eq (aref (buffer-name buffer) 0) ?\s)) @@ -923,20 +946,10 @@ activate snippets associated with that mode." Functions are called with no argument, and should return non-nil to prevent `yas-global-mode' from enabling yasnippet in this buffer. -In Emacsen < 24, this variable is buffer-local. Because -`yas-minor-mode-on' is called by `yas-global-mode' after -executing the buffer's major mode hook, setting this variable -there is an effective way to define exceptions to the \"global\" -activation behaviour. - -In Emacsen >= 24, only the global value is used. To define +Only the global value is used. To define per-mode exceptions to the \"global\" activation behaviour, call `yas-minor-mode' with a negative argument directily in the major -mode's hook.") -(unless (> emacs-major-version 23) - (with-no-warnings - (make-variable-buffer-local 'yas-dont-activate))) - +mode's hook.") ;; FIXME: Why do we say "Only the global value is used"? (defun yas-minor-mode-on () "Turn on YASnippet minor mode. @@ -1003,23 +1016,13 @@ Honour `yas-dont-activate-functions', which see." ;;;###autoload(autoload 'snippet-mode "yasnippet" "A mode for editing yasnippets" t nil) -(eval-and-compile - (if (fboundp 'prog-mode) - ;; `prog-mode' is new in 24.1. - (define-derived-mode snippet-mode prog-mode "Snippet" - "A mode for editing yasnippets" - (setq font-lock-defaults '(yas--font-lock-keywords)) - (set (make-local-variable 'require-final-newline) nil) - (set (make-local-variable 'comment-start) "#") - (set (make-local-variable 'comment-start-skip) "#+[\t ]*") - (add-hook 'after-save-hook #'yas-maybe-load-snippet-buffer nil t)) - (define-derived-mode snippet-mode fundamental-mode "Snippet" - "A mode for editing yasnippets" - (setq font-lock-defaults '(yas--font-lock-keywords)) - (set (make-local-variable 'require-final-newline) nil) - (set (make-local-variable 'comment-start) "#") - (set (make-local-variable 'comment-start-skip) "#+[\t ]*") - (add-hook 'after-save-hook #'yas-maybe-load-snippet-buffer nil t)))) +(define-derived-mode snippet-mode prog-mode "Snippet" + "A mode for editing yasnippets" + (setq font-lock-defaults '(yas--font-lock-keywords)) + (setq-local require-final-newline nil) + (setq-local comment-start "#") + (setq-local comment-start-skip "#+[\t ]*") + (add-hook 'after-save-hook #'yas-maybe-load-snippet-buffer nil t)) (defun yas-snippet-mode-buffer-p () "Return non-nil if current buffer should be in `snippet-mode'. @@ -1721,12 +1724,10 @@ Optional PROMPT sets the prompt to use." (redisplay) (or (x-popup-menu - (if (fboundp 'posn-at-point) - (let ((x-y (posn-x-y (posn-at-point (point))))) - (list (list (+ (car x-y) 10) - (+ (cdr x-y) 20)) - (selected-window))) - t) + (let ((x-y (posn-x-y (posn-at-point (point))))) + (list (list (+ (car x-y) 10) + (+ (cdr x-y) 20)) + (selected-window))) `(,prompt ("title" ,@(cl-mapcar (lambda (c d) `(,(concat " " d) . ,c)) choices @@ -2100,6 +2101,9 @@ This works by stubbing a few functions, then calling (or (ignore-errors (car (let ((default-directory yas--loaddir)) (process-lines "git" "describe" "--tags" "--dirty")))) + (eval-when-compile + (and (fboundp 'package-get-version) + (package-get-version))) (when (and (featurep 'package) (fboundp 'package-desc-version) (fboundp 'package-version-join)) @@ -2549,7 +2553,7 @@ visited file in `snippet-mode'." (cond ((and file (file-readable-p file)) (find-file-other-window file) (snippet-mode) - (set (make-local-variable 'yas--editing-template) template)) + (setq-local yas--editing-template template)) (file (message "Original file %s no longer exists!" file)) (t @@ -2571,9 +2575,10 @@ visited file in `snippet-mode'." (pp-to-string (yas--template-content template)) (yas--template-content template)))) (snippet-mode) - (set (make-local-variable 'yas--editing-template) template) - (set (make-local-variable 'default-directory) - (car (cdr (car (yas--guess-snippet-directories (yas--template-table template)))))))))) + (setq-local yas--editing-template template) + (setq-local default-directory + (car (cdr (car (yas--guess-snippet-directories + (yas--template-table template)))))))))) (defun yas--guess-snippet-directories-1 (table) "Guess possible snippet subdirectories for TABLE." @@ -2649,11 +2654,11 @@ NO-TEMPLATE is non-nil." (kill-all-local-variables) (snippet-mode) (yas-minor-mode 1) - (set (make-local-variable 'yas--guessed-modes) - (mapcar (lambda (d) (yas--table-mode (car d))) - guessed-directories)) - (set (make-local-variable 'default-directory) - (car (cdr (car guessed-directories)))) + (setq-local yas--guessed-modes + (mapcar (lambda (d) (yas--table-mode (car d))) + guessed-directories)) + (setq-local default-directory + (car (cdr (car guessed-directories)))) (if (and (not no-template) yas-new-snippet-default) (yas-expand-snippet yas-new-snippet-default)))) @@ -2703,8 +2708,8 @@ neither do the elements of PARENTS." ido-mode) 'ido-completing-read 'completing-read))) (unless yas--guessed-modes - (set (make-local-variable 'yas--guessed-modes) - (or (yas--compute-major-mode-and-parents buffer-file-name)))) + (setq-local yas--guessed-modes + (yas--compute-major-mode-and-parents buffer-file-name))) (intern (funcall prompt (format "Choose or enter a table (yas guesses %s): " (if yas--guessed-modes @@ -2736,11 +2741,12 @@ Return the `yas--template' object created" ;; (t (unless yas--guessed-modes - (set (make-local-variable 'yas--guessed-modes) (or (yas--compute-major-mode-and-parents buffer-file-name)))) + (setq-local yas--guessed-modes + (or (yas--compute-major-mode-and-parents buffer-file-name)))) (let* ((table (yas--table-get-create table))) - (set (make-local-variable 'yas--editing-template) - (yas--define-snippets-1 (yas--parse-template buffer-file-name) - table))))) + (setq-local yas--editing-template + (yas--define-snippets-1 (yas--parse-template buffer-file-name) + table))))) (when interactive (yas--message 3 "Snippet \"%s\" loaded for %s." (yas--template-name yas--editing-template) @@ -3097,14 +3103,13 @@ other fields." ;;; Snippet expansion and field management -(defvar yas--active-field-overlay nil +(defvar-local yas--active-field-overlay nil "Overlays the currently active field.") -(defvar yas--active-snippets nil +(defvar-local yas--active-snippets nil "List of currently active snippets") -(make-variable-buffer-local 'yas--active-snippets) -(defvar yas--field-protection-overlays nil +(defvar-local yas--field-protection-overlays nil "Two overlays protect the current active field.") (defvar yas-selected-text nil @@ -3113,8 +3118,6 @@ other fields." (defvar yas--start-column nil "The column where the snippet expansion started.") -(make-variable-buffer-local 'yas--active-field-overlay) -(make-variable-buffer-local 'yas--field-protection-overlays) (put 'yas--active-field-overlay 'permanent-local t) (put 'yas--field-protection-overlays 'permanent-local t) @@ -3494,8 +3497,7 @@ This renders the snippet as ordinary text." (yas--message 4 "Snippet %s exited." (yas--snippet-id snippet))) -(defvar yas--snippets-to-move nil) -(make-variable-buffer-local 'yas--snippets-to-move) +(defvar-local yas--snippets-to-move nil) (defun yas--prepare-snippets-for-move (beg end buf pos) "Gather snippets in BEG..END for moving to POS in BUF." @@ -3762,13 +3764,10 @@ BEG, END and LENGTH like overlay modification hooks." (defun yas--merge-and-drop-dups (list1 list2 cmp key) ;; `delete-consecutive-dups' + `cl-merge'. - (funcall (if (fboundp 'delete-consecutive-dups) - #'delete-consecutive-dups ; 24.4 - #'delete-dups) - (cl-merge 'list list1 list2 cmp :key key))) + (delete-consecutive-dups + (cl-merge 'list list1 list2 cmp :key key))) -(defvar yas--before-change-modified-snippets nil) -(make-variable-buffer-local 'yas--before-change-modified-snippets) +(defvar-local yas--before-change-modified-snippets nil) (defun yas--gather-active-snippets (overlay beg end then-delete) ;; Add active snippets in BEG..END into an OVERLAY keyed entry of @@ -3793,8 +3792,7 @@ BEG, END and LENGTH like overlay modification hooks." (when then-delete (cl-callf2 delq old yas--before-change-modified-snippets))))) -(defvar yas--todo-snippet-indent nil nil) -(make-variable-buffer-local 'yas--todo-snippet-indent) +(defvar-local yas--todo-snippet-indent nil nil) (defun yas--on-field-overlay-modification (overlay after? beg end &optional length) "Clears the field and updates mirrors, conditionally. @@ -4104,25 +4102,34 @@ Returns the newly created snippet." ;; content. (let ((buffer-undo-list t)) (goto-char begin) - ;; Call before and after change functions manually, - ;; otherwise cc-mode's cache can get messed up. Don't use - ;; `inhibit-modification-hooks' for that, that blocks - ;; overlay and text property hooks as well! FIXME: Maybe - ;; use `combine-change-calls'? (Requires Emacs 27+ though.) - (run-hook-with-args 'before-change-functions begin end) - (let ((before-change-functions nil) - (after-change-functions nil)) - ;; Some versions of cc-mode (might be the one with Emacs - ;; 24.3 only) fail when inserting snippet content in a - ;; narrowed buffer, so make sure to insert before - ;; narrowing. - (insert content) - (narrow-to-region begin (point)) - (goto-char (point-min)) - (yas--snippet-parse-create snippet)) - (run-hook-with-args 'after-change-functions - (point-min) (point-max) - (- end begin))) + (if (> emacs-major-version 29) + ;; Don't use the workaround for CC-mode's cache, + ;; since it was presumably a bug in CC-mode, so either + ;; it's fixed already, or it should get fixed. + (progn + (insert content) + (narrow-to-region begin (point)) + (goto-char (point-min)) + (yas--snippet-parse-create snippet)) + ;; Call before and after change functions manually, + ;; otherwise cc-mode's cache can get messed up. Don't use + ;; `inhibit-modification-hooks' for that, that blocks + ;; overlay and text property hooks as well! FIXME: Maybe + ;; use `combine-change-calls'? (Requires Emacs 27+ though.) + (run-hook-with-args 'before-change-functions begin end) + (let ((before-change-functions nil) + (after-change-functions nil)) + ;; Some versions of cc-mode (might be the one with Emacs + ;; 24.3 only) fail when inserting snippet content in a + ;; narrowed buffer, so make sure to insert before + ;; narrowing. + (insert content) + (narrow-to-region begin (point)) + (goto-char (point-min)) + (yas--snippet-parse-create snippet)) + (run-hook-with-args 'after-change-functions + (point-min) (point-max) + (- end begin)))) (when (listp buffer-undo-list) (push (cons (point-min) (point-max)) buffer-undo-list)) diff --git a/.emacs.d/snippets/c-mode/.yas-parents b/.emacs.d/snippets/c-mode/.yas-parents index ce9828b..b269357 100644 --- a/.emacs.d/snippets/c-mode/.yas-parents +++ b/.emacs.d/snippets/c-mode/.yas-parents @@ -1 +1,2 @@ cc-mode +c-lang-common diff --git a/.emacs.d/snippets/python-mode.statnett/.yas-setup.el b/.emacs.d/snippets/python-mode.statnett/.yas-setup.el index 76af532..8b29215 100644 --- a/.emacs.d/snippets/python-mode.statnett/.yas-setup.el +++ b/.emacs.d/snippets/python-mode.statnett/.yas-setup.el @@ -1,23 +1,33 @@ (require 'yasnippet) (defvar yas-text) +(defvar python-split-arg-arg-regex +"\\([[:alnum:]*]+\\)\\(:[[:blank:]]*[[:alpha:]]*\\)?\\([[:blank:]]*=[[:blank:]]*[[:alnum:]]*\\)?" +"Regular expression matching an argument of a python function. +First group should give the argument name.") + +(defvar python-split-arg-separator +"[[:space:]]*,[[:space:]]*" +"Regular expression matching the separator in a list of argument.") + (defun python-split-args (arg-string) - "Split a python argument string into ((name, default)..) tuples" + "Split a python argument string ARG-STRING into a tuple of argument names." (mapcar (lambda (x) - (split-string x "[[:blank:]]*=[[:blank:]]*" t)) - (split-string arg-string "[[:blank:]]*,[[:blank:]]*" t))) + (when (string-match python-split-arg-arg-regex x) + (match-string-no-properties 1 x))) + (split-string arg-string python-split-arg-separator t))) (defun python-args-to-docstring () - "return docstring format for the python arguments in yas-text" + "Return docstring format for the python arguments in yas-text." (let* ((indent (concat "\n" (make-string (current-column) 32))) (args (python-split-args yas-text)) (max-len (if args (apply 'max (mapcar (lambda (x) (length (nth 0 x))) args)) 0)) (formatted-args (mapconcat - (lambda (x) - (concat (nth 0 x) (make-string (- max-len (length (nth 0 x))) ? ) " -- " - (if (nth 1 x) (concat "\(default " (nth 1 x) "\)")))) - args - indent))) + (lambda (x) + (concat (nth 0 x) (make-string (- max-len (length (nth 0 x))) ? ) " -- " + (if (nth 1 x) (concat "\(default " (nth 1 x) "\)")))) + args + indent))) (unless (string= formatted-args "") (mapconcat 'identity (list "Keyword Arguments:" formatted-args) indent)))) @@ -33,6 +43,3 @@ (list "\nParameters\n----------" formatted-params "\nReturns\n-------" formatted-ret) "\n")))) - - -(add-hook 'python-mode-hook #'yasnippet-snippets--fixed-indent) diff --git a/.emacs.d/snippets/python-mode.statnett/__call__ b/.emacs.d/snippets/python-mode.statnett/__call__ new file mode 100644 index 0000000..e807be5 --- /dev/null +++ b/.emacs.d/snippets/python-mode.statnett/__call__ @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: __call__ +# key: _call +# group: Special methods +# -- +def __call__(self, ${1:*args}): + return $0 diff --git a/.emacs.d/snippets/python-mode.statnett/__repr__ b/.emacs.d/snippets/python-mode.statnett/__repr__ new file mode 100644 index 0000000..85cb80f --- /dev/null +++ b/.emacs.d/snippets/python-mode.statnett/__repr__ @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: __repr__ +# key: _repr +# group: Special methods +# -- +def __repr__(self): + return $0 diff --git a/.emacs.d/snippets/python-mode.statnett/__str__ b/.emacs.d/snippets/python-mode.statnett/__str__ new file mode 100644 index 0000000..f623df7 --- /dev/null +++ b/.emacs.d/snippets/python-mode.statnett/__str__ @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: __str__ +# key: _str +# group: Special methods +# -- +def __str__(self): + return $0 diff --git a/.emacs.d/snippets/python-mode.statnett/script b/.emacs.d/snippets/python-mode.statnett/script index 2e8cc35..4490e07 100644 --- a/.emacs.d/snippets/python-mode.statnett/script +++ b/.emacs.d/snippets/python-mode.statnett/script @@ -3,12 +3,11 @@ # key: script # -- #!/usr/bin/env python -# -*- coding: utf-8 -*- def main(inargs=None): """main entry point""" $0 -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/.emacs.d/snippets/python-mode.statnett/with-open b/.emacs.d/snippets/python-mode.statnett/with-open new file mode 100644 index 0000000..77c7210 --- /dev/null +++ b/.emacs.d/snippets/python-mode.statnett/with-open @@ -0,0 +1,6 @@ +# -*- mode: snippet -*- +# name: with-open +# key: wo +# -- +with open(${1:"filename"}${2:, encoding="${3:utf-8}"}${4:, mode="${5:w}"}) as ${6:myfile}: + $0 \ No newline at end of file diff --git a/.emacs.d/snippets/python-mode/.yas-setup.el b/.emacs.d/snippets/python-mode/.yas-setup.el index 76af532..8b29215 100644 --- a/.emacs.d/snippets/python-mode/.yas-setup.el +++ b/.emacs.d/snippets/python-mode/.yas-setup.el @@ -1,23 +1,33 @@ (require 'yasnippet) (defvar yas-text) +(defvar python-split-arg-arg-regex +"\\([[:alnum:]*]+\\)\\(:[[:blank:]]*[[:alpha:]]*\\)?\\([[:blank:]]*=[[:blank:]]*[[:alnum:]]*\\)?" +"Regular expression matching an argument of a python function. +First group should give the argument name.") + +(defvar python-split-arg-separator +"[[:space:]]*,[[:space:]]*" +"Regular expression matching the separator in a list of argument.") + (defun python-split-args (arg-string) - "Split a python argument string into ((name, default)..) tuples" + "Split a python argument string ARG-STRING into a tuple of argument names." (mapcar (lambda (x) - (split-string x "[[:blank:]]*=[[:blank:]]*" t)) - (split-string arg-string "[[:blank:]]*,[[:blank:]]*" t))) + (when (string-match python-split-arg-arg-regex x) + (match-string-no-properties 1 x))) + (split-string arg-string python-split-arg-separator t))) (defun python-args-to-docstring () - "return docstring format for the python arguments in yas-text" + "Return docstring format for the python arguments in yas-text." (let* ((indent (concat "\n" (make-string (current-column) 32))) (args (python-split-args yas-text)) (max-len (if args (apply 'max (mapcar (lambda (x) (length (nth 0 x))) args)) 0)) (formatted-args (mapconcat - (lambda (x) - (concat (nth 0 x) (make-string (- max-len (length (nth 0 x))) ? ) " -- " - (if (nth 1 x) (concat "\(default " (nth 1 x) "\)")))) - args - indent))) + (lambda (x) + (concat (nth 0 x) (make-string (- max-len (length (nth 0 x))) ? ) " -- " + (if (nth 1 x) (concat "\(default " (nth 1 x) "\)")))) + args + indent))) (unless (string= formatted-args "") (mapconcat 'identity (list "Keyword Arguments:" formatted-args) indent)))) @@ -33,6 +43,3 @@ (list "\nParameters\n----------" formatted-params "\nReturns\n-------" formatted-ret) "\n")))) - - -(add-hook 'python-mode-hook #'yasnippet-snippets--fixed-indent) diff --git a/.emacs.d/snippets/python-mode/__call__ b/.emacs.d/snippets/python-mode/__call__ new file mode 100644 index 0000000..e807be5 --- /dev/null +++ b/.emacs.d/snippets/python-mode/__call__ @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: __call__ +# key: _call +# group: Special methods +# -- +def __call__(self, ${1:*args}): + return $0 diff --git a/.emacs.d/snippets/python-mode/__repr__ b/.emacs.d/snippets/python-mode/__repr__ new file mode 100644 index 0000000..85cb80f --- /dev/null +++ b/.emacs.d/snippets/python-mode/__repr__ @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: __repr__ +# key: _repr +# group: Special methods +# -- +def __repr__(self): + return $0 diff --git a/.emacs.d/snippets/python-mode/__str__ b/.emacs.d/snippets/python-mode/__str__ new file mode 100644 index 0000000..f623df7 --- /dev/null +++ b/.emacs.d/snippets/python-mode/__str__ @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: __str__ +# key: _str +# group: Special methods +# -- +def __str__(self): + return $0 diff --git a/.emacs.d/snippets/python-mode/script b/.emacs.d/snippets/python-mode/script index 2e8cc35..9637f4c 100644 --- a/.emacs.d/snippets/python-mode/script +++ b/.emacs.d/snippets/python-mode/script @@ -3,7 +3,6 @@ # key: script # -- #!/usr/bin/env python -# -*- coding: utf-8 -*- def main(inargs=None): diff --git a/.emacs.d/snippets/python-mode/with-open b/.emacs.d/snippets/python-mode/with-open new file mode 100644 index 0000000..77c7210 --- /dev/null +++ b/.emacs.d/snippets/python-mode/with-open @@ -0,0 +1,6 @@ +# -*- mode: snippet -*- +# name: with-open +# key: wo +# -- +with open(${1:"filename"}${2:, encoding="${3:utf-8}"}${4:, mode="${5:w}"}) as ${6:myfile}: + $0 \ No newline at end of file -- cgit v1.3