Skip to content
This repository
Browse code

Clean up I/O operator handling

  • Loading branch information...
commit b416ad3d31bf269e1f1b5719c71083fac38a326a 1 parent b2cae07
Trent Ogren authored November 30, 2012
20  README.md
Source Rendered
@@ -12,11 +12,23 @@ And display their output just like Sublime's build systems:
12 12
 
13 13
 ![command output](https://img.skitch.com/20120207-e4wwrfr7s8tyds7rptfesxi65p.jpg)
14 14
 
15  
-To pipe the current file or selections to the command, prepend a pipe character
16  
-(i.e. `|`) to the command.  To redirect a command's output to the view append an
17  
-angle bracket (i.e. `>`) to the command.  For example, `| sort >` will sort the
18  
-active file or its selected lines.
19 15
 
  16
+Input and output
  17
+------------------------
  18
+Unix's familiar `|` and `>` operators can be used to pipe/redirect a command's
  19
+input and outout:
  20
+
  21
+  * To pipe the active view's selections to a command, add a leading pipe
  22
+    character (e.g. `|sort`).  If there are no non-empty selections the entire
  23
+    file will be piped to the command.
  24
+  * To pipe a command's output back into the view, add a trailing pipe
  25
+    character (e.g. `|sort|`).
  26
+  * To redirect the command's output to a new file, add a trailing greater than
  27
+    symbol to the command (e.g `ls>` or `|sort>`).
  28
+
  29
+
  30
+Using snippets
  31
+--------------
20 32
 Snippets are available for frequently used commands.  All snippets with the
21 33
 scope name `source.shell` (`source.dosbatch` for Windows users) can be used in
22 34
 the prompt shown above.  I have
73  shell_turtlestein.py
@@ -63,7 +63,7 @@ def cmd_settings(cmd):
63 63
 
64 64
 def parse_cmd(cmd_str):
65 65
     return re.match(
66  
-            r"(?P<pipe>\s*\|\s*)?(?P<shell_cmd>.*?)(?:\s*(?:(?P<redirect_new>>)|(?P<redirect>\|))\s*)?$",
  66
+            r"\s*(?P<input>\|)?\s*(?P<shell_cmd>.*?)\s*(?P<output>[|>])?\s*$",
67 67
             cmd_str
68 68
         ).groupdict()
69 69
 
@@ -109,57 +109,66 @@ def run(self):
109 109
 
110 110
     def on_done(self, cwd, cmd_str):
111 111
         cmd = parse_cmd(cmd_str)
  112
+        if not cmd['input'] and cmd['output'] == '|':
  113
+            sublime.error_message(
  114
+                "Piping output to the view requires piping input from the view as well."
  115
+                + " Please use a preceding |.")
  116
+            return
  117
+
  118
+        active_view = self.window.active_view()
  119
+        if cmd['input'] or cmd['output'] == '|':
  120
+            if not active_view:
  121
+                sublime.error_message(
  122
+                    "A view has to be active to pipe text from and/or to a view.")
  123
+                return
  124
+
112 125
         settings = cmd_settings(cmd['shell_cmd'])
113 126
 
114 127
         before, after = settings['surround_cmd']
115 128
         shell_cmd = before + cmd['shell_cmd'] + after
116 129
 
117  
-        if cmd['pipe'] or cmd['redirect']:
118  
-            view = self.window.active_view()
119  
-            if not view:
120  
-                sublime.error_message(
121  
-                    "A view has to be active to pipe or redirect commands.")
122  
-                return
123  
-            regions = [sel for sel in view.sel() if sel.size() > 0]
124  
-            if len(regions) == 0:
125  
-                regions = [sublime.Region(0, view.size())]
  130
+        if cmd['input']:
  131
+            input_regions = [sel for sel in active_view.sel() if sel.size() > 0]
  132
+            if len(input_regions) == 0:
  133
+                input_regions = [sublime.Region(0, active_view.size())]
  134
+        else:
  135
+            input_regions = None
126 136
 
127 137
 
128 138
         # We can leverage Sublime's (async) build systems unless we're
129  
-        # redirecting the output into the view. In that case, we use Popen
  139
+        # redirecting the output into a view. In that case, we use Popen
130 140
         # synchronously.
131  
-        if cmd['redirect']:
132  
-            for region in regions:
133  
-                self.process_region(view, region, cwd, shell_cmd, cmd['pipe'])
  141
+        if cmd['output']:
  142
+            for region in (input_regions or [None]):
  143
+                self.process_region(active_view, region, cwd, shell_cmd, cmd['output'])
134 144
         else:
135  
-            if cmd['pipe']:
  145
+            if input_regions:
136 146
                 # Since Sublime's build system don't support piping to STDIN
137 147
                 # directly, pipe the selected text via `echo`.
138  
-                text = "".join([view.substr(r) for r in regions])
  148
+                text = "".join([active_view.substr(r) for r in input_regions])
139 149
                 shell_cmd = "echo %s | %s" % (pipes.quote(text), shell_cmd)
140 150
             exec_args = settings['exec_args']
141 151
             exec_args.update({'cmd': shell_cmd, 'shell': True, 'working_dir': cwd})
142 152
 
143  
-            if cmd['redirect_new']:
144  
-                (success, output) = run_cmd(cwd, shell_cmd, True)
145  
-                self.window.run_command("new_file")
146  
-                view = self.window.active_view()
147  
-                edit = view.begin_edit()
148  
-                view.insert(edit, 0, output)
149  
-                view.end_edit(edit)
150  
-            else:
151  
-                self.window.run_command("exec", exec_args)
152  
-
153  
-    def process_region(self, view, selection, cwd, shell_cmd, pipe):
  153
+            self.window.run_command("exec", exec_args)
  154
+
  155
+    def process_region(self, active_view, selection, cwd, shell_cmd, outpt):
154 156
         input_str = None
155  
-        if pipe:
156  
-            input_str = view.substr(selection)
  157
+        if selection:
  158
+            input_str = active_view.substr(selection)
157 159
 
158 160
         (success, output) = run_cmd(cwd, shell_cmd, True, input_str)
159 161
         if success:
160  
-            edit = view.begin_edit()
161  
-            view.replace(edit, selection, output)
162  
-            view.end_edit(edit)
  162
+            if outpt == '|':
  163
+                edit = active_view.begin_edit()
  164
+                active_view.replace(edit, selection, output)
  165
+                active_view.end_edit(edit)
  166
+            elif outpt == '>':
  167
+                self.window.run_command("new_file")
  168
+                new_view = self.window.active_view()
  169
+                edit = new_view.begin_edit()
  170
+                new_view.insert(edit, 0, output)
  171
+                new_view.end_edit(edit)
163 172
 
164 173
 
165 174
 class SubprocessInCwdCommand(sublime_plugin.WindowCommand):

0 notes on commit b416ad3

Please sign in to comment.
Something went wrong with that request. Please try again.