#!/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()
