Настройка представления документа в Emacs по ширине страницы

Я пытаюсь использовать Document View в Emacs для чтения PDF-файлов, но я не могу понять, как заставить его вести себя так же, как команда "fit to width", которую имеют многие программы чтения PDF. Есть ли внутренний способ сделать это?

4 ответа

Решение

Следующий фрагмент определяет новый вспомогательный режим doc-view-autofit-mode, который я активировал ниже, используя doc-view-mode-hook, У меня это работает на Emacs 24.3 на Ubuntu 14.04, даже до изменения размера зума, когда я изменяю размер окна!

(Обычно есть небольшая задержка изменения размера благодаря doc-view-autofit-timer-start, но я счастлив с этим жить.)

Я не принимаю кредит на решение; Я нашел этот код в списке рассылки emacs-devel.

(require 'cl)

;;;; Automatic fitting minor mode
(defcustom doc-view-autofit-timer-start 1.0
  "Initial value (seconds) for the timer that delays the fitting when
`doc-view-autofit-fit' is called (Which is when a window
configuration change occurs and a document needs to be fitted)."
  :type 'number
  :group 'doc-view)

(defcustom doc-view-autofit-timer-inc 0.02
  "Value to increase (seconds) the timer (see `doc-view-autofit-timer-start')
by, if there is another window configuration change occuring, before
it runs out."
  :type 'number
  :group 'doc-view)

(defcustom doc-view-autofit-default-fit 'width
  "The fitting type initially used when mode is enabled.
Valid values are: width, height, page."
  :type 'symbol
  :group 'doc-view)

(defvar doc-view-autofit-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "C-c W") 'doc-view-autofit-width)
    (define-key map (kbd "C-c H") 'doc-view-autofit-height)
    (define-key map (kbd "C-c P") 'doc-view-autofit-page)
    map)
  "Keymap used by `doc-view-autofit-mode'.")

(defun doc-view-autofit-set (type)
  "Set autofitting to TYPE for current buffer."
  (when doc-view-autofit-mode
    (setq doc-view-autofit-type type)
    (doc-view-autofit-fit)))

(defun doc-view-autofit-width ()
  "Set autofitting to width for current buffer."
  (interactive) (doc-view-autofit-set 'width))

(defun doc-view-autofit-height ()
  "Set autofitting to height for current buffer."
  (interactive) (doc-view-autofit-set 'height))

(defun doc-view-autofit-page ()
  "Set autofitting to page for current buffer."
  (interactive) (doc-view-autofit-set 'page))

(defun doc-view-autofit-fit ()
  "Fits the document in the selected window's buffer
delayed with a timer, so multiple calls in succession
don't cause as much overhead."
  (lexical-let
      ((window (selected-window)))
    (if (equal doc-view-autofit-timer nil)
        (setq doc-view-autofit-timer
              (run-with-timer
               doc-view-autofit-timer-start nil
               (lambda ()
                 (if (window-live-p window)
                     (save-selected-window
                       (select-window window)
                       (cancel-timer doc-view-autofit-timer)
                       (setq doc-view-autofit-timer nil)
                       (cond
                        ((equal 'width doc-view-autofit-type)
                         (doc-view-fit-width-to-window))
                        ((equal 'height doc-view-autofit-type)
                         (doc-view-fit-height-to-window))
                        ((equal 'page doc-view-autofit-type)
                         (doc-view-fit-page-to-window))))))))
      (timer-inc-time doc-view-autofit-timer doc-view-autofit-timer-inc))))

(define-minor-mode doc-view-autofit-mode
  "Minor mode for automatic (timer based) fitting in DocView."
  :lighter " AFit" :keymap doc-view-autofit-mode-map :group 'doc-view
  (when doc-view-autofit-mode
    (set (make-local-variable 'doc-view-autofit-type)
         doc-view-autofit-default-fit)
    (set (make-local-variable 'doc-view-autofit-timer) nil)
    (add-hook 'window-configuration-change-hook
              'doc-view-autofit-fit nil t)
    (doc-view-autofit-fit))
  (when (not doc-view-autofit-mode)
    (remove-hook 'window-configuration-change-hook
                 'doc-view-autofit-fit t)
    (when doc-view-autofit-timer
      (cancel-timer doc-view-autofit-timer)
      (setq doc-view-autofit-timer nil))
    (setq doc-view-autofit-type nil)))

(add-hook 'doc-view-mode-hook 'doc-view-autofit-mode)

Меня устраивает:

(add-hook 'doc-view-mode-hook 'doc-view-fit-width-to-window)

Обновление: это не работает правильно, если преобразование (в png или что-то еще) все еще продолжается (сначала открыв документ). Есть альтернативный, более надежный способ, который обрабатывает этот особый случай (он вообще не использует ловушку, а использует совет):

(defadvice doc-view-display (after fit-width activate)
  (doc-view-fit-width-to-window))

Просто примечание: (требуется 'cl) устарело. Поскольку emacs-24.3 должен быть

(require ‘cl-lib) 

См. http://www.emacswiki.org/emacs/CommonLispForEmacs

Ниже приведено небольшое изменение ответа Криса - оно обеспечивает совместимость с такими функциями, как find-file-other-window - например, когда selected-window отличается от того, который отображает *.pdf файл.

(defvar last-displayed-doc-view-buffer nil)

(defun get-last-displayed-doc-view-buffer ()
  (setq last-displayed-doc-view-buffer (current-buffer)))

(add-hook 'doc-view-mode-hook 'get-last-displayed-doc-view-buffer)

(defun doc-view-autofit-fit ()
  "Fits the document in the selected window's buffer
delayed with a timer, so multiple calls in succession
don't cause as much overhead."
  (if (null doc-view-autofit-timer)
    (setq doc-view-autofit-timer
      (run-with-timer doc-view-autofit-timer-start nil (lambda ()
        (let* (
            (selected-window
              (cond
                ((eq major-mode 'doc-view-mode)
                  (selected-window))
                (t
                  (get-buffer-window last-displayed-doc-view-buffer))))
            (current-buffer
              (cond
                ((eq major-mode 'doc-view-mode)
                  (current-buffer))
                (t
                  (get-buffer last-displayed-doc-view-buffer))))
            (selected-fit
              (when (buffer-live-p (get-buffer current-buffer))
                (with-current-buffer (get-buffer current-buffer)
                  doc-view-autofit-type))) )
          (when (window-live-p selected-window)
            (with-selected-window selected-window
              (when doc-view-autofit-timer (cancel-timer doc-view-autofit-timer))
              (setq doc-view-autofit-timer nil)
              (cond
                ((eq 'width selected-fit)
                  (doc-view-fit-width-to-window))
                ((eq 'height selected-fit)
                  (doc-view-fit-height-to-window))
                ((eq 'page selected-fit)
                  (doc-view-fit-page-to-window)))))))))
    (timer-inc-time doc-view-autofit-timer doc-view-autofit-timer-inc)))

И, как отмечалось в моем предыдущем комментарии к ответу Криса, следующие переменные нуждаются в определениях:

(defvar doc-view-autofit-timer nil)

(defvar doc-view-autofit-type nil)

Поскольку приведенная выше модификация добавляет новую функцию к doc-view-mode-hook чтобы получить current-buffer, который необходим для функции doc-view-autofit-fitнеобходимо убедиться, что последняя функция добавлена ​​в конец doc-view-mode-hook, Таким образом, изменение выглядит следующим образом - т.е. мы добавляем t для аргумента добавления:

(add-hook 'doc-view-mode-hook 'doc-view-autofit-mode t)

Все остальное из ответа Криса, которое не было заменено вышеуказанными изменениями, остается в силе.


Делать

  • Создайте тест для проверки каждой страницы при прокрутке, чтобы убедиться, что представление совпадает с autofit-type, В настоящее время возникают ошибки в размере страницы при работе с длинными *.pdf файл.
Другие вопросы по тегам