Skip to content

Instantly share code, notes, and snippets.

@garaud
Last active October 3, 2023 13:11
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save garaud/06b38554103aa7120337 to your computer and use it in GitHub Desktop.
Save garaud/06b38554103aa7120337 to your computer and use it in GitHub Desktop.
Pipe to Emacs: Insert a result from an UNIX command into a new Emacs buffer
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Author: Damien Garaud
# Date: 2014-2015
# License: Simplified BSD
"""Allow you to pipe command results into an Emacs buffer. Suppose you have an
Emacs server since you launch 'emacsclient'.
Can be use such as:
> ls -l | pipe-to-emacs.py
> hg cat -r 42 filename.py | pipe-to-emacs.py
Copy/paste this code to your ~/bin, make it executable and/or create an alias
'pe'.
It's possible to apply a major-mode if you pass the optional arg such as:
> git show HEAD~4:script.py | pe python-mode
Note: this is a Python3 script.
"""
import os
import sys
import subprocess
EMACS = 'emacsclient'
OPTIONS = '-n'
EVAL = '--eval'
MAXLINE = 100
def escape_filter(data):
"""Escape backslash.
"""
return data.replace('\\', r"\\")
def double_quote_filter(data):
"""Escape double quotes.
"""
return data.replace('"', '\\"')
def read_stdin(maxline=MAXLINE):
"""Read stdin and return the content for each `maxline`
"""
buf = ''
for count, line in enumerate(sys.stdin):
buf += double_quote_filter(escape_filter(line))
if count % maxline == 0:
yield buf
buf = ''
yield buf
def emacs_eval(lisp):
"""Launch emacs with code to evaluate.
"""
cmd = [EMACS, OPTIONS, EVAL, lisp]
return subprocess.call(cmd, stdout=subprocess.DEVNULL)
def create_buffer(name='*piped*'):
elisp = '(pop-to-buffer (get-buffer-create "{}"))'.format(name)
return emacs_eval(elisp)
def insert_to_buffer(name, content):
elisp = ('(with-current-buffer "{0}" '
'(goto-char (point-max)) (insert "{1}"))').format(name, content)
return emacs_eval(elisp)
def set_major_mode(name, mode):
elisp = '(with-current-buffer "{0}" ({1}))'.format(name, mode)
return emacs_eval(elisp)
def main(mode=None):
"""Loop on stding and insert content into an new emacs buffer every `maxline`
linex (50 by default).
"""
bufname = '*piped*'
create_buffer(bufname)
for content in read_stdin():
insert_to_buffer(bufname, content)
if mode is not None:
set_major_mode(bufname, mode)
if __name__ == '__main__':
print("pipe to emacs")
args = sys.argv
# Suppose this is just the name of the Emacs major-mode to apply
if len(args) > 1:
main(args[1])
else:
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment