From 722f8a517f8aa73316e982c003b12438e8ad3269 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sun, 29 Apr 2018 12:09:34 +0200 Subject: [PATCH] org-macs: Re-order sections alphabetically --- lisp/org-macs.el | 674 +++++++++++++++++++++++------------------------ 1 file changed, 337 insertions(+), 337 deletions(-) diff --git a/lisp/org-macs.el b/lisp/org-macs.el index 65c62dca4..8ec2498c2 100644 --- a/lisp/org-macs.el +++ b/lisp/org-macs.el @@ -307,6 +307,48 @@ it for output." output)) + +;;; Indentation + +(defun org-get-indentation (&optional line) + "Get the indentation of the current line, interpreting tabs. +When LINE is given, assume it represents a line and compute its indentation." + (if line + (when (string-match "^ *" (org-remove-tabs line)) + (match-end 0)) + (save-excursion + (beginning-of-line 1) + (skip-chars-forward " \t") + (current-column)))) + +(defun org-do-remove-indentation (&optional n) + "Remove the maximum common indentation from the buffer. +When optional argument N is a positive integer, remove exactly +that much characters from indentation, if possible. Return nil +if it fails." + (catch :exit + (goto-char (point-min)) + ;; Find maximum common indentation, if not specified. + (let ((n (or n + (let ((min-ind (point-max))) + (save-excursion + (while (re-search-forward "^[ \t]*\\S-" nil t) + (let ((ind (1- (current-column)))) + (if (zerop ind) (throw :exit nil) + (setq min-ind (min min-ind ind)))))) + min-ind)))) + (if (zerop n) (throw :exit nil) + ;; Remove exactly N indentation, but give up if not possible. + (while (not (eobp)) + (let ((ind (progn (skip-chars-forward " \t") (current-column)))) + (cond ((eolp) (delete-region (line-beginning-position) (point))) + ((< ind n) (throw :exit nil)) + (t (indent-line-to (- ind n)))) + (forward-line))) + ;; Signal success. + t)))) + + ;;; Input @@ -431,6 +473,117 @@ is selected, only the bare key is returned." (t (error "No entry available"))))))) (when buffer (kill-buffer buffer)))))) + +;;; List manipulation + +(defsubst org-get-alist-option (option key) + (cond ((eq key t) t) + ((eq option t) t) + ((assoc key option) (cdr (assoc key option))) + (t (let ((r (cdr (assq 'default option)))) + (if (listp r) (delq nil r) r))))) + +(defsubst org-last (list) + "Return the last element of LIST." + (car (last list))) + +(defsubst org-uniquify (list) + "Non-destructively remove duplicate elements from LIST." + (let ((res (copy-sequence list))) (delete-dups res))) + +(defun org-uniquify-alist (alist) + "Merge elements of ALIST with the same key. + +For example, in this alist: + +\(org-uniquify-alist \\='((a 1) (b 2) (a 3))) + => \\='((a 1 3) (b 2)) + +merge (a 1) and (a 3) into (a 1 3). + +The function returns the new ALIST." + (let (rtn) + (dolist (e alist rtn) + (let (n) + (if (not (assoc (car e) rtn)) + (push e rtn) + (setq n (cons (car e) (append (cdr (assoc (car e) rtn)) (cdr e)))) + (setq rtn (assq-delete-all (car e) rtn)) + (push n rtn)))))) + +(defun org-delete-all (elts list) + "Remove all elements in ELTS from LIST. +Comparison is done with `equal'. It is a destructive operation +that may remove elements by altering the list structure." + (while elts + (setq list (delete (pop elts) list))) + list) + +(defun org-plist-delete (plist property) + "Delete PROPERTY from PLIST. +This is in contrast to merely setting it to 0." + (let (p) + (while plist + (if (not (eq property (car plist))) + (setq p (plist-put p (car plist) (nth 1 plist)))) + (setq plist (cddr plist))) + p)) + +(defun org-combine-plists (&rest plists) + "Create a single property list from all plists in PLISTS. +The process starts by copying the first list, and then setting properties +from the other lists. Settings in the last list are the most significant +ones and overrule settings in the other lists." + (let ((rtn (copy-sequence (pop plists))) + p v ls) + (while plists + (setq ls (pop plists)) + (while ls + (setq p (pop ls) v (pop ls)) + (setq rtn (plist-put rtn p v)))) + rtn)) + + + +;;; Local variables + +(defconst org-unique-local-variables + '(org-element--cache + org-element--cache-objects + org-element--cache-sync-keys + org-element--cache-sync-requests + org-element--cache-sync-timer) + "List of local variables that cannot be transferred to another buffer.") + +(defun org-get-local-variables () + "Return a list of all local variables in an Org mode buffer." + (delq nil + (mapcar + (lambda (x) + (let* ((binding (if (symbolp x) (list x) (list (car x) (cdr x)))) + (name (car binding))) + (and (not (get name 'org-state)) + (not (memq name org-unique-local-variables)) + (string-match-p + "\\`\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|\ +auto-fill\\|normal-auto-fill\\|fill-paragraph\\|indent-\\)" + (symbol-name name)) + binding))) + (with-temp-buffer + (org-mode) + (buffer-local-variables))))) + +(defun org-clone-local-variables (from-buffer &optional regexp) + "Clone local variables from FROM-BUFFER. +Optional argument REGEXP selects variables to clone." + (dolist (pair (buffer-local-variables from-buffer)) + (pcase pair + (`(,name . ,value) ;ignore unbound variables + (when (and (not (memq name org-unique-local-variables)) + (or (null regexp) (string-match-p regexp (symbol-name name)))) + (ignore-errors (set (make-local-variable name) value))))))) + + ;;; Logic @@ -439,6 +592,83 @@ is selected, only the bare key is returned." (if a (not b) b)) + +;;; Miscellaneous + +(defsubst org-call-with-arg (command arg) + "Call COMMAND interactively, but pretend prefix arg was ARG." + (let ((current-prefix-arg arg)) (call-interactively command))) + +(defsubst org-check-external-command (cmd &optional use no-error) + "Check if external program CMD for USE exists, error if not. +When the program does exist, return its path. +When it does not exist and NO-ERROR is set, return nil. +Otherwise, throw an error. The optional argument USE can describe what this +program is needed for, so that the error message can be more informative." + (or (executable-find cmd) + (if no-error + nil + (error "Can't find `%s'%s" cmd + (if use (format " (%s)" use) ""))))) + +(defun org-display-warning (message) + "Display the given MESSAGE as a warning." + (display-warning 'org message :warning)) + +(defun org-unlogged-message (&rest args) + "Display a message, but avoid logging it in the *Messages* buffer." + (let ((message-log-max nil)) + (apply #'message args))) + +(defun org-let (list &rest body) + (eval (cons 'let (cons list body)))) +(put 'org-let 'lisp-indent-function 1) + +(defun org-let2 (list1 list2 &rest body) + (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body))))))) +(put 'org-let2 'lisp-indent-function 2) + +(defun org-eval (form) + "Eval FORM and return result." + (condition-case error + (eval form) + (error (format "%%![Error: %s]" error)))) + +(defvar org-outline-regexp) ; defined in org.el +(defvar org-odd-levels-only) ; defined in org.el +(defvar org-inlinetask-min-level) ; defined in org-inlinetask.el +(defun org-get-limited-outline-regexp () + "Return outline-regexp with limited number of levels. +The number of levels is controlled by `org-inlinetask-min-level'" + (cond ((not (derived-mode-p 'org-mode)) + outline-regexp) + ((not (featurep 'org-inlinetask)) + org-outline-regexp) + (t + (let* ((limit-level (1- org-inlinetask-min-level)) + (nstars (if org-odd-levels-only + (1- (* limit-level 2)) + limit-level))) + (format "\\*\\{1,%d\\} " nstars))))) + + +(provide 'org-macs) + +;;; Motion + +(defsubst org-goto-line (N) + (save-restriction + (widen) + (goto-char (point-min)) + (forward-line (1- N)))) + +(defsubst org-current-line (&optional pos) + (save-excursion + (and pos (goto-char pos)) + ;; works also in narrowed buffer, because we start at 1, not point-min + (+ (if (bolp) 1 0) (count-lines 1 (point))))) + + ;;; Overlays @@ -477,45 +707,60 @@ SPEC is the invisibility spec, as a symbol." -;;; Indentation +;;; Regexp matching -(defun org-get-indentation (&optional line) - "Get the indentation of the current line, interpreting tabs. -When LINE is given, assume it represents a line and compute its indentation." - (if line - (when (string-match "^ *" (org-remove-tabs line)) - (match-end 0)) - (save-excursion - (beginning-of-line 1) - (skip-chars-forward " \t") - (current-column)))) +(defsubst org-pos-in-match-range (pos n) + (and (match-beginning n) + (<= (match-beginning n) pos) + (>= (match-end n) pos))) -(defun org-do-remove-indentation (&optional n) - "Remove the maximum common indentation from the buffer. -When optional argument N is a positive integer, remove exactly -that much characters from indentation, if possible. Return nil -if it fails." +(defun org-skip-whitespace () + "Skip over space, tabs and newline characters." + (skip-chars-forward " \t\n\r")) + +(defun org-match-line (regexp) + "Match REGEXP at the beginning of the current line." + (save-excursion + (beginning-of-line) + (looking-at regexp))) + +(defun org-match-any-p (re list) + "Non-nil if regexp RE matches an element in LIST." + (cl-some (lambda (x) (string-match-p re x)) list)) + +(defun org-in-regexp (regexp &optional nlines visually) + "Check if point is inside a match of REGEXP. + +Normally only the current line is checked, but you can include +NLINES extra lines around point into the search. If VISUALLY is +set, require that the cursor is not after the match but really +on, so that the block visually is on the match. + +Return nil or a cons cell (BEG . END) where BEG and END are, +respectively, the positions at the beginning and the end of the +match." (catch :exit - (goto-char (point-min)) - ;; Find maximum common indentation, if not specified. - (let ((n (or n - (let ((min-ind (point-max))) - (save-excursion - (while (re-search-forward "^[ \t]*\\S-" nil t) - (let ((ind (1- (current-column)))) - (if (zerop ind) (throw :exit nil) - (setq min-ind (min min-ind ind)))))) - min-ind)))) - (if (zerop n) (throw :exit nil) - ;; Remove exactly N indentation, but give up if not possible. - (while (not (eobp)) - (let ((ind (progn (skip-chars-forward " \t") (current-column)))) - (cond ((eolp) (delete-region (line-beginning-position) (point))) - ((< ind n) (throw :exit nil)) - (t (indent-line-to (- ind n)))) - (forward-line))) - ;; Signal success. - t)))) + (let ((pos (point)) + (eol (line-end-position (if nlines (1+ nlines) 1)))) + (save-excursion + (beginning-of-line (- 1 (or nlines 0))) + (while (and (re-search-forward regexp eol t) + (<= (match-beginning 0) pos)) + (let ((end (match-end 0))) + (when (or (> end pos) (and (= end pos) (not visually))) + (throw :exit (cons (match-beginning 0) (match-end 0)))))))))) + +(defun org-point-in-group (point group &optional context) + "Check if POINT is in match-group GROUP. +If CONTEXT is non-nil, return a list with CONTEXT and the boundaries of the +match. If the match group does not exist or point is not inside it, +return nil." + (and (match-beginning group) + (>= point (match-beginning group)) + (<= point (match-end group)) + (if context + (list context (match-beginning group) (match-end group)) + t))) @@ -730,147 +975,72 @@ as-is if removal failed." -;;; List manipulation +;;; Text properties -(defsubst org-get-alist-option (option key) - (cond ((eq key t) t) - ((eq option t) t) - ((assoc key option) (cdr (assoc key option))) - (t (let ((r (cdr (assq 'default option)))) - (if (listp r) (delq nil r) r))))) +(defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t + rear-nonsticky t mouse-map t fontified t + org-emphasis t) + "Properties to remove when a string without properties is wanted.") -(defsubst org-last (list) - "Return the last element of LIST." - (car (last list))) +(defsubst org-no-properties (s &optional restricted) + "Remove all text properties from string S. +When RESTRICTED is non-nil, only remove the properties listed +in `org-rm-props'." + (if restricted (remove-text-properties 0 (length s) org-rm-props s) + (set-text-properties 0 (length s) nil s)) + s) +(defun org-add-props (string plist &rest props) + "Add text properties to entire string, from beginning to end. +PLIST may be a list of properties, PROPS are individual properties and values +that will be added to PLIST. Returns the string that was modified." + (declare (indent 2)) + (add-text-properties + 0 (length string) (if props (append plist props) plist) string) + string) -(defsubst org-uniquify (list) - "Non-destructively remove duplicate elements from LIST." - (let ((res (copy-sequence list))) (delete-dups res))) +(defun org-make-parameter-alist (flat) + "Return alist based on FLAT. +FLAT is a list with alternating symbol names and values. The +returned alist is a list of lists with the symbol name in car and +the value in cdr." + (when flat + (cons (list (car flat) (cadr flat)) + (org-make-parameter-alist (cddr flat))))) -(defun org-uniquify-alist (alist) - "Merge elements of ALIST with the same key. +(defsubst org-get-at-bol (property) + "Get text property PROPERTY at the beginning of line." + (get-text-property (point-at-bol) property)) -For example, in this alist: +(defun org-get-at-eol (property n) + "Get text property PROPERTY at the end of line less N characters." + (get-text-property (- (point-at-eol) n) property)) -\(org-uniquify-alist \\='((a 1) (b 2) (a 3))) - => \\='((a 1 3) (b 2)) +(defun org-find-text-property-in-string (prop s) + "Return the first non-nil value of property PROP in string S." + (or (get-text-property 0 prop s) + (get-text-property (or (next-single-property-change 0 prop s) 0) + prop s))) -merge (a 1) and (a 3) into (a 1 3). +(defun org-invisible-p (&optional pos) + "Non-nil if the character after POS is invisible. +If POS is nil, use `point' instead." + (get-char-property (or pos (point)) 'invisible)) -The function returns the new ALIST." - (let (rtn) - (dolist (e alist rtn) - (let (n) - (if (not (assoc (car e) rtn)) - (push e rtn) - (setq n (cons (car e) (append (cdr (assoc (car e) rtn)) (cdr e)))) - (setq rtn (assq-delete-all (car e) rtn)) - (push n rtn)))))) +(defun org-truely-invisible-p () + "Check if point is at a character currently not visible. +This version does not only check the character property, but also +`visible-mode'." + (unless (bound-and-true-p visible-mode) + (org-invisible-p))) -(defun org-delete-all (elts list) - "Remove all elements in ELTS from LIST. -Comparison is done with `equal'. It is a destructive operation -that may remove elements by altering the list structure." - (while elts - (setq list (delete (pop elts) list))) - list) - -(defun org-plist-delete (plist property) - "Delete PROPERTY from PLIST. -This is in contrast to merely setting it to 0." - (let (p) - (while plist - (if (not (eq property (car plist))) - (setq p (plist-put p (car plist) (nth 1 plist)))) - (setq plist (cddr plist))) - p)) - -(defun org-combine-plists (&rest plists) - "Create a single property list from all plists in PLISTS. -The process starts by copying the first list, and then setting properties -from the other lists. Settings in the last list are the most significant -ones and overrule settings in the other lists." - (let ((rtn (copy-sequence (pop plists))) - p v ls) - (while plists - (setq ls (pop plists)) - (while ls - (setq p (pop ls) v (pop ls)) - (setq rtn (plist-put rtn p v)))) - rtn)) - - - -;;; Regexp matching - -(defsubst org-pos-in-match-range (pos n) - (and (match-beginning n) - (<= (match-beginning n) pos) - (>= (match-end n) pos))) - -(defun org-skip-whitespace () - "Skip over space, tabs and newline characters." - (skip-chars-forward " \t\n\r")) - -(defun org-match-line (regexp) - "Match REGEXP at the beginning of the current line." +(defun org-invisible-p2 () + "Check if point is at a character currently not visible. +If the point is at EOL (and not at the beginning of a buffer too), +move it back by one char before doing this check." (save-excursion - (beginning-of-line) - (looking-at regexp))) - -(defun org-match-any-p (re list) - "Non-nil if regexp RE matches an element in LIST." - (cl-some (lambda (x) (string-match-p re x)) list)) - -(defun org-in-regexp (regexp &optional nlines visually) - "Check if point is inside a match of REGEXP. - -Normally only the current line is checked, but you can include -NLINES extra lines around point into the search. If VISUALLY is -set, require that the cursor is not after the match but really -on, so that the block visually is on the match. - -Return nil or a cons cell (BEG . END) where BEG and END are, -respectively, the positions at the beginning and the end of the -match." - (catch :exit - (let ((pos (point)) - (eol (line-end-position (if nlines (1+ nlines) 1)))) - (save-excursion - (beginning-of-line (- 1 (or nlines 0))) - (while (and (re-search-forward regexp eol t) - (<= (match-beginning 0) pos)) - (let ((end (match-end 0))) - (when (or (> end pos) (and (= end pos) (not visually))) - (throw :exit (cons (match-beginning 0) (match-end 0)))))))))) - -(defun org-point-in-group (point group &optional context) - "Check if POINT is in match-group GROUP. -If CONTEXT is non-nil, return a list with CONTEXT and the boundaries of the -match. If the match group does not exist or point is not inside it, -return nil." - (and (match-beginning group) - (>= point (match-beginning group)) - (<= point (match-end group)) - (if context - (list context (match-beginning group) (match-end group)) - t))) - - - -;;; Motion - -(defsubst org-goto-line (N) - (save-restriction - (widen) - (goto-char (point-min)) - (forward-line (1- N)))) - -(defsubst org-current-line (&optional pos) - (save-excursion - (and pos (goto-char pos)) - ;; works also in narrowed buffer, because we start at 1, not point-min - (+ (if (bolp) 1 0) (count-lines 1 (point))))) + (when (and (eolp) (not (bobp))) + (backward-char 1)) + (org-invisible-p))) @@ -962,174 +1132,4 @@ This should be a lot faster than the `parse-time-string'." -;;; Text properties - -(defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t - rear-nonsticky t mouse-map t fontified t - org-emphasis t) - "Properties to remove when a string without properties is wanted.") - -(defsubst org-no-properties (s &optional restricted) - "Remove all text properties from string S. -When RESTRICTED is non-nil, only remove the properties listed -in `org-rm-props'." - (if restricted (remove-text-properties 0 (length s) org-rm-props s) - (set-text-properties 0 (length s) nil s)) - s) -(defun org-add-props (string plist &rest props) - "Add text properties to entire string, from beginning to end. -PLIST may be a list of properties, PROPS are individual properties and values -that will be added to PLIST. Returns the string that was modified." - (declare (indent 2)) - (add-text-properties - 0 (length string) (if props (append plist props) plist) string) - string) - -(defun org-make-parameter-alist (flat) - "Return alist based on FLAT. -FLAT is a list with alternating symbol names and values. The -returned alist is a list of lists with the symbol name in car and -the value in cdr." - (when flat - (cons (list (car flat) (cadr flat)) - (org-make-parameter-alist (cddr flat))))) - -(defsubst org-get-at-bol (property) - "Get text property PROPERTY at the beginning of line." - (get-text-property (point-at-bol) property)) - -(defun org-get-at-eol (property n) - "Get text property PROPERTY at the end of line less N characters." - (get-text-property (- (point-at-eol) n) property)) - -(defun org-find-text-property-in-string (prop s) - "Return the first non-nil value of property PROP in string S." - (or (get-text-property 0 prop s) - (get-text-property (or (next-single-property-change 0 prop s) 0) - prop s))) - -(defun org-invisible-p (&optional pos) - "Non-nil if the character after POS is invisible. -If POS is nil, use `point' instead." - (get-char-property (or pos (point)) 'invisible)) - -(defun org-truely-invisible-p () - "Check if point is at a character currently not visible. -This version does not only check the character property, but also -`visible-mode'." - (unless (bound-and-true-p visible-mode) - (org-invisible-p))) - -(defun org-invisible-p2 () - "Check if point is at a character currently not visible. -If the point is at EOL (and not at the beginning of a buffer too), -move it back by one char before doing this check." - (save-excursion - (when (and (eolp) (not (bobp))) - (backward-char 1)) - (org-invisible-p))) - - - -;;; Local variables - -(defconst org-unique-local-variables - '(org-element--cache - org-element--cache-objects - org-element--cache-sync-keys - org-element--cache-sync-requests - org-element--cache-sync-timer) - "List of local variables that cannot be transferred to another buffer.") - -(defun org-get-local-variables () - "Return a list of all local variables in an Org mode buffer." - (delq nil - (mapcar - (lambda (x) - (let* ((binding (if (symbolp x) (list x) (list (car x) (cdr x)))) - (name (car binding))) - (and (not (get name 'org-state)) - (not (memq name org-unique-local-variables)) - (string-match-p - "\\`\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|\ -auto-fill\\|normal-auto-fill\\|fill-paragraph\\|indent-\\)" - (symbol-name name)) - binding))) - (with-temp-buffer - (org-mode) - (buffer-local-variables))))) - -(defun org-clone-local-variables (from-buffer &optional regexp) - "Clone local variables from FROM-BUFFER. -Optional argument REGEXP selects variables to clone." - (dolist (pair (buffer-local-variables from-buffer)) - (pcase pair - (`(,name . ,value) ;ignore unbound variables - (when (and (not (memq name org-unique-local-variables)) - (or (null regexp) (string-match-p regexp (symbol-name name)))) - (ignore-errors (set (make-local-variable name) value))))))) - - - -;;; Miscellaneous - -(defsubst org-call-with-arg (command arg) - "Call COMMAND interactively, but pretend prefix arg was ARG." - (let ((current-prefix-arg arg)) (call-interactively command))) - -(defsubst org-check-external-command (cmd &optional use no-error) - "Check if external program CMD for USE exists, error if not. -When the program does exist, return its path. -When it does not exist and NO-ERROR is set, return nil. -Otherwise, throw an error. The optional argument USE can describe what this -program is needed for, so that the error message can be more informative." - (or (executable-find cmd) - (if no-error - nil - (error "Can't find `%s'%s" cmd - (if use (format " (%s)" use) ""))))) - -(defun org-display-warning (message) - "Display the given MESSAGE as a warning." - (display-warning 'org message :warning)) - -(defun org-unlogged-message (&rest args) - "Display a message, but avoid logging it in the *Messages* buffer." - (let ((message-log-max nil)) - (apply #'message args))) - -(defun org-let (list &rest body) - (eval (cons 'let (cons list body)))) -(put 'org-let 'lisp-indent-function 1) - -(defun org-let2 (list1 list2 &rest body) - (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body))))))) -(put 'org-let2 'lisp-indent-function 2) - -(defun org-eval (form) - "Eval FORM and return result." - (condition-case error - (eval form) - (error (format "%%![Error: %s]" error)))) - -(defvar org-outline-regexp) ; defined in org.el -(defvar org-odd-levels-only) ; defined in org.el -(defvar org-inlinetask-min-level) ; defined in org-inlinetask.el -(defun org-get-limited-outline-regexp () - "Return outline-regexp with limited number of levels. -The number of levels is controlled by `org-inlinetask-min-level'" - (cond ((not (derived-mode-p 'org-mode)) - outline-regexp) - ((not (featurep 'org-inlinetask)) - org-outline-regexp) - (t - (let* ((limit-level (1- org-inlinetask-min-level)) - (nstars (if org-odd-levels-only - (1- (* limit-level 2)) - limit-level))) - (format "\\*\\{1,%d\\} " nstars))))) - - -(provide 'org-macs) - ;;; org-macs.el ends here