|
3 | 3 | """ |
4 | 4 |
|
5 | 5 | import re |
| 6 | +import shlex |
| 7 | +import shutil |
| 8 | +import subprocess |
6 | 9 | import unicodedata |
7 | 10 | from collections import Counter |
8 | 11 | from datetime import datetime, timedelta |
| 12 | +from tempfile import NamedTemporaryFile |
9 | 13 | from time import sleep |
10 | 14 | from typing import Any, Callable, Dict, List, NamedTuple, Optional, Tuple |
11 | 15 |
|
@@ -839,6 +843,47 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]: |
839 | 843 | elif is_command_key("MARKDOWN_HELP", key): |
840 | 844 | self.view.controller.show_markdown_help() |
841 | 845 | return key |
| 846 | + elif is_command_key("OPEN_EXTERNAL_EDITOR", key): |
| 847 | + editor_command = self.view.controller.editor_command |
| 848 | + |
| 849 | + # None would indicate for shlex.split to read sys.stdin for Python < 3.12 |
| 850 | + # It should never occur in practice |
| 851 | + assert isinstance(editor_command, str) |
| 852 | + |
| 853 | + if editor_command == "": |
| 854 | + self.view.controller.report_error( |
| 855 | + "No external editor command specified; " |
| 856 | + "Set 'editor' in zuliprc file, or " |
| 857 | + "$ZULIP_EDITOR_COMMAND or $EDITOR environment variables." |
| 858 | + ) |
| 859 | + return key |
| 860 | + |
| 861 | + editor_command_line: List[str] = shlex.split(editor_command) |
| 862 | + if not editor_command_line: |
| 863 | + fullpath_program = None # A command may be specified, but empty |
| 864 | + else: |
| 865 | + fullpath_program = shutil.which(editor_command_line[0]) |
| 866 | + if fullpath_program is None: |
| 867 | + self.view.controller.report_error( |
| 868 | + "External editor command not found; " |
| 869 | + "Check your zuliprc file, $EDITOR or $ZULIP_EDITOR_COMMAND." |
| 870 | + ) |
| 871 | + return key |
| 872 | + editor_command_line[0] = fullpath_program |
| 873 | + |
| 874 | + with NamedTemporaryFile(suffix=".md") as edit_tempfile: |
| 875 | + with open(edit_tempfile.name, mode="w") as edit_writer: |
| 876 | + edit_writer.write(self.msg_write_box.edit_text) |
| 877 | + self.view.controller.loop.screen.stop() |
| 878 | + |
| 879 | + editor_command_line.append(edit_tempfile.name) |
| 880 | + subprocess.call(editor_command_line) |
| 881 | + |
| 882 | + with open(edit_tempfile.name, mode="r") as edit_reader: |
| 883 | + self.msg_write_box.edit_text = edit_reader.read().rstrip() |
| 884 | + self.view.controller.loop.screen.start() |
| 885 | + return key |
| 886 | + |
842 | 887 | elif is_command_key("SAVE_AS_DRAFT", key): |
843 | 888 | if self.msg_edit_state is None: |
844 | 889 | if self.compose_box_status == "open_with_private": |
|
0 commit comments