├── README.md └── js-doc.el /README.md: -------------------------------------------------------------------------------- 1 | # js-doc 2 | Insert JSDoc style comment easily in Emacs 3 | 4 | ## Installation 5 | 1. Put `js-doc.el` somewhere in your emacs load path. 6 | 2. Add a line below to your .emacs file: 7 | 8 | ```scheme 9 | (require 'js-doc) 10 | ``` 11 | 12 | ## Example 13 | Paste the codes below into your configuration file and you: 14 | 15 | 1. insert function document by pressing `Ctrl + c, i` 16 | 2. insert `@tag` easily by pressing `@` in the JSDoc style comment 17 | 18 | If you want to see the tag description, just input the next command 19 | M-x js-doc-describe-tag 20 | 21 | ## Configuration 22 | ```scheme 23 | (setq js-doc-mail-address "your email address" 24 | js-doc-author (format "your name <%s>" js-doc-mail-address) 25 | js-doc-url "url of your website" 26 | js-doc-license "license name") 27 | 28 | (add-hook 'js2-mode-hook 29 | #'(lambda () 30 | (define-key js2-mode-map "\C-ci" 'js-doc-insert-function-doc) 31 | (define-key js2-mode-map "@" 'js-doc-insert-tag))) 32 | ``` 33 | -------------------------------------------------------------------------------- /js-doc.el: -------------------------------------------------------------------------------- 1 | ;;; js-doc.el --- Insert JsDoc style comment easily 2 | 3 | ;; Author: mooz 4 | ;; Version: 0.0.5 5 | ;; Keywords: document, comment 6 | ;; URL: https://github.com/mooz/js-doc 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation; either version 2, or (at your option) 11 | ;; any later version. 12 | ;; 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | ;; 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program; if not, write to the Free Software 20 | ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 | 22 | ;;; Commentary: 23 | 24 | ;; Installation: 25 | ;; put `js-doc.el' somewhere in your emacs load path 26 | ;; add a line below to your .emacs file 27 | ;; (require 'js-doc) 28 | 29 | ;; Example: 30 | ;; paste the codes below into your .emacs.el file and you can 31 | ;; 32 | ;; 1. insert function document by pressing Ctrl + c, i 33 | ;; 2. insert @tag easily by pressing @ in the JsDoc style comment 34 | ;; 35 | ;; (setq js-doc-mail-address "your email address" 36 | ;; js-doc-author (format "your name <%s>" js-doc-mail-address) 37 | ;; js-doc-url "url of your website" 38 | ;; js-doc-license "license name") 39 | ;; 40 | ;; (add-hook 'js2-mode-hook 41 | ;; #'(lambda () 42 | ;; (define-key js2-mode-map "\C-ci" 'js-doc-insert-function-doc) 43 | ;; (define-key js2-mode-map "@" 'js-doc-insert-tag))) 44 | ;; 45 | ;; If you want to see the tag description, just input the next command 46 | ;; M-x js-doc-describe-tag 47 | 48 | ;;; Code: 49 | 50 | (require 'iswitchb) 51 | 52 | ;;; Custom: 53 | (defgroup js-doc nil 54 | "Insert JsDoc style comment easily." 55 | :group 'comment 56 | :prefix "js-doc") 57 | 58 | ;; Variables 59 | (defcustom js-doc-mail-address "" 60 | "Author's E-mail address." 61 | :group 'js-doc) 62 | 63 | (defcustom js-doc-author "" 64 | "Author of the source code." 65 | :group 'js-doc) 66 | 67 | (defcustom js-doc-license "" 68 | "License of the source code." 69 | :group 'js-doc) 70 | 71 | (defcustom js-doc-url "" 72 | "Author's Home page URL." 73 | :group 'js-doc) 74 | 75 | ;; from jsdoc-toolkit wiki 76 | ;; http://code.google.com/p/jsdoc-toolkit/wiki/TagReference 77 | (defvar js-doc-all-tag-alist 78 | '(("abstract" . "Identifies members that must be implemented (or overridden) by objects that inherit the member. Syntax: @abstrac") 79 | ("access" . "Specifies the access level of a member. @access ") 80 | ("alias" . "Causes JSDoc to treat all references to a member as if the member had a different name. Syntax: @alias ") 81 | ("augments" . "Indicates this class uses another class as its \"base.\" Syntax: @augments ") 82 | ("author" . "Indicates the author of the code being documented. Syntax: @author []") 83 | ("arg" . "Deprecated synonym for @param. Syntax: @arg [{}] [- ]") 84 | ("argument" . "Deprecated synonym for @param. Syntax: @argument [{}] [- ]") 85 | ("borrows" . "Document that class's member as if it were a member of this class. Syntax: @borrows as ") 86 | ("callback" . "Provides information about a callback function that can be passed to other functions, including the callback's parameters and return value. Syntax: @callback ") 87 | ("class" . "Marks a function as being a constructor, meant to be called with the new keyword to return an instance. Syntax: @class [ ]") 88 | ("classdesc" . "Provides a description for a class, separate from the constructor function's description. Syntax: @classdesc ") 89 | ("const" . "Synonym of @constant. Syntax: @const [ ]") 90 | ("constant" . "Indicates that a variable's value is a constant. Syntax: @constant [ ]") 91 | ("constructor" . "Synonym of @class. Syntax: @constructor [ ]") 92 | ("constructs" . "Indicates that a particular function will be used to construct instances of that class. Syntax: @constructs []") 93 | ("copyright" . "Indicates copyright information in a file overview comment. Use this tag in combination with the @file tag. Syntax: @copyright ") 94 | ("default" . "Describes the assigned value of a symbol (default value). Syntax: @default []") 95 | ("deprecated" . "Indicates that use of the symbol is no longer supported. Syntax: @deprecated []") 96 | ("desc" . "Synonym of @description. Syntax: @desc ") 97 | ("description" . "Provides a general description of a symbol (untagged first-line is used if none is provide). It may include HTML markup or Markdown if the plugin is enabled. Syntax: @description ") 98 | ("emits" . "Synonym of @fires. Syntax: @emits #[event:]") 99 | ("enum" . "Documents a collection of static properties whose values are all of the same type. An enum is similar to a collection of properties, except that an enum is documented in its own doc comment, whereas properties are documented within the doc comment of their container. Often this tag is used with @readonly, as an enum typically represents a collection of constants. Syntax: @enum []") 100 | ("event" . "Document an event that can be fired. A typical event is represented by an object with a defined set of properties. Once an event is documented, @fires may be used to indicate that a method fires that event. @listen may also be used to indicate that a symbol listens for the event. Syntax: @event #[event:]") 101 | ("example" . "Provides an example of how to use a documented item. The text that follows this tag will be displayed as highlighted code. Syntax: @example ") 102 | ("exception" . "Synonym of @throws. Syntax: @exception free-form description | @exception {} | @exception {} free-form description") 103 | ("exports" . "Documents that a JavaScript module exports anything other than the \"exports\" object or the \"module.exports\" property. Syntax: @exports ") 104 | ("extends" . "Synonym for @augments. Syntax: @extends ") 105 | ("external" . "Identifies a class, namespace, or module that is defined outside of the current package. Syntax: @external ") 106 | ("field" . "Indicate that the variable refers to a non-function.") 107 | ("file" . "Provides a description for a file. Use the tag in a JSDoc comment at the beginning of the file. Syntax: @file ") 108 | ("fileOverview" . "Synonym of @file. Syntax: @fileOverview ") 109 | ("fires" . "indicates that a method can fire a specified type of event when it is called. @event tag is used to document the event's content. Syntax: @fires #[event:]") 110 | ("func" . "Synonym of @function. Syntax: @funct []") 111 | ("function" . "Indicate that the variable refers to a function. Syntax: @function []") 112 | ("global" . "Specifies that a symbol should appear in the documentation as a global symbol. JSDoc ignores the symbol's actual scope within the source file. This tag is especially useful for symbols that are defined locally, then assigned to a global symbol. Syntax: @global") 113 | ("host" . "Synonym of @external. Syntax: @host ") 114 | ("ignore" . "Indicates that a symbol in your code should never appear in the documentation. This tag takes precedence over all others. Syntax: @ignore") 115 | ("implements" . "Indicates that a symbol implements an interface. The @implements tag should be at the top-level symbol that implements the interface (for example, a constructor function). @implements tag dont't need to be attached to each member of the implementation (for example, the implementation's instance methods). Syntax: @implements {typeExpression}") 116 | ("inheritdoc" . "Indicates that a symbol should inherit its documentation from its parent class. Any other tags included in the JSDoc comment will be ignored. The presence of the @inheritdoc tag implies the presence of the @override tag. Syntax: @inheritdoc") 117 | ("inner" . "Marks a symbol as an inner member of its parent symbol (and so is also private). This means it can be referred to by \"Parent~Child\". Using @inner will override a doclet's default scope. Syntax: @inner") 118 | ("instance" . "Marks a symbol as an instance member of its parent symbol. This means it can be referred to by \"Parent#Child\". Using @instance will override a doclet's default scope. Syntax: @instance") 119 | ("interface" . "Marks a symbol as an interface that other symbols can implement (children). Syntax: @interface []") 120 | ("kind" . "Documents what kind of symbol is being documented (for example, a class or a module). The kind of symbol differs from a symbol's type (for example, string or boolean). Syntax: @kind ") 121 | ("lends" . "Documents all the members of an object literal as if they were members of a symbol with the given name. Syntax: @lends ") 122 | ("license" . "Identifies the software license that applies to any portion of your code. Syntax: @license ") 123 | ("link" . "Creates link to the namepath or URL specified. Using {@link} tag, link text can be provided using one of several different formats. Syntax: {@link namepathOrURL} | [link text]{@link namepathOrURL} | {@link namepathOrURL|link text} | {@link namepathOrURL link text (after space)}") 124 | ("linkcode" . "Synonym of @link, but forces the link's text to use a monospace font.") 125 | ("linkplain" . "Synonym of @link, but forces the link's text to appear as normal text, without a monospace font.") 126 | ("listens" . "Indicates that a symbol listens for the specified event. The @event tag is uded to document the event's content. Syntax: @listens ") 127 | ("member" . "Identifies any member that does not have a more specialized kind, such as \"class\", \"function\", or \"constant\". A member can optionally have a type as well as a name. Syntax: @member [] []") 128 | ("memberOf" . "Identifies a member symbol that belongs to a parent symbol. By default, the @memberof tag documents member symbols as static members. For inner and instance members, scoping punctuation can be used after the namepath, or the @inner or @instance tag can be added. Syntax: @memberof ") 129 | ("memberOf!" . "Synonym of @memberOf, except it forces the object to be documented as belonging to a specific parent even if it appears to have a different parent.") 130 | ("method" . "Synonym of @function. Syntax: @method []") 131 | ("mixes" . "Indicates that the current object mixes in all the members from OtherObjectPath, which is a @mixin. Syntax: @mixes ") 132 | ("mixin" . "Provides functionality that is intended to be added to other objects. If desired, the @mixin tag may be added to indicate that an object is a mixin. The @mixes tag may than be added to objects that use the mixin. Syntax: @mixin []") 133 | ("module" . "Marks the current file as being its own module. All symbols in the file are assumed to be members of the module unless documented otherwise. Syntax: @module [[{}] ]") 134 | ("name" . "Forces JSDoc to associate the remainder of the JSDoc comment with the given name, ignoring all surrounding code. This tag is best used in \"virtual comments\" for symbols that are not readily visible in the code, such as methods that are generated at runtime. Syntax: @name ") 135 | ("namespace" . "Indicates that an object creates a namespace for its members. Syntax: @namespace [{}] ") 136 | ("override" . "Indicates that a symbol overrides a symbol with the same name in a parent class. Syntax: @override") 137 | ("overview" . "Synonym of @file. Syntax: @overview ") 138 | ("param" . "Provides the name, type, and description of a function parameter Syntax: @param [{}] [- ]") 139 | ("private" . "Marks a symbol as private, or not meant for general use (-p command line option to include these). Synonym of \"@access private\". Syntax: @private") 140 | ("property" . "Is a way to easily document a list of static properties of a class, namespace or other object within its doclet.") 141 | ("protected" . "Marks a symbol as protected. Typically, this tag indicates that a symbol is only available, or should only be used, within the current module (-a/--access command-line option to include these). Synonym of \"@access protected\". Syntax: @protected") 142 | ("public" . "Indicates that a symbol should be documented as if it were public. By default, JSDoc treats all symbols as public. It doesn't affect the symbol scope. The @instance, @static, and @global tags may be used to change a symbol's scope. Synonym of \"@access public\". Syntax: @public") 143 | ("readonly" . "Indicates that a symbol is intended to be read-only. Note this is for the purpose of documentation only. Syntax: @readonly") 144 | ("requires" . "Documents that a module is needed to use this code. Syntax: @requires ") 145 | ("return" . "Synonym of @returns. Syntax: @return {} [} [ | @see ") 148 | ("since" . "Indicates that a class, method, or other symbol was added in a specific version. Syntax: @since ") 149 | ("static" . "ndicates that a symbol is contained within a parent and can be accessed without instantiating the parent. Using the @static tag will override a symbol's default scope. Syntax: @static") 150 | ("summary" . "Is a shorter version of the full description. It can be added to any doclet. Syntax: @summary Summary goes here.") 151 | ("this" . "Indicates what the this keyword refers to when used within another symbol. Syntax: @this ") 152 | ("throws" . "Documents an error that a function might throw. It may be used more than once. Syntax: @throws free-form description | @throws {} | @throws {} free-form description") 153 | ("todo" . "Documents tasks to be completed for some part of code. It may be used more than once. Syntax: @todo text describing thing to do.") 154 | ("tutorial" . "Inserts a link to a tutorial file that is provided as part of the documentation. It may be used more than once. It can be used inline. Syntax: @tutorial tutorialID") 155 | ("type" . "Provides a type expression identifying the type of value that a symbol may contain, or the type of value returned by a function. Syntax: @type {typeName}") 156 | ("typedef" . "Is useful for documenting custom types, particularly to refer to them repeatedly. These types can then be used within other tags expecting a type, such as @type or @param. Syntax: @typedef [] ") 157 | ("var" . "Synonym of @member. Syntax: @var [] []") 158 | ("variation" . "Helps distinguish between different symbols with the same longname. Syntax: @variation ") 159 | ("version" . "Documents the version of an item. The text following the @version tag will be used to denote the version of the item. Syntax: @version ") 160 | ("virtual" . "Synonym for @abstract.")) 161 | "JsDoc tag list 162 | This list contains tag name and its description") 163 | 164 | (defvar js-doc-file-doc-lines 165 | '(js-doc-top-line 166 | " * @fileOverview\n" 167 | " * @name %F\n" 168 | " * @author %a\n" 169 | " * @license %l\n" 170 | js-doc-bottom-line) 171 | "JsDoc style file document format. 172 | When the `js-doc-insert-file-doc' is called, 173 | each lines in a list will be formatted by `js-doc-format-string' 174 | and inserted to the top of current buffer.") 175 | 176 | (defvar js-doc-format-string-alist 177 | '(("%F" . (buffer-name)) 178 | ("%P" . (buffer-file-name)) 179 | ("%a" . js-doc-author) 180 | ("%l" . js-doc-license) 181 | ("%d" . (current-time-string)) 182 | ("%p" . js-doc-current-parameter-name) 183 | ("%f" . js-doc-current-function-name)) 184 | "Format and value pair 185 | Format will be replaced its value in `js-doc-format-string'") 186 | 187 | ;;; Lines 188 | 189 | ;; %F => file name 190 | ;; %P => file path 191 | ;; %a => author name 192 | ;; %d => current date 193 | ;; %p => parameter name 194 | ;; %f => function name 195 | 196 | (defcustom js-doc-top-line "/**\n" 197 | "top line of the js-doc style comment." 198 | :group 'js-doc) 199 | 200 | (defcustom js-doc-description-line" * \n" 201 | "description line." 202 | :group 'js-doc) 203 | 204 | (defcustom js-doc-bottom-line " */\n" 205 | "bottom line." 206 | :group 'js-doc) 207 | 208 | ;; formats for function-doc 209 | 210 | (defcustom js-doc-parameter-line " * @param {} %p\n" 211 | "parameter line. 212 | %p will be replaced with the parameter name." 213 | :group 'js-doc) 214 | 215 | (defcustom js-doc-return-line " * @returns {} \n" 216 | "return line." 217 | :group 'js-doc) 218 | 219 | (defcustom js-doc-throw-line " * @throws {} \n" 220 | "bottom line." 221 | :group 'js-doc) 222 | 223 | ;; ========== Regular expresisons ========== 224 | 225 | (defcustom js-doc-return-regexp "return " 226 | "regular expression of return 227 | When the function body contains this pattern, 228 | js-doc-return-line will be inserted" 229 | :group 'js-doc) 230 | 231 | (defcustom js-doc-throw-regexp "throw" 232 | "regular expression of throw 233 | When the function body contains this pattern, 234 | js-doc-throw-line will be inserted" 235 | :group 'js-doc) 236 | 237 | (defcustom js-doc-document-regexp "^\[ \]*\\*[^//]" 238 | "regular expression of JsDoc comment 239 | When the string ahead of current point matches this pattarn, 240 | js-doc regards current state as in JsDoc style comment" 241 | :group 'js-doc) 242 | 243 | ;;; Main codes: 244 | 245 | ;; from smart-compile.el 246 | (defun js-doc-format-string (fmt) 247 | "Format given string and return its result 248 | 249 | %F => file name 250 | %P => file path 251 | %a => author name 252 | %d => current date 253 | %p => parameter name 254 | %f => function name 255 | " 256 | (let ((case-fold-search nil)) 257 | (dolist (pair js-doc-format-string-alist fmt) 258 | (when (string-match (car pair) fmt) 259 | (setq fmt (replace-match (eval (cdr pair)) t nil fmt)))))) 260 | 261 | (defun js-doc-tail (list) 262 | "Return the last cons cell of the list" 263 | (if (cdr list) 264 | (js-doc-tail (cdr list)) 265 | (car list))) 266 | 267 | (defun js-doc-pick-symbol-name (str) 268 | "Pick up symbol-name from str" 269 | (js-doc-tail (delete "" (split-string str "[^a-zA-Z0-9_$]")))) 270 | 271 | (defun js-doc-block-has-regexp (begin end regexp) 272 | "Return t when regexp matched the current buffer string between begin-end" 273 | (save-excursion 274 | (goto-char begin) 275 | (and t 276 | (re-search-forward regexp end t 1)))) 277 | 278 | ;;;###autoload 279 | (defun js-doc-insert-file-doc () 280 | "Insert specified-style comment top of the file" 281 | (interactive) 282 | (goto-char 1) 283 | (dolist (line-format js-doc-file-doc-lines) 284 | (insert (js-doc-format-string (eval line-format))))) 285 | 286 | (defun js-doc--beginning-of-defun () 287 | ;; prevent odd behaviour of beginning-of-defun 288 | ;; when user call this command in the certain comment, 289 | ;; the cursor skip the current function and go to the 290 | ;; outside block 291 | (end-of-line) 292 | (while (or (js-doc-in-comment-p (point)) 293 | (js-doc-blank-line-p (point))) 294 | (forward-line -1) 295 | (end-of-line)) 296 | (end-of-line) 297 | (beginning-of-defun)) 298 | 299 | (defun js-doc--parse-function-params (from to) 300 | (mapcar #'js-doc-pick-symbol-name 301 | (split-string (buffer-substring-no-properties from to) ","))) 302 | 303 | (defun js-doc--function-doc-metadata () 304 | "Parse the function's metadata for use with JsDoc. 305 | The point should be at the beginning of the function, 306 | which is accomplished with js-doc--beginning-of-defun." 307 | (interactive) 308 | ;; Parse function info 309 | (let ((metadata '()) 310 | (params '()) 311 | from 312 | to 313 | begin 314 | end) 315 | (save-excursion 316 | (setq from (search-forward "(" nil t) 317 | to (1- (search-forward ")" nil t))) 318 | 319 | ;; Now we got the string between () 320 | (when (> to from) 321 | (add-to-list 322 | 'metadata 323 | `(params . ,(js-doc--parse-function-params from to)))) 324 | 325 | ;; begin-end contains whole function body 326 | (setq begin (search-forward "{" nil t) 327 | end (scan-lists (1- begin) 1 0)) 328 | 329 | ;; return / throw 330 | (when (js-doc-block-has-regexp begin end js-doc-return-regexp) 331 | (add-to-list 'metadata `(returns . t))) 332 | 333 | (when (js-doc-block-has-regexp begin end js-doc-throw-regexp) 334 | (add-to-list 'metadata `(throws . t))) 335 | 336 | metadata))) 337 | 338 | ;;;###autoload 339 | (defun js-doc-insert-function-doc () 340 | "Insert JsDoc style comment of the function 341 | The comment style can be custimized via `customize-group js-doc'" 342 | (interactive) 343 | (js-doc--beginning-of-defun) 344 | 345 | ;; Parse function info 346 | (let ((metadata (js-doc--function-doc-metadata)) 347 | (document-list '()) 348 | (description-marker (make-marker)) 349 | from) 350 | (save-excursion 351 | ;; params 352 | (dolist (param (cdr (assoc 'params metadata))) 353 | (setq js-doc-current-parameter-name param) 354 | (add-to-list 'document-list 355 | (js-doc-format-string js-doc-parameter-line) t)) 356 | ;; return / throw 357 | (when (assoc 'returns metadata) 358 | (add-to-list 'document-list 359 | (js-doc-format-string js-doc-return-line) t)) 360 | (when (assoc 'throws metadata) 361 | (add-to-list 'document-list 362 | (js-doc-format-string js-doc-throw-line) t)) 363 | ;; end 364 | (add-to-list 'document-list 365 | (js-doc-format-string js-doc-bottom-line) t) 366 | ;; Insert the document 367 | (setq from (point)) ; for indentation 368 | 369 | ;; put document string into document-list 370 | (insert (js-doc-format-string js-doc-top-line)) 371 | (insert (js-doc-format-string js-doc-description-line)) 372 | 373 | (set-marker description-marker (1- (point))) 374 | 375 | (dolist (document document-list) 376 | (insert document)) 377 | 378 | ;; Indent 379 | (indent-region from (point))) 380 | 381 | (goto-char description-marker) 382 | (set-marker description-marker nil))) 383 | 384 | ;;;###autoload 385 | (defun js-doc-insert-function-doc-snippet () 386 | "Insert JsDoc style comment of the function with yasnippet." 387 | (interactive) 388 | 389 | (with-eval-after-load 'yasnippet 390 | (js-doc--beginning-of-defun) 391 | 392 | (let ((metadata (js-doc--function-doc-metadata)) 393 | (field-count 1)) 394 | (yas-expand-snippet 395 | (concat 396 | js-doc-top-line 397 | " * ${1:Function description.}\n" 398 | (mapconcat (lambda (param) 399 | (format 400 | " * @param {${%d:Type of %s}} %s - ${%d:Parameter description.}\n" 401 | (incf field-count) 402 | param 403 | param 404 | (incf field-count))) 405 | (cdr (assoc 'params metadata)) 406 | "") 407 | (when (assoc 'returns metadata) 408 | (format 409 | " * @returns {${%d:Return Type}} ${%d:Return description.}\n" 410 | (incf field-count) 411 | (incf field-count))) 412 | (when (assoc 'throws metadata) 413 | (format 414 | " * @throws {${%d:Exception Type}} ${%d:Exception description.}\n" 415 | (incf field-count) 416 | (incf field-count))) 417 | js-doc-bottom-line))))) 418 | 419 | ;; http://www.emacswiki.org/emacs/UseIswitchBuffer 420 | (defun js-doc-icompleting-read (prompt collection) 421 | (let ((iswitchb-make-buflist-hook 422 | #'(lambda () 423 | (setq iswitchb-temp-buflist collection)))) 424 | (iswitchb-read-buffer prompt nil nil))) 425 | 426 | (defun js-doc-make-tag-list () 427 | (let ((taglist '())) 428 | (dolist (tagpair js-doc-all-tag-alist) 429 | (add-to-list 'taglist (car tagpair))) 430 | (reverse taglist))) 431 | 432 | (defun js-doc-blank-line-p (p) 433 | "Return t when the line at the current point is blank line" 434 | (save-excursion (eql (progn (beginning-of-line) (point)) 435 | (progn (end-of-line) (point))))) 436 | 437 | (defun js-doc-in-comment-p (p) 438 | "Return t when the point p is in the comment" 439 | (save-excursion 440 | (let (begin end) 441 | (beginning-of-line) 442 | (setq begin (point)) 443 | (end-of-line) 444 | (setq end (point)) 445 | (or (js-doc-block-has-regexp begin end "//") 446 | (js-doc-block-has-regexp begin end "/\\*"))))) 447 | 448 | (defun js-doc-in-document-p (p) 449 | "Return t when the point p is in JsDoc document" 450 | ;; Method 1 :: just search for the JsDoc 451 | (save-excursion 452 | (goto-char p) 453 | (and (search-backward "/**" nil t) 454 | (not (search-forward "*/" p t))))) 455 | 456 | ;;;###autoload 457 | (defun js-doc-insert-tag () 458 | "Insert a JsDoc tag interactively." 459 | (interactive) 460 | (insert "@") 461 | (when (js-doc-in-document-p (point)) 462 | (let ((tag (completing-read "Tag: " (js-doc-make-tag-list) 463 | nil nil nil nil nil))) 464 | (unless (string-equal tag "") 465 | (insert tag " "))))) 466 | 467 | ;;;###autoload 468 | (defun js-doc-describe-tag () 469 | "Describe the JsDoc tag" 470 | (interactive) 471 | (let ((tag (completing-read "Tag: " (js-doc-make-tag-list) 472 | nil t (thing-at-point 'word) nil nil)) 473 | (temp-buffer-show-hook #'(lambda () 474 | (fill-region 0 (buffer-size)) 475 | (fit-window-to-buffer)))) 476 | (unless (string-equal tag "") 477 | (with-output-to-temp-buffer "JsDocTagDescription" 478 | (princ (format "@%s\n\n%s" 479 | tag 480 | (cdr (assoc tag js-doc-all-tag-alist)))))))) 481 | 482 | (provide 'js-doc) 483 | 484 | ;;; js-doc.el ends here 485 | 486 | --------------------------------------------------------------------------------