diff options
| -rw-r--r-- | Cask | 3 | ||||
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | lisp/pdf-cache.el | 2 | ||||
| -rw-r--r-- | lisp/pdf-info.el | 153 | ||||
| -rw-r--r-- | lisp/pdf-isearch.el | 16 | ||||
| -rw-r--r-- | lisp/pdf-links.el | 164 | ||||
| -rw-r--r-- | lisp/pdf-occur.el | 15 | ||||
| -rw-r--r-- | lisp/pdf-outline.el | 95 | ||||
| -rw-r--r-- | lisp/pdf-sync.el | 25 | ||||
| -rw-r--r-- | lisp/pdf-tools.el | 2 | ||||
| -rw-r--r-- | test/pdf-info.ert | 64 |
11 files changed, 252 insertions, 291 deletions
@@ -8,4 +8,5 @@ "server/epdfinfo") (development - (depends-on "emacs" "24.3")) + (depends-on "emacs" "24.3") + (depends-on "let-alist")) @@ -54,10 +54,10 @@ server/configure: server/configure.ac cd server && ./autogen.sh bytecompile: - $(EMACS) $(EFLAGS) -f batch-byte-compile lisp/*.el + cask exec $(EMACS) $(EFLAGS) -f batch-byte-compile lisp/*.el test: all - $(EMACS) $(EFLAGS) -l test/run-tests.el $(PACKAGE_NAME).tar + cask exec $(EMACS) $(EFLAGS) -l test/run-tests.el $(PACKAGE_NAME).tar check: bytecompile test diff --git a/lisp/pdf-cache.el b/lisp/pdf-cache.el index 1103e06..216d90c 100644 --- a/lisp/pdf-cache.el +++ b/lisp/pdf-cache.el @@ -378,7 +378,7 @@ See also `pdf-info-renderpage-highlight' and (mapcar 'cl-cadddr (cl-remove-if-not - (lambda (link) (eq (cadr link) 'goto-dest)) + (lambda (link) (eq (assq 'type link) 'goto-dest)) (pdf-cache-pagelinks (pdf-view-current-page))))))))) diff --git a/lisp/pdf-info.el b/lisp/pdf-info.el index 1bb8db9..36c5520 100644 --- a/lisp/pdf-info.el +++ b/lisp/pdf-info.el @@ -414,38 +414,28 @@ interrupted." (string-to-number (cadr elt)))) response)) ((search-string search-regexp) - (let* ((matches - (mapcar - (lambda (r) - `(,(string-to-number (nth 0 r)) - ,(let (case-fold-search) + (mapcar + (lambda (r) + `((page . ,(string-to-number (nth 0 r))) + (text . ,(let (case-fold-search) (pdf-util-highlight-regexp-in-string - (regexp-quote (nth 1 r)) (nth 2 r))) - ,@(mapcar (lambda (m) + (regexp-quote (nth 1 r)) (nth 2 r)))) + (edges . ,(mapcar (lambda (m) (mapcar 'string-to-number (split-string m " " t))) - (cddr (cdr r))))) - response)) - result) - (while matches - (let ((page (caar matches)) - items) - (while (and matches - (= (caar matches) page)) - (push (cdr (pop matches)) items)) - (push (cons page (nreverse items)) result))) - (nreverse result))) + (cddr (cdr r)))))) + response)) (outline (mapcar (lambda (r) - (cons (string-to-number (pop r)) - (pdf-info-query--transform-action r))) + `((depth . ,(string-to-number (pop r))) + ,@(pdf-info-query--transform-action r))) response)) (pagelinks (mapcar (lambda (r) - (cons - (mapcar 'string-to-number ;area - (split-string (pop r) " " t)) - (pdf-info-query--transform-action r))) + `((edges . + ,(mapcar 'string-to-number ;area + (split-string (pop r) " " t))) + ,@(pdf-info-query--transform-action r))) response)) (metadata (let ((md (car response))) @@ -482,11 +472,16 @@ interrupted." (mapcar 'pdf-info-query--transform-attachment response)) ((getattachment-from-annot) (pdf-info-query--transform-attachment (car response))) - ((synctex-forward-search boundingbox) + (boundingbox (mapcar 'string-to-number (car response))) + (synctex-forward-search + (let ((list (mapcar 'string-to-number (car response)))) + `((page . ,(car list)) + (edges . ,(cdr list))))) (synctex-backward-search - (cons (caar response) - (mapcar 'string-to-number (cdar response)))) + `((filename . ,(caar response)) + (line . ,(string-to-number (cadr (car response)))) + (column . ,(string-to-number (cadr (cdar response)))))) (delannot nil) ((save) (caar response)) ((renderpage renderpage-text-regions renderpage-highlight) @@ -509,21 +504,19 @@ interrupted." (defun pdf-info-query--transform-action (action) "Transform ACTION response into a Lisp form." (let ((type (intern (pop action)))) - (cons type - (cons (pop action) - (cl-case type - (goto-dest - (list (string-to-number (pop action)) - (and (> (length (car action)) 0) - (string-to-number (pop action))))) - (goto-remote - (list (pop action) - (string-to-number (pop action)) - (and (> (length (car action)) 0) - (string-to-number (pop action))) - (and (> (length (car action)) 0) - (string-to-number (pop action))))) - (t action)))))) + `((type . ,type) + (title . ,(pop action)) + ,@(cl-case type + (goto-dest + `((page . ,(string-to-number (pop action))) + (top . ,(and (> (length (car action)) 0) + (string-to-number (pop action)))))) + (goto-remote + `((filename . ,(pop action)) + (page . ,(string-to-number (pop action))) + (top . ,(and (> (length (car action)) 0) + (string-to-number (pop action)))))) + (t `((uri . ,(pop action)))))))) (defun pdf-info-query--transform-annotation (a) (cl-labels ((not-empty (s) @@ -890,16 +883,18 @@ document." (pdf-info--normalize-file-or-buffer file-or-buffer))) (defun pdf-info-search-string (string &optional pages file-or-buffer) - "Search for STRING in PAGES of docüment FILE-OR-BUFFER. + "Search for STRING in PAGES of document FILE-OR-BUFFER. See `pdf-info-normalize-page-range' for valid PAGES formats. -This function returns a list \(\((PAGE . MATCHES\) ... \), where -MATCHES represents a list of matches on PAGE. Each MATCHES item -looks like \(LINE EDGES\), where EDGES represent the coordinates -of the match as a list of four relative values \(LEFT TOP RIGHT -BOTTOM\). LINE is the matched line, containing `match' face -properties on the matched parts. +This function returns a list of matches. Each item is an alist +containing keys PAGE, TEXT and EDGES, where PAGE and TEXT are the +matched page resp. line. EDGES is a list containing a single +edges element \(LEFT TOP RIGHT BOTTOM\). This is for consistency +with `pdf-info-search-regexp', which may return matches with +multiple edges. + +The TEXT contains `match' face properties on the matched parts. Search is case-insensitive, unless `case-fold-search' is nil and searching case-sensitive is supported by the server." @@ -975,15 +970,8 @@ See the glib documentation at url file-or-buffer) "Search for a PCRE on PAGES of docüment FILE-OR-BUFFER. -See `pdf-info-normalize-page-range' for valid PAGES formats. - -This function returns a list \(\((PAGE . MATCHES\) ... \), where -MATCHES represents a list of matches on PAGE. Each MATCHES item -looks like \(LINE EDGES EDGES ...\), where the EDGES elements -represent the coordinates of the match, each one beeing a list of -four relative values \(LEFT TOP RIGHT BOTTOM\). LINE is the -matched line, containing `match' face properties on the matched -parts. +See `pdf-info-normalize-page-range' for valid PAGES formats and +`pdf-info-search-string' for it's return value. Uses the flags in `pdf-info-regexp-flags', which see. If `case-fold-search' is non-nil, the caseless flag is added. @@ -1031,27 +1019,24 @@ this kind of error as a `invalid-regexp' error." (defun pdf-info-pagelinks (page &optional file-or-buffer) "Return a list of links on PAGE in docüment FILE-OR-BUFFER. -This function returns a list \(\(EDGES . ACTION\) ... \), where -EDGES has the same form as in `pdf-info-search-string'. ACTION -represents a PDF Action and has the form \(TYPE TITLE . ARGS\), -there TYPE is the type of the action, TITLE is a, possibly empty, -name for this action and ARGS a list of the action's arguments. +This function returns a list of alists with the following keys. +EDGES represents the relative bounding-box of the link , TYPE is +the type of the action, TITLE is a, possibly empty, name for this +action. TYPE may be one of -goto-dest -- This is a internal link to some page. ARGS has the -form \(PAGE TOP\), where PAGE is the page of the link and TOP -it's vertical position. +goto-dest -- This is a internal link to some page. Each element +contains additional keys PAGE and TOP, where PAGE is the page of +the link and TOP it's vertical position. -goto-remote -- This a external link to some document. ARGS is of -the form \(PDFFILE PAGE TOP\), where PDFFILE is the filename of -the external PDF, PAGE the page number and TOP the vertical -position. +goto-remote -- This a external link to some document. Same as +goto-dest, with an additional FILENAME of the external PDF. -uri -- A link in form of some URI. ARGS contains a single -element, namely the URI. +uri -- A link in form of some URI. Alist contains additional key +URI. -In the first two cases, PAGE may be 0 and TOP be nil, which means +In the first two cases, PAGE may be 0 and TOP nil, which means these data is unspecified." (cl-check-type page natnum) (pdf-info-query @@ -1068,10 +1053,9 @@ these data is unspecified." (defun pdf-info-outline (&optional file-or-buffer) "Return the PDF outline of document FILE-OR-BUFFER. -This function returns a list \(\(DEPTH . ACTION\) ... \) of -outline items, where DEPTH >= 1 is the depth of this element in -the tree and ACTION has the same format as in -`pdf-info-pagelinks', which see." +This function returns a list of alists like `pdf-info-pagelinks'. +Additionally every alist has a DEPTH (>= 1) entry with the depth +of this element in the tree." (pdf-info-query 'outline @@ -1126,8 +1110,8 @@ aforementioned function, when called with the same arguments." (defun pdf-info-charlayout (page edges-or-pos &optional file-or-buffer) "Return the layout of characters of PAGE in/at EDGES-OR-POS. -Returns a list of elements \(CHAR . \(LEFT TOP RIGHT BOT\)\) of -character and corresponding boundingboxes. +Returns a list of elements \(CHAR . \(LEFT TOP RIGHT BOT\)\) mapping +character to their corresponding relative bounding-boxes. EDGES-OR-POS may be a region \(LEFT TOP RIGHT BOT\) restricting the returned value to include only characters fully contained in @@ -1382,9 +1366,9 @@ corresponding file. LINE and COLUMN represent the position in the buffer or file. Finally FILE-OR-BUFFER corresponds to the PDF document. -Returns a list of \(PAGE LEFT TOP RIGHT BOT\) of coordinates -describing the position in the PDF document corresponding to the -SOURCE location." +Returns an alist with entries PAGE and relative EDGES describing +the position in the PDF document corresponding to the SOURCE +location." (let ((source (if (buffer-live-p (get-buffer source)) (buffer-file-name (get-buffer source)) @@ -1399,10 +1383,11 @@ SOURCE location." (defun pdf-info-synctex-backward-search (page &optional x y file-or-buffer) "Perform a backward search with synctex. -This find the source location corresponding to the coordinates +Find the source location corresponding to the coordinates \(X . Y\) on PAGE in FILE-OR-BUFFER. -Returns a list \(SOURCE LINE COLUMN\)." +Returns an alist with entries FILENAME, LINE and COLUMN." + (pdf-info-query 'synctex-backward-search diff --git a/lisp/pdf-isearch.el b/lisp/pdf-isearch.el index 3e0d3c6..5dc6f9b 100644 --- a/lisp/pdf-isearch.el +++ b/lisp/pdf-isearch.el @@ -30,6 +30,8 @@ (require 'pdf-misc) (require 'pdf-view) (require 'pdf-cache) +(require 'let-alist) + ;;; Code: @@ -439,14 +441,12 @@ Returns a list of edges (LEFT TOP RIGHT BOTTOM) in PDF coordinates, sorted top to bottom, then left to right." (unless page (setq page (pdf-view-current-page))) - (let* ((case-fold-search isearch-case-fold-search) - (matches - (cdr (assq page - (funcall (pdf-isearch-search-fun) - string page))))) - (mapcar (lambda (edge-list) - (pdf-util-scale-relative-to-pixel edge-list 'round)) - (mapcar 'cdr matches)))) + (mapcar (lambda (match) + (let-alist match + (pdf-util-scale-relative-to-pixel .edges 'round))) + (let ((case-fold-search isearch-case-fold-search)) + (funcall (pdf-isearch-search-fun) + string page)))) (defun pdf-isearch-search-fun () (funcall (or pdf-isearch-search-fun-function diff --git a/lisp/pdf-links.el b/lisp/pdf-links.el index 86d3160..6138357 100644 --- a/lisp/pdf-links.el +++ b/lisp/pdf-links.el @@ -26,6 +26,7 @@ (require 'pdf-misc) (require 'pdf-cache) (require 'pdf-isearch) +(require 'let-alist) ;;; Code: @@ -129,7 +130,8 @@ links via \\[pdf-links-isearch-link]. (pointer 'hand) hotspots) (dolist (l links) - (let ((e (pdf-util-scale (car l) size 'round)) + (let ((e (pdf-util-scale + (cdr (assq 'edges l)) size 'round)) (id (intern (format id-fmt page (cl-incf i))))) (push `((rect . ((,(nth 0 e) . ,(nth 1 e)) @@ -137,112 +139,85 @@ links via \\[pdf-links-isearch-link]. ,id (pointer ,pointer - help-echo ,(pdf-links-action-to-string (cdr l)))) + help-echo ,(pdf-links-action-to-string l))) hotspots) (local-set-key (vector id 'mouse-1) (lambda nil (interactive "@") - (pdf-links-action-perform (cdr l)))) + (pdf-links-action-perform l))) (local-set-key (vector id t) 'pdf-util-image-map-mouse-event-proxy))) (nreverse hotspots))) -(defun pdf-links-action-to-string (action) +(defun pdf-links-action-to-string (link) "Return a string representation of ACTION." - (let ((title (nth 1 action)) - (str - (cl-case (car action) - (goto-dest - (let ((page (nth 2 action))) - (if (> page 0) - (format "Goto page %d" page) - "Destination not found"))) - (goto-remote - (let* ((file (nth 2 action)) - (page (nth 3 action)) - (exists-p (and file (file-exists-p file)))) - (cond - (exists-p - (format "Goto %sfile '%s'" - (if (> page 0) - (format "p. %d of " page) - "") - file)) - (t - (format "Link to nonexistent file '%s'" file))))) - (launch - (let* ((prg (nth 2 action)) - (args (nth 3 action)) - (exists-p (and prg (file-executable-p prg)))) - (if exists-p - (format "Launch '%s' with arguments '%s'" - prg args) - (format "Link to nonexecutable program '%s'" prg)))) - (uri - (let ((uri (nth 2 action))) - (if (> (length uri) 0) - (format "Link to uri '%s'" uri) - (format "Link to empty uri")))) - (t - (error "Invalid link-type :%s" (car action)))))) - (if (> (length title) 0) - (concat str (format " (%s)" title)) - str))) + (let-alist link + (concat + (cl-case .type + (goto-dest + (if (> .page 0) + (format "Goto page %d" .page) + "Destination not found")) + (goto-remote + (if (and .filename (file-exists-p .filename)) + (format "Goto %sfile '%s'" + (if (> .page 0) + (format "p.%d of " .page) + "") + .file) + (format "Link to nonexistent file '%s'" .filename))) + (uri + (if (> (length .uri) 0) + (format "Link to uri '%s'" .uri) + (format "Link to empty uri"))) + (t (format "Unrecognized link type: %s" .type))) + (if (> (length .title) 0) + (format " (%s)" .title))))) ;;;###autoload -(defun pdf-links-action-perform (action) - "Invoke ACTION, depending on it's type. +(defun pdf-links-action-perform (link) + "Follow LINK, depending on it's type. This may turn to another page, switch to another PDF buffer or invoke `pdf-links-browse-uri-function'. -Interactively, action is read via `pdf-links-read-link-action'. +Interactively, link is read via `pdf-links-read-link-action'. This function displays characters around the links in the current page and starts reading characters (ignoring case). After a sufficient number of characters have been read, the corresponding -link's action is invoked. Additionally, SPC may be used to +link's link is invoked. Additionally, SPC may be used to scroll the current page." (interactive (list (or (pdf-links-read-link-action "Activate link (SPC scrolls): ") (error "No link selected")))) - (let ((type (car action)) - ;; (title (cadr action)) - ) - (cl-case type + (let-alist link + (cl-case .type ((goto-dest goto-remote) - (let (file page top) - (cl-case type + (let ((window (selected-window))) + (cl-case .type (goto-dest - (setq page (nth 2 action) - top (nth 3 action)) - (unless (> page 0) + (unless (> .page 0) (error "Link points to nowhere"))) (goto-remote - (setq file (nth 2 action) - page (nth 3 action) - top (nth 4 action)) - (unless (file-exists-p file) - (error "Link points to nonexistent file %s" file)))) - - (when (and file (file-exists-p file)) - (display-buffer - (or (find-buffer-visiting file) - (find-file-noselect file)))) - (when (derived-mode-p 'pdf-view-mode) - (when (> page 0) - (pdf-view-goto-page page)) - (when top - ;; Showing the tooltip is somewhat slow. - (sit-for 0) - (pdf-util-tooltip-arrow top))))) + (unless (and .filename (file-exists-p .filename)) + (error "Link points to nonexistent file %s" .filename)) + (setq window (display-buffer + (or (find-buffer-visiting .filename) + (find-file-noselect .filename)))))) + (with-selected-window window + (when (derived-mode-p 'pdf-view-mode) + (when (> .page 0) + (pdf-view-goto-page .page)) + (when .top + ;; Showing the tooltip is somewhat slow. + (sit-for 0) + (pdf-util-tooltip-arrow .top)))))) (uri - (funcall pdf-links-browse-uri-function (nth 2 action))) - ;; (launch - ;; (shell-command (concat (nth 2 action) " " (nth 3 action)))) + (funcall pdf-links-browse-uri-function .uri)) (t - (error "Invalid link:%s" action))) + (error "Unrecognized link type: %s" .type))) nil)) (defun pdf-links-read-link-action (prompt) @@ -265,13 +240,14 @@ See `pdf-links-action-perform' for the interface." :foreground (car colors) :background (cdr colors) :formats - `((?c . ,(lambda (_edges) (pop key-strings))) - (?P . ,(number-to-string - (max 1 (* (cdr size) - pdf-links-convert-pointsize-scale))))) - :commands pdf-links-read-link-convert-commands - :apply (pdf-util-scale-relative-to-pixel - (mapcar 'car links))))) + `((?c . ,(lambda (_edges) (pop key-strings))) + (?P . ,(number-to-string + (max 1 (* (cdr size) + pdf-links-convert-pointsize-scale))))) + :commands pdf-links-read-link-convert-commands + :apply (pdf-util-scale-relative-to-pixel + (mapcar (lambda (l) (cdr (assq 'edges l))) + links))))) (unless links (error "No links on this page")) (unwind-protect @@ -286,7 +262,7 @@ See `pdf-links-action-perform' for the interface." (car size) image-data 'pdf-links-read-link-action)) (pdf-view-display-image (create-image image-data (pdf-view-image-type) t)) - (cdr (pdf-links-read-link-action--read-chars prompt alist))) + (pdf-links-read-link-action--read-chars prompt alist)) (pdf-view-redisplay)))) (defun pdf-links-read-link-action--read-chars (prompt alist) @@ -347,21 +323,23 @@ See `pdf-links-action-perform' for the interface." (lambda (e) (= 0 (pdf-util-edges-intersection-area (car e) match))) (mapcar (lambda (l) - (cons (pdf-util-scale - (car l) size) - (cdr l))) + (cons (pdf-util-scale (alist-get 'edges l) size) + l)) (pdf-cache-pagelinks page))) (lambda (e1 e2) - (> (pdf-util-edges-intersection-area (car e1) match) - (pdf-util-edges-intersection-area (car e2) match)))))) + (> (pdf-util-edges-intersection-area + (alist-get 'edges e1) match) + (pdf-util-edges-intersection-area + (alist-get 'edges e2) match)))))) (unless links (error "No link found at this position")) - (pdf-links-action-perform (cdar links)))))) + (pdf-links-action-perform (car links)))))) (defun pdf-links-isearch-link-filter-matches (matches) (let ((links (pdf-util-scale - (mapcar 'car (pdf-cache-pagelinks - (pdf-view-current-page))) + (mapcar (apply-partially 'alist-get 'edges) + (pdf-cache-pagelinks + (pdf-view-current-page))) (pdf-view-image-size)))) (cl-remove-if-not (lambda (m) diff --git a/lisp/pdf-occur.el b/lisp/pdf-occur.el index ea64e9e..3d7f4b5 100644 --- a/lisp/pdf-occur.el +++ b/lisp/pdf-occur.el @@ -29,6 +29,7 @@ (require 'tablist) (require 'ibuf-ext) (require 'dired) +(require 'let-alist) ;;; Code: @@ -572,12 +573,10 @@ matches linked with PAGE." (pdf-occur-assert-occur-buffer-p) (when matches (let (entries) - (dolist (page-match matches) - (let ((page (car page-match)) - (page-matches (cdr page-match))) - (dolist (match page-matches) - (push (pdf-occur-create-entry filename page match) - entries)))) + (dolist (match matches) + (let-alist match + (push (pdf-occur-create-entry filename .page (cons .text .edges)) + entries))) (setq entries (nreverse entries)) (pdf-occur-insert-entries entries)))) @@ -623,9 +622,7 @@ matches linked with PAGE." :key 'car :test 'equal) (cl-incf pdf-occur-number-of-matches - (cl-reduce (lambda (n elt) - (+ n (length (cdr elt)))) - (cons 0 response))) + (length response)) (pdf-occur-add-matches document response) (pdf-occur-update-header-line)))) (lambda (status buffer) diff --git a/lisp/pdf-outline.el b/lisp/pdf-outline.el index b6712a1..91a074b 100644 --- a/lisp/pdf-outline.el +++ b/lisp/pdf-outline.el @@ -26,6 +26,7 @@ (require 'pdf-view) (require 'cl-lib) (require 'imenu) +(require 'let-alist) ;;; Code: @@ -248,29 +249,26 @@ buffer, unless NO-SELECT-WINDOW-P is non-nil." (defun pdf-outline-insert-outline (pdf-file) (let ((labels (and pdf-outline-display-labels (pdf-info-pagelabels pdf-file))) - (outline (cl-remove-if-not - (lambda (type) - (eq type 'goto-dest)) - (pdf-info-outline pdf-file) - :key 'cadr))) - (dolist (item outline) - (cl-destructuring-bind (lvl _type title page _top) - item - (insert-text-button - (concat - (make-string (* (1- lvl) pdf-outline-buffer-indent) ?\s) - title - (if (> page 0) - (format " (%s)" - (if labels - (nth (1- page) labels) - page)) - "(invalid)")) - 'type 'pdf-outline - 'help-echo (pdf-links-action-to-string (cdr item)) - 'pdf-outline-link (cdr item)) - (newline))) - (length outline))) + (nitems 0)) + (dolist (item (pdf-info-outline pdf-file)) + (let-alist item + (when (eq .type 'goto-dest) + (insert-text-button + (concat + (make-string (* (1- .depth) pdf-outline-buffer-indent) ?\s) + .title + (if (> .page 0) + (format " (%s)" + (if labels + (nth (1- .page) labels) + .page)) + "(invalid)")) + 'type 'pdf-outline + 'help-echo (pdf-links-action-to-string item) + 'pdf-outline-link item) + (newline) + (cl-incf nitems)))) + nitems)) (defun pdf-outline-get-pdf-window (&optional if-visible-p) (save-selected-window @@ -420,7 +418,7 @@ Then quit the outline window." (let (curpage) (save-excursion (goto-char (point-min)) - (while (and (setq curpage (nth 2 (pdf-outline-link-at-pos))) + (while (and (setq curpage (alist-get 'page (pdf-outline-link-at-pos))) (< curpage page)) (forward-line)) (point)))) @@ -454,12 +452,11 @@ Then quit the outline window." (use-local-map (keymap-parent (current-local-map))))) -(defun pdf-outline-imenu-create-item (_lvl link &optional labels) - (cl-destructuring-bind ( _type title page _top) - link - (list (format "%s (%s)" title (if labels - (nth (1- page) labels) - page)) +(defun pdf-outline-imenu-create-item (link &optional labels) + (let-alist link + (list (format "%s (%s)" .title (if labels + (nth (1- .page) labels) + .page)) 0 'pdf-outline-imenu-activate-link link))) @@ -468,16 +465,12 @@ Then quit the outline window." (let ((labels (and pdf-outline-display-labels (pdf-info-pagelabels (pdf-view-buffer-file-name)))) - (outline (cl-remove-if-not - (lambda (type) - (eq type 'goto-dest)) - (pdf-info-outline (pdf-view-buffer-file-name)) - :key 'cadr)) index) - (dolist (o outline) - (push (pdf-outline-imenu-create-item - (car o) (cdr o) labels) - index)) + (dolist (item (pdf-info-outline (pdf-view-buffer-file-name))) + (let-alist item + (when (eq .type 'goto-dest) + (push (pdf-outline-imenu-create-item item labels) + index)))) (nreverse index))) @@ -488,22 +481,20 @@ Then quit the outline window." (lambda (type) (eq type 'goto-dest)) (pdf-info-outline (pdf-view-buffer-file-name)) - :key 'cadr)) + :key (apply-partially 'alist-get 'type))) (and pdf-outline-display-labels (pdf-info-pagelabels (pdf-view-buffer-file-name))))) (defun pdf-outline-imenu-create-index-tree-1 (nodes &optional labels) (mapcar (lambda (node) (let (children) - (when (consp (car node)) + (when (consp (caar node)) (setq children (cdr node) node (car node))) - (let ((title (nth 2 node)) - (item - (pdf-outline-imenu-create-item - (car node) (cdr node) labels))) + (let ((item + (pdf-outline-imenu-create-item node labels))) (if children - (cons title + (cons (alist-get 'title node) (cons item (pdf-outline-imenu-create-index-tree-1 children labels))) item)))) @@ -511,16 +502,16 @@ Then quit the outline window." (defun pdf-outline-treeify-outline-list (list) (when list - (let ((level (caar list)) + (let ((depth (alist-get 'depth (car list))) result) (while (and list - (>= (caar list) - level)) - (when (= (caar list) level) + (>= (alist-get 'depth (car list)) + depth)) + (when (= (alist-get 'depth (car list)) depth) (let ((item (car list))) (when (and (cdr list) - (> (car (cadr list)) - level)) + (> (alist-get 'depth (cadr list)) + depth)) (setq item (cons item diff --git a/lisp/pdf-sync.el b/lisp/pdf-sync.el index 1825211..80221a5 100644 --- a/lisp/pdf-sync.el +++ b/lisp/pdf-sync.el @@ -34,6 +34,7 @@ (require 'pdf-view) (require 'pdf-info) (require 'pdf-util) +(require 'let-alist) ;;; Code: @@ -323,14 +324,13 @@ point to the correct position." (page (pdf-view-current-page))) (setq x (/ x (float (car size))) y (/ y (float (cdr size)))) - (cl-destructuring-bind (source line column) - (pdf-info-synctex-backward-search page x y) - (let ((data (list (expand-file-name source) - line column))) + (let-alist (pdf-info-synctex-backward-search page x y) + (let ((data (list (expand-file-name .filename) + .line .column))) (cl-destructuring-bind (source line column) (or (save-selected-window (apply 'run-hook-with-args-until-success - 'pdf-sync-backward-redirect-functions data)) + 'pdf-sync-backward-redirect-functions data)) data) (list source (if (not pdf-sync-backward-use-heuristic) @@ -697,10 +697,11 @@ Returns a list \(PDF PAGE X1 Y1 X2 Y2\)." (buffer-file-name) pdf))) (condition-case err (cons pdf - (pdf-info-synctex-forward-search - (or sfilename - (buffer-file-name)) - line column pdf)) + (let-alist (pdf-info-synctex-forward-search + (or sfilename + (buffer-file-name)) + line column pdf) + (cons .page .edges))) (error (if (null sfilename) (signal (car err) (cdr err)) @@ -708,9 +709,9 @@ Returns a list \(PDF PAGE X1 Y1 X2 Y2\)." ;; would actually work for some reason. (condition-case nil (cons pdf - (pdf-info-synctex-forward-search - (buffer-file-name) - line column pdf)) + (let-alist (pdf-info-synctex-forward-search + (buffer-file-name) line column pdf) + (cons .page .edges))) (error (signal (car err) (cdr err))))))))) diff --git a/lisp/pdf-tools.el b/lisp/pdf-tools.el index 6d8d5f9..ec9e03b 100644 --- a/lisp/pdf-tools.el +++ b/lisp/pdf-tools.el @@ -6,7 +6,7 @@ ;; Keywords: files, multimedia ;; Package: pdf-tools ;; Version: 0.70 -;; Package-Requires: ((emacs "24.3") (tablist "0.70")) +;; Package-Requires: ((emacs "24.3") (tablist "0.70") (let-alist)) ;; 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 diff --git a/test/pdf-info.ert b/test/pdf-info.ert index 75e0fb4..82f3e38 100644 --- a/test/pdf-info.ert +++ b/test/pdf-info.ert @@ -1,5 +1,6 @@ ;; -*- lexical-binding: t -*- +(require 'let-alist) (require 'pdf-info) (require 'ert) @@ -17,38 +18,44 @@ (ert-deftest pdf-info-search-string () (pdf-test-with-test-pdf - (let (matches) - (should (setq matches (pdf-info-search-string "PDF Tools"))) - (should (= 1 (length matches))) - (should (= 2 (length (cdar matches)))) - (should (cl-every 'stringp - (mapcar 'car (cdar matches)))) - (should (cl-every 'pdf-test-relative-edges-p - (mapcar 'cadr (cdar matches))))))) + (let (matches) + (should (setq matches (pdf-info-search-string "PDF Tools"))) + (should (= 2 (length matches))) + (should (cl-every (lambda (m) + (let-alist m + (and (stringp .text) + (cl-every 'pdf-test-relative-edges-p .edges) + (= 1 .page)))) + matches))))) (ert-deftest pdf-info-search-regexp () (pdf-test-with-test-pdf (let (case-fold-search matches) (should (setq matches (pdf-info-search-regexp "PDF Tools"))) - (should (= 1 (length matches))) - (should (= 2 (length (cdar matches)))) - (should (cl-every 'stringp - (mapcar 'car (cdar matches)))) - (should (cl-every 'pdf-test-relative-edges-p - (mapcar 'cadr (cdar matches))))))) + (should (= 2 (length matches))) + (should (cl-every (lambda (m) + (let-alist m + (and (stringp .text) + (cl-every 'pdf-test-relative-edges-p .edges) + (= 1 .page)))) + matches))))) (ert-deftest pdf-info-pagelinks () (pdf-test-with-test-pdf - (let (links) - (should (= 2 (length (setq links (pdf-info-pagelinks 3))))) + (let ((links (pdf-info-pagelinks 3))) + (should (= 2 (length links))) (should (cl-every 'pdf-test-relative-edges-p - (mapcar 'car links))) - (setq links (mapcar 'cdr links)) - (should (equal (mapcar 'car links) + (mapcar (apply-partially 'alist-get 'edges) + links))) + (should (equal (mapcar (apply-partially 'alist-get 'type) links) '(goto-dest uri))) - (should (equal (mapcar 'car (mapcar 'cddr links)) - '(1 "http://www.gnu.org")))))) + (should (equal (mapcar (apply-partially 'alist-get 'uri) + links) + '(nil "http://www.gnu.org"))) + (should (equal (mapcar (apply-partially 'alist-get 'page) + links) + '(1 nil)))))) (ert-deftest pdf-info-number-of-pages () (pdf-test-with-test-pdf @@ -56,13 +63,14 @@ (ert-deftest pdf-info-outline () (pdf-test-with-test-pdf - (let (outline) - (should (= 7 (length (setq outline (pdf-info-outline))))) - (should (equal (mapcar 'car outline) - '(1 1 1 1 1 2 3))) - (should (cl-every (lambda (type) - (equal type 'goto-dest)) - (mapcar 'cadr outline)))))) + (let ((outline (pdf-info-outline))) + (should (= 7 (length outline))) + (should (equal (mapcar (apply-partially 'alist-get 'depth) outline) + '(1 1 1 1 1 2 3))) + (should (cl-every (lambda (elt) + (eq (alist-get 'type elt) + 'goto-dest)) + outline))))) (ert-deftest pdf-info-gettext () (pdf-test-with-test-pdf |
