Sublime Forum

Run file contents through external command

#1

Hello,
I want to take the contents of my current file as input, send it through a series of pipes (using sed and awk to fix mistakes) and replace the contents with the output of the pipes. What’s the best way to do this?

Example file:
My apointment is tomorow.

I want to run the command
sed ‘s/apointment/appointment/’ | sed ‘s/tomorow/tomorrow/’

To get the output
My appointment is tomorrow.

0 Likes

#2

You can write a plugin that will, for example, take a command line to execute, send the contents of the current buffer (or current selection) to the command line, and replace the buffer or selection with the output.

0 Likes

#3

Does that mean I have to learn Python? In Textmate is was as easy as point and click.

0 Likes

#4

So, I’m trying something like this, but I can’t get it to work

import sublime, sublime_plugin
import subprocess

"""
Runs an external command with the selected text,
which will then be replaced by the command output.
"""
class ExternalCommand(sublime_plugin.TextCommand):
    def run(self, edit, args):
        # nothing selected: process the entire file
        region = sublime.Region(0L, self.view.size())
        
        p = subprocess.Popen(
            args,
            shell   = True,
            bufsize = -1,
            stdout  = subprocess.PIPE,
            stderr  = subprocess.PIPE,
            stdin   = subprocess.PIPE)

        output, error = p.communicate(self.view.substr(region).encode('utf-8'))

        if error:
            sublime.errorMessage(error.decode('utf-8'))
        else:
            edit.replace(region, output.decode('utf-8'))
0 Likes

#5

[quote=“nachocab”]So, I’m trying something like this, but I can’t get it to work

edit.replace(region, output.decode('utf-8')) [/quote]

You aren’t calling replace correctly, it’s a View method. There should have been an error message in the console. Try:

self.view.replace(edit, region, output.decode('utf-8'))
0 Likes

#6

When I do that, sublime crashes and I don’t know how to fix it because I can’t see the error message. Is there a way to debug this? I’m pretty new at this.

0 Likes

#7

I found this post when searching google to find out how to apply a unix command to a selection in sublime and it provided a great start for a solution. Here is a version of the original code that does the job. It’d be great if sublime could have a similar feature built in or this command bundled.

To use it, select some text and then from the console enter “view.run_command(‘external_filter’)”, sublime will prompt you for a command, enter a valid unix command and it will pipe your selection through the command and replace the text with it’s output.

import sublime
import sublime_plugin
import subprocess

# view.run_command('external_filter')
class ExternalFilterCommand(sublime_plugin.TextCommand):
  def run(self, edit):
    self.view.window().show_input_panel('Command', '',
      lambda command: self.runCommand(edit, command),
      None, None)

  def runCommand(self, edit, command):
    regions = self.view.sel()
    if len(regions) == 1 and regions[0].empty():
      # No selection use the entire buffer
      regions = [sublime.Region(0, self.view.size())]

    for region in regions:
      self.execCommand(edit, command, region)  

  def execCommand(self, edit, command, region):
    p = subprocess.Popen(command, shell=True, bufsize=-1,
      stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    output, error = p.communicate(self.view.substr(region).encode('utf-8'))
    if error:
      sublime.error_message(error.decode('utf-8'))
    else:
      self.view.replace(edit, region, output.decode('utf-8'))
0 Likes

#8

This just needs to be included in the default distribution.
Select buffer, press hotkey, prompt for command, replace buffer with command output.

0 Likes

#9

Late to the party, but for anyone searching, here is the FilterPipes addon:

https://packagecontrol.io/packages/FilterPipes

0 Likes

#10

Just found this really useful. Thanks!

0 Likes