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

Return to bug 744370