aboutsummary
aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorRichard van Velzen <rvanvelzen1@gmail.com>2015-08-07 14:11:50 +0200
committerRichard van Velzen <rvanvelzen1@gmail.com>2015-08-07 14:11:50 +0200
commitd7a4a4a462f5a9ff7a902fdf277701ddd9ae77d9 (patch)
tree824ab943b3891a4a315a310e3cc5984c31d13234 /test
parent759b3f7d6df1cecaefd987218373ce3db3646845 (diff)
parent65ee5af78ca3ec85dee8870a452845f1a4c871f7 (diff)
downloadtracifyjs-d7a4a4a462f5a9ff7a902fdf277701ddd9ae77d9.tar.gz
tracifyjs-d7a4a4a462f5a9ff7a902fdf277701ddd9ae77d9.zip
Merge pull request #729 from DrewML/keep_fnames_docs
Add keep_fnames compressor option to README.md
Diffstat (limited to 'test')
0 files changed, 0 insertions, 0 deletions
> 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
;;; 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:

(require 'guix-utils)

(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-minor-mode-activate t
  "If non-nil, then `guix-build-log-minor-mode' is automatically
activated in `shell-mode' buffers."
  :type 'boolean
  :group 'guix-build-log)

(defcustom guix-build-log-mode-hook '()
  "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+ (or 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)
     (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-common-map
  (let ((map (make-sparse-keymap)))
    (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)
  "Parent keymap for 'build-log' buffers.
For `guix-build-log-mode' this map is used as is.
For `guix-build-log-minor-mode' this map is prefixed with 'C-c'.")

(defvar guix-build-log-mode-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent
     map (make-composed-keymap (list guix-build-log-common-map)
                               special-mode-map))
    (define-key map (kbd "c") 'compilation-shell-minor-mode)
    (define-key map (kbd "v") 'view-mode)
    map)
  "Keymap for `guix-build-log-mode' buffers.")

(defvar guix-build-log-minor-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "C-c") guix-build-log-common-map)
    map)
  "Keymap for `guix-build-log-minor-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))
    (let ((fun (save-excursion
                 (re-search-forward guix-build-log-phase-start-regexp nil t)
                 (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
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)

\\{guix-build-log-minor-mode-map}"
  :init-value nil
  :lighter " Guix-Build-Log"
  :keymap guix-build-log-minor-mode-map
  :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)))

;;;###autoload
(defun guix-build-log-minor-mode-activate-maybe ()
  "Activate `guix-build-log-minor-mode' depending on
`guix-build-log-minor-mode-activate' variable."
  (when guix-build-log-minor-mode-activate
    (guix-build-log-minor-mode)))

(defun guix-build-log-find-file (file-or-url)
  "Open FILE-OR-URL in `guix-build-log-mode'."
  (guix-find-file-or-url file-or-url)
  (guix-build-log-mode))

;;;###autoload
(add-hook 'shell-mode-hook 'guix-build-log-minor-mode-activate-maybe)

;;;###autoload
(add-to-list 'auto-mode-alist
             ;; Regexp for log files (usually placed in /var/log/guix/...)
             (cons (rx "/guix/drvs/" (= 2 alnum) "/" (= 30 alnum)
                       "-" (+ (any alnum "-+.")) ".drv" string-end)
                   'guix-build-log-mode))

(provide 'guix-build-log)

;;; guix-build-log.el ends here