From b34d115efd7a4754a137c5edf7551c994fefec78 Mon Sep 17 00:00:00 2001 From: Alexandr Ruchkin Date: Tue, 16 Dec 2014 17:25:59 +0300 Subject: [PATCH 1/3] Added 'shell' setting to specify shell program It is useful in Windows to run PowerShell commands --- OsShell.py | 29 +++++++++++++++++++++++------ ShellCommand.py | 13 +++++++------ ShellCommand.sublime-settings | 11 +++++++++++ SublimeHelper.py | 5 +++-- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/OsShell.py b/OsShell.py index 741f103..f7c424b 100644 --- a/OsShell.py +++ b/OsShell.py @@ -9,7 +9,7 @@ from . import SublimeHelper as SH -def process(commands, callback=None, stdin=None, settings=None, working_dir=None, wait_for_completion=None, **kwargs): +def process(commands, callback=None, stdin=None, settings=None, working_dir=None, wait_for_completion=None, shell=None, **kwargs): # If there's no callback method then just return the output as # a string: @@ -26,12 +26,13 @@ def process(commands, callback=None, stdin=None, settings=None, working_dir=None 'stdin': stdin, 'settings': settings, 'working_dir': working_dir, - 'wait_for_completion': wait_for_completion + 'wait_for_completion': wait_for_completion, + 'shell': shell }) thread.start() -def _process(commands, callback=None, stdin=None, settings=None, working_dir=None, wait_for_completion=None, **kwargs): +def _process(commands, callback=None, stdin=None, settings=None, working_dir=None, wait_for_completion=None, shell=None, **kwargs): '''Process one or more OS commands.''' if wait_for_completion is None: @@ -57,6 +58,23 @@ def _process(commands, callback=None, stdin=None, settings=None, working_dir=Non startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + # If 'shell' is not set, get it from setrtings + if shell is None: + shell = settings.get('shell') + + is_shell = isinstance(shell, str) + + # Replace $input var + if not is_shell and '$input' in shell: + shell = list(filter(lambda sharg: sharg is not None, [stdin if sh == '$input' else sh for sh in shell])) + stdin = None + + def decorate_shell_command(cmd): + if is_shell: + return shell.replace('$cmd', cmd) + else: + return [arg.replace('$cmd', cmd) for arg in shell] + # Now we can execute each command: # for command in commands: @@ -73,12 +91,11 @@ def _process(commands, callback=None, stdin=None, settings=None, working_dir=Non command = '. {} && {}'.format(bash_env, command) try: - - proc = subprocess.Popen(command, + proc = subprocess.Popen(decorate_shell_command(command), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - shell=True, + shell=is_shell, cwd=working_dir, startupinfo=startupinfo) diff --git a/ShellCommand.py b/ShellCommand.py index d975196..0f224ca 100644 --- a/ShellCommand.py +++ b/ShellCommand.py @@ -16,7 +16,7 @@ def __init__(self, plugin, default_prompt=None, **kwargs): self.data_key = 'ShellCommand' self.output_written = False - def run(self, edit, command=None, command_prefix=None, prompt=None, region=None, arg_required=None, stdin=None, panel=None, title=None, syntax=None, refresh=None, wait_for_completion=None, root_dir=False): + def run(self, edit, command=None, command_prefix=None, prompt=None, region=None, arg_required=None, stdin=None, panel=None, title=None, syntax=None, refresh=None, wait_for_completion=None, root_dir=False, shell=None): # Map previous use of 'region' parameter: # @@ -61,7 +61,7 @@ def _C(command): if arg is not None: command = command + ' ' + arg - self.run_shell_command(command, stdin=stdin, panel=panel, title=title, syntax=syntax, refresh=refresh, wait_for_completion=wait_for_completion, root_dir=root_dir) + self.run_shell_command(command, stdin=stdin, panel=panel, title=title, syntax=syntax, refresh=refresh, wait_for_completion=wait_for_completion, root_dir=root_dir, shell=shell) # If no command is specified then we prompt for one, otherwise # we can just execute the command: @@ -73,7 +73,7 @@ def _C(command): else: _C(command) - def run_shell_command(self, command=None, stdin=None, panel=False, title=None, syntax=None, refresh=False, console=None, working_dir=None, wait_for_completion=None, root_dir=False): + def run_shell_command(self, command=None, stdin=None, panel=False, title=None, syntax=None, refresh=False, console=None, working_dir=None, wait_for_completion=None, root_dir=False, shell=None): view = self.view window = view.window() @@ -143,7 +143,8 @@ def _C(output): title=title, syntax=syntax, panel=panel, - console=console) + console=console, + shell=shell) # Switch our progress bar to the new window: # @@ -159,7 +160,7 @@ def _C(output): self.output_target.append_text(output) self.output_written = True - OsShell.process(command, _C, stdin=stdin, settings=settings, working_dir=working_dir, wait_for_completion=wait_for_completion) + OsShell.process(command, _C, stdin=stdin, settings=settings, working_dir=working_dir, wait_for_completion=wait_for_completion, shell=shell) class ShellCommandOnRegionCommand(ShellCommandCommand): @@ -186,5 +187,5 @@ def run(self, edit, callback=None): console.run_command('sublime_helper_clear_buffer') console.set_read_only(True) - self.run_shell_command(command=data['command'], console=console, working_dir=data['working_dir']) + self.run_shell_command(command=data['command'], console=console, working_dir=data['working_dir'], shell=data['shell']) diff --git a/ShellCommand.sublime-settings b/ShellCommand.sublime-settings index d596c32..b3e4e5f 100644 --- a/ShellCommand.sublime-settings +++ b/ShellCommand.sublime-settings @@ -17,4 +17,15 @@ */ , "progress_display_heartbeat": 500 + + /** + * Command to invoke + * String stays for shell command, so default '$cmd' means just 'run command with shell' + * List stays for process name with args, for example + * ['powershell', '-Command', '& { $cmd }'] will run powershell with specified arguments + * There are also $input metavar which is used when there are some input + * if '$input' present, input will be passed as argument instead of writing it to stdin + */ + +, "shell": "$cmd" } diff --git a/SublimeHelper.py b/SublimeHelper.py index 28f47e2..f45bd6a 100644 --- a/SublimeHelper.py +++ b/SublimeHelper.py @@ -152,7 +152,7 @@ def run(self, edit): class OutputTarget(): - def __init__(self, window, data_key, command, working_dir, title=None, syntax=None, panel=False, console=None): + def __init__(self, window, data_key, command, working_dir, title=None, syntax=None, panel=False, console=None, shell=None): # If a panel has been requested then create one and show it, # otherwise create a new buffer, and set its caption: @@ -189,7 +189,8 @@ def __init__(self, window, data_key, command, working_dir, title=None, syntax=No # data = { 'command': command, - 'working_dir': working_dir + 'working_dir': working_dir, + 'shell': shell } settings.set(data_key + '_data', data) From 1dd2d93ce99187b48aa2e79e1b4f4491ed9af84b Mon Sep 17 00:00:00 2001 From: Alexandr Ruchkin Date: Tue, 16 Dec 2014 17:57:38 +0300 Subject: [PATCH 2/3] Added $file $path and $dir vars --- ShellCommand.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ShellCommand.py b/ShellCommand.py index 0f224ca..5c5626c 100644 --- a/ShellCommand.py +++ b/ShellCommand.py @@ -1,4 +1,6 @@ import sublime +import os.path +import shlex from . import SublimeHelper as SH from . import OsShell @@ -83,6 +85,12 @@ def run_shell_command(self, command=None, stdin=None, panel=False, title=None, s sublime.message_dialog('No command provided.') return + # replace '$path' with view file path, '$file' with view file name and '$dir' with view file dir + file_path = view.file_name() + if file_path: + (file_dir, file_name) = os.path.split(file_path) + command = command.replace('$path', shlex.quote(file_path)).replace('$file', shlex.quote(file_name)).replace('$dir', shlex.quote(file_dir)) + if working_dir is None: working_dir = self.get_working_dir(root_dir=root_dir) From 83651459a28711ce8a257a91f3c164a071f0df86 Mon Sep 17 00:00:00 2001 From: Alexandr Ruchkin Date: Tue, 16 Dec 2014 21:52:40 +0300 Subject: [PATCH 3/3] Added 'syntax_match' option --- ShellCommand.py | 8 ++++++++ ShellCommand.sublime-settings | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/ShellCommand.py b/ShellCommand.py index 5c5626c..e1d79de 100644 --- a/ShellCommand.py +++ b/ShellCommand.py @@ -1,6 +1,7 @@ import sublime import os.path import shlex +import re from . import SublimeHelper as SH from . import OsShell @@ -94,6 +95,13 @@ def run_shell_command(self, command=None, stdin=None, panel=False, title=None, s if working_dir is None: working_dir = self.get_working_dir(root_dir=root_dir) + # Match syntax by settings regexes + if syntax is None: + syntax_match = settings.get('syntax_match') + for syntax_re, syntax_sy in syntax_match.items(): + if re.match(syntax_re, command): + syntax = syntax_sy + # Run the command and write any output to the buffer: # message = self.default_prompt + ': (' + ''.join(command)[:20] + ')' diff --git a/ShellCommand.sublime-settings b/ShellCommand.sublime-settings index b3e4e5f..5828d41 100644 --- a/ShellCommand.sublime-settings +++ b/ShellCommand.sublime-settings @@ -28,4 +28,11 @@ */ , "shell": "$cmd" + /** + * Set syntax if command matches specified regex + * Example: + * { "^svn.*\bdiff\b": "Diff" } + * Will set 'Diff' syntax for commands like 'svn diff ...' or 'svn log -l 10 --diff' + */ +, "syntax_match": {} }