├── .no-sublime-package ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── wiki ├── intellidocs-php.png ├── intellidocs-python.png └── intellidocs-javascript.png ├── test ├── test.py ├── test.php └── test.js ├── .gitignore ├── IntelliDocs.sublime-settings ├── LICENSE ├── README.md ├── Main.sublime-menu ├── intellidocs.py └── db └── updatedb.py /.no-sublime-package: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["f2"], "command": "intelli_docs" } 3 | ] 4 | -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["f2"], "command": "intelli_docs" } 3 | ] 4 | -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["f2"], "command": "intelli_docs" } 3 | ] 4 | -------------------------------------------------------------------------------- /wiki/intellidocs-php.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shortcutme/Sublime-IntelliDocs/HEAD/wiki/intellidocs-php.png -------------------------------------------------------------------------------- /wiki/intellidocs-python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shortcutme/Sublime-IntelliDocs/HEAD/wiki/intellidocs-python.png -------------------------------------------------------------------------------- /wiki/intellidocs-javascript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shortcutme/Sublime-IntelliDocs/HEAD/wiki/intellidocs-javascript.png -------------------------------------------------------------------------------- /test/test.py: -------------------------------------------------------------------------------- 1 | Dont run this file, just for testing purposes! :) 2 | ------------------------------------------------- 3 | 4 | self.patterns[pattern_name].format(name = entry["name"]) 5 | re.match(self.patterns["skip"], entry["name"]) 6 | match.group(1) 7 | part.strip() 8 | open(path_db+"/"+self.name+".json", "w").write(json.dumps(db, sort_keys=True, indent=4)) 9 | s.replace("\n", "") 10 | bytes.fromhex('2Ef0 F1f2 ') 11 | for directory, name in docs.items(): -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | __pycache__ 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | -------------------------------------------------------------------------------- /IntelliDocs.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "help_links": { 3 | ".*": "http://devdocs.io/%(path)s", 4 | "php": "http://php.net/manual-lookup.php?pattern=%(name)s", 5 | "python": "http://docs.python.org/3/search.html?q=%(name)s", 6 | "jquery": "http://api.jquery.com/%(name)s", 7 | "javascript|dom": "https://developer.mozilla.org/en-US/search?topic=js&topic=html&topic=api&q=%(name)s", 8 | }, 9 | "docs": { 10 | "source.php" : "PHP", 11 | "source.js" : "Javascript", 12 | "source.coffee" : "Javascript", 13 | "source.python" : "Python" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/test.php: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | Dont run this file, just for testing purposes! :) 2 | ------------------------------------------------- 3 | 4 | return val.toLowerCase(); 5 | clearTimeout($.gsuggest.suggestDelay); 6 | setTimeout($.gsuggest.suggestDelay); 7 | if ($.gsuggest.config.debug)timerstart = new Date().getTime(); 8 | data.sort(); 9 | new RegExp("("+escapeRe(objval).replace(/ /g, "|")+")","gi") 10 | $(id).click(function(){$(this).blur(); $(this).focus()}); 11 | console.log("inited"); 12 | document.getElementById("map_canvas") 13 | var c_lat = parseFloat( min_lat) + parseFloat((max_lat-min_lat)/2); 14 | el = document.createElement("div"); 15 | me.latlngs.push({latlng: latlng, c: d[dlen].count}); 16 | 17 | $("#pp"+last_pppid).removeClass("selected"); 18 | $(row).appendTo($('#valaszto')); 19 | $('#selected_pickpack_title').html(' '); 20 | return $(e.target).parents().children().filter('div.blockUI').length == 0; 21 | $( document ).ajaxComplete(function() { $( ".log" ).text( "Triggered ajaxComplete handler." ); }); 22 | console.log( $( this ).serializeArray() ); 23 | $.each( fields, function( i, field ) { $( "#results" ).append( field.value + " " ); }).each(); 24 | 25 | elem.addClass "flash" 26 | elem[0].remove -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sublime-IntelliDocs 2 | =================== 3 | 4 | Quick function parameter help for Sublime 3.x. 5 | Currently supported languages: 6 | - Javascript & DOM & jQuery `new!` 7 | - PHP 8 | - Python 9 | - More soon :) (Suggest me your favorite language) 10 | 11 | 12 | ## Changelog ## 13 | - 1.1.6 (2014-03-18) 14 | - Lookup key binded to F2 by default (thanks tlqmj!) 15 | - 1.1.5 (2014-03-06) 16 | - Support for embedded languages (eg. Javascript in HTML) 17 | - Support for Javascript hints in Coffeescript 18 | - More intelligent function name matcher 19 | - Javascript and jQuery hints working with jQuery syntax 20 | - 1.1.1 (2014-03-05) 21 | - Added to Package Settings menu for easier configuration 22 | - 1.1.0 (2014-03-05) 23 | - Javascript & DOM & jQuery support 24 | - Custom reference doc links via config. (php.net, api.jquery.com, developer.mozilla.org, docs.python.org configured by default) 25 | - 1.0.0 (2014-03-02) 26 | - Initial release. 27 | - PHP, Python support 28 | 29 | 30 | ## Features ## 31 | - Parameter hint 32 | - Function description 33 | - Parameter description 34 | - Last function hint stays in status bar 35 | - Open devdocs.io and other, customizable reference docs in browser 36 | 37 | 38 | ## Screenshots ## 39 | 40 | ### Javascript/jQuery ### 41 | ![Sublime Javascript hints](https://raw.github.com/shortcutme/Sublime-IntelliDocs/master/wiki/intellidocs-javascript.png) 42 | 43 | ### PHP ### 44 | ![Sublime PHP hints](https://raw.github.com/shortcutme/Sublime-IntelliDocs/master/wiki/intellidocs-php.png) 45 | 46 | ### Python ### 47 | ![Sublime Python hints](https://raw.github.com/shortcutme/Sublime-IntelliDocs/master/wiki/intellidocs-python.png) 48 | 49 | 50 | ## Installation ## 51 | 52 | - Download the [zip-ball](https://github.com/shortcutme/Sublime-IntelliDocs/archive/master.zip) and unpack to `sublime\data\packages` OR via [packageControl](https://sublime.wbond.net/) 53 | 54 | ## Usage ## 55 | 56 | - Set your cursor over a function or object you want to look up and press F2 to see relevant documentation 57 | 58 | 59 | ## Thanks to ## 60 | - Wonderful Devdocs.io for documents database 61 | 62 | 63 | ## Suggestions are welcomed! Thank you! :) ## 64 | https://github.com/shortcutme/Sublime-IntelliDocs/issues/3 65 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [{ 2 | "caption": "Preferences", 3 | "mnemonic": "n", 4 | "id": "preferences", 5 | "children": [ { 6 | "caption": "Package Settings", 7 | "mnemonic": "P", 8 | "id": "package-settings", 9 | "children": [ { 10 | "caption": "IntelliDocs", 11 | "children":[ 12 | { 13 | "command": "open_file", 14 | "args": {"file": "${packages}/IntelliDocs/IntelliDocs.sublime-settings"}, 15 | "caption": "Settings – Default" 16 | }, 17 | { 18 | "command": "open_file", 19 | "args": {"file": "${packages}/User/IntelliDocs.sublime-settings"}, 20 | "caption": "Settings – User" 21 | }, 22 | { "caption": "-" }, 23 | { 24 | "command": "open_file", 25 | "args": { 26 | "file": "${packages}/IntelliDocs/Default (OSX).sublime-keymap", 27 | "platform": "OSX" 28 | }, 29 | "caption": "Key Bindings – Default" 30 | }, 31 | { 32 | "command": "open_file", 33 | "args": { 34 | "file": "${packages}/IntelliDocs/Default (Linux).sublime-keymap", 35 | "platform": "Linux" 36 | }, 37 | "caption": "Key Bindings – Default" 38 | }, 39 | { 40 | "command": "open_file", 41 | "args": { 42 | "file": "${packages}/IntelliDocs/Default (Windows).sublime-keymap", 43 | "platform": "Windows" 44 | }, 45 | "caption": "Key Bindings – Default" 46 | }, 47 | { 48 | "command": "open_file", 49 | "args": { 50 | "file": "${packages}/User/Default (OSX).sublime-keymap", 51 | "platform": "OSX" 52 | }, 53 | "caption": "Key Bindings – User" 54 | }, 55 | { 56 | "command": "open_file", 57 | "args": { 58 | "file": "${packages}/User/Default (Linux).sublime-keymap", 59 | "platform": "Linux" 60 | }, 61 | "caption": "Key Bindings – User" 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 | } ] 73 | } ] 74 | }] 75 | -------------------------------------------------------------------------------- /intellidocs.py: -------------------------------------------------------------------------------- 1 | 2 | import sublime_plugin, sublime, json 3 | import re, threading, time, os, webbrowser 4 | 5 | class IntelliDocsCommand(sublime_plugin.TextCommand): 6 | 7 | last_function_name = None 8 | last_found = False 9 | cache = {} 10 | menu_links = {} 11 | def __init__(self, view): 12 | self.view = view 13 | self.settings = sublime.load_settings("IntelliDocs.sublime-settings") 14 | 15 | def run(self, edit): 16 | # Find db for lang 17 | lang = self.getLang() 18 | if lang not in self.cache: #DEBUG disable cache: or 1 == 1 19 | path_db = os.path.dirname(os.path.abspath(__file__))+"/db/%s.json" % lang 20 | self.debug("Loaded intelliDocs db:", path_db) 21 | if os.path.exists(path_db): 22 | self.cache[lang] = json.load(open(path_db)) 23 | else: 24 | self.cache[lang] = {} 25 | 26 | completions = self.cache[lang] 27 | 28 | # Find in completions 29 | if completions: 30 | function_names = self.getFunctionNames(completions) 31 | found = False 32 | for function_name in function_names: 33 | completion = completions.get(function_name) 34 | if completion: 35 | found = completion 36 | break 37 | 38 | if found: 39 | self.view.set_status('hint', found["syntax"]+" | ") 40 | menus = [] 41 | # Syntax 42 | menus.append(found["syntax"]) 43 | 44 | # Description 45 | for descr in re.sub("(.{80,100}[\.]) ", "\\1||", found["descr"]).split("||"): #Spit long description lines 46 | menus.append(" "+descr) 47 | 48 | #Parameters 49 | if found["params"]: 50 | menus.append("Parameters:") 51 | for parameter in found["params"]: 52 | menus.append(" - "+parameter["name"]+": "+parameter["descr"]) 53 | """first = True 54 | for part in re.sub("(.{50,150}?)\. ", "\\1.|", parameter["descr"]).split("|"): 55 | if first: 56 | menus.append(parameter["name"]+": "+part.strip()) 57 | else: 58 | menus.append("- "+part) 59 | first = False""" 60 | self.last_found = found 61 | 62 | menu = self.appendLinks(menus, found) 63 | 64 | self.view.show_popup_menu(menus, self.action) 65 | else: 66 | self.view.erase_status('hint') 67 | 68 | def getLang(self): 69 | scope = self.view.scope_name(self.view.sel()[0].b) #try to match against the current scope 70 | for match, lang in self.settings.get("docs").items(): 71 | if re.match(".*"+match, scope): return lang 72 | self.debug(scope) 73 | return re.match(".*/(.*?).tmLanguage", self.view.settings().get("syntax")).group(1) #no match in predefined docs, return from syntax filename 74 | 75 | def getFunctionNames(self, completions): 76 | # Find function name 77 | word = self.view.word(self.view.sel()[0]) 78 | word.a = word.a - 100 # Look back 100 character 79 | word.b = word.b + 1 # Ahead word +1 char 80 | buff = self.view.substr(word).strip() 81 | 82 | buff = " "+re.sub(".*\n", "", buff) # Keep only last line 83 | 84 | # find function names ending with ( 85 | matches = re.findall("([A-Za-z0-9_\]\.\$\)]+\.[A-Za-z0-9_\.\$]+|[A-Za-z0-9_\.\$]+[ ]*\()", buff) 86 | matches.reverse() 87 | function_names = [] 88 | for function_name in matches: 89 | function_name = function_name.strip(".()[] ") 90 | if len(function_name) < 2: continue 91 | function_names.append(function_name) 92 | if "." in function_name: 93 | function_names.append(re.sub(".*\.(.*?)$", "\\1", function_name)) 94 | function_names.append(self.view.substr(self.view.word(self.view.sel()[0]))) #append current word 95 | self.debug(function_names) 96 | return function_names 97 | 98 | 99 | def appendLinks(self, menus, found): 100 | self.menu_links = {} 101 | for pattern, link in sorted(self.settings.get("help_links").items()): 102 | if re.match(pattern, found["path"]): 103 | host = re.match(".*?//(.*?)/", link).group(1) 104 | self.menu_links[len(menus)] = link % found 105 | menus.append(" > Goto: %s" % host) 106 | return menus 107 | 108 | def action(self, item): 109 | if item in self.menu_links: 110 | webbrowser.open_new_tab(self.menu_links[item]) 111 | 112 | def debug(self, *text): 113 | if self.settings.get("debug"): 114 | print(*text) 115 | -------------------------------------------------------------------------------- /db/updatedb.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import os, re, json 3 | 4 | # Update DB from local devdocs.io dump: https://github.com/Thibaut/devdocs 5 | # (Tested on Python 2.7 win7) 6 | 7 | path_devdocs = "../var/devdocs" 8 | path_db = "." 9 | docs = { 10 | "php": "PHP", 11 | "python": "Python", 12 | "javascript": "Javascript", 13 | "dom": "Javascript", 14 | "jquery": "Javascript" 15 | } 16 | 17 | patterns = { 18 | "PHP": { 19 | #"skip" : '.*::', 20 | "syntax": ".*?methodsynopsis.*?>(.*?)", 21 | "descr" : ".*rdfs-comment.*?>(.*?)

", 22 | "params": "
(.*?)
(.*?)
" 23 | }, 24 | "Python": { 25 | "doc" : '.*(.*?)', 26 | "alias" : '^(str|dict|int|float|list|bytes|bytearray|array.array|array|re.match)\.', 27 | "syntax": "(.*?)", 28 | "descr" : ".*?

(.*?)

", 29 | }, 30 | "Javascript": { 31 | "alias" : '^(Array|String|Date|Function|Object|RegExp|Number|window)\.', 32 | "syntax": ".*?(?:[sS]yntax|section).*?<(?:code|pre|span).*?>(.*?\).*?)", 33 | "descr" : ".*?h1.*?

(.*?)

", 34 | "params": "(?:
(.*?)
(.*?)
|
  • .{5,30}(.*?)(.*?)
  • )" 35 | } 36 | } 37 | 38 | def stripTags(s): 39 | s = re.sub("<[a-zA-Z/]+.*?>", "", s) 40 | s = s.replace("&", "&") 41 | s = s.replace(">", ">") 42 | s = s.replace("<", "<") 43 | s = s.replace("\n", "") 44 | s = s.strip() 45 | return s 46 | 47 | class Parser: 48 | def __init__(self, directory, name): 49 | self.name = name 50 | self.directory = directory 51 | self.patterns = patterns[name] 52 | path = path_devdocs+"/public/docs/"+directory+"/" 53 | self.updateDoc(path) 54 | 55 | 56 | def getPattern(self, pattern_name): 57 | self.patterns[pattern_name].format(name = entry["name"]) 58 | 59 | 60 | def getDescr(self, doc): 61 | match_descr = re.match(self.patterns["descr"], doc, re.DOTALL) 62 | if match_descr: 63 | descr = match_descr.group(1) 64 | else: 65 | descr = "" 66 | return stripTags(descr) 67 | 68 | 69 | def getParams(self, doc): 70 | params = [] 71 | if "params" not in self.patterns: return params 72 | for match in re.findall(self.patterns["params"], doc, re.DOTALL): 73 | name, descr = [group for group in match if group] 74 | descr = re.sub("^(.{30,200}?)(\. |$).*", "\\1\\2", stripTags(descr)) 75 | params.append({"name": stripTags(name), "descr": descr}) 76 | return params 77 | 78 | 79 | def updateDoc(self, path): 80 | index = json.load(open(path+"/index.json")) 81 | db = json.load(open(path_db+"/"+self.name+".json")) 82 | no_match = [] 83 | for entry in index["entries"]: 84 | # Open doc file 85 | entry["name"] = entry["name"].replace(" (class)", "").strip("().") 86 | if "skip" in self.patterns and re.match(self.patterns["skip"], entry["name"]): 87 | print("S", end="") 88 | continue 89 | 90 | path_doc = path+re.sub("#.*$", "", entry["path"])+".html" 91 | try: 92 | doc = open(path_doc).read() 93 | except Exception, err: 94 | print(err) 95 | 96 | #if entry["name"] != "removeClass": continue # DEBUG 97 | 98 | if "doc" in self.patterns: # Prefilter doc 99 | match = re.match(self.patterns["doc"] % entry, doc, re.DOTALL) 100 | if match: 101 | doc = match.group(1) 102 | else: 103 | doc = "" 104 | 105 | # Match sytax 106 | match = re.match(self.patterns["syntax"], doc, re.DOTALL) 107 | 108 | # Add to db 109 | if match: 110 | syntax = stripTags(match.group(1)) 111 | syntax = syntax.replace(")Returns:", ") Returns:") # jQuery doc returns fix 112 | 113 | #multiple syntax possible 114 | if ");" in syntax: 115 | parts = syntax.split(");") 116 | syntax = ");\n or ".join( [part for part in parts if part.strip()] )+");" 117 | 118 | db[entry["name"]] = { 119 | "name" : entry["name"], 120 | "path" : self.directory+"/"+entry["path"], 121 | "type" : entry["type"], 122 | "syntax": syntax, 123 | "descr" : self.getDescr(doc), 124 | "params": self.getParams(doc) 125 | } 126 | print(".", end="") 127 | 128 | # Create alias like str.replace -> replace 129 | if "alias" in self.patterns: 130 | name_alias = re.sub(self.patterns["alias"], "", entry["name"]) 131 | if name_alias != entry["name"]: 132 | db[name_alias] = db[entry["name"]] 133 | print("A", end="") 134 | 135 | # jQuery.* -> $.* alias 136 | if entry["name"].startswith("jQuery"): 137 | name_alias = entry["name"].replace("jQuery.", "$.") 138 | db[name_alias] = db[entry["name"]] 139 | 140 | else: 141 | print("-", end="") 142 | no_match.append(entry["name"]) 143 | open(path_db+"/"+self.name+".json", "w").write(json.dumps(db, sort_keys=True, indent=4)) 144 | print("No match:", no_match) 145 | print("Done!") 146 | 147 | # Create empty files 148 | for directory, name in docs.items(): 149 | open(path_db+"/"+name+".json", "w").write("{}") 150 | 151 | 152 | # Fill db 153 | for directory, name in docs.items(): 154 | print(" * Updating", directory, "->", name) 155 | Parser(directory, name) 156 | --------------------------------------------------------------------------------