]> gitweb.factorcode.org Git - factor.git/blob - misc/fuel/fuel-edit.el
FUEL: New option fuel-xref-follow-link-method (current buffer, new window or frame).
[factor.git] / misc / fuel / fuel-edit.el
1 ;;; fuel-edit.el -- utilities for file editing
2
3 ;; Copyright (C) 2009 Jose Antonio Ortega Ruiz
4 ;; See http://factorcode.org/license.txt for BSD license.
5
6 ;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
7 ;; Keywords: languages, fuel, factor
8 ;; Start date: Mon Jan 05, 2009 21:16
9
10 ;;; Comentary:
11
12 ;; Locating and opening factor source and documentation files.
13
14 ;;; Code:
15
16 (require 'fuel-completion)
17 (require 'fuel-eval)
18 (require 'fuel-base)
19
20 (require 'etags)
21
22 \f
23 ;;; Customization
24
25 (defmacro fuel-edit--define-custom-visit (var group doc)
26   `(defcustom ,var nil
27      ,doc
28      :group ',group
29      :type '(choice (const :tag "Other window" window)
30                     (const :tag "Other frame" frame)
31                     (const :tag "Current window" nil))))
32
33 (fuel-edit--define-custom-visit
34  fuel-edit-word-method fuel
35  "How the new buffer is opened when invoking \\[fuel-edit-word-at-point]")
36
37 \f
38 ;;; Auxiliar functions:
39
40 (defun fuel-edit--visit-file (file method)
41   (cond ((eq method 'window) (find-file-other-window file))
42         ((eq method 'frame) (find-file-other-frame file))
43         (t (find-file file))))
44
45 (defun fuel-edit--looking-at-vocab ()
46   (save-excursion
47     (fuel-syntax--beginning-of-defun)
48     (looking-at "USING:\\|USE:")))
49
50 (defun fuel-edit--try-edit (ret)
51   (let* ((err (fuel-eval--retort-error ret))
52          (loc (fuel-eval--retort-result ret)))
53     (when (or err (not loc) (not (listp loc)) (not (stringp (car loc))))
54       (error "Couldn't find edit location"))
55     (unless (file-readable-p (car loc))
56       (error "Couldn't open '%s' for read" (car loc)))
57     (fuel-edit--visit-file (car loc) fuel-edit-word-method)
58     (goto-line (if (numberp (cadr loc)) (cadr loc) 1))))
59
60 (defun fuel-edit--read-vocabulary-name (refresh)
61   (let* ((vocabs (fuel-completion--vocabs refresh))
62          (prompt "Vocabulary name: "))
63     (if vocabs
64         (completing-read prompt vocabs nil nil nil fuel-edit--vocab-history)
65       (read-string prompt nil fuel-edit--vocab-history))))
66
67 (defun fuel-edit--edit-article (name)
68   (let ((cmd `(:fuel* (,name fuel-get-article-location) "fuel" t)))
69     (fuel-edit--try-edit (fuel-eval--send/wait cmd))))
70
71 \f
72 ;;; Editing commands:
73
74 (defvar fuel-edit--word-history nil)
75 (defvar fuel-edit--vocab-history nil)
76 (defvar fuel-edit--previous-location nil)
77
78 (defun fuel-edit-vocabulary (&optional refresh vocab)
79   "Visits vocabulary file in Emacs.
80 When called interactively, asks for vocabulary with completion.
81 With prefix argument, refreshes cached vocabulary list."
82   (interactive "P")
83   (let* ((vocab (or vocab (fuel-edit--read-vocabulary-name refresh)))
84          (cmd `(:fuel* (,vocab fuel-get-vocab-location) "fuel" t)))
85     (fuel-edit--try-edit (fuel-eval--send/wait cmd))))
86
87 (defun fuel-edit-word (&optional arg)
88   "Asks for a word to edit, with completion.
89 With prefix, only words visible in the current vocabulary are
90 offered."
91   (interactive "P")
92   (let* ((word (fuel-completion--read-word "Edit word: "
93                                            nil
94                                            fuel-edit--word-history
95                                            arg))
96          (cmd `(:fuel* ((:quote ,word) fuel-get-edit-location))))
97     (fuel-edit--try-edit (fuel-eval--send/wait cmd))))
98
99 (defun fuel-edit-word-at-point (&optional arg)
100   "Opens a new window visiting the definition of the word at point.
101 With prefix, asks for the word to edit."
102   (interactive "P")
103   (let* ((word (or (and (not arg) (fuel-syntax-symbol-at-point))
104                    (fuel-completion--read-word "Edit word: ")))
105          (cmd `(:fuel* ((:quote ,word) fuel-get-edit-location)))
106          (marker (and (not arg) (point-marker))))
107     (if (and (not arg) (fuel-edit--looking-at-vocab))
108         (fuel-edit-vocabulary nil word)
109       (fuel-edit--try-edit (fuel-eval--send/wait cmd)))
110     (when marker (ring-insert find-tag-marker-ring marker))))
111
112 (defun fuel-edit-word-doc-at-point (&optional arg word)
113   "Opens a new window visiting the documentation file for the word at point.
114 With prefix, asks for the word to edit."
115   (interactive "P")
116   (let* ((word (or word
117                    (and (not arg) (fuel-syntax-symbol-at-point))
118                    (fuel-completion--read-word "Edit word: ")))
119          (cmd `(:fuel* ((:quote ,word) fuel-get-doc-location)))
120          (marker (and (not arg) (point-marker))))
121     (condition-case nil
122         (fuel-edit--try-edit (fuel-eval--send/wait cmd))
123       (error
124        (message "Documentation for '%s' not found" word)
125        (when (and (eq major-mode 'factor-mode)
126                   (y-or-n-p (concat "No documentation found. "
127                                     "Do you want to open the vocab's "
128                                     "doc file? ")))
129          (when marker (ring-insert find-tag-marker-ring marker))
130          (find-file-other-window
131           (format "%s-docs.factor"
132                   (file-name-sans-extension (buffer-file-name)))))))))
133
134 (defun fuel-edit-pop-edit-word-stack ()
135   "Pop back to where \\[fuel-edit-word-at-point] or \\[fuel-edit-word-doc-at-point]
136 was last invoked."
137   (interactive)
138   (condition-case nil
139       (pop-tag-mark)
140     (error "No previous location for find word or vocab invokation")))
141
142 (defvar fuel-edit--buffer-history nil)
143
144 (defun fuel-switch-to-buffer (&optional method)
145   "Switch to any of the existing Factor buffers, with completion."
146   (interactive)
147   (let ((buffer (completing-read "Factor buffer: "
148                                  (remove (buffer-name)
149                                          (mapcar 'buffer-name (buffer-list)))
150                                  '(lambda (s) (string-match "\\.factor$" s))
151                                  t
152                                  nil
153                                  fuel-edit--buffer-history)))
154     (cond ((eq method 'window) (switch-to-buffer-other-window buffer))
155           ((eq method 'frame) (switch-to-buffer-other-frame buffer))
156           (t (switch-to-buffer buffer)))))
157
158 (defun fuel-switch-to-buffer-other-window ()
159   "Switch to any of the existing Factor buffers, in other window."
160   (interactive)
161   (fuel-switch-to-buffer 'window))
162
163 (defun fuel-switch-to-buffer-other-frame ()
164   "Switch to any of the existing Factor buffers, in other frame."
165   (interactive)
166   (fuel-switch-to-buffer 'frame))
167
168 \f
169 (provide 'fuel-edit)
170 ;;; fuel-edit.el ends here