From: Stefan Kangas <stefan@marxist.se>
To: Juri Linkov <juri@jurta.org>
Cc: Reuben Thomas <rrt@sc3d.org>, 12098@debbugs.gnu.org
Subject: bug#12098: How to trap errors in man?
Date: Wed, 19 Aug 2020 12:49:39 +0000 [thread overview]
Message-ID: <CADwFkmnieZFT=pLca1ZyREEVQ5pRQrWXOAib-n6ZH5P2X23WsQ@mail.gmail.com> (raw)
In-Reply-To: <87txwnxbbx.fsf@mail.jurta.org> (Juri Linkov's message of "Wed, 01 Aug 2012 11:23:30 +0300")
severity 12098 wishlist
tags 12098 + patch moreinfo
thanks
Juri Linkov <juri@jurta.org> writes:
>> There are plenty of things that freeze the session for much longer
>> than the fraction of a second it takes to format most man pages! Even
>> bash(1) only takes about a second.
>
> You are right, the largest man page `man bash' takes just 2 sec to format,
> so perhaps it makes no sense to run the man command asynchronously nowadays.
>
> The patch below introduces a new variable `Man-async' whose value
> could be set to nil to run `man' synchronously.
>
>> Are you sure about that bug number? I looked and it seems to be about
>> window layout.
>
> That's right, currently the async mode of man has its peculiarities:
> it arranges window layouts after formatting is done, so formatting
> can't fit into window layout.
>
> So perhaps we should have two asynchronous modes:
> 1. delay changes in window configuration
> until the process is finished and man page is formatted.
> 2. prepare window layout before formatting;
>
> I'm still not sure whether we need the former for backward compatibility,
> so `Man-async' could have a special value for it.
>
>> I can't see how to use this to communicate back to a particular caller
>> that man failed; help?
>
> I don't know if it's possible with lack of multi-threading
> to yield to the command loop while waiting for the process output.
> But with the following patch you can run `man' synchronously
> by using just `(let ((Man-async nil)) (man "bash"))' when its
> default value is not nil.
This patch adds the possibility to run man asynchronously. I'm not sure
it's worth the added complexity. Any other opinions?
> === modified file 'lisp/man.el'
> --- lisp/man.el 2012-07-11 23:13:41 +0000
> +++ lisp/man.el 2012-08-01 08:23:10 +0000
> @@ -144,6 +144,20 @@ (defcustom Man-reverse-face 'highlight
> :type 'face
> :group 'man)
>
> +(defcustom Man-async nil
> + "Synchronicity of the manpage command.
> +If nil, run the manpage command synchronously.
> +If t, run the manpage command asynchronously
> +preparing output windows before the process is started.
> +If the value is `delayed', run the manpage command
> +asynchronously but delay changes in window configuration
> +until the process is finished and man page is formatted."
> + :type '(choice (const :tag "Synchronous" nil)
> + (const :tag "Asynchronous" t)
> + (const :tag "Delayed" delayed))
> + :group 'man
> + :version "24.2")
> +
> ;; Use the value of the obsolete user option Man-notify, if set.
> (defcustom Man-notify-method (if (boundp 'Man-notify) Man-notify 'friendly)
> "Selects the behavior when manpage is ready.
> @@ -904,16 +920,37 @@ (defun Man-getpage-in-background (topic)
> Return the buffer in which the manpage will appear."
> (let* ((man-args topic)
> (bufname (concat "*Man " man-args "*"))
> - (buffer (get-buffer bufname)))
> + (buffer (get-buffer bufname))
> + (procbufname (concat " " bufname))
> + procbuffer)
> (if buffer
> (Man-notify-when-ready buffer)
> (require 'env)
> - (message "Invoking %s %s in the background" manual-program man-args)
> - (setq buffer (generate-new-buffer bufname))
> - (with-current-buffer buffer
> - (setq buffer-undo-list t)
> - (setq Man-original-frame (selected-frame))
> - (setq Man-arguments man-args))
> + (cond
> + ((eq Man-async 'delayed)
> + (message "Invoking %s %s in the background" manual-program man-args)
> + (setq buffer (generate-new-buffer bufname))
> + (with-current-buffer buffer
> + (setq buffer-undo-list t)
> + (setq Man-original-frame (selected-frame))
> + (setq Man-arguments man-args)))
> + (t
> + (setq buffer (generate-new-buffer bufname))
> + (setq procbuffer (generate-new-buffer procbufname))
> + ;; Display empty output buffer.
> + (unless (memq Man-notify-method '(polite quiet meek))
> + (Man-notify-when-ready buffer))
> + (with-current-buffer buffer
> + (insert (format "Invoking %s %s in the background\n"
> + manual-program man-args))
> + (setq buffer-undo-list t)
> + (setq Man-original-frame (selected-frame))
> + (setq Man-arguments man-args))
> + (with-current-buffer procbuffer
> + (setq buffer-undo-list t)
> + (setq Man-original-frame (selected-frame))
> + (setq Man-arguments man-args))))
> +
> (let ((process-environment (copy-sequence process-environment))
> ;; The following is so Awk script gets \n intact
> ;; But don't prevent decoding of the outside.
> @@ -952,16 +989,26 @@ (defun Man-getpage-in-background (topic)
> (cond
> ((and (integerp Man-width) (> Man-width 0))
> Man-width)
> - (Man-width (frame-width))
> - ((window-width))))))
> + (Man-width
> + (if (eq Man-async 'delayed)
> + (frame-width)
> + (with-selected-window (get-buffer-window
> + buffer t)
> + (frame-width))))
> + (t
> + (if (eq Man-async 'delayed)
> + (window-width)
> + (with-selected-window (get-buffer-window
> + buffer t)
> + (window-width))))))))
> (setenv "GROFF_NO_SGR" "1")
> ;; Since man-db 2.4.3-1, man writes plain text with no escape
> ;; sequences when stdout is not a tty. In 2.5.0, the following
> ;; env-var was added to allow control of this (see Debian Bug#340673).
> (setenv "MAN_KEEP_FORMATTING" "1")
> - (if (fboundp 'start-process)
> + (if (and Man-async (fboundp 'start-process))
> (set-process-sentinel
> - (start-process manual-program buffer
> + (start-process manual-program (if (eq Man-async 'delayed) buffer procbuffer)
> (if (memq system-type '(cygwin windows-nt))
> shell-file-name
> "sh")
> @@ -969,7 +1016,7 @@ (defun Man-getpage-in-background (topic)
> (format (Man-build-man-command) man-args))
> 'Man-bgproc-sentinel)
> (let ((exit-status
> - (call-process shell-file-name nil (list buffer nil) nil
> + (call-process shell-file-name nil (list procbuffer nil) nil
> shell-command-switch
> (format (Man-build-man-command) man-args)))
> (msg ""))
> @@ -980,7 +1027,7 @@ (defun Man-getpage-in-background (topic)
> (format "exited abnormally with code %d"
> exit-status)))
> (setq msg exit-status))
> - (Man-bgproc-sentinel bufname msg)))))
> + (Man-bgproc-sentinel procbufname msg)))))
> buffer))
>
> (defun Man-notify-when-ready (man-buffer)
> @@ -1216,16 +1263,18 @@ (defun Man-bgproc-sentinel (process msg)
> synchronously, PROCESS is the name of the buffer where the manpage
> command is run. Second argument MSG is the exit message of the
> manpage command."
> - (let ((Man-buffer (if (stringp process) (get-buffer process)
> - (process-buffer process)))
> - (delete-buff nil)
> - (err-mess nil))
> + (let* ((Man-procbuffer (if (stringp process) (get-buffer process)
> + (process-buffer process)))
> + (Man-buffer (get-buffer (replace-regexp-in-string
> + "\\` " "" (buffer-name Man-procbuffer))))
> + (delete-buff nil)
> + (err-mess nil))
>
> (if (null (buffer-name Man-buffer)) ;; deleted buffer
> (or (stringp process)
> (set-process-buffer process nil))
>
> - (with-current-buffer Man-buffer
> + (with-current-buffer Man-procbuffer
> (let ((case-fold-search nil))
> (goto-char (point-min))
> (cond ((or (looking-at "No \\(manual \\)*entry for")
> @@ -1261,11 +1310,17 @@ (defun Man-bgproc-sentinel (process msg)
> (Man-fontify-manpage)
> (Man-cleanup-manpage))
>
> + (unless (eq Man-async 'delayed)
> + (copy-to-buffer Man-buffer (point-min) (point-max))))))
> +
> + (unless delete-buff
> + (with-current-buffer (if (eq Man-async 'delayed) Man-procbuffer Man-buffer)
> (run-hooks 'Man-cooked-hook)
> (Man-mode)
>
> @@ -1279,11 +1342,13 @@ (defun Man-bgproc-sentinel (process msg)
> ;; Man-notify-when-ready because it may switch buffers.
>
> (if (not delete-buff)
> - (Man-notify-when-ready Man-buffer))
> + (when (or (eq Man-async 'delayed)
> + (memq Man-notify-method '(polite quiet meek)))
> + (Man-notify-when-ready Man-buffer)))
>
> (if err-mess
> (error "%s" err-mess))
> - ))))
> + )))
>
> (defun Man-page-from-arguments (args)
> ;; Skip arguments and only print the page name.
Best regards,
Stefan Kangas
next prev parent reply other threads:[~2020-08-19 12:49 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-31 11:53 bug#12098: How to trap errors in man? Reuben Thomas
[not found] ` <handler.12098.B.13437360754310.ack@debbugs.gnu.org>
2012-07-31 13:36 ` bug#12098: Acknowledgement (How to trap errors in man?) Reuben Thomas
2012-07-31 16:27 ` Eli Zaretskii
2012-08-01 0:15 ` bug#12098: How to trap errors in man? Juri Linkov
2012-08-01 0:38 ` Reuben Thomas
2012-08-01 8:23 ` Juri Linkov
2012-08-01 11:11 ` Reuben Thomas
2020-08-19 12:49 ` Stefan Kangas [this message]
2020-08-19 12:53 ` Reuben Thomas via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-08-19 13:08 ` Stefan Kangas
2020-08-19 13:08 ` Lars Ingebrigtsen
2020-08-19 13:10 ` Reuben Thomas via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-08-19 13:24 ` Stefan Kangas
2020-08-19 13:28 ` Reuben Thomas via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-08-19 13:51 ` Stefan Kangas
2020-08-19 13:51 ` Reuben Thomas via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-08-19 14:12 ` Stefan Kangas
2020-08-19 14:21 ` Reuben Thomas via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-08-19 15:17 ` Stefan Kangas
2020-08-19 15:22 ` Reuben Thomas via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-10-14 6:05 ` Lars Ingebrigtsen
2020-08-19 13:14 ` Stefan Kangas
2020-08-20 0:37 ` Juri Linkov
2020-08-21 7:25 ` Stefan Kangas
2020-08-21 7:41 ` Eli Zaretskii
2020-08-21 9:41 ` Reuben Thomas via Bug reports for GNU Emacs, the Swiss army knife of text editors
2012-08-01 9:05 ` Andy Moreton
2012-08-01 23:10 ` Juri Linkov
2012-08-01 8:27 ` Thierry Volpiatto
2012-08-01 8:41 ` Juri Linkov
2012-08-01 8:58 ` Thierry Volpiatto
2012-08-01 9:29 ` Thierry Volpiatto
2012-08-01 23:12 ` Juri Linkov
2012-08-02 5:20 ` Thierry Volpiatto
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CADwFkmnieZFT=pLca1ZyREEVQ5pRQrWXOAib-n6ZH5P2X23WsQ@mail.gmail.com' \
--to=stefan@marxist.se \
--cc=12098@debbugs.gnu.org \
--cc=juri@jurta.org \
--cc=rrt@sc3d.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.