├── README.md └── dtrace-script-mode.el /README.md: -------------------------------------------------------------------------------- 1 | # DTrace mode 2 | 3 | [![MELPA](http://melpa.org/packages/dtrace-script-mode-badge.svg)](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 | --------------------------------------------------------------------------------