58
58
; ; auto
59
59
; ; none
60
60
61
-
61
+ (defvar scimax-lp-consider-all nil
62
+ " If non-nil consider all src blocks when making tags." )
62
63
63
64
(defvar scimax-lp-etags-language-map
64
65
'((" emacs-lisp" . " lisp" )
@@ -70,12 +71,13 @@ Each cons cell is (src-block lang . etags language)")
70
71
71
72
72
73
(defun scimax-lp-tangle-p ()
73
- " Return t if the block should be tangled.
74
+ " Return absolute tangle filename if the block should be tangled.
74
75
That means :tangle is not no."
75
- (and (org-in-src-block-p )
76
- (not (string= " no"
77
- (cdr (assq :tangle
78
- (nth 2 (org-babel-get-src-block-info 'light ))))))))
76
+ (when (org-in-src-block-p )
77
+ (let ((tangle (cdr (assq :tangle (nth 2 (org-babel-get-src-block-info 'light ))))))
78
+ ; ; Note this might be a "yes"
79
+ (when (not (string= " no" tangle))
80
+ (expand-file-name tangle)))))
79
81
80
82
81
83
(defun scimax-lp-update-lang-tags (org-file lang )
@@ -93,7 +95,9 @@ should make this a safe operation."
93
95
(let ((open (find-buffer-visiting org-file)))
94
96
(with-current-buffer (find-file-noselect org-file)
95
97
(save-buffer )
96
- (let* ((content (buffer-string )))
98
+
99
+ (let* ((content (buffer-string ))
100
+ (inhibit-read-only t ))
97
101
; ; This has potential for disaster since it deletes the buffer! I think
98
102
; ; this is pretty safe, but you should be prepared for disaster. If
99
103
; ; there is any error in this, I think it undoes the buffer damage.
@@ -102,7 +106,7 @@ should make this a safe operation."
102
106
(while (and (not (eobp )))
103
107
(if (and (org-in-src-block-p )
104
108
(string= lang (car (org-babel-get-src-block-info 'light )))
105
- (scimax-lp-tangle-p))
109
+ (or ( scimax-lp-tangle-p) scimax-lp-consider-all ))
106
110
(let* ((src (org-element-context ))
107
111
(end (org-element-property :end src))
108
112
(len (length (buffer-substring
@@ -138,44 +142,62 @@ should make this a safe operation."
138
142
(unless open (kill-buffer (find-buffer-visiting org-file))))))
139
143
140
144
141
- (defun scimax-lp-generate-tags ()
145
+ (defvar scimax-lp-update-tags-always t
146
+ " If non-nil, update TAGS file whenever the org file is newer." )
147
+
148
+
149
+ (defun scimax-lp-generate-tags (&optional refresh )
142
150
" Generate a list of tags from org-files and visit the tag-file.
143
151
This will attempt to get tags for every language defined in
144
152
`scimax-lp-etags-language-map' ."
145
- (interactive )
146
- (save-buffer )
147
- (when (file-exists-p " TAGS" ) (delete-file " TAGS" ))
148
- (let* ((current-point (point ))
149
- (org-files (f-entries
150
- " ."
151
- (lambda (f ) (f-ext? f " org" )) t ))
152
- langs)
153
- (loop for org-file in org-files do
154
- (setq langs '())
155
- (org-babel-map-src-blocks org-file
156
- (pushnew lang langs :test 'string= ))
157
- (loop for lang in langs do
158
- (scimax-lp-update-lang-tags org-file lang)))
159
- (goto-char current-point)
160
- (let ((tag-buffer (or (find-buffer-visiting " TAGS" )
161
- (find-file-noselect " TAGS" ))))
153
+ (interactive " P" )
154
+ (when (and (eq major-mode 'org-mode )
155
+ (or scimax-lp-update-tags-always refresh))
156
+ (save-buffer )
157
+ ; ; (when (file-exists-p "TAGS") (delete-file "TAGS"))
158
+ (let* ((current-point (point ))
159
+ (org-files (f-entries
160
+ " ."
161
+ (lambda (f ) (f-ext? f " org" )) t ))
162
+ langs)
163
+ (loop for org-file in org-files do
164
+ (setq langs '())
165
+ (org-babel-map-src-blocks org-file
166
+ (pushnew lang langs :test 'string= ))
167
+ (loop for lang in langs do
168
+ (scimax-lp-update-lang-tags org-file lang)))
169
+ (goto-char current-point)))
170
+ (let ((tag-buffer (or (find-buffer-visiting " TAGS" )
171
+ (find-file-noselect " TAGS" ))))
172
+ (when tag-buffer
162
173
(with-current-buffer tag-buffer
163
174
(revert-buffer :ignore-auto :noconfirm )
164
175
(visit-tags-table " TAGS" )))))
165
176
166
177
178
+ ; ; I had to make this small function for a reason I don't understand. I could
179
+ ; ; not use the `scimax-lp-generate-tags' function directly without an error
180
+ ; ; related to number of arguments.
181
+ (defun scimax-lp-xref-advice (arg )
182
+ " :before advice for xref-find-definitions to automatically make tags."
183
+ (scimax-lp-generate-tags))
184
+
185
+ (advice-add 'xref-find-definitions :before #'scimax-lp-xref-advice )
186
+
167
187
(defun scimax-lp-signature-doc ()
168
188
" Get signature and docstring for thing at point.
169
189
For emacs-lisp this should work for defun and defvar. For other
170
190
languages you will get see the definition line."
171
191
(interactive )
172
192
(when (org-in-src-block-p )
173
193
; ; This is a weird issue. It seems like read moves the point inside the
174
- ; ; save-window-excursion, so I save the point here to move back later.
194
+ ; ; save-window-excursion and doesn't restore it, so I save the point here to
195
+ ; ; move back later.
175
196
(let ((current-point (point )))
176
197
(save-window-excursion
177
- (let* ((fname (symbol-name (symbol-at-point )))
178
- (p (xref-find-definitions fname)))
198
+ (let* ((sname (symbol-name (symbol-at-point )))
199
+ (p (condition-case nil (xref-find-definitions sname)
200
+ (error nil ))))
179
201
(cond
180
202
((string= (get-char-property (point ) 'lang ) 'emacs-lisp )
181
203
(cond
@@ -184,22 +206,66 @@ languages you will get see the definition line."
184
206
(args (nth 2 def))
185
207
(n3 (nth 3 def))
186
208
(docstring (if (stringp n3) n3 " " )))
187
- (message " %s : (%s ) \" %s \" " fname args docstring)))
209
+ (message " %s : (%s ) \" %s \" " sname args docstring)))
188
210
((looking-at " (defvar" )
189
211
(let* ((def (read (current-buffer )))
190
212
(var (nth 1 def))
191
213
(val (nth 2 def))
192
214
(ds (nth 3 def)))
193
215
(message " %s =%s \" %s \" " var val ds)))))
194
216
(t
195
- ; ; This assumes that xref-find-definitions moved the point. I don't
196
- ; ; know any better way to get reasonable information about the
197
- ; ; definition. You need parsing to get it in general.
217
+ ; ; if p is nil it means nothing was found, so we try searching
218
+ ; ; instead. this is not a very sophisticated search yet, we should
219
+ ; ; search until we are in the right kind of code block. This will
220
+ ; ; fail on things not defined in the current file, e.g. variable
221
+ ; ; names that are imported.
222
+ (unless p
223
+ (goto-char (point-min ))
224
+ (re-search-forward sname))
225
+ ; ; Then, we show the context
198
226
(message (buffer-substring
199
227
(line-beginning-position )
200
228
(line-end-position )))))))
201
229
(goto-char current-point))))
202
230
231
+ ; ; * Advice on org-babel-load-file
232
+
233
+ ; ; The idea here is to replace all definitions of the tangled files with the
234
+ ; ; org-file in `load-history' so that describe-function/variable points to them
235
+ ; ; instead.
236
+
237
+ (defun scimax-lp-modify-load-history (&rest args )
238
+ " Modify the load-history to point all tangled files to compile."
239
+ (interactive )
240
+ (let* ((file (nth 0 args))
241
+ (compile (nth 1 args))
242
+ (open (find-buffer-visiting file))
243
+ tf
244
+ (tangle-files '()))
245
+ (org-babel-map-src-blocks file
246
+ ; ; I am not sure if it matters if the
247
+ (setq tf (cdr (assq :tangle (nth 2 (org-babel-get-src-block-info 'light )))))
248
+ (cond
249
+ ((string= " yes" tf)
250
+ (setq tf (concat (file-name-sans-extension (buffer-file-name )) " .el" )))
251
+ ((not (string= " no" tf))
252
+ (setq tf (expand-file-name tf)))
253
+ (t
254
+ (setq tf nil )))
255
+ (when tf
256
+ (setq tf (concat tf (if compile " c" " " )))
257
+ (pushnew (expand-file-name tf) tangle-files :test #'string= )))
258
+ ; ; now modify the load-history
259
+ (mapc (lambda (tf )
260
+ (when (car (assoc tf load-history))
261
+ (setf (car (assoc tf load-history)) (expand-file-name file))))
262
+ tangle-files)
263
+ (unless open (kill-buffer open))))
264
+
265
+ (advice-add 'org-babel-load-file :after #'scimax-lp-modify-load-history )
266
+
267
+ ; ; (advice-remove 'org-babel-load-file 'scimax-lp-modify-load-history)
268
+
203
269
204
270
(provide 'scimax-literate-programming )
205
271
0 commit comments