├── .gitignore ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── Default.sublime-commands ├── Main.sublime-menu ├── README.markdown ├── goto_documentation.py └── goto_documentation.sublime-settings /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["super+shift+h"], "command": "goto_documentation" } 3 | ] 4 | -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["super+shift+h"], "command": "goto_documentation" } 3 | ] 4 | -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["super+shift+h"], "command": "goto_documentation" } 3 | ] 4 | -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Goto Documentation", 4 | "command": "goto_documentation" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Preferences", 4 | "mnemonic": "n", 5 | "id": "preferences", 6 | "children": 7 | [ 8 | { 9 | "caption": "Package Settings", 10 | "mnemonic": "P", 11 | "id": "package-settings", 12 | "children": 13 | [ 14 | { 15 | "caption": "GotoDocumentation", 16 | "children": 17 | [ 18 | { 19 | "command": "open_file", 20 | "args": { 21 | "file": "${packages}/GotoDocumentation/Default (Windows).sublime-keymap", 22 | "platform": "Windows" 23 | }, 24 | "caption": "Key Bindings – Default" 25 | }, 26 | { 27 | "command": "open_file", 28 | "args": { 29 | "file": "${packages}/GotoDocumentation/Default (OSX).sublime-keymap", 30 | "platform": "OSX" 31 | }, 32 | "caption": "Key Bindings – Default" 33 | }, 34 | { 35 | "command": "open_file", 36 | "args": { 37 | "file": "${packages}/GotoDocumentation/Default (Linux).sublime-keymap", 38 | "platform": "Linux" 39 | }, 40 | "caption": "Key Bindings – Default" 41 | }, 42 | { 43 | "command": "open_file", 44 | "args": { 45 | "file": "${packages}/User/Default (Windows).sublime-keymap", 46 | "platform": "Windows" 47 | }, 48 | "caption": "Key Bindings – User" 49 | }, 50 | { 51 | "command": "open_file", 52 | "args": { 53 | "file": "${packages}/User/Default (OSX).sublime-keymap", 54 | "platform": "OSX" 55 | }, 56 | "caption": "Key Bindings – User" 57 | }, 58 | { 59 | "command": "open_file", 60 | "args": { 61 | "file": "${packages}/User/Default (Linux).sublime-keymap", 62 | "platform": "Linux" 63 | }, 64 | "caption": "Key Bindings – User" 65 | }, 66 | { "caption": "-" }, 67 | { 68 | "command": "open_file", 69 | "args": {"file": "${packages}/GotoDocumentation/goto_documentation.sublime-settings"}, 70 | "caption": "Settings – Default" 71 | }, 72 | { 73 | "command": "open_file", 74 | "args": {"file": "${packages}/User/goto_documentation.sublime-settings"}, 75 | "caption": "Settings – User" 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | ] 84 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | GotoDocumentation 2 | =========================== 3 | A Sublime Text plugin to jump to documentation for the current keyword. 4 | 5 | 6 | ## Supports 7 | 8 | * PHP 9 | * JS / CoffeeScript 10 | * HTML 11 | * CSS/SASS/LESS 12 | * Python (via `pydoc`) 13 | * Clojure 14 | * Go 15 | * Ruby (+Rails) 16 | * C / C++ 17 | * Perl 18 | * C# 19 | * Lua 20 | * Postgres 21 | * Erlang 22 | * Smarty 23 | * Haskell 24 | * ...you can add any other language via settings 25 | 26 | 27 | Installation 28 | -------------- 29 | 30 | **Via Package Control** 31 | Search for `GotoDocumentation` 32 | 33 | **Manually** 34 | Clone this project in your Packages folder under the name `GotoDocumentation`. 35 | `git clone https://github.com/kemayo/sublime-text-2-goto-documentation.git GotoDocumentation` 36 | 37 | 38 | How to use 39 | ---------------- 40 | Move the cursor inside the word you want the docs for and: 41 | * Press `Super+Shift+H` or 42 | * Open command palette (Ctrl+Shift+P) and search for for GotoDocumentation 43 | 44 | ## Edit the urls 45 | GotoDocumentation allows you to edit the url that opens by editing the settings. 46 | ### The available settings are: 47 | ```json 48 | { 49 | "prefix": "", // added at the begging of the query 50 | "suffix": "", // added at the end of the query 51 | "docs": { // obj containing the docs for each scope 52 | // these are merged with the default ones 53 | 54 | 55 | // the key value pair represent scope -> doc url 56 | // supported placeholders: 57 | // - %(query)s the selected text/word 58 | // - %(scope)s the current scope 59 | "css": "http://devdocs.io/#q=%(scope)s+%(query)s", 60 | 61 | // we can also have an object to 62 | // run a command for finding docs 63 | // inside the command you can use the same placeholders 64 | "python": { 65 | // the command to be executed 66 | "command": ["python", "-m", "pydoc", "%(query)s"], 67 | // a regex to determine if this was an invalid response from the console 68 | "failTest": ".*no Python documentation found for.*", 69 | // regex to select something from the valid response 70 | "changeMatch": "(Related help topics)", 71 | // regex to replace the matched result 72 | "changeWith": "-------\n\\1", 73 | // fallback url: if failTest returns true this will be used 74 | "url": "http://docs.python.org/3/search.html?q=%(query)s" 75 | } 76 | }, 77 | // if we have no docs for the current scope 78 | // we will try using the fallback one, 79 | // to disable set to false 80 | "fallback_scope": "google" 81 | } 82 | 83 | ``` 84 | The change replace is done with the [`re.sub`](https://docs.python.org/2/library/re.html#re.sub) method 85 | 86 | ## How to get the scope 87 | To get the scope for a specific place open your sublime console with `` ctrl + ` `` and paste in this command 88 | `view.scope_name(view.sel()[0].begin()).rpartition('.')[2].strip()` 89 | You can then use that scope to set a rule in the `docs` dictionary(object). 90 | 91 | 92 | Contributions 93 | ----------------- 94 | Submit a patch adding more and I'll include it. 95 | 96 | If you find a bug or have suggestions open an issue [here](https://github.com/kemayo/sublime-text-2-goto-documentation/issues) 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /goto_documentation.py: -------------------------------------------------------------------------------- 1 | # GotoDocumentation Sublime Plugin 2 | # Jun 2014 3 | 4 | import webbrowser 5 | import sublime, sublime_plugin 6 | import re, os 7 | import subprocess 8 | 9 | default_docs = { 10 | "ahk": "http://www.ahkscript.org/docs/commands/%(query)s.htm", 11 | "rails": "http://api.rubyonrails.org/?q=%(query)s", 12 | "controller": "http://api.rubyonrails.org/?q=%(query)s", 13 | "ruby": "http://ruby-doc.com/search.html?q=%(query)s", 14 | "js": "https://developer.mozilla.org/en-US/search?q=%(query)s&topic=js", 15 | "html": "https://developer.mozilla.org/en-US/search?q=%(query)s&topic=html", 16 | "coffee": "https://developer.mozilla.org/en-US/search?q=%(query)s", 17 | "php": "http://php.net/manual-lookup.php?pattern=%(query)s", 18 | "clojure": "http://clojuredocs.org/search?x=0&y=0&q=%(query)s", 19 | "go": "http://golang.org/search?q=%(query)s", 20 | "c": "http://www.cplusplus.com/search.do?q=%(query)s", 21 | "cpp": "http://www.cplusplus.com/search.do?q=%(query)s", 22 | "smarty": "http://www.smarty.net/%(query)s", 23 | "cmake": "http://cmake.org/cmake/help/v2.8.8/cmake.html#command:%(query)s", 24 | "perl": "http://perldoc.perl.org/search.html?q=%(query)s", 25 | "cs": "http://social.msdn.microsoft.com/Search/?query=%(query)s", 26 | "lua": "http://pgl.yoyo.org/luai/i/%(query)s", 27 | "pgsql": "http://www.postgresql.org/search/?u=%%2Fdocs%%2Fcurrent%%2F&q=%(query)s", 28 | "erlang": "http://erldocs.com/R16B03/?search=%(query)s", 29 | "haskell": "http://hayoo.fh-wedel.de/?query=%(query)s", 30 | "scala": "http://scalex.org/?q=%(query)s", 31 | "css": "http://devdocs.io/#q=%(scope)s+%(query)s", 32 | "scss": "http://devdocs.io/#q=%(scope)s+%(query)s", 33 | "less": "http://devdocs.io/#q=%(scope)s+%(query)s", 34 | "google": "https://google.com/search?q=%(scope)s+%(query)s", 35 | "python": { 36 | "command": ["python", "-m", "pydoc", "%(query)s"], 37 | "failTest": ".*no Python documentation found for.*", 38 | "changeMatch": "(Related help topics)", 39 | "changeWith": "-------\n\\1", 40 | "url": "http://docs.python.org/3/search.html?q=%(query)s" 41 | } 42 | } 43 | 44 | def combineDicts(dictionary1, dictionary2): 45 | new_dict = dictionary1.copy() 46 | new_dict.update(dictionary2) 47 | return new_dict 48 | 49 | class GotoDocumentationCommand(sublime_plugin.TextCommand): 50 | """ 51 | Search the selected text or the current word 52 | """ 53 | def run(self, edit): 54 | # grab the word or the selection from the view 55 | for region in self.view.sel(): 56 | location = False 57 | if region.empty(): 58 | # if we have no selection grab the current word 59 | location = self.view.word(region) 60 | else: 61 | # grab the selection 62 | location = region 63 | 64 | if location and not location.empty(): 65 | q = self.view.substr(location) 66 | scope = self.view.scope_name(location.begin()).rpartition('.')[2].strip() 67 | 68 | self.open_doc(q, scope) 69 | 70 | def open_doc(self, query, scope): 71 | 72 | settings = sublime.load_settings("goto_documentation.sublime-settings") 73 | 74 | # attach the prefix and suffix 75 | query = settings.get('prefix', '') + query + settings.get('suffix', '') 76 | 77 | # merge the default docs with the one provided by the user 78 | docs = combineDicts(default_docs, settings.get('docs')) 79 | 80 | # we use a temp scope so we don't replace the "real" scope 81 | tscope = scope 82 | 83 | if not tscope in docs: 84 | tscope = settings.get('fallback_scope', 'google') 85 | 86 | if not tscope in docs: 87 | self.show_status("No docs available for the current scope !") 88 | return 89 | 90 | 91 | 92 | # if we have the scope defined in settings 93 | # build the url and open it 94 | doc = docs[tscope] 95 | 96 | # if it is a dict we must have: 97 | # - a command to run 98 | # - a regex to check against 99 | # - an optional fallback url 100 | if type(doc) is dict: 101 | # build the command 102 | command = [x%{'query': query, 'scope': scope} for x in doc['command']] 103 | 104 | # Per http://bugs.python.org/issue8557 shell=True 105 | shell = os.name == 'nt' 106 | # run it 107 | process = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 108 | stdout = [x.decode('unicode_escape').rstrip() for x in process.stdout.readlines()] 109 | 110 | stdout = '\n'.join(stdout) 111 | 112 | 113 | # match the result agains the regex 114 | reg = re.compile(doc['failTest']) 115 | if reg.match(stdout): 116 | # use the fallback url 117 | if 'url' in doc: 118 | fullUrl = doc['url']%{'query': query, 'scope': scope} 119 | webbrowser.open(fullUrl) 120 | else: 121 | self.show_status("No docs available for the current word !") 122 | 123 | 124 | else: 125 | # regex to change something before it's sent to the panel 126 | if 'changeMatch' in doc and 'changeWith' in doc: 127 | stdout = re.sub(doc['changeMatch'], doc['changeWith'], stdout) 128 | 129 | # we have a valid result from console 130 | # so we place it in the output panel 131 | self.panel(stdout) 132 | 133 | else: 134 | if not doc: 135 | self.show_status("This scope is disabled !") 136 | return 137 | 138 | # we have an url so we build and open it 139 | fullUrl = doc%{'query': query, 'scope': scope} 140 | webbrowser.open(fullUrl) 141 | 142 | 143 | # Open and write on the output panel 144 | def panel(self, output): 145 | active_window = sublime.active_window() 146 | 147 | if not hasattr(self, 'output_view'): 148 | self.output_view = active_window.get_output_panel("gotodocumentation") 149 | 150 | self.output_view.set_read_only(False) 151 | 152 | self.output_view.run_command('goto_documentation_output', { 153 | 'output': output, 154 | 'clear': True 155 | }) 156 | 157 | self.output_view.set_read_only(True) 158 | active_window.run_command("show_panel", {"panel": "output.gotodocumentation"}) 159 | 160 | def show_status(self, status): 161 | sublime.status_message(status) 162 | print("\nGoto Documentation Plugin: " + status + "\n") 163 | 164 | 165 | 166 | 167 | class GotoDocumentationOutputCommand(sublime_plugin.TextCommand): 168 | def run(self, edit, output = '', output_file = None, clear = False): 169 | 170 | if clear: 171 | region = sublime.Region(0, self.view.size()) 172 | self.view.erase(edit, region) 173 | 174 | self.view.insert(edit, 0, output) 175 | 176 | 177 | -------------------------------------------------------------------------------- /goto_documentation.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "", // added at the begging of the query 3 | "suffix": "", // added at the end of the query 4 | "docs": { // obj containing the docs for each scope 5 | // these are merged with the default ones 6 | 7 | 8 | // the key value pair represent scope -> doc url 9 | // supported placeholders: 10 | // - %(query)s the selected text/word 11 | // - %(scope)s the current scope 12 | "css": "http://devdocs.io/#q=%(scope)s+%(query)s", 13 | 14 | // we can also have an object to 15 | // run a command for finding docs 16 | // inside the command you can use the same placeholders 17 | "python": { 18 | // the command to be executed 19 | "command": ["python", "-m", "pydoc", "%(query)s"], 20 | // a regex to determine if this was an invalid response from the console 21 | "failTest": ".*no Python documentation found for.*", 22 | // regex to select something from the valid response 23 | "changeMatch": "(Related help topics)", 24 | // regex to replace the matched result 25 | "changeWith": "-------\n\\1", 26 | // fallback url: if failTest returns true this will be used 27 | "url": "http://docs.python.org/3/search.html?q=%(query)s" 28 | } 29 | }, 30 | // if we have no docs for the current scope 31 | // we will try using the fallback one, 32 | // to disable set to false 33 | "fallback_scope": "google" 34 | } 35 | --------------------------------------------------------------------------------