Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 744370 | Differences between
and this patch

Collapse All | Expand All

(-)a/ebuild-mode.el (-1 / +13 lines)
Lines 31-36 Link Here
31
(require 'font-lock)
31
(require 'font-lock)
32
(require 'easymenu)
32
(require 'easymenu)
33
(require 'skeleton)
33
(require 'skeleton)
34
(eval-and-compile
35
  (unless (featurep 'xemacs)
36
    (eval-when-compile (require 'cl-macs))
37
    (require 'ebuild-run-mode)))
34
38
35
39
36
;;; Compatibility code.
40
;;; Compatibility code.
Lines 362-367 Optional argument LIMIT restarts collection after that number of elements." Link Here
362
366
363
;;; Run ebuild command.
367
;;; Run ebuild command.
364
368
369
(eval-and-compile (when (featurep 'xemacs) (defalias 'cl-macrolet 'macrolet)))
370
365
(defun ebuild-run-command (command)
371
(defun ebuild-run-command (command)
366
  "Run ebuild COMMAND, with output to a compilation buffer."
372
  "Run ebuild COMMAND, with output to a compilation buffer."
367
  (interactive
373
  (interactive
Lines 375-381 Optional argument LIMIT restarts collection after that number of elements." Link Here
375
	;;(compilation-mode-hook (lambda () (setq truncate-lines t)))
381
	;;(compilation-mode-hook (lambda () (setq truncate-lines t)))
376
	(compilation-buffer-name-function
382
	(compilation-buffer-name-function
377
	 (list 'lambda '(mode) (concat "*ebuild " command "*"))))
383
	 (list 'lambda '(mode) (concat "*ebuild " command "*"))))
378
    (compile (format "ebuild %s %s" file command))))
384
    (cl-macrolet ((ebuild-run-compile-ignoring-mode-in-xemacs
385
                   (command mode)
386
                   (if (featurep 'xemacs)
387
                       `(compile ,command)
388
                     `(compile ,command ,mode))))
389
      (ebuild-run-compile-ignoring-mode-in-xemacs
390
       (format "ebuild %s %s" file command) 'ebuild-run-mode))))
379
391
380
392
381
;;; Modify package keywords.
393
;;; Modify package keywords.
(-)a/ebuild-run-mode.el (-1 / +300 lines)
Line 0 Link Here
0
- 
1
;;; ebuild-run-mode.el --- major mode for Compilation buffers running ebuild commands  -*- lexical-binding: t -*-
2
3
;; Copyright 2006-2020 Gentoo Authors
4
5
;; Author: Dima Akater <nuclearspace@gmail.com>
6
;; Maintainer: <emacs@gentoo.org>
7
;; Version: 1.51
8
;; Keywords: compilation, processes
9
10
;; This file is free software: you can redistribute it and/or modify
11
;; it under the terms of the GNU General Public License as published by
12
;; the Free Software Foundation, either version 2 of the License, or
13
;; (at your option) any later version.
14
15
;; This file is distributed in the hope that it will be useful,
16
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
;; GNU General Public License for more details.
19
20
;; You should have received a copy of the GNU General Public License
21
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
22
23
;;; Commentary:
24
25
;; This file should be ignored in app-xemacs/ebuild-mode ebuild
26
;; as the feature is not supported in XEmacs
27
28
;; Some issues:
29
;; - A naming scheme is needed that would follow names outlined in
30
;;   man ebuild(5) while still looking good in Lisp code
31
32
;;; Code:
33
34
;;; Dependencies:
35
36
(eval-when-compile (require 'cl-macs))
37
(eval-when-compile (require 'rx))
38
(require 'compile)
39
(require 'tramp)
40
41
42
;;; Macros:
43
44
(defmacro ebuild-macs-expand-file-namef (place filename)
45
  "Update PLACE (a directory) to the full path to FILENAME, relative to PLACE.
46
47
Useful in imperative algorithms involving movement across file system(s)."
48
  `(setf ,place (expand-file-name ,filename ,place)))
49
50
(eval-and-compile
51
  (when (and (version<= "24.0" emacs-version)
52
             ;; Strengthen these conditions as support for older Emacs drops.
53
             ;; Eventually, this will turn into (when nil ..);
54
             ;; then the whole `eval-and-compile' toplevel form can be dropped.
55
             (version<= emacs-version "25.3.1"))
56
57
    ;; We include dependencies from future Emacs verbatim,
58
    ;; namely from Emacs 28.0
59
60
    (defvar gensym-counter 0
61
      "Number used to construct the name of the next symbol created by `gensym'.")
62
63
    (defun gensym (&optional prefix)
64
      "Return a new uninterned symbol.
65
The name is made by appending `gensym-counter' to PREFIX.
66
PREFIX is a string, and defaults to \"g\"."
67
      (let ((num (prog1 gensym-counter
68
                   (setq gensym-counter (1+ gensym-counter)))))
69
        (make-symbol (format "%s%d" (or prefix "g") num))))
70
71
    (defun file-local-name (file)
72
      "Return the local name component of FILE.
73
This function removes from FILE the specification of the remote host
74
and the method of accessing the host, leaving only the part that
75
identifies FILE locally on the remote system.
76
The returned file name can be used directly as argument of
77
`process-file', `start-file-process', or `shell-command'."
78
      (or (file-remote-p file 'localname) file))
79
80
    (defun tramp-file-local-name (name)
81
      "Return the local name component of NAME.
82
This function removes from NAME the specification of the remote
83
host and the method of accessing the host, leaving only the part
84
that identifies NAME locally on the remote system.  If NAME does
85
not match `tramp-file-name-regexp', just `file-local-name' is
86
called.  The returned file name can be used directly as argument
87
of `process-file', `start-file-process', or `shell-command'."
88
      (or (and (tramp-tramp-file-p name)
89
               (string-match (nth 0 tramp-file-name-structure) name)
90
               (match-string (nth 4 tramp-file-name-structure) name))
91
          (tramp-compat-file-local-name name)))
92
  
93
    (defalias 'tramp-compat-file-local-name 'file-local-name)))
94
95
(defmacro with-file-buffer/ebuild-macs (filename &rest body)
96
  "Visit FILENAME unless already visited.  Set the buffer as current,
97
evaluate BODY forms.  Kill the buffer if it did not exist initially."
98
  ;; We want a with- name but we also need ebuild- namespace,
99
  ;; and with-ebuild-macs-file-buffer is ugly
100
  ;; while with-ebuild-file-buffer is misleading
101
  (declare (indent 1))
102
  (let ((o-o-filename (gensym "filename-"))
103
        (existing-buffer-g (gensym "existing-buffer-"))
104
        (buffer-g (gensym "buffer-")))
105
    `(let* ((,o-o-filename ,filename)
106
            (,existing-buffer-g (get-file-buffer ,o-o-filename))
107
            (,buffer-g (or ,existing-buffer-g (find-file ,o-o-filename))))
108
       (unwind-protect (with-current-buffer ,buffer-g ,@body)
109
         (unless ,existing-buffer-g (kill-buffer ,buffer-g))))))
110
111
(defmacro with-ebuild-compilation-buffer (buffer &rest body)
112
  "Evaluate BODY forms in buffer BUFFER, presumbaly compilation-mode buffer
113
where ebuild command is being executed.  The following variables are captured:
114
- COMMAND as is, e.g. ebuild frobnicate-99999999.ebuild ‹command›
115
- FILENAME passed to COMMAND as the first argument
116
- PACKAGE-VERSION: counterpart of ebuild's ${PV}, e.g. frobnicate-99999999
117
- EXPANDED-FILENAME: full path to FILENAME
118
- PORTAGE-HOME/CATEGORY/PV: full path to PACKAGE-VERSION dir in Portage build
119
                            directory."
120
  (declare (indent 1))
121
  `(with-current-buffer ,buffer
122
     (let ((command (car compilation-arguments)))
123
       (if (string-match (rx line-start
124
                             "ebuild" (one-or-more whitespace)
125
                             (group (one-or-more (not whitespace))))
126
                         command)
127
           (let* ((filename (match-string-no-properties 1 command))
128
                  (package-version (file-name-base filename))
129
                  (expanded-filename (expand-file-name filename))
130
                  (category (file-name-base
131
                             (ebuild-util-up-directory expanded-filename 2)))
132
                  (portage-home/category/pv
133
                   (ebuild-util-file-name-join
134
                    (ebuild-run-mode-tramp-portage-homedir)
135
                    (list category package-version))))
136
             ;; Arguably, it would be convenient to also provide access
137
             ;; to environment file and maybe other objects.
138
             ;; Things to consider prior to doing this:
139
             ;; - naming conventions: we should follow Gentoo naming scheme
140
             ;;   but this can be done in different ways, e.g., we could use
141
             ;;   elisp symbol `pv', or `PV', or `$PV', or `$pv'.
142
             ;;   Or we could have them all and give them different meaning
143
             ;; - permissions burden: depending on the method for determining
144
             ;;   relevant values, we might need to access Portage environment
145
             ;;   via tramp; such events should be isolated, at least,
146
             ;;   and minimized, at most.
147
             ,@body)
148
         (error "Does not look like ebuild command in %s; maybe `compilation-arguments' value is broken" (current-buffer))))))
149
150
151
;;; Utilities:
152
153
(defun ebuild-util-file-name-join (root names)
154
  "Join file name.
155
156
Examples:
157
158
ELISP> (ebuild-util-file-name-join \"/a/b\" '(\"c\" \"d\"))
159
\"/a/b/c/d\"
160
161
ELISP> (ebuild-util-file-name-join \"/a/b\" '(\"c\" \"d/\"))
162
\"/a/b/c/d/\"
163
164
ELISP> (ebuild-util-file-name-join \"/a/b\" '(\"c/\" \"d\"))
165
\"/a/b/c/d\"
166
167
ELISP> (ebuild-util-file-name-join \"/a/b/\" '(\"c\" \"d\"))
168
\"/a/b/c/d\""
169
  (dolist (name names root) (ebuild-macs-expand-file-namef root name)))
170
171
(defun ebuild-util-up-directory (root &optional n)
172
  "Return file name of directory N (1 by default) times upwards the directory
173
tree.
174
175
File name is returned without trailing slash so that `file-name-base' works
176
with it hassle-free.
177
178
Examples:
179
180
ELISP> (ebuild-util-up-directory \"/a/b/c/d\")
181
\"/a/b/c\"
182
183
ELISP> (ebuild-util-up-directory \"/a/b/c/d\" 2)
184
\"/a/b\"
185
186
ELISP> (ebuild-util-up-directory \"/a/b/c/d\" 3)
187
\"/a\""
188
  (cl-loop repeat (or n 1) do (ebuild-macs-expand-file-namef root ".."))
189
  root)
190
191
(defun ebuild-util-maybe-remove-quotes (string)
192
  "Remove quotes at the beginning and at the end of STRING, if present."
193
  (let ((length (length string)) long-enough first-quote-p)
194
    (cl-symbol-macrolet ((last-quote-p
195
                          (char-equal ?\" (aref string (1- length)))))
196
      (if (and (setq long-enough (> length 1))
197
               (setq first-quote-p (char-equal ?\" (aref string 0)))
198
               last-quote-p)
199
          (substring string 1 -1)
200
        (when long-enough
201
          (warn "Missing %s quote in string “%s”"
202
                (if first-quote-p 'trailing 'leading) string))
203
        string))))
204
205
206
;;; Main part:
207
208
(defun ebuild-run-mode-tramp-prefix ()
209
  "In `ebuild-run-mode', return tramp prefix necessary to access build files
210
and portage cache, as seen in `default-directory' of the buffer."
211
  (cl-ecase major-mode
212
    (ebuild-run-mode
213
     (substring-no-properties default-directory
214
                              0 (- (length (tramp-file-local-name
215
                                            default-directory)))))))
216
217
(defvar ebuild-run-mode-portage-homedir "/var/tmp/portage/"
218
  "Absolute path to main portage build directory.")
219
220
(defun ebuild-run-mode-tramp-portage-homedir ()
221
  "Path to main portage build directory, with all tramp prefixes necessary
222
to access build files."
223
  (concat (ebuild-run-mode-tramp-prefix) ebuild-run-mode-portage-homedir))
224
225
(defun ebuild-run-mode-tramp-default-current-sourcedir (&optional buffer)
226
  "For buffer BUFFER where ebuild command is being executed, return
227
corresponding default temporary build directory (default value for ${S}, as
228
specified e.g. in man ebuild(5)), derived from `compilation-arguments' of
229
BUFFER.
230
231
The retuned directory name is prefixed with appropriate `tramp' prefix."
232
  (with-ebuild-compilation-buffer (or buffer (current-buffer))
233
    (file-name-as-directory
234
     (ebuild-util-file-name-join portage-home/category/pv
235
                                 (list "work" package-version)))))
236
237
(defun ebuild-run-mode-tramp-current-sourcedir (&optional buffer)
238
  "For buffer BUFFER where ebuild command is being executed, return
239
corresponding temporary build directory (counterpart of ${S}), derived from
240
`compilation-arguments' of BUFFER.
241
242
The returned directory name is prefixed with appropriate `tramp' prefix."
243
  (with-ebuild-compilation-buffer (or buffer (current-buffer))
244
    (file-name-as-directory
245
     (concat
246
      (ebuild-run-mode-tramp-prefix)
247
      (ebuild-util-maybe-remove-quotes
248
       (let ((env-file
249
              (ebuild-util-file-name-join portage-home/category/pv
250
                                          (list "temp"
251
                                                "environment"))))
252
         (with-file-buffer/ebuild-macs env-file
253
           (save-excursion
254
             (goto-char (point-min))
255
             (re-search-forward
256
              (rx line-start "declare -x S="
257
                  (group (one-or-more (not whitespace)))
258
                  line-end)))
259
           (match-string-no-properties 1))))))))
260
261
(defun ebuild-run-mode-goto-error ()
262
  "Visit the source for the error message at point.
263
Use this command in `ebuild-run-mode' buffers."
264
  (interactive)
265
  (let ((default-directory
266
          (or (ebuild-run-mode-tramp-current-sourcedir)
267
              (progn
268
                (warn "Current Portage Sourcedir is unknown.")
269
                (ebuild-run-mode-tramp-default-current-sourcedir)))))
270
    (compile-goto-error)))
271
272
(defvar ebuild-run-font-lock-keywords
273
  '(("^Ebuild \\(finished\\).*"
274
     (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
275
     (1 compilation-info-face))
276
    ("^>>> Source \\(compiled\\).*"
277
     (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
278
     (1 compilation-info-face))
279
    ("^Ebuild \\(exited abnormally\\|interrupt\\|killed\\|terminated\\|segmentation fault\\)\\(?:.*with code \\([0-9]+\\)\\)?.*"
280
     (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
281
     (1 compilation-error-face)
282
     (2 compilation-error-face nil t)))
283
  "Substrings to highlight in `ebuild-run-mode'.")
284
285
(eval-and-compile
286
  (when (version= "27.1" emacs-version)
287
    (defvar ebuild-run-mode nil "Set to t when `ebuild-run-mode' is enabled.")))
288
289
(define-compilation-mode ebuild-run-mode "Ebuild"
290
  "Major mode for non-interactive buffers spawned by `ebuild-run-command'."
291
  (setq buffer-read-only t)
292
  (font-lock-add-keywords nil ebuild-run-font-lock-keywords)
293
  (setq-local ebuild-run-mode t))
294
295
(define-key ebuild-run-mode-map [remap compile-goto-error]
296
  #'ebuild-run-mode-goto-error)
297
298
(provide 'ebuild-run-mode)
299
300
;;; ebuild-run-mode.el ends here

Return to bug 744370