├── LICENSE
├── README.md
├── doc
└── codepull.txt
└── plugin
└── codepull.vim
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Kyle Sandell
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, 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,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #Code Pull
2 | This vim plugin allows you to pull code from the web into your own code, without ever leaving the editor
3 | ##Setup
4 | This plugin is pathogen compatible. If you do not have pathogen, simply clone this project in your system's ```~/.vim``` directory.
5 | After installing, the plugin should load whenever vim is launched.
6 | ##Usage
7 | To use this plugin, open vim, position your cursor on the line above where you want to put the code. Then enter command mode and type
8 |
:Pull search terms
9 | where *search terms* is a description of the function you want to pull. You do not need to include the language name, as the plugin infers this from the file type of the file you are editing.
10 | ###Example
11 | Open vim with a python file, say *rev.py*. Once in the editor, type ```:Pull reverse string```. The plugin will run for a few seconds, and then insert a method that reverses a string below the cursor position.
12 | ##Contributing
13 | Any and all help or improvements on this project is very much welcome. You should start by taking a look at [current issues](https://github.com/kasandell/Code-Pull/issues), and seeing what you can fix/improve there.
14 | ###Current Contribution Ideas
15 | •Port to [Atom text editor](https://atom.io)
16 |
17 |
18 | •Use [searchcode's](https://searchcode.com/api/) api to correctly map more filetypes(```echo &filetype```) to their id number as assigned by searchcode
19 |
20 |
21 | •Help me create a psuedo-style language to allow for easy prototyping of functions, that you can pass to the plugin, and have the function built in your code in your preferred language.
22 |
--------------------------------------------------------------------------------
/doc/codepull.txt:
--------------------------------------------------------------------------------
1 | This file describes the code pulling plugin, which allows you to easily pull
2 | code from sites like Github, Quora, Stack Overflow, and BitBucket without
3 | leaving your editor. To use this plugin, simply enter command mode, and type
4 | ':Pull' followed by a description of the function you want. For example, if you
5 | are writing in Python, and you want a function that reverses a string, you
6 | simply have to type :Pull reverse string. Your file type is automatically
7 | checked by the plugin to filter only relevant code. This plugin inserts the code
8 | most likely to fulfill your search terms under the current line.
9 |
--------------------------------------------------------------------------------
/plugin/codepull.vim:
--------------------------------------------------------------------------------
1 | if !has('python')
2 | finish
3 | endif
4 |
5 | command! -nargs=1 Pull call PullCode()
6 | function! PullCode(description)
7 |
8 |
9 | python <<_EOF_
10 |
11 | import json
12 | import requests
13 | import vim
14 | import re
15 |
16 | def getLineGroups(lineDict):
17 | lineNumbers = [int(k) for k in lineDict.keys()]
18 | result = []
19 | segment = []
20 | lineNumbers.sort()
21 | for lineNumber in lineNumbers:
22 | if segment and lineNumber != int(max(segment))+1:
23 | #it belongs in a new group, so finalize the old group, and start a new one
24 | result.append(segment)
25 | segment = []
26 | segment.append(lineNumber)
27 | result.append(segment)
28 | return result
29 |
30 |
31 | def removeCommentOnlyCode(codeGroups):
32 |
33 | def isComment(line):
34 | if not line:
35 | return True
36 | return line[0] in '#\'"' or line.startswith('//')
37 |
38 |
39 | def hasComments(group):
40 | return any([isComment(line) for line in group.splitlines()])
41 |
42 | return [g for g in codeGroups if not hasComments(g)]
43 |
44 |
45 | class CodeRetriever:
46 |
47 |
48 | def __init__(self, initKeywords, language):
49 | """Initialize the class with keywords and language"""
50 | self.keywords = initKeywords
51 | language_codes = {'javascript': 22,
52 | 'swift':137,
53 | 'python':19,
54 | 'c': 28,
55 | 'java':23,
56 | 'php':24,
57 | 'cpp':16,
58 | 'lisp':29,
59 | 'html':3,
60 | 'header':15,
61 | 'ruby':32,
62 | 'perl':51,
63 | 'vimscript':33,
64 | 'haskell':40,
65 | 'scala':47,
66 | 'markdown':118,
67 | 'pascal':46,
68 | 'erlang':25,
69 | 'actionscript':42,
70 | 'lua':54,
71 | 'go':55,
72 | 'objective-c':21,
73 | 'json':122,
74 | 'd':45,
75 | 'config':113,
76 | 'ocaml':64,
77 | 'coffeescript':106,
78 | 'matlab':20,
79 | 'assembly':34,
80 | 'typescript':151}
81 | self.language = language_codes[language] # this will be determined from the ending of the file
82 |
83 |
84 | def pickMostLikelyCode(self, lineSegments, code):
85 | """Get the groupings of lines that are returned
86 |
87 | Here we look for code that:
88 |
89 | a) does shit(we don't want method declarations and all that shit, we want code)
90 | b) seems to do the right thing (methods that are named similar to keywords)
91 | TODO: implement an algorithm that finds other ways to predict if code does the right thing
92 | """
93 | def wanted(word):
94 | #list of general programming terms we don't want included
95 | unwanted = ['string', 'int', 'double', 'float', 'bool', 'boolean', 'char', 'integer']
96 | return word.lower() not in unwanted
97 |
98 | #delete all general terms from the keywords
99 | self.keywords = [w for w in self.keywords if wanted(w)]
100 |
101 | #compile the lines into code segments
102 | codeGroups = []
103 | for lineSegment in lineSegments:
104 | codeLine = '\n'.join([code[str(s)] for s in lineSegment])
105 | codeGroups.append(codeLine)
106 | codeGroups = removeCommentOnlyCode(codeGroups)
107 | highestKeywords = []
108 | keywordCount = 0
109 | #find the code segment that best matches our needs, based on keywords found in the code
110 | for segment in codeGroups:
111 | for word in self.keywords:
112 | keywordCount = keywordCount + segment.count(word)
113 | highestKeywords.append(keywordCount)
114 | keywordCount = 0
115 | wantedCode = highestKeywords.index(max(highestKeywords))
116 | return codeGroups[wantedCode]
117 |
118 | def querySearchCode(self):
119 | """Scrape and grab code from github"""
120 |
121 | params = '+'.join(self.keywords)
122 | #params += self.language
123 | query = 'https://searchcode.com/api/codesearch_I/'
124 | q = {'q':params,
125 | 'lan':self.language}#for testing purposes, make this python. Will add a dict later that has language to number mappings
126 | param_str = '&'.join('%s=%s' %(k, v) for k,v in q.items())
127 | param_str = param_str.replace(' ', '+')
128 | #request the data from the page, and then we will pull the code out? or open the file to the location and pull out from start to end braces/ indent?
129 | page = requests.get(query, params = param_str)
130 | js = json.loads(page.content)
131 | firstCodeSet = js['results'][0]['lines']
132 | lineGroups = getLineGroups(firstCodeSet)
133 | #extract section of html containing top answer
134 | return self.pickMostLikelyCode(lineGroups, firstCodeSet)
135 | #if we did, follow the link to the code, and extract the entire method that is there
136 |
137 |
138 | args = vim.eval("a:description")
139 |
140 | argsDict = args.split(' ')
141 |
142 | vim.command("let r = &filetype")
143 |
144 |
145 | ftype = vim.eval("r")
146 |
147 |
148 | cr = CodeRetriever(argsDict, ftype)
149 |
150 | fin = cr.querySearchCode()
151 |
152 | codeArr = fin.splitlines()
153 | vim.command("let ret = \"%s\"" %fin)
154 |
155 | vim.command("let ret = \"%s\"" %re.escape(fin))
156 |
157 |
158 | _EOF_
159 |
160 |
161 | let codeArr = split(ret, "\n")
162 | let codeArrReverse = reverse(codeArr)
163 | for i in codeArrReverse
164 | call append('.', i)
165 | endfor
166 |
167 | endfunction
168 |
--------------------------------------------------------------------------------