From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Kangas Newsgroups: gmane.emacs.bugs Subject: bug#12098: How to trap errors in man? Date: Wed, 19 Aug 2020 12:49:39 +0000 Message-ID: References: <87pq7b5uvr.fsf@mail.jurta.org> <87txwnxbbx.fsf@mail.jurta.org> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="14473"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) Cc: Reuben Thomas , 12098@debbugs.gnu.org To: Juri Linkov Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Aug 19 14:50:11 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k8NXf-0003bz-7t for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 19 Aug 2020 14:50:11 +0200 Original-Received: from localhost ([::1]:47002 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k8NXd-00053g-O1 for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 19 Aug 2020 08:50:09 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45928) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k8NXW-000534-8A for bug-gnu-emacs@gnu.org; Wed, 19 Aug 2020 08:50:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:55195) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1k8NXV-0003VP-Ui for bug-gnu-emacs@gnu.org; Wed, 19 Aug 2020 08:50:01 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1k8NXV-0000Dq-S7 for bug-gnu-emacs@gnu.org; Wed, 19 Aug 2020 08:50:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Kangas Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 19 Aug 2020 12:50:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 12098 X-GNU-PR-Package: emacs Original-Received: via spool by 12098-submit@debbugs.gnu.org id=B12098.1597841389827 (code B ref 12098); Wed, 19 Aug 2020 12:50:01 +0000 Original-Received: (at 12098) by debbugs.gnu.org; 19 Aug 2020 12:49:49 +0000 Original-Received: from localhost ([127.0.0.1]:38508 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1k8NXI-0000DB-EE for submit@debbugs.gnu.org; Wed, 19 Aug 2020 08:49:48 -0400 Original-Received: from mail-yb1-f177.google.com ([209.85.219.177]:43076) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1k8NXG-0000Co-6T for 12098@debbugs.gnu.org; Wed, 19 Aug 2020 08:49:46 -0400 Original-Received: by mail-yb1-f177.google.com with SMTP id m200so13249622ybf.10 for <12098@debbugs.gnu.org>; Wed, 19 Aug 2020 05:49:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:in-reply-to:references:user-agent :mime-version:date:message-id:subject:to:cc; bh=oHtZIygjTBgZQVR6Z4szAgtdGLfEiOUciiC82pEodTo=; b=TlL1Xm/nat8UeOXd6YQoEiGU2mtnZIFOqFwXYIjelLn1sdvvzin2ccrT5SsiSCUDPo 1DKvvASh4cwNGGioakeAoZ6/wJV/m+bQAIsrGOEMJHvyFbe8CZHyW/G2QamrXn95rdHH Fp64ooZ1oS4w9FeG3oldkPgnecexG/y4dWSw0OsSJhmDZ0mO+mxhqODtTDmt4IQ5Y4eE 5os9DrHoyQ284hOfP4EXKGiae3Qr5WU6/YvG5Rkkm1j6gXZXEudppyZsbNoTEoSqNk7t VgOnLxebFBhrbvPMu3FyPtJyGl7huxtZ/b0mKNiPeUZUhshfm1bORGMIrzHYFVUYzEi6 bQag== X-Gm-Message-State: AOAM531KSPbcXX8+Mw1IUTVX3AOJztmpe8VpQ5riSmkZVAjqunPk1y1B ccs2AS/xTmSUGkV5tBN5oAlYmD2eOXENJvBzP1ANmp/Rr3g= X-Google-Smtp-Source: ABdhPJxIS4M2sZXrsVbAxWbKPtZXkYeuluiRwmB9H7JBkq9Bi8LcWV8vk6ac3sQgGHs6l+Pxan6QxfbrbQOOkinhNb8= X-Received: by 2002:a25:4ed7:: with SMTP id c206mr35215933ybb.129.1597841380472; Wed, 19 Aug 2020 05:49:40 -0700 (PDT) Original-Received: from 753933720722 named unknown by gmailapi.google.com with HTTPREST; Wed, 19 Aug 2020 12:49:39 +0000 In-Reply-To: <87txwnxbbx.fsf@mail.jurta.org> (Juri Linkov's message of "Wed, 01 Aug 2012 11:23:30 +0300") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:185589 Archived-At: severity 12098 wishlist tags 12098 + patch moreinfo thanks Juri Linkov 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