command_line: allow external editor for writing

exec
dece 3 years ago
parent 7b9a314481
commit 535ab0aa16

@ -4,7 +4,6 @@ import curses
import curses.ascii
import curses.textpad
import os
import subprocess
import tempfile
from math import inf
@ -13,6 +12,7 @@ from bebop.bookmarks import (
)
from bebop.colors import ColorPair, init_colors
from bebop.command_line import CommandLine
from bebop.external import open_external_program
from bebop.history import History
from bebop.links import Links
from bebop.mouse import ButtonState
@ -428,15 +428,6 @@ class Browser:
save_bookmark(self.current_url, title)
self.reset_status()
def open_external_program(self, command):
"""Pauses the curses modes to open an external program."""
curses.nocbreak()
curses.echo()
subprocess.run(command)
curses.noecho()
curses.cbreak()
self.refresh_windows()
def edit_page(self):
"""Open a text editor to edit the page source.
@ -463,6 +454,7 @@ class Browser:
delete_source_after = True
command.append(source_filename)
self.open_external_program(command)
open_external_program(command)
if delete_source_after:
os.unlink(source_filename)
self.refresh_windows()

@ -3,12 +3,21 @@
import curses
import curses.ascii
import curses.textpad
import os
import tempfile
from bebop.external import open_external_program
from bebop.links import Links
class CommandLine:
"""Basic and flaky command-line à la Vim, using curses module's Textbox."""
"""Basic and flaky command-line à la Vim, using curses module's Textbox.
I don't understand how to get proper pad-like behaviour, e.g. to scroll past
the window's right border when writing more content than the width allows.
Therefore I just added the M-e keybind to call an external editor and use
its content as result.
"""
def __init__(self, window):
self.window = window
@ -78,6 +87,9 @@ class CommandLine:
ch = self.window.getch()
if ch == -1:
raise EscapeCommandInterrupt()
else: # ALT keybinds.
if ch == ord("e"):
self.open_editor(self.gather())
self.window.nodelay(False)
return ch
@ -151,6 +163,27 @@ class CommandLine:
# Everything else could be a control character and should be processed.
return ch
def open_editor(self, existing_content=None):
"""Open an external editor and raise termination interrupt."""
try:
with tempfile.NamedTemporaryFile("w+t", delete=False) as temp_file:
if existing_content:
temp_file.write(existing_content)
temp_filepath = temp_file.name
except OSError:
return
command = ["vi", temp_filepath]
open_external_program(command)
try:
with open(temp_filepath, "rt") as temp_file:
content = temp_file.read()
os.unlink(temp_filepath)
except OSError:
return
raise TerminateCommandInterrupt(content)
class EscapeCommandInterrupt(Exception):
"""Signal that ESC has been pressed during command line."""

@ -0,0 +1,17 @@
"""Call external commands."""
import curses
import subprocess
def open_external_program(command):
"""Call command as a subprocess, suspending curses rendering.
The caller has to refresh whatever windows it manages after calling this
method or garbage may be left on the screen.
"""
curses.nocbreak()
curses.echo()
subprocess.run(command)
curses.noecho()
curses.cbreak()
Loading…
Cancel
Save