├── .gitignore ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── LICENSE ├── Main.sublime-menu ├── README.md ├── ruby.sublime-completions ├── yardoc-auto-complete.sublime-macro ├── yardoc.py └── yardoc.sublime-settings /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | { "keys": ["ctrl+enter"], "command": "yardoc"} 2 | -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["ctrl+enter"], "command": "yardoc"} 3 | ] 4 | -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["ctrl+enter"], "command": "yardoc"}, 3 | { "keys": ["enter"], "command": "addhashtag", "context": 4 | [ 5 | { "key": "preceding_text", "operator": "regex_contains", "operand": "^(|[ ]+)\\#", "match_all": false }, 6 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 7 | ] 8 | }, 9 | { "keys": ["@"], "command": "run_macro_file", "args": {"file": "Packages/yardoc/yardoc-auto-complete.sublime-macro"}, "context": 10 | [ 11 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, 12 | { "key": "preceding_text", "operator": "regex_contains", "operand": "^(|[ ]+)\\#(|[ ]+)", "match_all": false }, 13 | { "key": "selector", "operator": "equal", "operand" : "comment", "match_all": true } 14 | ] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2013 Revath S Kumar 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "edit", 4 | "children": 5 | [ 6 | {"id": "wrap"}, 7 | { "command": "yardoc" } 8 | ] 9 | }, 10 | { 11 | "id": "preferences", 12 | "children": 13 | [ 14 | { 15 | "caption": "Package Settings", 16 | "mnemonic": "P", 17 | "id": "package-settings", 18 | "children": 19 | [ 20 | { 21 | "caption": "Sublime-Yardoc", 22 | "children": 23 | [ 24 | { 25 | "command": "open_file", "args": 26 | { 27 | "file": "${packages}/yardoc/yardoc.sublime-settings" 28 | }, 29 | "caption": "Settings – Default" 30 | }, 31 | { 32 | "command": "open_file", "args": 33 | { 34 | "file": "${packages}/User/yardoc.sublime-settings" 35 | }, 36 | "caption": "Settings – User" 37 | }, 38 | { "caption": "-" }, 39 | { 40 | "command": "open_file", 41 | "args": { 42 | "file": "${packages}/yardoc/Default (Windows).sublime-keymap", 43 | "platform": "Windows" 44 | }, 45 | "caption": "Key Bindings – Default" 46 | }, 47 | { 48 | "command": "open_file", 49 | "args": { 50 | "file": "${packages}/yardoc/Default (OSX).sublime-keymap", 51 | "platform": "OSX" 52 | }, 53 | "caption": "Key Bindings – Default" 54 | }, 55 | { 56 | "command": "open_file", 57 | "args": { 58 | "file": "${packages}/yardoc/Default (Linux).sublime-keymap", 59 | "platform": "Linux" 60 | }, 61 | "caption": "Key Bindings – Default" 62 | }, 63 | { 64 | "command": "open_file", 65 | "args": { 66 | "file": "${packages}/User/Default (Windows).sublime-keymap", 67 | "platform": "Windows" 68 | }, 69 | "caption": "Key Bindings – User" 70 | }, 71 | { 72 | "command": "open_file", 73 | "args": { 74 | "file": "${packages}/User/Default (OSX).sublime-keymap", 75 | "platform": "OSX" 76 | }, 77 | "caption": "Key Bindings – User" 78 | }, 79 | { 80 | "command": "open_file", 81 | "args": { 82 | "file": "${packages}/User/Default (Linux).sublime-keymap", 83 | "platform": "Linux" 84 | }, 85 | "caption": "Key Bindings – User" 86 | }, 87 | { "caption": "-" } 88 | ] 89 | } 90 | ] 91 | } 92 | ] 93 | } 94 | ] 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## SublimeText package for generating Yardoc 2 | 3 | ### Installation 4 | 5 | ### With Package Control 6 | The easiest way to install this is with [Package Control](http://wbond.net/sublime\_packages/package\_control). 7 | 8 | * If you just went and installed Package Control, you probably need to restart Sublime Text 2 before doing this next bit. 9 | * Bring up the Command Palette (Command+Shift+p on OS X, Control+Shift+p on Linux/Windows). 10 | * Select "Package Control: Install Package" (it'll take a few seconds) 11 | * Select Yardoc when the list appears. 12 | 13 | Package Control will automatically keep Yardoc up to date with the latest version. 14 | 15 | ### Without Package Control 16 | 17 | Go to your Sublime Text 2 **Packages** directory and clone the repository using the command below: 18 | 19 | git clone git@github.com:revathskumar/sublime-yardoc.git yardoc 20 | 21 | Don't forget to keep updating it, though! 22 | 23 | ### Usage 24 | 25 | Pressing **ctrl+enter** on the line of the method definition 26 | ```ruby 27 | def hello a, b 28 | 29 | end 30 | ``` 31 | 32 | results 33 | 34 | ```ruby 35 | # 36 | # [hello description] 37 | # @param a [type] [description] 38 | # @param b [type] [description] 39 | # 40 | # @return [type] [description] 41 | def hello a, b 42 | 43 | end 44 | ``` 45 | 46 | ![Method yardoc](https://lh6.googleusercontent.com/-C9V-e0vzDq0/UERyoS0I4oI/AAAAAAAAG48/M2cptkMfmgA/s458/123.gif) 47 | 48 | Pressing **ctrl+enter** on the line of the class definition 49 | 50 | ```ruby 51 | class Hello 52 | 53 | end 54 | ``` 55 | 56 | results 57 | 58 | ```ruby 59 | # 60 | # [class description] 61 | # 62 | # @author 63 | # 64 | class Hello 65 | 66 | end 67 | ``` 68 | 69 | ### Settings 70 | 71 | Two settings are available: 72 | 73 | ```json 74 | // Determines if empty comment lines have a trailing space 75 | "trailing_spaces": false, 76 | // Add an initial empty line at the beginning of the comment 77 | "initial_empty_line": false 78 | ``` 79 | 80 | ### License 81 | 82 | ``` 83 | The MIT License (MIT) 84 | Copyright (c) 2013 Revath S Kumar 85 | 86 | Permission is hereby granted, free of charge, to any person obtaining a copy of 87 | this software and associated documentation files (the "Software"), to deal in the 88 | Software without restriction, including without limitation the rights to use, 89 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 90 | Software, and to permit persons to whom the Software is furnished to do so, 91 | subject to the following conditions: 92 | 93 | The above copyright notice and this permission notice shall be included in all 94 | copies or substantial portions of the Software. 95 | 96 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 97 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 98 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 99 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 100 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 101 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 102 | ``` 103 | -------------------------------------------------------------------------------- /ruby.sublime-completions: -------------------------------------------------------------------------------- 1 | { 2 | "scope": "source.ruby comment", 3 | "completions": 4 | [ 5 | { "trigger" : "@abstract" ,"contents": "@abstract ${1:[description]}"}, 6 | { "trigger" : "@api","contents": "@api ${1:description}"}, 7 | { "trigger" : "@attr","contents": "@attr ${1:name} [${2:type}] ${3:[description]}"}, 8 | { "trigger" : "@attr_reader","contents": "@attr_reader [${1:type}] ${2:[description]}"}, 9 | { "trigger" : "@attr_writer","contents": "@attr_writer [${1:type}] ${2:[description]}"}, 10 | { "trigger" : "@author","contents": "@author ${1:author}"}, 11 | { "trigger" : "@deprecated","contents": "@deprecated ${1:[description]}"}, 12 | { "trigger" : "@example","contents": "@example ${1:[description]}"}, 13 | { "trigger" : "@note","contents": "@note ${1:description}"}, 14 | { "trigger" : "@option","contents": "@option ${1:name} [${2:type}] ${3:option_key} (${4:default_value}) ${5:[description]}"}, 15 | { "trigger" : "@overload","contents": "@overload ${1:method}(${2:[parameters]})"}, 16 | { "trigger" : "@param","contents": "@param ${1:name} [${2:type}] ${3:[description]}"}, 17 | { "trigger" : "@private","contents": ""}, 18 | { "trigger" : "@raise","contents": "@raise [${1:type}] ${2:[description]}"}, 19 | { "trigger" : "@return","contents": "@return [${1:type}] ${2:[description]}"}, 20 | { "trigger" : "@see","contents": "@see ${1:name} ${2:[description]}"}, 21 | { "trigger" : "@since","contents": "@since ${1:version}"}, 22 | { "trigger" : "@todo","contents": "@todo ${1:description}"}, 23 | { "trigger" : "@version","contents": "@version ${1:description}"}, 24 | { "trigger" : "@yield","contents": "@yield [${1:[parameters]}] ${2:[description]}"}, 25 | { "trigger" : "@yieldparam","contents": "@yieldparam ${1:name} [${2:type}] ${3:[description]}"}, 26 | { "trigger" : "@yieldreturn","contents": "@yieldreturn [${1:type}] ${2:[description]}"}, 27 | 28 | // Directives 29 | { "trigger" : "@attribute", "contents": "@!attribute [${1:r|w|rw}] ${2:attribute_name}"}, 30 | { "trigger" : "@endgroup", "contents": "@!endgroup"}, 31 | { "trigger" : "@group", "contents": "@!group ${1:description}"}, 32 | { "trigger" : "@macro", "contents": "@!macro [${1:attach|new}] ${2:[optional_name]}"}, 33 | { "trigger" : "@method", "contents": "@!method ${1:method_signature(parameters)}"}, 34 | { "trigger" : "@parse", "contents": "@!parse [${1:language}] ${2:code}"}, 35 | { "trigger" : "@scope", "contents": "@!scope ${1:class|instance}"}, 36 | { "trigger" : "@visibility", "contents": "@!visibility ${1:public|protected|private}"} 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /yardoc-auto-complete.sublime-macro: -------------------------------------------------------------------------------- 1 | [ 2 | {"command": "insert_snippet", "args": {"contents": "@"}}, 3 | {"command": "auto_complete"} 4 | ] 5 | -------------------------------------------------------------------------------- /yardoc.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sublime Yardoc 3 | by Revath S Kumar 4 | https://github.com/revathskumar/sublime-yardoc 5 | """ 6 | import sublime 7 | import sublime_plugin 8 | import re 9 | import os 10 | 11 | 12 | class YardocCommand(sublime_plugin.TextCommand): 13 | 14 | def load_config(self): 15 | self.settings = {} 16 | settings = sublime.load_settings('yardoc.sublime-settings') 17 | for setting in ['trailing_spaces', 'initial_empty_line', 'trailing_empty_line']: 18 | if settings.get(setting) is None: 19 | continue 20 | self.settings[setting] = settings.get(setting) 21 | self.trailing_spaces = "" 22 | if settings.get('trailing_spaces'): 23 | self.trailing_spaces = " " 24 | 25 | def trailing_spaces(self): 26 | return self.trailing_spaces 27 | 28 | def counter(self): 29 | count = 0 30 | while True: 31 | count += 1 32 | yield(count) 33 | 34 | def set_tab_index(self, doc): 35 | if doc: 36 | tabIndex = self.counter() 37 | for index, outputLine in enumerate(doc): 38 | doc[index] = re.sub("(\\$\\{)\\d+(:[^}]+\\})", lambda m: "%s%d%s" % (m.group(1), tabIndex.next() if hasattr(tabIndex, 'next') else next(tabIndex), m.group(2)), outputLine) 39 | return doc 40 | 41 | def reset_cursor(self, point, force=False): 42 | self.view.sel().clear() 43 | if (self.view.rowcol(point)[0] == self.view.rowcol(point + 1)[0]) or force: 44 | self.view.sel().add(sublime.Region(self.point - 1)) 45 | else: 46 | self.view.sel().add(sublime.Region(self.point)) 47 | 48 | def write(self, view, str): 49 | if None == str: 50 | str = self.line_ending() 51 | else: 52 | str = self.line_ending() + str 53 | view.run_command( 54 | 'insert_snippet', { 55 | 'contents': str.decode('utf-8') if hasattr(str, 'decode') else bytes(str, 'utf-8').decode('utf-8') 56 | } 57 | ) 58 | 59 | def run(self, edit): 60 | self.load_config() 61 | point = self.view.sel()[0].end() 62 | self.point = self.view.text_point(self.view.rowcol(point)[0],0) 63 | scope = self.view.scope_name(point) 64 | if not re.search("source\\.ruby", scope): 65 | self.view.insert(edit, point, self.line_ending()) 66 | return 67 | if not self.check_doc(self.point): 68 | self.view.insert(edit, point, self.line_ending()) 69 | return 70 | line = self.read_line(point + 1) 71 | doc = self.compose_doc(line, edit) 72 | self.reset_cursor(point) 73 | if None == doc: 74 | # we were maybe at the end of a valid line, run it here again 75 | line = self.read_line(point) 76 | doc = self.compose_doc(line, edit) 77 | self.reset_cursor(point,True) 78 | 79 | self.write(self.view, doc) 80 | 81 | def check_doc(self, point): 82 | current_line = self.read_line(point) 83 | params_match = re.search('#\s+@return |#\s+@param |#\s+@author |# ?|#\s+@', current_line) 84 | if not params_match: 85 | return True 86 | return False 87 | 88 | def get_author(self): 89 | if os.name == 'nt': 90 | username = os.environ['USERNAME'] 91 | else: 92 | username = os.environ['USER'] 93 | author = "${1:[" + username + "]}" 94 | return ["#" + self.trailing_spaces, "# @author " + author, "#" + self.trailing_spaces] 95 | 96 | def line_ending(self): 97 | ending = "\n" 98 | if(self.view.line_endings() == "Windows"): 99 | ending = "\r\n" 100 | return ending 101 | 102 | def format_lines(self, indent, lines): 103 | ending = self.line_ending() 104 | lines = self.set_tab_index(lines) 105 | return indent + (ending + indent).join(lines) 106 | 107 | def method_doc(self, params_match, current_line, indent): 108 | params = [p.strip() for p in params_match.group(1).split(',') if len(p.strip()) > 0] 109 | 110 | # includes all operator methods as per http://stackoverflow.com/a/10542599/120818 111 | method_name = re.search("def (?P[a-zA-Z_][a-zA-Z_0-9]+[!?=]?|~|\+|\*\*|-|\*|/|%|<<|>>|&|\||\^|<=>|<|<=|=>|>|==|===|!=|=~|!~|!|\[\]=|\[\])", current_line).group("name") 112 | lines = [] 113 | if(self.settings.get('initial_empty_line')): 114 | lines.append("#" + self.trailing_spaces) 115 | lines.append("# ${1:[%s description]}" % (method_name)) 116 | 117 | for param in params: 118 | lines.append("# @param %s [${1:type}] ${1:[description]}" % (param)) 119 | 120 | lines.append("#" + self.trailing_spaces) 121 | lines.append("# @return [${1:type}] ${1:[description]}") 122 | if(self.settings.get('trailing_empty_line')): 123 | lines.append("#" + self.trailing_spaces) 124 | 125 | return self.format_lines(indent, lines) 126 | 127 | def module_doc(self, current_line, indent): 128 | lines = [] 129 | if(self.settings.get('initial_empty_line')): 130 | lines.append("#" + self.trailing_spaces) 131 | lines.append("# ${1:[module description]}") 132 | lines.extend(self.get_author()) 133 | if(self.settings.get('trailing_empty_line')): 134 | lines.append("#" + self.trailing_spaces) 135 | return self.format_lines(indent, lines) 136 | 137 | def class_doc(self, params_match, current_line, indent): 138 | lines = [] 139 | if(self.settings.get('initial_empty_line')): 140 | lines.append("#" + self.trailing_spaces) 141 | lines.append("# ${1:[class description]}") 142 | lines.extend(self.get_author()) 143 | if(self.settings.get('trailing_empty_line')): 144 | lines.append("#" + self.trailing_spaces) 145 | return self.format_lines(indent, lines) 146 | 147 | def compose_doc(self, current_line, edit): 148 | indent = re.search('(^\s*)', current_line).group(0) 149 | col = self.view.rowcol(self.point)[1] 150 | if(col != 0): 151 | indent = " " * (len(indent) - col) 152 | # indent = "" 153 | 154 | params_match = re.search('def +[^ (]+[ (]*([^)]*)\)?', current_line) 155 | if params_match: 156 | return self.method_doc(params_match, current_line, indent) 157 | params_match = re.search('class ', current_line) 158 | if params_match: 159 | return self.class_doc(params_match, current_line, indent) 160 | params_match = re.search('module ', current_line) 161 | if params_match: 162 | return self.module_doc(current_line, indent) 163 | 164 | def read_line(self, point): 165 | if (point >= self.view.size()): 166 | return 167 | 168 | line = self.view.line(point) 169 | return self.view.substr(line) 170 | 171 | 172 | class AddhashtagCommand(YardocCommand): 173 | def run(self, edit): 174 | self.load_config() 175 | point = self.view.sel()[0].end() 176 | scope = self.view.scope_name(point) 177 | ending = self.line_ending() 178 | if not re.search("source\\.ruby", scope): 179 | self.view.insert(edit, point, ending) 180 | return 181 | # not using the trailing_spaces option here because in most doc writing 182 | # it will be desired on the next line 183 | line = "# " 184 | self.write(self.view, line) 185 | -------------------------------------------------------------------------------- /yardoc.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | // Determines if empty comment lines have a trailing space 3 | "trailing_spaces": true, 4 | // Add an initial empty line at the beginning of the comment 5 | "initial_empty_line": true, 6 | // Add an empty line at the end of the comment 7 | "trailing_empty_line": false 8 | } 9 | --------------------------------------------------------------------------------