2020-12-09 15:20:26 +00:00
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
import shlex
|
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
import tempfile
|
|
|
|
|
2021-05-13 19:20:19 +00:00
|
|
|
from voussoirkit import betterhelp
|
2020-12-09 15:20:26 +00:00
|
|
|
from voussoirkit import pipeable
|
|
|
|
from voussoirkit import subproctools
|
|
|
|
from voussoirkit import winwhich
|
2021-09-23 06:17:12 +00:00
|
|
|
from voussoirkit import vlogging
|
|
|
|
|
|
|
|
log = vlogging.getLogger(__name__, 'tempeditor')
|
2020-12-09 15:20:26 +00:00
|
|
|
|
|
|
|
class NoEditor(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
class BadStatus(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def tempeditor(initial_text=None):
|
|
|
|
editor = os.environ.get('EDITOR')
|
|
|
|
if not editor:
|
|
|
|
raise NoEditor('You do not have an EDITOR variable.')
|
|
|
|
|
|
|
|
command = shlex.split(editor)
|
|
|
|
command[0] = winwhich.which(command[0])
|
|
|
|
|
|
|
|
file = tempfile.TemporaryFile('r+', encoding='utf-8', prefix='tempeditor-', delete=False)
|
|
|
|
command.append(file.name)
|
|
|
|
|
|
|
|
if initial_text:
|
|
|
|
file.write(initial_text)
|
|
|
|
|
|
|
|
# The text editor may not be allowed to write to the file while Python has
|
|
|
|
# the file handle, so let's close it and re-open after the user is finished.
|
|
|
|
file.close()
|
|
|
|
|
|
|
|
status = subprocess.check_call(command)
|
|
|
|
if status == 0:
|
|
|
|
handle = open(file.name, 'r', encoding='utf-8')
|
|
|
|
text = handle.read()
|
|
|
|
handle.close()
|
|
|
|
|
|
|
|
try:
|
|
|
|
os.remove(file.name)
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if status == 0:
|
|
|
|
return text
|
|
|
|
else:
|
|
|
|
raise BadStatus(subproctools.format_command(command), status)
|
|
|
|
|
|
|
|
def tempeditor_argparse(args):
|
2021-09-23 06:20:15 +00:00
|
|
|
if args.initial_text is None:
|
|
|
|
initial_text = None
|
|
|
|
else:
|
2021-08-17 21:06:07 +00:00
|
|
|
initial_text = pipeable.input(args.initial_text, split_lines=False)
|
|
|
|
|
2020-12-09 15:20:26 +00:00
|
|
|
try:
|
2021-09-23 06:20:15 +00:00
|
|
|
text = tempeditor(initial_text=initial_text)
|
2021-05-25 08:35:46 +00:00
|
|
|
pipeable.stdout(text)
|
2020-12-09 15:20:26 +00:00
|
|
|
return 0
|
|
|
|
except NoEditor as exc:
|
2021-09-23 06:17:12 +00:00
|
|
|
log.fatal(exc)
|
2020-12-09 15:20:26 +00:00
|
|
|
return 1
|
|
|
|
except BadStatus as exc:
|
2021-09-23 06:17:12 +00:00
|
|
|
log.fatal(f'Command {exc.args[0]} returned status {exc.args[1]}.')
|
2020-12-09 15:20:26 +00:00
|
|
|
return 1
|
|
|
|
|
2021-09-23 06:17:12 +00:00
|
|
|
@vlogging.main_decorator
|
2020-12-09 15:20:26 +00:00
|
|
|
def main(argv):
|
2022-02-13 03:50:00 +00:00
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description='''
|
|
|
|
This program allows you to use your preferred text editor as an
|
|
|
|
intermediate step in a processing pipeline. The user will use the text
|
|
|
|
editor to edit a temp file, and when they close the editor the contents
|
|
|
|
of the temp file will be sent to stdout.
|
|
|
|
''',
|
|
|
|
)
|
|
|
|
|
|
|
|
parser.add_argument(
|
|
|
|
'--text',
|
|
|
|
dest='initial_text',
|
|
|
|
default=None,
|
|
|
|
type=str,
|
|
|
|
help='''
|
|
|
|
The initial text in the document.
|
|
|
|
Uses pipeable to support !c clipboard, !i stdin.
|
|
|
|
If not provided, the user starts with a blank document.
|
|
|
|
''',
|
|
|
|
)
|
2020-12-09 15:20:26 +00:00
|
|
|
parser.set_defaults(func=tempeditor_argparse)
|
|
|
|
|
2022-02-13 03:50:00 +00:00
|
|
|
return betterhelp.go(parser, argv)
|
2020-12-09 15:20:26 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
raise SystemExit(main(sys.argv[1:]))
|