unofficial mirror of guix-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends.
@ 2015-09-13 19:39 Alex Kost
  2015-09-13 19:39 ` [PATCH 1/3] emacs: Display guix command errors in the minibuffer Alex Kost
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Alex Kost @ 2015-09-13 19:39 UTC (permalink / raw)
  To: guix-devel

Ludovic Courtès (2015-09-11 00:55 +0300) wrote:

> ‘guix build --log-file’ can now return URLs of remote build logs:
>
>   $ ./pre-inst-env guix build --log-file gdb -s mips64el-linux 
>   http://hydra.gnu.org/log/qzcw62lnvijv1qmdn66mjdk06y9ffh4p-gdb-7.10
>
> (Works best in Emacs shell-mode where you can C-x C-f on the URL to open
> it in a browser.)

Or "M-x browse-url-emacs" on the URL and open it in Emacs.

> Enjoy!

Wow, thanks, I enjoy it!  I didn't notice ‘--log-file’ before (shame on
me).  Now it is really useful!  So this pushed me to add major and minor
modes for highlighting build logs and to add an alternative way to
receive/view them in Emacs (through "M-x guix RET b" popup).

(Unluckily, hydra is not very fast and responsive, so receiving big logs
may take much time.)

Patches:

[PATCH 1/3] emacs: Display guix command errors in the minibuffer.
[PATCH 2/3] emacs: Add modes for viewing build logs.
[PATCH 3/3] emacs: Add "View build log" action to build popup.

The first patch is an auxiliary one to print guix warnings/errors in the
Emacs minibuffer.  For example, when hydra does not have a log, a user
will see:

  guix build: error: no build log for '/gnu/store/g785jl0pgi4gfvbqa0w3mzxhlkji9jz7-emms-4.0.drv'

in the minibuffer.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/3] emacs: Display guix command errors in the minibuffer.
  2015-09-13 19:39 [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends Alex Kost
@ 2015-09-13 19:39 ` Alex Kost
  2015-09-14  7:22   ` Alex Kost
  2015-09-14 11:54   ` Ludovic Courtès
  2015-09-13 19:39 ` [PATCH 2/3] emacs: Add modes for viewing build logs Alex Kost
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 14+ messages in thread
From: Alex Kost @ 2015-09-13 19:39 UTC (permalink / raw)
  To: guix-devel

* emacs/guix-main.scm (output+error): New procedure.
  (guix-command-output): Use it.
* emacs/guix-base.el (guix-command-output): Display error output in the
  minibuffer.
---
 emacs/guix-base.el  |  9 ++++++---
 emacs/guix-main.scm | 20 +++++++++++++++++---
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/emacs/guix-base.el b/emacs/guix-base.el
index 3bee910..8d14095 100644
--- a/emacs/guix-base.el
+++ b/emacs/guix-base.el
@@ -1129,9 +1129,12 @@ The function is called with a single argument - a command line string."
 
 (defun guix-command-output (args)
   "Return string with 'guix ARGS ...' output."
-  (guix-eval-read
-   (apply #'guix-make-guile-expression
-          'guix-command-output args)))
+  (cl-multiple-value-bind (output error)
+      (guix-eval (apply #'guix-make-guile-expression
+                        'guix-command-output args))
+    ;; Remove trailing new space from the error string.
+    (message (replace-regexp-in-string "\n\\'" "" (read error)))
+    (read output)))
 
 (defun guix-help-string (&optional commands)
   "Return string with 'guix COMMANDS ... --help' output."
diff --git a/emacs/guix-main.scm b/emacs/guix-main.scm
index c9b84d3..10165c1 100644
--- a/emacs/guix-main.scm
+++ b/emacs/guix-main.scm
@@ -71,6 +71,18 @@
 (define (list-maybe obj)
   (if (list? obj) obj (list obj)))
 
+(define (output+error thunk)
+  "Call THUNK and return 2 values: output and error output as strings."
+  (let ((output-port (open-output-string))
+        (error-port  (open-output-string)))
+    (with-output-to-port output-port
+      (lambda () (with-error-to-port error-port thunk)))
+    (let ((strings (list (get-output-string output-port)
+                         (get-output-string error-port))))
+      (close-output-port output-port)
+      (close-output-port error-port)
+      (apply values strings))))
+
 (define (full-name->name+version spec)
   "Given package specification SPEC with or without output,
 return two values: name and version.  For example, for SPEC
@@ -953,9 +965,11 @@ GENERATIONS is a list of generation numbers."
     (const #t)))
 
 (define (guix-command-output . args)
-  "Return string with 'guix ARGS ...' output."
-  (with-output-to-string
-    (lambda () (apply guix-command args))))
+  "Return 2 strings with 'guix ARGS ...' output and error output."
+  (output+error
+   (lambda ()
+     (guix-warning-port (current-error-port))
+     (apply guix-command args))))
 
 (define (help-string . commands)
   "Return string with 'guix COMMANDS ... --help' output."
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] emacs: Add modes for viewing build logs.
  2015-09-13 19:39 [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends Alex Kost
  2015-09-13 19:39 ` [PATCH 1/3] emacs: Display guix command errors in the minibuffer Alex Kost
@ 2015-09-13 19:39 ` Alex Kost
  2015-09-14 12:01   ` Ludovic Courtès
  2015-09-14 12:02   ` Ludovic Courtès
  2015-09-13 19:39 ` [PATCH 3/3] emacs: Add "View build log" action to build popup Alex Kost
  2015-09-14 11:54 ` [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends Ludovic Courtès
  3 siblings, 2 replies; 14+ messages in thread
From: Alex Kost @ 2015-09-13 19:39 UTC (permalink / raw)
  To: guix-devel

* emacs/guix-build-log.el: New file.
* emacs.am (ELFILES): Add it.
* doc/emacs.texi (Emacs Build Log): Document it.  New node.
  (Emacs Interface): Add it.
* doc/guix.texi (Top): Likewise.
---
 doc/emacs.texi          |  31 ++++++
 doc/guix.texi           |   1 +
 emacs.am                |   1 +
 emacs/guix-build-log.el | 252 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 285 insertions(+)
 create mode 100644 emacs/guix-build-log.el

diff --git a/doc/emacs.texi b/doc/emacs.texi
index db2e657..33bdbd2 100644
--- a/doc/emacs.texi
+++ b/doc/emacs.texi
@@ -11,6 +11,7 @@ Guix convenient and fun.
 * Package Management: Emacs Package Management.	Managing packages and generations.
 * Popup Interface: Emacs Popup Interface.	Magit-like interface for guix commands.
 * Prettify Mode: Emacs Prettify.	Abbreviating @file{/gnu/store/@dots{}} file names.
+* Build Log Mode: Emacs Build Log.	Highlighting Guix build logs.
 * Completions: Emacs Completions.       Completing @command{guix} shell command.
 @end menu
 
@@ -571,6 +572,36 @@ mode hooks (@pxref{Hooks,,, emacs, The GNU Emacs Manual}), for example:
 @end example
 
 
+@node Emacs Build Log
+@section Build Log Mode
+
+GNU@tie{}Guix provides major and minor modes for highlighting build
+logs.  So when you have a file with a package build output---for
+example, a file returned by @command{guix build --log-file @dots{}}
+command (@pxref{Invoking guix build}), you may call @kbd{M-x
+guix-build-log-mode} command in the buffer with this file.  This major
+mode highlights some lines specific to build output and provides the
+following key bindings:
+
+@table @kbd
+
+@item M-n
+Move to the next build phase.
+
+@item M-p
+Move to the previous build phase.
+
+@end table
+
+There is also @kbd{M-x guix-build-log-minor-mode} which also provides
+the same highlighting (but not key bindings).  And as it is a minor
+mode, it can be enabled in any buffer.  For example, if you are building
+some package in a shell buffer (@pxref{Interactive Shell,,, emacs, The
+GNU Emacs Manual}), you may enable @command{guix-build-log-minor-mode}
+to make it more colorful.  Guix build output is rather specific, so this
+new highlighting shouldn't conflict with the existing one.
+
+
 @node Emacs Completions
 @section Shell Completions
 
diff --git a/doc/guix.texi b/doc/guix.texi
index 9ae91a8..c9860c2 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -114,6 +114,7 @@ Emacs Interface
 * Package Management: Emacs Package Management.	Managing packages and generations.
 * Popup Interface: Emacs Popup Interface.	Magit-like interface for guix commands.
 * Prettify Mode: Emacs Prettify.	Abbreviating @file{/gnu/store/@dots{}} file names.
+* Build Log Mode: Emacs Build Log.	Highlighting Guix build logs.
 * Completions: Emacs Completions.       Completing @command{guix} shell command.
 
 Programming Interface
diff --git a/emacs.am b/emacs.am
index 5d3cb81..a9147ed 100644
--- a/emacs.am
+++ b/emacs.am
@@ -21,6 +21,7 @@ AUTOLOADS = emacs/guix-autoloads.el
 ELFILES =					\
   emacs/guix-backend.el				\
   emacs/guix-base.el				\
+  emacs/guix-build-log.el			\
   emacs/guix-command.el				\
   emacs/guix-emacs.el				\
   emacs/guix-external.el			\
diff --git a/emacs/guix-build-log.el b/emacs/guix-build-log.el
new file mode 100644
index 0000000..6d71521
--- /dev/null
+++ b/emacs/guix-build-log.el
@@ -0,0 +1,252 @@
+;;; guix-build-log.el --- Major and minor modes for build logs   -*- lexical-binding: t -*-
+
+;; Copyright © 2015 Alex Kost <alezost@gmail.com>
+
+;; This file is part of GNU Guix.
+
+;; GNU Guix is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Guix is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file provides a major mode (`guix-build-log-mode') and a minor mode
+;; (`guix-build-log-minor-mode') for highlighting Guix build logs.
+
+;;; Code:
+
+(defgroup guix-build-log nil
+  "Settings for `guix-build-log-mode'."
+  :group 'guix)
+
+(defgroup guix-build-log-faces nil
+  "Faces for `guix-build-log-mode'."
+  :group 'guix-build-log
+  :group 'guix-faces)
+
+(defface guix-build-log-title-head
+  '((t :inherit font-lock-keyword-face))
+  "Face for '@' symbol of a log title."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-title-start
+  '((t :inherit guix-build-log-title-head))
+  "Face for a log title denoting a start of a process."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-title-success
+  '((t :inherit guix-build-log-title-head))
+  "Face for a log title denoting a successful end of a process."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-title-fail
+  '((t :inherit error))
+  "Face for a log title denoting a failed end of a process."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-title-end
+  '((t :inherit guix-build-log-title-head))
+  "Face for a log title denoting an undefined end of a process."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-phase-name
+  '((t :inherit font-lock-function-name-face))
+  "Face for a phase name."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-phase-start
+  '((default :weight bold)
+    (((class grayscale) (background light)) :foreground "Gray90")
+    (((class grayscale) (background dark))  :foreground "DimGray")
+    (((class color) (min-colors 16) (background light))
+     :foreground "DarkGreen")
+    (((class color) (min-colors 16) (background dark))
+     :foreground "LimeGreen")
+    (((class color) (min-colors 8)) :foreground "green"))
+  "Face for the start line of a phase."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-phase-end
+  '((((class grayscale) (background light)) :foreground "Gray90")
+    (((class grayscale) (background dark))  :foreground "DimGray")
+    (((class color) (min-colors 16) (background light))
+     :foreground "ForestGreen")
+    (((class color) (min-colors 16) (background dark))
+     :foreground "LightGreen")
+    (((class color) (min-colors 8)) :foreground "green")
+    (t :weight bold))
+  "Face for the end line of a phase."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-phase-success
+  '((t))
+  "Face for the 'succeeded' word of a phase line."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-phase-fail
+  '((t :inherit error))
+  "Face for the 'failed' word of a phase line."
+  :group 'guix-build-log-faces)
+
+(defface guix-build-log-phase-seconds
+  '((t :inherit font-lock-constant-face))
+  "Face for the number of seconds for a phase."
+  :group 'guix-build-log-faces)
+
+(defcustom guix-build-log-mode-hook
+  ;; Not using `compilation-minor-mode' because it rebinds some standard
+  ;; keys, including M-n/M-p.
+  '(compilation-shell-minor-mode view-mode)
+  "Hook run after `guix-build-log-mode' is entered."
+  :type 'hook
+  :group 'guix-build-log)
+
+(defvar guix-build-log-phase-name-regexp "`\\([^']+\\)'"
+  "Regexp for a phase name.")
+
+(defvar guix-build-log-phase-start-regexp
+  (concat "^starting phase " guix-build-log-phase-name-regexp)
+  "Regexp for the start line of a 'build' phase.")
+
+(defun guix-build-log-title-regexp (&optional state)
+  "Return regexp for the log title.
+STATE is a symbol denoting a state of the title.  It should be
+`start', `fail', `success' or `nil' (for a regexp matching any
+state)."
+  (let* ((word-rx (rx (1+ (any word "-"))))
+         (state-rx (cond ((eq state 'start)   (concat word-rx "started"))
+                         ((eq state 'success) (concat word-rx "succeeded"))
+                         ((eq state 'fail)    (concat word-rx "failed"))
+                         (t word-rx))))
+    (rx-to-string
+     `(and bol (group "@") " " (group (regexp ,state-rx)))
+     t)))
+
+(defun guix-build-log-phase-end-regexp (&optional state)
+  "Return regexp for the end line of a 'build' phase.
+STATE is a symbol denoting how a build phase was ended.  It should be
+`fail', `success' or `nil' (for a regexp matching any state)."
+  (let ((state-rx (cond ((eq state 'success) "succeeded")
+                        ((eq state 'fail)    "failed")
+                        (t (regexp-opt '("succeeded" "failed"))))))
+    (rx-to-string
+     `(and bol "phase " (regexp ,guix-build-log-phase-name-regexp)
+           " " (group (regexp ,state-rx)) " after "
+           (group (1+ digit)) " seconds")
+     t)))
+
+(defvar guix-build-log-font-lock-keywords
+  `((,(guix-build-log-title-regexp 'start)
+     (1 'guix-build-log-title-head)
+     (2 'guix-build-log-title-start))
+    (,(guix-build-log-title-regexp 'success)
+     (1 'guix-build-log-title-head)
+     (2 'guix-build-log-title-success))
+    (,(guix-build-log-title-regexp 'fail)
+     (1 'guix-build-log-title-head)
+     (2 'guix-build-log-title-fail))
+    (,(guix-build-log-title-regexp)
+     (1 'guix-build-log-title-head)
+     (2 'guix-build-log-title-end))
+    (,guix-build-log-phase-start-regexp
+     (0 'guix-build-log-phase-start)
+     (1 'guix-build-log-phase-name prepend))
+    (,(guix-build-log-phase-end-regexp 'success)
+     (0 'guix-build-log-phase-end)
+     (1 'guix-build-log-phase-name prepend)
+     (2 'guix-build-log-phase-success prepend)
+     (3 'guix-build-log-phase-seconds prepend))
+    (,(guix-build-log-phase-end-regexp 'fail)
+     (0 'guix-build-log-phase-end)
+     (1 'guix-build-log-phase-name prepend)
+     (2 'guix-build-log-phase-fail prepend)
+     (3 'guix-build-log-phase-seconds prepend)))
+  "A list of `font-lock-keywords' for `guix-build-log-mode'.")
+
+(defvar guix-build-log-mode-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map special-mode-map)
+    (define-key map (kbd "M-n") 'guix-build-log-next-phase)
+    (define-key map (kbd "M-p") 'guix-build-log-previous-phase)
+    map)
+  "Keymap for `guix-build-log-mode' buffers.")
+
+(defun guix-build-log-next-phase (&optional arg)
+  "Move to the next build phase.
+With ARG, do it that many times.  Negative ARG means move
+backward."
+  (interactive "^p")
+  (if arg
+      (when (zerop arg) (user-error "Try again"))
+    (setq arg 1))
+  (let ((search-fun (if (> arg 0)
+                        #'re-search-forward
+                      #'re-search-backward))
+        (n (abs arg))
+        found last-found)
+    (save-excursion
+      (end-of-line (if (> arg 0) 1 0))  ; skip the current line
+      (while (and (not (zerop n))
+                  (setq found
+                        (funcall search-fun
+                                 guix-build-log-phase-start-regexp
+                                 nil t)))
+        (setq n (1- n)
+              last-found found)))
+    (when last-found
+      (goto-char last-found)
+      (forward-line 0))
+    (or found
+        (user-error (if (> arg 0)
+                        "No next build phase"
+                      "No previous build phase")))))
+
+(defun guix-build-log-previous-phase (&optional arg)
+  "Move to the previous build phase.
+With ARG, do it that many times.  Negative ARG means move
+forward."
+  (interactive "^p")
+  (guix-build-log-next-phase (- (or arg 1))))
+
+;;;###autoload
+(define-derived-mode guix-build-log-mode special-mode
+  "Guix-Build-Log"
+  "Major mode for viewing Guix build logs.
+
+\\{guix-build-log-mode-map}"
+  (setq font-lock-defaults '(guix-build-log-font-lock-keywords t)))
+
+;;;###autoload
+(define-minor-mode guix-build-log-minor-mode
+  "Toggle Guix Build Log minor mode.
+
+With a prefix argument ARG, enable Guix Build Log minor mode if
+ARG is positive, and disable it otherwise.  If called from Lisp,
+enable the mode if ARG is omitted or nil.
+
+When Guix Build Log minor mode is enabled, it highlights build
+log in the current buffer.  This mode can be enabled
+programmatically using hooks:
+
+  (add-hook 'shell-mode-hook 'guix-build-log-minor-mode)"
+  :init-value nil
+  :lighter " Guix-Build-Log"
+  :group 'guix-build-log
+  (if guix-build-log-minor-mode
+      (font-lock-add-keywords nil guix-build-log-font-lock-keywords)
+    (font-lock-remove-keywords nil guix-build-log-font-lock-keywords))
+  (when font-lock-mode
+    (font-lock-fontify-buffer)))
+
+(provide 'guix-build-log)
+
+;;; guix-build-log.el ends here
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] emacs: Add "View build log" action to build popup.
  2015-09-13 19:39 [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends Alex Kost
  2015-09-13 19:39 ` [PATCH 1/3] emacs: Display guix command errors in the minibuffer Alex Kost
  2015-09-13 19:39 ` [PATCH 2/3] emacs: Add modes for viewing build logs Alex Kost
@ 2015-09-13 19:39 ` Alex Kost
  2015-09-14 12:03   ` Ludovic Courtès
  2015-09-14 11:54 ` [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends Ludovic Courtès
  3 siblings, 1 reply; 14+ messages in thread
From: Alex Kost @ 2015-09-13 19:39 UTC (permalink / raw)
  To: guix-devel

* emacs/guix-command.el (guix-run-view-build-log): New function.
  (guix-command-additional-execute-arguments,
  guix-command-special-executors): Add entries for "View build log"
  action.
* emacs/guix-utils.el (guix-find-file-or-url): New function.
---
 emacs/guix-command.el | 19 ++++++++++++++++++-
 emacs/guix-utils.el   | 10 ++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/emacs/guix-command.el b/emacs/guix-command.el
index 81f619f..ddafac9 100644
--- a/emacs/guix-command.el
+++ b/emacs/guix-command.el
@@ -497,7 +497,10 @@ to be modified."
   "List of default 'execute' action arguments.")
 
 (defvar guix-command-additional-execute-arguments
-  `((("graph")
+  `((("build")
+     ,(guix-command-make-argument
+       :name "log" :char ?l :doc "View build log"))
+    (("graph")
      ,(guix-command-make-argument
        :name "view" :char ?v :doc "View graph")))
   "Alist of guix commands and additional 'execute' action arguments.")
@@ -518,6 +521,8 @@ to be modified."
      ("repl" . guix-run-environment-command-in-repl))
     (("pull")
      ("repl" . guix-run-pull-command-in-repl))
+    (("build")
+     ("log" . guix-run-view-build-log))
     (("graph")
      ("view" . guix-run-view-graph)))
   "Alist of guix commands and alists of special executers for them.
@@ -556,6 +561,18 @@ Perform pull-specific actions after operation, see
    (apply #'guix-make-guile-expression 'guix-command args)
    nil 'pull))
 
+(defun guix-run-view-build-log (args)
+  "Add --log-file to ARGS, run 'guix ARGS ...' build command, and
+open the log file(s)."
+  (let* ((args (if (member "--log-file" args)
+                   args
+                 (apply #'list (car args) "--log-file" (cdr args))))
+         (output (guix-command-output args))
+         (files  (split-string output "\n" t)))
+    (dolist (file files)
+      (guix-find-file-or-url file)
+      (guix-build-log-mode))))
+
 (defun guix-run-view-graph (args)
   "Run 'guix ARGS ...' graph command, make the image and open it."
   (let* ((graph-file (guix-dot-file-name))
diff --git a/emacs/guix-utils.el b/emacs/guix-utils.el
index c1ce954..682609d 100644
--- a/emacs/guix-utils.el
+++ b/emacs/guix-utils.el
@@ -208,6 +208,16 @@ single argument."
       (funcall guix-find-file-function file)
     (message "File '%s' does not exist." file)))
 
+(defvar url-handler-regexp)
+
+(defun guix-find-file-or-url (file-or-url)
+  "Find FILE-OR-URL."
+  (require 'url-handlers)
+  (let ((file-name-handler-alist
+         (cons (cons url-handler-regexp 'url-file-handler)
+               file-name-handler-alist)))
+    (find-file file-or-url)))
+
 (defmacro guix-while-search (regexp &rest body)
   "Evaluate BODY after each search for REGEXP in the current buffer."
   (declare (indent 1) (debug t))
-- 
2.5.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] emacs: Display guix command errors in the minibuffer.
  2015-09-13 19:39 ` [PATCH 1/3] emacs: Display guix command errors in the minibuffer Alex Kost
@ 2015-09-14  7:22   ` Alex Kost
  2015-09-14 11:55     ` Ludovic Courtès
  2015-09-14 11:54   ` Ludovic Courtès
  1 sibling, 1 reply; 14+ messages in thread
From: Alex Kost @ 2015-09-14  7:22 UTC (permalink / raw)
  To: guix-devel

Alex Kost (2015-09-13 22:39 +0300) wrote:

[...]
>  (define (guix-command-output . args)
> -  "Return string with 'guix ARGS ...' output."
> -  (with-output-to-string
> -    (lambda () (apply guix-command args))))
> +  "Return 2 strings with 'guix ARGS ...' output and error output."
> +  (output+error
> +   (lambda ()
> +     (guix-warning-port (current-error-port))
> +     (apply guix-command args))))

Ouch, it should be:

   (lambda ()
     (parameterize ((guix-warning-port (current-error-port)))
       (apply guix-command args)))

-- 
Alex

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends.
  2015-09-13 19:39 [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends Alex Kost
                   ` (2 preceding siblings ...)
  2015-09-13 19:39 ` [PATCH 3/3] emacs: Add "View build log" action to build popup Alex Kost
@ 2015-09-14 11:54 ` Ludovic Courtès
  3 siblings, 0 replies; 14+ messages in thread
From: Ludovic Courtès @ 2015-09-14 11:54 UTC (permalink / raw)
  To: Alex Kost; +Cc: guix-devel

Alex Kost <alezost@gmail.com> skribis:

> Wow, thanks, I enjoy it!  I didn't notice ‘--log-file’ before (shame on
> me).  Now it is really useful!  So this pushed me to add major and minor
> modes for highlighting build logs and to add an alternative way to
> receive/view them in Emacs (through "M-x guix RET b" popup).

Excellent!  :-)

Ludo'.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] emacs: Display guix command errors in the minibuffer.
  2015-09-13 19:39 ` [PATCH 1/3] emacs: Display guix command errors in the minibuffer Alex Kost
  2015-09-14  7:22   ` Alex Kost
@ 2015-09-14 11:54   ` Ludovic Courtès
  1 sibling, 0 replies; 14+ messages in thread
From: Ludovic Courtès @ 2015-09-14 11:54 UTC (permalink / raw)
  To: Alex Kost; +Cc: guix-devel

Alex Kost <alezost@gmail.com> skribis:

> * emacs/guix-main.scm (output+error): New procedure.
>   (guix-command-output): Use it.
> * emacs/guix-base.el (guix-command-output): Display error output in the
>   minibuffer.

LGTM.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] emacs: Display guix command errors in the minibuffer.
  2015-09-14  7:22   ` Alex Kost
@ 2015-09-14 11:55     ` Ludovic Courtès
  0 siblings, 0 replies; 14+ messages in thread
From: Ludovic Courtès @ 2015-09-14 11:55 UTC (permalink / raw)
  To: Alex Kost; +Cc: guix-devel

Alex Kost <alezost@gmail.com> skribis:

> Alex Kost (2015-09-13 22:39 +0300) wrote:
>
> [...]
>>  (define (guix-command-output . args)
>> -  "Return string with 'guix ARGS ...' output."
>> -  (with-output-to-string
>> -    (lambda () (apply guix-command args))))
>> +  "Return 2 strings with 'guix ARGS ...' output and error output."
>> +  (output+error
>> +   (lambda ()
>> +     (guix-warning-port (current-error-port))
>> +     (apply guix-command args))))
>
> Ouch, it should be:
>
>    (lambda ()
>      (parameterize ((guix-warning-port (current-error-port)))
>        (apply guix-command args)))

Yes, right.

Ludo’.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] emacs: Add modes for viewing build logs.
  2015-09-13 19:39 ` [PATCH 2/3] emacs: Add modes for viewing build logs Alex Kost
@ 2015-09-14 12:01   ` Ludovic Courtès
  2015-09-14 12:02   ` Ludovic Courtès
  1 sibling, 0 replies; 14+ messages in thread
From: Ludovic Courtès @ 2015-09-14 12:01 UTC (permalink / raw)
  To: Alex Kost; +Cc: guix-devel

Alex Kost <alezost@gmail.com> skribis:

> * emacs/guix-build-log.el: New file.
> * emacs.am (ELFILES): Add it.
> * doc/emacs.texi (Emacs Build Log): Document it.  New node.
>   (Emacs Interface): Add it.
> * doc/guix.texi (Top): Likewise.

This is awesome.  M-n and M-p are super useful.

OK to push.

Thanks!

Ludo’.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] emacs: Add modes for viewing build logs.
  2015-09-13 19:39 ` [PATCH 2/3] emacs: Add modes for viewing build logs Alex Kost
  2015-09-14 12:01   ` Ludovic Courtès
@ 2015-09-14 12:02   ` Ludovic Courtès
  2015-09-15 12:21     ` Alex Kost
  2015-09-15 18:56     ` [PATCH] emacs: Add commands to show/hide build log phases Alex Kost
  1 sibling, 2 replies; 14+ messages in thread
From: Ludovic Courtès @ 2015-09-14 12:02 UTC (permalink / raw)
  To: Alex Kost; +Cc: guix-devel

As future work ;-), it would be neat if tab and S-tab would do
folding/unfolding of build phases as in Magit and Org.

Ludo’.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] emacs: Add "View build log" action to build popup.
  2015-09-13 19:39 ` [PATCH 3/3] emacs: Add "View build log" action to build popup Alex Kost
@ 2015-09-14 12:03   ` Ludovic Courtès
  0 siblings, 0 replies; 14+ messages in thread
From: Ludovic Courtès @ 2015-09-14 12:03 UTC (permalink / raw)
  To: Alex Kost; +Cc: guix-devel

Alex Kost <alezost@gmail.com> skribis:

> * emacs/guix-command.el (guix-run-view-build-log): New function.
>   (guix-command-additional-execute-arguments,
>   guix-command-special-executors): Add entries for "View build log"
>   action.
> * emacs/guix-utils.el (guix-find-file-or-url): New function.

OK, thanks!

Ludo'.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] emacs: Add modes for viewing build logs.
  2015-09-14 12:02   ` Ludovic Courtès
@ 2015-09-15 12:21     ` Alex Kost
  2015-09-15 18:56     ` [PATCH] emacs: Add commands to show/hide build log phases Alex Kost
  1 sibling, 0 replies; 14+ messages in thread
From: Alex Kost @ 2015-09-15 12:21 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: guix-devel

Ludovic Courtès (2015-09-14 15:02 +0300) wrote:

> As future work ;-), it would be neat if tab and S-tab would do
> folding/unfolding of build phases as in Magit and Org.

Good idea!  I'll look at it.

I have pushed this patchset, thanks for reviewing it.  Also I have
pushed an "uninteresting" commit for putting faces into separate
customization groups ('guix-faces' and its subgroups).

-- 
Alex

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] emacs: Add commands to show/hide build log phases.
  2015-09-14 12:02   ` Ludovic Courtès
  2015-09-15 12:21     ` Alex Kost
@ 2015-09-15 18:56     ` Alex Kost
  2015-09-18  9:42       ` Ludovic Courtès
  1 sibling, 1 reply; 14+ messages in thread
From: Alex Kost @ 2015-09-15 18:56 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: guix-devel

[-- Attachment #1: Type: text/plain, Size: 215 bytes --]

Ludovic Courtès (2015-09-14 15:02 +0300) wrote:

> As future work ;-), it would be neat if tab and S-tab would do
> folding/unfolding of build phases as in Magit and Org.

Here it is.  Thanks for the idea!


[-- Attachment #2: 0001-emacs-Add-commands-to-show-hide-build-log-phases.patch --]
[-- Type: text/x-patch, Size: 5639 bytes --]

From f4fad1ab1c78a84ac3b2fdedba4850c5e589ce0d Mon Sep 17 00:00:00 2001
From: Alex Kost <alezost@gmail.com>
Date: Tue, 15 Sep 2015 21:27:44 +0300
Subject: [PATCH] emacs: Add commands to show/hide build log phases.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Suggested by Ludovic Courtès <ludo@gnu.org>.

* emacs/guix-build-log.el (guix-build-log-phase-end-regexp): New
  variable.
  (guix-build-log-phase-start, guix-build-log-phase-end,
  guix-build-log-phase-hide, guix-build-log-phase-show,
  guix-build-log-phase-hidden-p, guix-build-log-phase-toggle-function,
  guix-build-log-phase-toggle, guix-build-log-phase-toggle-all): New functions.
  (guix-build-log-mode-map): Add 'TAB'/'S-TAB' key bindings.
* doc/emacs.texi (Emacs Build Log): Document them.
---
 doc/emacs.texi          |  6 ++++
 emacs/guix-build-log.el | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/doc/emacs.texi b/doc/emacs.texi
index 33bdbd2..6777346 100644
--- a/doc/emacs.texi
+++ b/doc/emacs.texi
@@ -591,6 +591,12 @@ Move to the next build phase.
 @item M-p
 Move to the previous build phase.
 
+@item @key{TAB}
+Toggle (show/hide) the body of the current build phase.
+
+@item S-@key{TAB}
+Toggle (show/hide) the bodies of all build phases.
+
 @end table
 
 There is also @kbd{M-x guix-build-log-minor-mode} which also provides
diff --git a/emacs/guix-build-log.el b/emacs/guix-build-log.el
index 6d71521..6faa37c 100644
--- a/emacs/guix-build-log.el
+++ b/emacs/guix-build-log.el
@@ -144,6 +144,12 @@ STATE is a symbol denoting how a build phase was ended.  It should be
            (group (1+ digit)) " seconds")
      t)))
 
+(defvar guix-build-log-phase-end-regexp
+  ;; For efficiency, it is better to have a regexp for the general line
+  ;; of the phase end, then to call the function all the time.
+  (guix-build-log-phase-end-regexp)
+  "Regexp for the end line of a 'build' phase.")
+
 (defvar guix-build-log-font-lock-keywords
   `((,(guix-build-log-title-regexp 'start)
      (1 'guix-build-log-title-head)
@@ -177,9 +183,84 @@ STATE is a symbol denoting how a build phase was ended.  It should be
     (set-keymap-parent map special-mode-map)
     (define-key map (kbd "M-n") 'guix-build-log-next-phase)
     (define-key map (kbd "M-p") 'guix-build-log-previous-phase)
+    (define-key map (kbd "TAB") 'guix-build-log-phase-toggle)
+    (define-key map (kbd "<tab>") 'guix-build-log-phase-toggle)
+    (define-key map (kbd "<backtab>") 'guix-build-log-phase-toggle-all)
+    (define-key map [(shift tab)] 'guix-build-log-phase-toggle-all)
     map)
   "Keymap for `guix-build-log-mode' buffers.")
 
+(defun guix-build-log-phase-start (&optional with-header?)
+  "Return the start point of the current build phase.
+If WITH-HEADER? is non-nil, do not skip 'starting phase ...' header.
+Return nil, if there is no phase start before the current point."
+  (save-excursion
+    (end-of-line)
+    (when (re-search-backward guix-build-log-phase-start-regexp nil t)
+      (unless with-header? (end-of-line))
+      (point))))
+
+(defun guix-build-log-phase-end ()
+  "Return the end point of the current build phase."
+  (save-excursion
+    (beginning-of-line)
+    (when (re-search-forward guix-build-log-phase-end-regexp nil t)
+      (point))))
+
+(defun guix-build-log-phase-hide ()
+  "Hide the body of the current build phase."
+  (interactive)
+  (let ((beg (guix-build-log-phase-start))
+        (end (guix-build-log-phase-end)))
+    (when (and beg end)
+      ;; If not on the header line, move to it.
+      (when (and (> (point) beg)
+                 (< (point) end))
+        (goto-char (guix-build-log-phase-start t)))
+      (remove-overlays beg end 'invisible t)
+      (let ((o (make-overlay beg end)))
+        (overlay-put o 'evaporate t)
+        (overlay-put o 'invisible t)))))
+
+(defun guix-build-log-phase-show ()
+  "Show the body of the current build phase."
+  (interactive)
+  (let ((beg (guix-build-log-phase-start))
+        (end (guix-build-log-phase-end)))
+    (when (and beg end)
+      (remove-overlays beg end 'invisible t))))
+
+(defun guix-build-log-phase-hidden-p ()
+  "Return non-nil, if the body of the current build phase is hidden."
+  (let ((beg (guix-build-log-phase-start)))
+    (and beg
+         (cl-some (lambda (o)
+                    (overlay-get o 'invisible))
+                  (overlays-at beg)))))
+
+(defun guix-build-log-phase-toggle-function ()
+  "Return a function to toggle the body of the current build phase."
+  (if (guix-build-log-phase-hidden-p)
+      #'guix-build-log-phase-show
+    #'guix-build-log-phase-hide))
+
+(defun guix-build-log-phase-toggle ()
+  "Show/hide the body of the current build phase."
+  (interactive)
+  (funcall (guix-build-log-phase-toggle-function)))
+
+(defun guix-build-log-phase-toggle-all ()
+  "Show/hide the bodies of all build phases."
+  (interactive)
+  (save-excursion
+    ;; Some phases may be hidden, and some shown.  Whether to hide or to
+    ;; show them, it is determined by the state of the first phase here.
+    (goto-char (point-min))
+    (guix-build-log-next-phase)
+    (let ((fun (guix-build-log-phase-toggle-function)))
+      (while (re-search-forward guix-build-log-phase-start-regexp nil t)
+        (funcall fun)))))
+
 (defun guix-build-log-next-phase (&optional arg)
   "Move to the next build phase.
 With ARG, do it that many times.  Negative ARG means move
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] emacs: Add commands to show/hide build log phases.
  2015-09-15 18:56     ` [PATCH] emacs: Add commands to show/hide build log phases Alex Kost
@ 2015-09-18  9:42       ` Ludovic Courtès
  0 siblings, 0 replies; 14+ messages in thread
From: Ludovic Courtès @ 2015-09-18  9:42 UTC (permalink / raw)
  To: Alex Kost; +Cc: guix-devel

Alex Kost <alezost@gmail.com> skribis:

> From f4fad1ab1c78a84ac3b2fdedba4850c5e589ce0d Mon Sep 17 00:00:00 2001
> From: Alex Kost <alezost@gmail.com>
> Date: Tue, 15 Sep 2015 21:27:44 +0300
> Subject: [PATCH] emacs: Add commands to show/hide build log phases.
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> Suggested by Ludovic Courtès <ludo@gnu.org>.
>
> * emacs/guix-build-log.el (guix-build-log-phase-end-regexp): New
>   variable.
>   (guix-build-log-phase-start, guix-build-log-phase-end,
>   guix-build-log-phase-hide, guix-build-log-phase-show,
>   guix-build-log-phase-hidden-p, guix-build-log-phase-toggle-function,
>   guix-build-log-phase-toggle, guix-build-log-phase-toggle-all): New functions.
>   (guix-build-log-mode-map): Add 'TAB'/'S-TAB' key bindings.
> * doc/emacs.texi (Emacs Build Log): Document them.

Awesome, thank you!

Ludo’.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-09-18  9:42 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-13 19:39 [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends Alex Kost
2015-09-13 19:39 ` [PATCH 1/3] emacs: Display guix command errors in the minibuffer Alex Kost
2015-09-14  7:22   ` Alex Kost
2015-09-14 11:55     ` Ludovic Courtès
2015-09-14 11:54   ` Ludovic Courtès
2015-09-13 19:39 ` [PATCH 2/3] emacs: Add modes for viewing build logs Alex Kost
2015-09-14 12:01   ` Ludovic Courtès
2015-09-14 12:02   ` Ludovic Courtès
2015-09-15 12:21     ` Alex Kost
2015-09-15 18:56     ` [PATCH] emacs: Add commands to show/hide build log phases Alex Kost
2015-09-18  9:42       ` Ludovic Courtès
2015-09-13 19:39 ` [PATCH 3/3] emacs: Add "View build log" action to build popup Alex Kost
2015-09-14 12:03   ` Ludovic Courtès
2015-09-14 11:54 ` [PATCH 0/3] emacs: Add 'guix-build-log-mode' and friends Ludovic Courtès

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).