├── README.md
└── dtrace-script-mode.el
/README.md:
--------------------------------------------------------------------------------
1 | # DTrace mode
2 |
3 | [](http://melpa.org/#/dtrace-script-mode)
4 |
5 | [DTrace][dtrace] script mode.
6 |
7 | Originally written by **Alexander Kolbasov**.
8 |
9 | ## Install
10 |
11 | You can install it from [MELPA][melpa]:
12 |
13 | M-x package-install [RET] dtrace-script-mode [RET]
14 |
15 | Or manually: put the file `dtrace-script-mode.el` in a directory where
16 | Emacs can find it during startup.
17 |
18 | [dtrace]: https://en.wikipedia.org/wiki/DTrace
19 | [melpa]: http://melpa.org/
20 |
--------------------------------------------------------------------------------
/dtrace-script-mode.el:
--------------------------------------------------------------------------------
1 | ;;; dtrace-script-mode.el --- DTrace code editing commands for Emacs
2 |
3 | ;;; Commentary:
4 |
5 | ;; dtrace-script-mode: Mode for editing DTrace D language.
6 | ;;
7 | ;; You can add the following to your .emacs:
8 | ;;
9 | ;; (autoload 'dtrace-script-mode "dtrace-script-mode" () t)
10 | ;; (add-to-list 'auto-mode-alist '("\\.d\\'" . dtrace-script-mode))
11 | ;;
12 | ;; When loaded, runs all hooks from dtrace-script-mode-hook
13 | ;; You may try
14 | ;;
15 | ;; (add-hook 'dtrace-script-mode-hook 'imenu-add-menubar-index)
16 | ;; (add-hook 'dtrace-script-mode-hook 'font-lock-mode)
17 | ;;
18 | ;; Alexander Kolbasov
19 | ;;
20 |
21 | ;;
22 | ;; The dtrace-script-mode inherits from C-mode.
23 | ;; It supports imenu and syntax highlighting.
24 | ;;
25 |
26 | ;; $Id: dtrace-script-mode.el,v 1.4 2007/07/17 22:10:23 akolb Exp $
27 |
28 | ;;; This file is NOT part of GNU Emacs
29 | ;;
30 | ;; Copyright (c) 2007, Alexander Kolbasov
31 | ;; All rights reserved.
32 | ;;
33 | ;; Redistribution and use in source and binary forms, with or without
34 | ;; modification, are permitted provided that the following conditions
35 | ;; are met:
36 | ;; 1. Redistributions of source code must retain the above copyright
37 | ;; notice, this list of conditions and the following disclaimer.
38 | ;; 2. Redistributions in binary form must reproduce the above
39 | ;; copyright notice, this list of conditions and the following
40 | ;; disclaimer in the documentation and/or other materials provided
41 | ;; with the distribution.
42 | ;;
43 | ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 | ;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 | ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
46 | ;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
47 | ;; COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
48 | ;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49 | ;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50 | ;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 | ;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
52 | ;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 | ;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
54 | ;; OF THE POSSIBILITY OF SUCH DAMAGE.
55 |
56 | ;;; Code:
57 |
58 | (require 'cc-mode)
59 |
60 | (defvar dtrace-script-mode-map nil "Keymap used in D mode buffers.")
61 |
62 | ;;
63 | ;; Define dtrace-script-mode map unless it was defined already
64 | ;;
65 | ;; We just use c-mode-map with a few tweaks:
66 | ;;
67 | ;; M-C-a is bound to dtrace-script-mode-beginning-of-function
68 | ;; M-C-e is bound to dtrace-script-mode-end-of-function
69 | ;; M-C-h is bound to dtrace-script-mode-mark-function
70 | ;;
71 | ;; Ideally I would like to just replace whatever keybindings exist in c-mode-map
72 | ;; for the above with the new bindings. But up until recently, C-M-a was bound
73 | ;; to beginning-of-defun and not to c-beginning-of-defun and the same goes for
74 | ;; C-M-e, so we just define the new bindings.
75 | ;;
76 | (unless dtrace-script-mode-map
77 | (setq dtrace-script-mode-map
78 | (let ((map (c-make-inherited-keymap)))
79 | (define-key map "\e\C-a" 'dtrace-script-mode-beginning-of-function)
80 | (define-key map "\e\C-e" 'dtrace-script-mode-end-of-function)
81 | ;; Separate M-BS from C-M-h. The former should remain
82 | ;; backward-kill-word.
83 | (define-key map [(control meta h)] 'dtrace-script-mode-mark-function)
84 | map)))
85 |
86 | (defvar dtrace-script-mode-syntax-table
87 | (let ((st (make-syntax-table (standard-syntax-table))))
88 | (modify-syntax-entry ?/ "$" st)
89 | (modify-syntax-entry ?` "." st)
90 | (modify-syntax-entry ?: "." st)
91 | (modify-syntax-entry ?_ "w" st)
92 | (modify-syntax-entry ?$ "/" st)
93 | (modify-syntax-entry ?& "." st)
94 | (modify-syntax-entry ?* "." st)
95 | (modify-syntax-entry ?+ "." st)
96 | (modify-syntax-entry ?- "." st)
97 | (modify-syntax-entry ?< "." st)
98 | (modify-syntax-entry ?= "." st)
99 | (modify-syntax-entry ?> "." st)
100 | (modify-syntax-entry ?\\ "\\" st)
101 | (modify-syntax-entry ?/ ". 14" st)
102 | (modify-syntax-entry ?* ". 23" st)
103 | st)
104 | "Syntax table in use in `dtrace-script-mode' buffers.")
105 |
106 | ;;
107 | ;; Show probes, pragmas and inlines in imenu
108 | ;;
109 | (defvar dtrace-script-mode-imenu-generic-expression
110 | '(
111 | (nil "^\\s-*\\(\\sw+:.+\\)" 1 )
112 | (nil "\\s-*\\(BEGIN\\|END\\)" 1 )
113 | ("Pramgas" "^#pragma\\s-+D\\s-+\\(.+\\)" 1)
114 | ("Inlines" "\\s-*inline\\s-+\\(.*\\);" 1)
115 | )
116 | "Imenu generic expression for D mode. See `imenu-generic-expression'.")
117 |
118 | (defvar dtrace-script-mode-hook nil
119 | "Hooks to run when entering D mode.")
120 |
121 | ;;
122 | ;; Definition of various DTrace keywords for font-lock-mode
123 | ;;
124 | (defconst dtrace-script-mode-font-lock-keywords
125 | (eval-when-compile
126 | (list
127 | ;;
128 | ;; Function names.
129 | ;'("^\\(\\sw+\\):\\(\\sw+\\|:\\)?"
130 | ; (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
131 | ;;
132 | ;; Variable names.
133 | (cons (regexp-opt
134 | '(
135 | "egid" "euid" "gid" "pid" "pgid" "ppid" "projid" "sid"
136 | "taskid" "uid") 'words)
137 | 'font-lock-variable-name-face)
138 |
139 | ;;
140 | ;; DTrace built-in variables
141 | ;;
142 | (cons (regexp-opt
143 | '(
144 | "NULL"
145 | "arg0" "arg1" "arg2" "arg3" "arg4" "arg5" "arg6" "arg7"
146 | "arg8" "arg9"
147 | "args"
148 | "caller"
149 | "chip"
150 | "cpu"
151 | "curcpu"
152 | "curlwpsinfo"
153 | "curpsinfo"
154 | "curthread"
155 | "cwd"
156 | "epid"
157 | "errno"
158 | "execname"
159 | "gid"
160 | "id"
161 | "ipl"
162 | "lgrp"
163 | "pid"
164 | "ppid"
165 | "probefunc"
166 | "probemod"
167 | "probename"
168 | "probeprov"
169 | "pset"
170 | "pwd"
171 | "root"
172 | "self"
173 | "stackdepth"
174 | "target"
175 | "this"
176 | "tid"
177 | "timestamp"
178 | "uid"
179 | "uregs"
180 | "vtimestamp"
181 | "walltimestamp"
182 | ) 'words)
183 | 'font-lock-constant-face)
184 | ;;
185 | ;; DTrace functions.
186 | ;;
187 | (list (regexp-opt
188 | '(
189 | "alloca"
190 | "avg"
191 | "basename"
192 | "bcopy"
193 | "cleanpath"
194 | "commit"
195 | "copyin"
196 | "copyinstr"
197 | "copyinto"
198 | "copyout"
199 | "copyoutstr"
200 | "count"
201 | "dirname"
202 | "discard"
203 | "exit"
204 | "jstack"
205 | "lquantize"
206 | "max"
207 | "min"
208 | "msgdsize"
209 | "msgsize"
210 | "mutex_owned"
211 | "mutex_owner"
212 | "mutex_type_adaptive"
213 | "mutex_type_spin"
214 | "offsetof"
215 | "printa"
216 | "printf"
217 | "progenyof"
218 | "quantize"
219 | "raise"
220 | "rand"
221 | "rand"
222 | "rw_iswriter"
223 | "rw_read_held"
224 | "rw_write_held"
225 | "speculate"
226 | "speculation"
227 | "stack"
228 | "stop"
229 | "stringof"
230 | "strjoin"
231 | "strlen"
232 | "sum"
233 | "system"
234 | "trace"
235 | "tracemem"
236 | "trunc"
237 | "ustack"
238 | ) 'words)
239 | 1 'font-lock-builtin-face)
240 | ;;
241 | ;; Destructive actions
242 | ;;
243 | (list (regexp-opt
244 | '(
245 | "breakpoint"
246 | "chill"
247 | "panic"
248 | ) 'words)
249 | 1 'font-lock-warning-face)
250 | ;;
251 | ;; DTrace providers
252 | ;;
253 | (regexp-opt
254 | '(
255 | "BEGIN"
256 | "END"
257 | "dtrace"
258 | "dtrace"
259 | "entry"
260 | "fasttrap"
261 | "fbt"
262 | "fpuinfo"
263 | "io"
264 | "lockstat"
265 | "mib"
266 | "pid"
267 | "plockstat"
268 | "proc"
269 | "profile"
270 | "return"
271 | "sched"
272 | "sdt"
273 | "syscall"
274 | "sysinfo"
275 | "tick"
276 | "vm"
277 | "vminfo"
278 | "vtrace"
279 | ) 'words)))
280 | "Default expressions to highlight in D mode.")
281 |
282 | (defun dtrace-script-mode-beginning-of-function (&optional arg)
283 | "Move backward to next beginning-of-function, or as far as possible.
284 | With argument, repeat that many times; negative args move forward.
285 | Returns new value of point in all cases."
286 | (interactive "p")
287 | (or arg (setq arg 1))
288 | (if (< arg 0) (forward-char 1))
289 | (end-of-line)
290 | (and (/= arg 0)
291 | (re-search-backward "^[ \t]*\\([a-z_]+:.*\\|BEGIN\\|END\\)$"
292 | nil 'move arg)
293 | (goto-char (1- (match-end 0))))
294 | (beginning-of-line))
295 |
296 | (defun dtrace-script-mode-end-of-current-function ()
297 | "Locate the end of current D function"
298 | (dtrace-script-mode-beginning-of-function 1)
299 | ;; Now locate opening curly brace
300 | (search-forward "{")
301 | (backward-char 1)
302 | ;; Find closing curly brace
303 | (forward-list 1))
304 |
305 | ;; note: this routine is adapted directly from emacs perl-mode.el.
306 | ;; no bugs have been removed :-)
307 | (defun dtrace-script-mode-end-of-function (&optional arg)
308 | "Move forward to next end-of-function.
309 | The end of a function is found by moving forward from the beginning of one.
310 | With argument, repeat that many times; negative args move backward."
311 | (interactive "p")
312 | (or arg (setq arg 1))
313 | (let ((first t))
314 | (while (and (> arg 0) (< (point) (point-max)))
315 | (let ((pos (point)) npos)
316 | (while (progn
317 | (if (and first
318 | (progn
319 | (forward-char 1)
320 | (dtrace-script-mode-beginning-of-function 1)
321 | (not (bobp))))
322 | nil
323 | (or (bobp) (forward-char -1))
324 | (dtrace-script-mode-beginning-of-function -1))
325 | (setq first nil)
326 | (dtrace-script-mode-end-of-current-function)
327 | (skip-chars-forward " \t")
328 | (if (looking-at "[#\n]")
329 | (forward-line 1))
330 | (<= (point) pos))))
331 | (setq arg (1- arg)))
332 | (while (< arg 0)
333 | (let ((pos (point)))
334 | (dtrace-script-mode-end-of-function)
335 | (forward-line 1)
336 | (if (>= (point) pos)
337 | (if (progn (dtrace-script-mode-beginning-of-function 2) (not (bobp)))
338 | (progn
339 | (forward-list 1)
340 | (skip-chars-forward " \t")
341 | (if (looking-at "[#\n]")
342 | (forward-line 1)))
343 | (goto-char (point-min)))))
344 | (setq arg (1+ arg)))))
345 |
346 |
347 | (defun dtrace-script-mode-mark-function ()
348 | "Put mark at end of D function, point at beginning."
349 | (interactive)
350 | (push-mark (point))
351 | (dtrace-script-mode-end-of-function)
352 | (push-mark (point))
353 | (dtrace-script-mode-beginning-of-function))
354 |
355 |
356 | ;;;###autoload
357 | (define-derived-mode dtrace-script-mode c-mode "DTrace"
358 | "Major mode for editing DTrace code.
359 | This is much like C mode. Its keymap inherits from C mode's and it has the same
360 | variables for customizing indentation. It has its own abbrev table and its own
361 | syntax table.
362 | \\{dtrace-script-mode-map}
363 |
364 | Turning on DTrace mode runs `dtrace-script-mode-hook'."
365 | (setq imenu-generic-expression dtrace-script-mode-imenu-generic-expression)
366 | (setq font-lock-defaults '(dtrace-script-mode-font-lock-keywords nil nil ((?_ . "w")))))
367 |
368 | (provide 'dtrace-script-mode)
369 |
370 | ;;; dtrace-script-mode.el ends here
371 |
--------------------------------------------------------------------------------