├── LICENSE ├── README.md ├── doc └── http-client.txt ├── examples ├── demo.gif └── examples.txt └── plugin ├── http_client.py └── http_client.vim /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-http-client 2 | 3 | Make HTTP requests from Vim with the HTTP format you already know, rather than wrestling with `curl -X POST -b cookie=$1 -F csrf_token=$2 -F "request={\"user_id\":123}" http://example.org`! Then parse the results right in Vim, syntax highlighted the way you expect! 4 | 5 | ![Demo](https://raw.githubusercontent.com/aquach/vim-http-client/master/examples/demo.gif) 6 | 7 | See `examples/examples.txt` for other examples. 8 | 9 | ## Installation 10 | 11 | vim-http-client requires Vim compiled with python support and the [python `requests` library](http://docs.python-requests.org/en/latest/). 12 | 13 | You likely have Python support, but you can check with `vim --version | grep +python`. MacVim comes with Python support. 14 | 15 | To check if you have the `requests` library, try `python -c 'import requests'`. If you get an error, try `pip install requests` to get the library. Many distros ship Python support with Vim and the `requests` library with Python. 16 | 17 | Once you have these, use your favorite Vim plugin manager to install `aquach/vim-http-client`, or copy `plugin` and `doc` into your `.vim` folder. 18 | 19 | ## Usage 20 | 21 | Put your cursor anywhere in a newline-delimited block of text and hit `tt`. `vim-http-client` will parse the text into a HTTP request, execute it, and display its results will appear in a split. You can also directly invoke the HTTP client with `:HTTPClientDoRequest`. The format mirrors HTTP's format: 22 | 23 | ``` 24 | # Comments start with #. 25 | # First request. 26 | 27 | : 28 | : 29 | ... 30 | : 31 | 32 | 33 | # Second request. 34 | 35 | : 36 | : 37 | ... 38 | : 39 | 40 | ``` 41 | 42 | Depending on where you put your cursor, the first or second request will execute. You can also substitute variables anywhere in the request: 43 | 44 | ``` 45 | # Second request. 46 | # :foo = bar 47 | POST http://httpbin.org/post 48 | { 49 | "data": ":foo", 50 | "otherkey": "hello" 51 | } 52 | ``` 53 | 54 | Each variable lives in a separate commented line. Variables beginning with `:` are request variables only considered in the request block they live in. Variables beginning with `$` are global variables that affect all requests in the entire buffer. Local variables always override global variables. 55 | 56 | ``` 57 | # $endpoint = http://httpbin.org 58 | 59 | GET $endpoint/get 60 | 61 | # :request_var = 3 62 | POST $endpoint/post 63 | 64 | GET $endpoint/resource 65 | ``` 66 | 67 | Variables are substituted with simple string substitution. 68 | 69 | If you'd like to pass form-encoded data, set your body like this: 70 | 71 | ``` 72 | = 73 | = 74 | ... 75 | = 76 | ``` 77 | 78 | You can also send files using absolute path to file: `!file(PATH_TO_FILE)` or by simply providing it's content: `!content(my file content)`. 79 | 80 | Example: 81 | ``` 82 | POST http://httpbin.org/post 83 | foo=vim rocks 84 | bar=!file(/tmp/my_file.txt) 85 | baz=!content(sample content) 86 | ``` 87 | 88 | 89 | 90 | See `examples/examples.txt` for more examples. 91 | 92 | The output appears in a new split. Based on the `Content-Type` header of the HTTP response, vim-http-client chooses a filetype for syntax highlighting. It currently supports XML, JSON, and HTML; all others will get `ft=text`. 93 | 94 | ## Configuration 95 | 96 | #### g:http_client_bind_hotkey (default 1) 97 | 98 | Controls whether or not `tt` will run the HTTP client. Regardless of the setting, vim-http-client will not overwrite your existing `tt` mapping if it exists. 99 | 100 | #### g:http_client_json_ft (default 'javascript') 101 | 102 | Sets the vim filetype when vim-http-client detects a JSON response. Though JSON-specific syntax highlighting like [vim-json](https://github.com/elzr/vim-json) provides prettier highlighting than the default Javascript highlighting, Javascript highlighting comes with Vim and is therefore a safer default. Use this setting to configure the filetype to your liking. 103 | 104 | #### g:http_client_json_escape_utf (default 1) 105 | 106 | By default json.dumps will escape any utf8 characters beyond ascii range. This option (if set to 0) allows you to get the actual special characters instead of \uxxxx encoded ones. 107 | 108 | #### g:http_client_result_vsplit (default 1) 109 | 110 | By default the request result appears in a vertical split. Setting this option to 0 displays the result in a horizontal split. 111 | 112 | #### g:http_client_focus_output_window (default 1) 113 | 114 | By default the focus will go to the output window. If set to 0 the focus will return to the window with request definitions. 115 | 116 | #### g:http_client_verify_ssl (default 1) 117 | 118 | By default requests will verify SSL certificates for HTTPS endpoints. Setting this option to 0 disables SSL verification which allows requests to sites using self-signed certificates, for example. 119 | 120 | #### g:http_client_preserve_responses (default 0) 121 | 122 | By default responses will be written to the output buffer replacing any previous response. Setting this option to 1 will preserve previous responses, adding the latest response to the top of the buffer. 123 | 124 | ## Contributing 125 | 126 | This plugin is currently quite simple. Contributions, suggestions, and feedback are all welcomed! 127 | -------------------------------------------------------------------------------- /doc/http-client.txt: -------------------------------------------------------------------------------- 1 | http-client.txt 2 | 3 | _ _ _ _ _ _ ~ 4 | | | | | | | | |(_) | | ~ 5 | | |__ | |_ | |_ _ __ ______ ___ | | _ ___ _ __ | |_ ~ 6 | | '_ \ | __|| __|| '_ \|______|/ __|| || | / _ \| '_ \ | __| ~ 7 | | | | || |_ | |_ | |_) | | (__ | || || __/| | | || |_ ~ 8 | |_| |_| \__| \__|| .__/ \___||_||_| \___||_| |_| \__| ~ 9 | | | ~ 10 | |_| ~ 11 | 12 | 13 | ============================================================================== 14 | CONTENTS |http-client-contents| 15 | 16 | Introduction |http-client-introduction| 17 | Use |http-client-use| 18 | Configuration |http-client-configuration| 19 | Installation |http-client-installation| 20 | 21 | ============================================================================== 22 | Introduction *http-client* *http-client-introduction* 23 | 24 | With vim-http-client, you can make HTTP calls from Vim with the HTTP format 25 | you already know, rather than learning new command line tools fraught with 26 | complex flags and escaped quotes. You can also parse the results right in 27 | Vim, syntax highlighted the way you expect! 28 | 29 | ============================================================================== 30 | Use *http-client-use* 31 | 32 | Put your cursor anywhere in a newline-delimited block of text and hit 33 | `tt`. The text will be parsed and executed as a HTTP request, and its 34 | results will appear in a split. You can also directly invoke the HTTP client 35 | with :call HTTPClientDoRequest(). Here's the format of a request: > 36 | 37 | # Comments start with #. 38 | # First request. 39 | 40 | : 41 | : 42 | ... 43 | : 44 | 45 | 46 | # Second request. 47 | 48 | : 49 | : 50 | ... 51 | : 52 | 53 | 54 | Depending on where you put your cursor, the first or second request will 55 | execute. You can also substitute variables anywhere in the request: > 56 | 57 | # Second request. 58 | # :foo = bar 59 | # :asdf = 3 60 | POST http://httpbin.org/post 61 | { "data": ":foo" } 62 | 63 | Each variable lives in a separate commented line. Variables beginning with : 64 | are request variables only considered in the request block they live in. 65 | Variables beginning with $ are global variables that affect all requests in 66 | the entire buffer. Local variables always override global variables. > 67 | 68 | # $endpoint = http://httpbin.org 69 | 70 | GET $endpoint/get 71 | 72 | # :request_var = 3 73 | POST $endpoint/post 74 | 75 | GET $endpoint/resource 76 | 77 | If you'd like to pass form-encoded data, set your body like this: > 78 | 79 | = 80 | = 81 | ... 82 | = 83 | 84 | See `examples/examples.txt` for more examples. 85 | 86 | The output appears in a new split. Syntax highlighting is interpreted from the 87 | Content-Type header of the result. It currently supports XML, JSON, and HTML; 88 | all others will get ft=text. 89 | 90 | ============================================================================== 91 | Configuration *http-client-configuration* 92 | *g:http_client_bind_hotkey* 93 | *g:http_client_json_ft* 94 | *g:http_client_json_escape_utf* 95 | *g:http_client_result_vsplit* 96 | *g:http_client_verify_ssl* 97 | *g:http_client_preserve_responses* 98 | 99 | g:http_client_bind_hotkey (default 1) 100 | 101 | Controls whether or not `tt` will run the HTTP client. 102 | 103 | g:http_client_json_ft (default 'javascript') 104 | 105 | Sets the vim filetype when vim-http-client detects a JSON response. Though 106 | JSON-specific syntax highlighting provides prettier highlighting than the 107 | default Javascript highlighting, Javascript highlighting comes with Vim and is 108 | therefore a safer default. Use this setting to configure the filetype to your 109 | liking. 110 | 111 | g:http_client_json_escape_utf (default 1) 112 | 113 | By default json.dumps will escape any utf8 characters beyond ascii range. This 114 | option (if set to 0) allows you to get the actual special characters instead 115 | of \uxxxx encoded ones. 116 | 117 | g:http_client_result_vsplit (default 1) 118 | 119 | By default the request result appears in a vertical split. Setting this option 120 | to 0 displays the result in a horizontal split. 121 | 122 | g:http_client_focus_output_window (default 1) 123 | 124 | By default the focus will go to the output window. If set to 0 the focus will 125 | return to the window with request definitions. 126 | 127 | g:http_client_verify_ssl (default 1) 128 | 129 | By default requests will verify SSL certificates for HTTPS endpoints. Setting 130 | this option to 0 disables SSL verification which allows requests to sites 131 | using self-signed certificates, for example. 132 | 133 | g:http_client_preserve_responses (default 0) 134 | 135 | By default responses will be written to the output buffer replacing any 136 | previous response. Setting this option to 1 will preserve previous responses, 137 | adding the latest response to the top of the buffer. 138 | 139 | ============================================================================== 140 | Installation *http-client-installation* 141 | 142 | vim-http-client requires Vim compiled with python support and the python 143 | requests library. 144 | 145 | To check if you have Python support, try: > 146 | 147 | vim --version | grep +python. 148 | 149 | To check if you have the requests library, try: > 150 | 151 | python -c 'import requests' 152 | 153 | If you get an error, try pip install requests to get the library. Many distros 154 | ship Python support with Vim and the requests library with Python. 155 | 156 | Once the two are installed, install the plugin into 157 | ~/.vim/plugin/http-client.vim or with your favorite Vim plugin manager. 158 | 159 | ============================================================================== 160 | vim:tw=78:sw=4:ts=8:ft=help:norl: 161 | -------------------------------------------------------------------------------- /examples/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aquach/vim-http-client/777c9a44872d14ae8d1d13f13c13a61da4aed852/examples/demo.gif -------------------------------------------------------------------------------- /examples/examples.txt: -------------------------------------------------------------------------------- 1 | GET http://jsonip.com 2 | 3 | # Straight data. 4 | POST http://httpbin.org/post 5 | X-Custom-Header: four 6 | { "data": { "hello": "three" }} 7 | 8 | GET http://coinabul.com/api.php 9 | 10 | # Form-encoded data. 11 | POST http://httpbin.org/post 12 | X-Custom-Header: four 13 | request={ "data": { "hello": "three" }} 14 | othervalue=3 15 | 16 | # Example of sending files (note that you have to have file '/tmp/sample.txt' to run this example) 17 | POST http://httpbin.org/post 18 | key1=value1 19 | key2=value2 20 | key3=!file(/tmp/sample.txt) 21 | key4=!content(my sample content) 22 | -------------------------------------------------------------------------------- /plugin/http_client.py: -------------------------------------------------------------------------------- 1 | import json 2 | import re 3 | import requests 4 | 5 | from_cmdline = False 6 | try: 7 | __file__ 8 | from_cmdline = True 9 | except NameError: 10 | pass 11 | 12 | if not from_cmdline: 13 | import vim 14 | 15 | METHOD_REGEX = re.compile('^(GET|POST|DELETE|PUT|HEAD|OPTIONS|PATCH) (.*)$') 16 | HEADER_REGEX = re.compile('^([^()<>@,;:\<>/\[\]?={}]+):\\s*(.*)$') 17 | VAR_REGEX = re.compile('^# ?(:[^: ]+)\\s*=\\s*(.+)$') 18 | GLOBAL_VAR_REGEX = re.compile('^# ?(\$[^$ ]+)\\s*=\\s*(.+)$') 19 | FILE_REGEX = re.compile("!((?:file)|(?:(?:content)))\((.+)\)") 20 | JSON_REGEX = re.compile("(javascript|json)$", re.IGNORECASE) 21 | 22 | verify_ssl = vim.eval('g:http_client_verify_ssl') == '1' 23 | 24 | 25 | def replace_vars(string, variables): 26 | for var, val in variables.items(): 27 | string = string.replace(var, val) 28 | return string 29 | 30 | 31 | def is_comment(s): 32 | return s.startswith('#') 33 | 34 | 35 | def do_request(block, buf): 36 | variables = dict((m.groups() for m in (GLOBAL_VAR_REGEX.match(l) for l in buf) if m)) 37 | variables.update(dict((m.groups() for m in (VAR_REGEX.match(l) for l in block) if m))) 38 | 39 | block = [line for line in block if not is_comment(line) and line.strip() != ''] 40 | 41 | if len(block) == 0: 42 | print('Request was empty.') 43 | return 44 | 45 | method_url = block.pop(0) 46 | method_url_match = METHOD_REGEX.match(method_url) 47 | if not method_url_match: 48 | print('Could not find method or URL!') 49 | return 50 | 51 | method, url = method_url_match.groups() 52 | url = replace_vars(url, variables) 53 | url = url.strip() 54 | 55 | headers = {} 56 | while len(block) > 0: 57 | header_match = HEADER_REGEX.match(block[0]) 58 | if header_match: 59 | block.pop(0) 60 | header_name, header_value = header_match.groups() 61 | headers[header_name] = replace_vars(header_value, variables) 62 | else: 63 | break 64 | 65 | data = [ replace_vars(l, variables) for l in block ] 66 | files = None 67 | if all([ '=' in l for l in data ]): 68 | # Form data: separate entries into data dict, and files dict 69 | key_value_pairs = dict([ l.split('=', 1) for l in data ]) 70 | def to_file(expr): 71 | type, arg = FILE_REGEX.match(expr).groups() 72 | arg = arg.replace('\\(', '(').replace('\\)', ')') 73 | return open(arg, 'rb') if type == 'file' else (arg) 74 | 75 | files = dict([(k, to_file(v)) for (k, v) in key_value_pairs.items() if FILE_REGEX.match(v)]) 76 | data = dict([(k, v) for (k, v) in key_value_pairs.items() if not FILE_REGEX.match(v)]) 77 | else: 78 | # Straight data: just send it off as a string. 79 | data = '\n'.join(data) 80 | 81 | if not verify_ssl: 82 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 83 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 84 | 85 | json_data = None 86 | if headers.get('Content-Type') == 'application/json': 87 | json_data = json.loads(data) 88 | data = None 89 | 90 | response = requests.request(method, url, verify=verify_ssl, headers=headers, data=data, files=files, json=json_data) 91 | content_type = response.headers.get('Content-Type', '').split(';')[0] 92 | 93 | response_body = response.text 94 | if JSON_REGEX.search(content_type): 95 | content_type = 'application/json' 96 | try: 97 | response_body = json.dumps( 98 | json.loads(response.text), sort_keys=True, indent=2, 99 | separators=(',', ': '), 100 | ensure_ascii=vim.eval('g:http_client_json_escape_utf')=='1') 101 | except ValueError: 102 | pass 103 | 104 | display = ( 105 | response_body.split('\n') + 106 | ['', '// status code: %s' % response.status_code] + 107 | ['// %s: %s' % (k, v) for k, v in response.headers.items()] 108 | ) 109 | 110 | return display, content_type 111 | 112 | 113 | # Vim methods. 114 | 115 | def vim_filetypes_by_content_type(): 116 | return { 117 | 'application/json': vim.eval('g:http_client_json_ft'), 118 | 'application/xml': 'xml', 119 | 'text/html': 'html' 120 | } 121 | 122 | BUFFER_NAME = '__HTTP_Client_Response__' 123 | 124 | 125 | def find_block(buf, line_num): 126 | length = len(buf) 127 | is_buffer_terminator = lambda s: s.strip() == '' 128 | 129 | block_start = line_num 130 | while block_start > 0 and not is_buffer_terminator(buf[block_start]): 131 | block_start -= 1 132 | 133 | block_end = line_num 134 | while block_end < length and not is_buffer_terminator(buf[block_end]): 135 | block_end += 1 136 | 137 | return buf[block_start:block_end + 1] 138 | 139 | 140 | def open_scratch_buffer(contents, filetype): 141 | previous_window = vim.current.window 142 | existing_buffer_window_id = vim.eval('bufwinnr("%s")' % BUFFER_NAME) 143 | if existing_buffer_window_id == '-1': 144 | if vim.eval('g:http_client_result_vsplit') == '1': 145 | split_cmd = 'vsplit' 146 | else: 147 | split_cmd = 'split' 148 | vim.command('rightbelow %s %s' % (split_cmd, BUFFER_NAME)) 149 | vim.command('setlocal buftype=nofile nospell') 150 | else: 151 | vim.command('%swincmd w' % existing_buffer_window_id) 152 | 153 | vim.command('set filetype=%s' % filetype) 154 | write_buffer(contents, vim.current.buffer) 155 | 156 | if vim.eval('g:http_client_focus_output_window') != '1': 157 | vim.current.window = previous_window 158 | 159 | 160 | def do_request_from_buffer(): 161 | win = vim.current.window 162 | line_num = win.cursor[0] - 1 163 | block = find_block(win.buffer, line_num) 164 | result = do_request(block, win.buffer) 165 | if result: 166 | response, content_type = result 167 | vim_ft = vim_filetypes_by_content_type().get(content_type, 'text') 168 | open_scratch_buffer(response, vim_ft) 169 | 170 | 171 | def write_buffer(contents, buffer): 172 | if vim.eval('g:http_client_preserve_responses') == '1': 173 | if len(buffer): 174 | buffer[0:0] = [""] 175 | buffer[0:0] = contents 176 | vim.command('0') 177 | else: 178 | buffer[:] = contents 179 | 180 | # Tests. 181 | 182 | def run_tests(): 183 | import json 184 | 185 | def extract_json(resp): 186 | return json.loads(''.join([ l for l in resp[0] if not l.startswith('//') ])) 187 | 188 | def test(assertion, test): 189 | print('Test %s: %s' % ('passed' if assertion else 'failed', test)) 190 | if not assertion: 191 | raise AssertionError 192 | 193 | resp = extract_json(do_request([ 194 | '# comment', 195 | '# :a=barf', 196 | 'GET http://httpbin.org/headers', 197 | 'X-Hey: :a', 198 | '# comment' 199 | ], [])) 200 | test(resp['headers']['X-Hey'] == 'barf', 'Headers are passed with variable substitution.') 201 | 202 | resp = extract_json(do_request([ 203 | '# :a = barf', 204 | 'GET http://httpbin.org/get?data=:a' 205 | ], [])) 206 | test(resp['args']['data'] == 'barf', 'GET data is passed with variable substitution.') 207 | 208 | resp = extract_json(do_request([ 209 | 'POST http://httpbin.org/post', 210 | 'some data' 211 | ], [])) 212 | test(resp['data'] == 'some data', 'POST data is passed with variable substitution.') 213 | 214 | resp = extract_json(do_request([ 215 | 'POST http://httpbin.org/post', 216 | 'forma=a', 217 | 'formb=b', 218 | ], [])) 219 | test(resp['form']['forma'] == 'a', 'POST form data is passed.') 220 | 221 | resp = extract_json(do_request([ 222 | 'POST http://$global/post', 223 | 'forma=a', 224 | 'formb=b', 225 | ], [ '# $global = httpbin.org'])) 226 | test(resp['form']['forma'] == 'a', 'Global variables are substituted.') 227 | 228 | import os 229 | from tempfile import NamedTemporaryFile 230 | 231 | SAMPLE_FILE_CONTENT = 'sample file content' 232 | 233 | temp_file = NamedTemporaryFile(delete = False) 234 | temp_file.write(SAMPLE_FILE_CONTENT) 235 | temp_file.close() 236 | resp = extract_json(do_request([ 237 | 'POST http://httpbin.org/post', 238 | 'forma=a', 239 | 'formb=b', 240 | "formc=!file(%s)" % temp_file.name, 241 | ], [])) 242 | test(resp['files']['formc'] == SAMPLE_FILE_CONTENT, 'Files given as path are sent properly.') 243 | test(not 'formc' in resp['form'], 'File not included in form data.') 244 | os.unlink(temp_file.name) 245 | 246 | resp = extract_json(do_request([ 247 | 'POST http://httpbin.org/post', 248 | 'forma=a', 249 | 'formb=b', 250 | "formc=!content(%s)" % SAMPLE_FILE_CONTENT, 251 | ], [])) 252 | test(resp['files']['formc'] == SAMPLE_FILE_CONTENT, 'Files given as content are sent properly.') 253 | 254 | resp = extract_json(do_request([ 255 | 'POST http://httpbin.org/post', 256 | "c=!content(foo \\(bar\\))", 257 | ], [])) 258 | test(resp['files']['c'] == 'foo (bar)', 'Escaped parenthesis should be unescaped during request') 259 | 260 | 261 | if from_cmdline: 262 | run_tests() 263 | -------------------------------------------------------------------------------- /plugin/http_client.vim: -------------------------------------------------------------------------------- 1 | let s:initialized_client = 0 2 | let s:script_path = fnamemodify(resolve(expand(':p')), ':h') 3 | 4 | if !exists('http_client_bind_hotkey') 5 | let g:http_client_bind_hotkey = 1 6 | endif 7 | 8 | if !exists('http_client_json_ft') 9 | let g:http_client_json_ft = 'javascript' 10 | endif 11 | 12 | if !exists('http_client_json_escape_utf') 13 | let g:http_client_json_escape_utf = 1 14 | endif 15 | 16 | if !exists('http_client_result_vsplit') 17 | let g:http_client_result_vsplit = 1 18 | endif 19 | 20 | if !exists('http_client_focus_output_window') 21 | let g:http_client_focus_output_window = 1 22 | endif 23 | 24 | if !exists('http_client_verify_ssl') 25 | let g:http_client_verify_ssl = 1 26 | endif 27 | 28 | if !exists('http_client_preserve_responses') 29 | let g:http_client_preserve_responses = 0 30 | endif 31 | 32 | function! s:DoHTTPRequest() 33 | if has('python') 34 | command! -nargs=1 Python python 35 | command! -nargs=1 Pyfile pyfile 36 | elseif has('python3') 37 | command! -nargs=1 Python python3 38 | command! -nargs=1 Pyfile py3file 39 | else 40 | echo 'Error: this plugin requires vim compiled with python support.' 41 | finish 42 | endif 43 | 44 | if !s:initialized_client 45 | let s:initialized_client = 1 46 | execute 'Pyfile ' . s:script_path . '/http_client.py' 47 | endif 48 | 49 | Python do_request_from_buffer() 50 | endfunction 51 | 52 | command! -nargs=0 HTTPClientDoRequest call DoHTTPRequest() 53 | 54 | if g:http_client_bind_hotkey 55 | silent! nnoremap tt :HTTPClientDoRequest 56 | endif 57 | --------------------------------------------------------------------------------