Rewrite org-format-outline-path

* lisp/org.el (org-format-outline-path): Avoid out-of-range error when
  the length of PREFIX is greater than the value given for WIDTH.
  Prevent result from extending beyond WIDTH.  Simplify code.
* testing/lisp/test-org.el (test-org/format-outline-path): Add tests.

Reported-by: Simon Thum <simon.thum@gmx.de>
<http://permalink.gmane.org/gmane.emacs.orgmode/102241>
This commit is contained in:
Kyle Meyer 2015-10-26 22:49:45 -04:00
parent 3efb519ff5
commit 1c740023f7
2 changed files with 55 additions and 32 deletions

View File

@ -11751,38 +11751,27 @@ such as the file name.
SEPARATOR is inserted between the different parts of the path, SEPARATOR is inserted between the different parts of the path,
the default is \"/\"." the default is \"/\"."
(setq width (or width 79)) (setq width (or width 79))
(if prefix (setq width (- width (length prefix)))) (unless (> width 0)
(if (not path) (user-error "Argument `width' must be positive"))
(or prefix "") (setq separator (or separator "/"))
(let* ((nsteps (length path)) (let* ((org-odd-levels-only nil)
(total-width (+ nsteps (apply '+ (mapcar 'length path)))) (fpath (concat
(maxwidth (if (<= total-width width) prefix (and prefix path separator)
10000 ;; everything fits (mapconcat
;; we need to shorten the level headings (lambda (s) (replace-regexp-in-string "[ \t]+\\'" "" s))
(/ (- width nsteps) nsteps))) (loop for head in path
(org-odd-levels-only nil) for n upto (length path)
(n 0) collect (org-add-props
(total (1+ (length prefix)))) head nil 'face
(setq maxwidth (max maxwidth 10)) (nth (% n org-n-level-faces) org-level-faces)))
(concat prefix separator))))
(if prefix (or separator "/")) (when (> (length fpath) width)
(mapconcat (if (< width 7)
(lambda (h) ;; It's unlikely that `width' will be this small, but don't
(setq n (1+ n)) ;; waste characters by adding ".." if it is.
(if (and (= n nsteps) (< maxwidth 10000)) (setq fpath (substring fpath 0 width))
(setq maxwidth (- total-width total))) (setf (substring fpath (- width 2)) "..")))
(if (< (length h) maxwidth) fpath))
(progn (setq total (+ total (length h) 1)) h)
(setq h (substring h 0 (- maxwidth 2))
total (+ total maxwidth 1))
(if (string-match "[ \t]+\\'" h)
(setq h (substring h 0 (match-beginning 0))))
(setq h (concat h "..")))
(org-add-props h nil 'face
(nth (% (1- n) org-n-level-faces)
org-level-faces))
h)
path (or separator "/"))))))
(defun org-display-outline-path (&optional file current separator just-return-string) (defun org-display-outline-path (&optional file current separator just-return-string)
"Display the current outline path in the echo area. "Display the current outline path in the echo area.

View File

@ -1311,6 +1311,40 @@
'(org-block-todo-from-children-or-siblings-or-parent))) '(org-block-todo-from-children-or-siblings-or-parent)))
(org-entry-blocked-p))))) (org-entry-blocked-p)))))
(ert-deftest test-org/format-outline-path ()
(should
(string= (org-format-outline-path (list "one" "two" "three"))
"one/two/three"))
;; Empty path.
(should
(string= (org-format-outline-path '())
""))
;; Empty path and prefix.
(should
(string= (org-format-outline-path '() nil ">>")
">>"))
;; Trailing whitespace in headings.
(should
(string= (org-format-outline-path (list "one\t" "tw o " "three "))
"one/tw o/three"))
;; Non-default prefix and separators.
(should
(string= (org-format-outline-path (list "one" "two" "three") nil ">>" "|")
">>|one|two|three"))
;; Truncate.
(should
(string= (org-format-outline-path (list "one" "two" "three" "four") 10)
"one/two/.."))
;; Give a very narrow width.
(should
(string= (org-format-outline-path (list "one" "two" "three" "four") 2)
"on"))
;; Give a prefix that extends beyond the width.
(should
(string= (org-format-outline-path (list "one" "two" "three" "four") 10
">>>>>>>>>>")
">>>>>>>>..")))
;;; Keywords ;;; Keywords