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

Return to bug 744370