Compare commits
	
		
			No commits in common. "master" and "v1.0.2" have entirely different histories.
		
	
	
		|  | @ -1 +0,0 @@ | |||
| * text=auto | ||||
|  | @ -1,6 +0,0 @@ | |||
| [ | ||||
|     { | ||||
|         "keys": ["ctrl+alt+r"], | ||||
|         "command": "beau" | ||||
|     } | ||||
| ] | ||||
|  | @ -25,23 +25,6 @@ | |||
| 								"args": { | ||||
| 									"file": "${packages}/User/Beau.sublime-settings" | ||||
| 								} | ||||
| 							}, | ||||
| 							{ | ||||
| 								"caption": "-" | ||||
| 							}, | ||||
| 							{ | ||||
| 								"caption": "Key Bindings – Default", | ||||
| 								"command": "open_file", | ||||
| 								"args": { | ||||
| 									"file": "${packages}/Beau/Default.sublime-keymap" | ||||
| 								} | ||||
| 							}, | ||||
| 							{ | ||||
| 								"caption": "Key Bindings – User", | ||||
| 								"command": "open_file", | ||||
| 								"args": { | ||||
| 									"file": "${packages}/User/Default.sublime-keymap" | ||||
| 								} | ||||
| 							} | ||||
| 						] | ||||
| 					} | ||||
|  |  | |||
							
								
								
									
										128
									
								
								beau.py
								
								
								
								
							
							
						
						
									
										128
									
								
								beau.py
								
								
								
								
							|  | @ -1,19 +1,13 @@ | |||
| import json | ||||
| import platform | ||||
| import sublime_plugin | ||||
| import subprocess | ||||
| import sublime | ||||
| from .status_loops import loop_status_msg | ||||
| from threading import Thread | ||||
| import sublime_plugin | ||||
| from http.client import responses | ||||
| from sublime import load_settings, active_window | ||||
| from subprocess import check_output | ||||
| from subprocess import Popen, PIPE | ||||
| 
 | ||||
| SETTINGS_FILE = 'Beau.sublime-settings' | ||||
| SYNTAX = 'Packages/JavaScript/JSON.sublime-syntax' | ||||
| 
 | ||||
| is_windows = (platform.system() == 'Windows') | ||||
| 
 | ||||
| class InsertTextCommand(sublime_plugin.TextCommand): | ||||
| 	def run(self, edit, text): | ||||
| 		self.view.insert(edit, 0, text) | ||||
|  | @ -21,74 +15,89 @@ class InsertTextCommand(sublime_plugin.TextCommand): | |||
| class BeauCommand(sublime_plugin.TextCommand): | ||||
| 	requests = [] | ||||
| 	path = '' | ||||
| 	active_view = None | ||||
| 	scope = None | ||||
| 	folders = [] | ||||
| 	stop = None | ||||
| 
 | ||||
| 	def inThread(self, command, onComplete, cwd=None): | ||||
| 		def thread(command, onComplete): | ||||
| 			try: | ||||
| 				self.stop = loop_status_msg([' ⣾', ' ⣽', ' ⣻', ' ⢿', ' ⡿', ' ⣟', ' ⣯', ' ⣷'], .1) | ||||
| 				proc = check_output(command, shell=is_windows, stderr=subprocess.STDOUT, cwd=cwd) | ||||
| 				onComplete(proc) | ||||
| 				return | ||||
| 			except subprocess.CalledProcessError as e: | ||||
| 				self.stop() | ||||
| 				sublime.set_timeout_async(lambda: active_window().status_message('Beau Command Failed. Open the console for more info.'), 1000) | ||||
| 				print(e.output) | ||||
| 
 | ||||
| 		thread = Thread(target=thread, args=(command, onComplete)) | ||||
| 		thread.start() | ||||
| 
 | ||||
| 		return thread | ||||
| 
 | ||||
| 	def run(self, edit): | ||||
| 		settings = load_settings(SETTINGS_FILE) | ||||
| 		settings = sublime.load_settings(SETTINGS_FILE) | ||||
| 		self.path = settings.get('cli_path', '') | ||||
| 		self.active_view = active_window().active_view() | ||||
| 		self.folders = active_window().folders() | ||||
| 		active_window = sublime.active_window() | ||||
| 		active_view = active_window.active_view() | ||||
| 
 | ||||
| 		self.scope = self.active_view.scope_name(self.active_view.sel()[0].b) | ||||
| 		command = [self.path, 'list', '--no-format'] | ||||
| 		if self.scope.startswith('source.yaml'): | ||||
| 			command.extend(['-c', self.active_view.file_name()]) | ||||
| 		scope = active_view.scope_name(active_view.sel()[0].b) | ||||
| 		if not scope.startswith('source.yaml'): | ||||
| 			active_window.status_message('Beau can only be ran on yaml files.') | ||||
| 			return | ||||
| 
 | ||||
| 		self.inThread( | ||||
| 			command, | ||||
| 			self.listFetched, | ||||
| 			cwd=self.folders[0] if len(self.folders) > 0 else None | ||||
| 		) | ||||
| 		print('Using ' + self.path) | ||||
| 		print([ self.path, '-c', active_view.file_name(), '--clean-list' ]) | ||||
| 
 | ||||
| 	def listFetched(self, list): | ||||
| 		self.stop(True) | ||||
| 		proc = Popen([ | ||||
| 			self.path, | ||||
| 			'-c', | ||||
| 			active_view.file_name(), | ||||
| 			'--clean-list' | ||||
| 		], stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=self.is_windows()) | ||||
| 
 | ||||
| 		for line in iter(proc.stderr.readline, b''): | ||||
| 			print(line) | ||||
| 			active_window.status_message(line.decode("utf-8")) | ||||
| 
 | ||||
| 		requests = [] | ||||
| 		self.requests[:] = [] | ||||
| 		for line in list.splitlines(): | ||||
| 		for line in iter(proc.stdout.readline, b''): | ||||
| 			req = line.decode('utf-8').rstrip().split('\t') | ||||
| 
 | ||||
| 			if len(req) == 3: | ||||
| 				method, alias, endpoint = req | ||||
| 				requests.append([alias, endpoint]) | ||||
| 				self.requests.append(req) | ||||
| 
 | ||||
| 		active_window().show_quick_panel(requests, self.on_request_selected) | ||||
| 			elif len(req) == 5: | ||||
| 				method, alias, endpoint, title, description = req | ||||
| 				self.requests.append([method, alias, endpoint]) | ||||
| 
 | ||||
| 	def on_request_selected(self, index): | ||||
| 				if description == 'undefined': | ||||
| 					description = endpoint | ||||
| 
 | ||||
| 				if title == 'undefined': | ||||
| 					title = alias | ||||
| 				else: | ||||
| 					title = title + ' (' + alias + ')' | ||||
| 
 | ||||
| 				requests.append([title, description]) | ||||
| 
 | ||||
| 		proc.wait() | ||||
| 		active_window.show_quick_panel(requests, self.on_done) | ||||
| 
 | ||||
| 	def on_done(self, index): | ||||
| 		if index == -1: | ||||
| 			return | ||||
| 
 | ||||
| 		active_window = sublime.active_window() | ||||
| 		active_view = active_window.active_view() | ||||
| 
 | ||||
| 		method, alias, endpoint = self.requests[index] | ||||
| 
 | ||||
| 		active_window().status_message('Running: ' + alias) | ||||
| 		active_window.status_message('Executing: ' + alias) | ||||
| 
 | ||||
| 		def handleResult(result): | ||||
| 			self.stop(True) | ||||
| 		print([ self.path, '-c', active_view.file_name(), '-R', alias ]) | ||||
| 
 | ||||
| 		proc = Popen([ | ||||
| 			self.path, | ||||
| 			'-c', | ||||
| 			active_view.file_name(), | ||||
| 			'-R', | ||||
| 			alias | ||||
| 		], stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=self.is_windows()) | ||||
| 
 | ||||
| 		for line in iter(proc.stderr.readline, b''): | ||||
| 			print(line) | ||||
| 			active_window.status_message(line.decode("utf-8")) | ||||
| 
 | ||||
| 		response = [] | ||||
| 			for line in result.splitlines(): | ||||
| 		for line in iter(proc.stdout.readline, b''): | ||||
| 			response.append(line.rstrip()) | ||||
| 
 | ||||
| 			active_window().status_message('') | ||||
| 		active_window.status_message('') | ||||
| 
 | ||||
| 		status, endpoint, headers, body = response | ||||
| 
 | ||||
|  | @ -97,15 +106,13 @@ class BeauCommand(sublime_plugin.TextCommand): | |||
| 		headers = headers.decode('utf-8') | ||||
| 		body = body.decode('utf-8') | ||||
| 
 | ||||
| 			results_view = active_window().new_file() | ||||
| 		results_view = active_window.new_file() | ||||
| 		results_view.set_name('Results: ' + alias) | ||||
| 
 | ||||
| 		content = method + ' ' + endpoint + '\n' | ||||
| 		content += status + ' ' + responses[int(status)] + '\n\n' | ||||
| 
 | ||||
| 		content += 'Response Headers: \n' | ||||
| 		content += self.autoindent(headers) | ||||
| 
 | ||||
| 		content += '\n\nResponse Body: \n' | ||||
| 		content += self.autoindent(body) | ||||
| 
 | ||||
|  | @ -113,20 +120,7 @@ class BeauCommand(sublime_plugin.TextCommand): | |||
| 		results_view.set_scratch(True) | ||||
| 		results_view.set_syntax_file(SYNTAX) | ||||
| 
 | ||||
| 		command = [self.path, 'request', alias, '--no-format'] | ||||
| 		if self.scope.startswith('source.yaml'): | ||||
| 			command.extend(['-c', self.active_view.file_name()]) | ||||
| 
 | ||||
| 		self.inThread( | ||||
| 			command, | ||||
| 			onComplete=handleResult, | ||||
| 			cwd=self.folders[0] if len(self.folders) > 0 else None | ||||
| 		) | ||||
| 
 | ||||
| 	def autoindent(self, obj): | ||||
| 		if not obj.strip(): | ||||
| 			return 'Empty'; | ||||
| 
 | ||||
| 		parsed = json.loads(obj) | ||||
| 		return json.dumps( | ||||
| 			parsed, | ||||
|  |  | |||
|  | @ -1,16 +1,15 @@ | |||
| Installation | ||||
| # Beau | ||||
| 
 | ||||
| ## Installation | ||||
| Before beginning you need to have installed beau, you can find out how to | ||||
| do so here: https://github.com/seich/beau. | ||||
| 
 | ||||
| Setup | ||||
| 
 | ||||
| ## Setup | ||||
| The first thing you should do now if open up the settings | ||||
| file (Preferences > Package Settings > Beau > Settings - User) and set up your cli_path. | ||||
| It should be pointing to the location of your beau installation. | ||||
| 
 | ||||
| Usage | ||||
| 
 | ||||
| ## Usage | ||||
| Once that's done, you can start use beau without leaving sublime. | ||||
| To use this plugin, open up a beau config file and open the commands palette (ctrl + shift + p). | ||||
| Type Beau Request and select the request you want to make. A new file should open showing you the | ||||
|  |  | |||
							
								
								
									
										67
									
								
								send_self.py
								
								
								
								
							
							
						
						
									
										67
									
								
								send_self.py
								
								
								
								
							|  | @ -1,67 +0,0 @@ | |||
| """ | ||||
| The MIT License (MIT) | ||||
| Copyright (c) 2015 Clay Sweetser | ||||
| 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: | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
| 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. | ||||
| """ | ||||
| 
 | ||||
| from weakref import proxy, WeakKeyDictionary | ||||
| from sys import version_info | ||||
| from functools import wraps | ||||
| import sublime | ||||
| 
 | ||||
| def get_next_method(generator_instance): | ||||
|     if version_info[0] >= 3: | ||||
|         return generator_instance.__next__ | ||||
|     else: | ||||
|         return generator_instance.next | ||||
| 
 | ||||
| 
 | ||||
| def send_self(use_proxy): | ||||
|     """ A decorator which sends a generator a reference to itself via the first | ||||
|     'yield' used. | ||||
|     Useful for creating generators that can leverage callback-based functions | ||||
|     in a linear style, by passing their 'send' method as callbacks. | ||||
|     Note that by default, the generator instance reference sent is a weakly | ||||
|     referenced proxy. To override this behavior, pass `False` or | ||||
|     `use_proxy=False` as the first argument to the decorator. | ||||
|     """ | ||||
|     _use_proxy = True | ||||
| 
 | ||||
|     # We either directly call this, or return it, to be called by python's | ||||
|     # decorator mechanism. | ||||
|     def _send_self(func): | ||||
|         @wraps(func) | ||||
|         def send_self_wrapper(*args, **kwargs): | ||||
|             generator = func(*args, **kwargs) | ||||
|             generator.send(None) | ||||
|             if _use_proxy: | ||||
|                 generator.send(proxy(generator)) | ||||
|             else: | ||||
|                 generator.send(generator) | ||||
| 
 | ||||
|         return send_self_wrapper | ||||
| 
 | ||||
|     # If the argument is a callable, we've been used without being directly | ||||
|     # passed an arguement by the user, and thus should call _send_self directly | ||||
|     if callable(use_proxy): | ||||
|         # No arguments, this is the decorator | ||||
|         return _send_self(use_proxy) | ||||
|     else: | ||||
|         # Someone has used @send_self(bool), and thus we need to return | ||||
|         # _send_self to be called indirectly. | ||||
|         _use_proxy = use_proxy | ||||
|     return _send_self | ||||
							
								
								
									
										123
									
								
								status_loops.py
								
								
								
								
							
							
						
						
									
										123
									
								
								status_loops.py
								
								
								
								
							|  | @ -1,123 +0,0 @@ | |||
| 
 | ||||
| """ | ||||
| The MIT License (MIT) | ||||
| Copyright (c) 2015 Clay Sweetser | ||||
| 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: | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
| 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. | ||||
| """ | ||||
| from .send_self import send_self, get_next_method | ||||
| import sublime | ||||
| 
 | ||||
| def loop_status_msg(frames, speed, view=None, key=''): | ||||
|     """ Creates and runs a generator which continually sets the status | ||||
|     text to a series of strings. Returns a function which, when called, | ||||
|     stops the generator. | ||||
|     Useful for creating 'animations' in the status bar. | ||||
|     Parameters: | ||||
|         `frames`: A sequence of strings displayed in order on the status bar | ||||
|         `speed`: Delay between frame shifts, in seconds | ||||
|         `view`: View to set the status on. If not provided, then | ||||
|                 sublime.status_message is used. | ||||
|         `key`: Key used when setting the status on a view. Ignored if no | ||||
|                view is given. | ||||
|     To stop the loop, the returned function must be called with no arguments, | ||||
|     or a single argument for which `bool(arg) == true`. As a special condition, | ||||
|     if the first argument is a callable for which `bool(arg) == True`, then | ||||
|     the argument will be called after the last animation loop has finished. | ||||
|     If for the the given argument, `bool(arg) == False`, nothing will | ||||
|     happen. | ||||
|     """ | ||||
|     flag = _FlagObject() | ||||
|     flag.flag = False | ||||
| 
 | ||||
|     @send_self | ||||
|     def loop_status_generator(): | ||||
|         self = yield | ||||
| 
 | ||||
|         # Get the correct status function | ||||
|         set_timeout = sublime.set_timeout | ||||
|         if view is None: | ||||
|             set_status = sublime.status_message | ||||
|         else: | ||||
|             set_status = lambda f: view.set_status(key, f) | ||||
| 
 | ||||
|         # Main loop | ||||
|         while not flag.flag: | ||||
|             for frame in frames: | ||||
|                 set_status(frame) | ||||
|                 yield set_timeout(get_next_method(self), int(speed * 1000)) | ||||
|         if callable(flag.flag): | ||||
|             flag.flag() | ||||
|         set_status('') | ||||
|         yield | ||||
| 
 | ||||
|     def stop_status_loop(callback=True): | ||||
|         flag.flag = callback | ||||
| 
 | ||||
|     sublime.set_timeout(loop_status_generator, 0) | ||||
|     return stop_status_loop | ||||
| 
 | ||||
| 
 | ||||
| def static_status_msg(frame, speed=1): | ||||
|     """ Creates and runs a generator which displays an updatable message in | ||||
|     the current window. | ||||
|     Parameters: | ||||
|         `frame`: Initial message text | ||||
|         `speed`: Update speed, in seconds. Faster speed means faster message | ||||
|                  update, but more CPU usage. Slower update speed means less | ||||
|                  CPU usage, but slower message update. | ||||
|     To update the loop, call the returned function with the new message. | ||||
|     To stop displaying the message, call the returned function with 'true' or | ||||
|     a callable as the second parameter. | ||||
|     """ | ||||
|     flag = _FlagObject() | ||||
|     flag.flag = False | ||||
|     flag.frame = frame | ||||
| 
 | ||||
|     @send_self | ||||
|     def static_status_generator(): | ||||
|         self = yield | ||||
| 
 | ||||
|         # Get the correct status function | ||||
|         set_timeout = sublime.set_timeout | ||||
|         set_status = sublime.status_message | ||||
| 
 | ||||
|         # Main loop | ||||
|         while not flag.flag: | ||||
|             set_status(flag.frame) | ||||
|             yield set_timeout(get_next_method(self), int(speed * 1000)) | ||||
|         if callable(flag.flag): | ||||
|             flag.flag() | ||||
|         yield | ||||
| 
 | ||||
|     def update_status_loop(message, stop=False): | ||||
|         flag.flag = stop | ||||
|         flag.frame = message | ||||
| 
 | ||||
|     sublime.set_timeout(static_status_generator, 0) | ||||
|     return update_status_loop | ||||
| 
 | ||||
| 
 | ||||
| class _FlagObject(object): | ||||
| 
 | ||||
|     """ | ||||
|     Used with loop_status_msg to signal when a status message loop should end. | ||||
|     """ | ||||
|     __slots__ = ['flag', 'frame'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.flag = False | ||||
|         self.frame = None | ||||
		Loading…
	
		Reference in New Issue