Skip to content

Commit

Permalink
feat(command): open external editor command in composing message
Browse files Browse the repository at this point in the history
OPEN_EXTERNAL_EDITOR command paste the composing message in a python tempfile,
run external editor over it and wait the exit before update the message.

$ZULIP_EDITOR_COMMAND and fallback $EDITOR are use for the external editor
command.
  • Loading branch information
mek-yt committed May 24, 2023
1 parent 5d34ef0 commit 2d4ecaf
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
25 changes: 25 additions & 0 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,31 @@ If any of the hotkeys don't work for you, feel free to open an issue or discuss
it on
[#zulip-terminal](https://chat.zulip.org/#narrow/stream/206-zulip-terminal).

## Can I compose messages in another editor ?

In the main branch of zulip-terminal, you can now use an external editor to
compose your message using `ctrl o` shortcut. If `ZULIP_EDITOR_COMMAND` or
`EDITOR` environment variable is set, this command or program would be used
to open the message by appending a temporary file filepath of the current message.

It will work directly for most terminal editors with only the program name `vim`,
`nano`, `helix`, `kakoune`, `nvim`...

It can also be used for desktop editor with some constraint which needs to be
address using `ZULIP_EDITOR_COMMAND` custom command. The program must not fork
or detach from the running terminal and should open in a new window, some
examples:

- [lapce](https://github.com/lapce/lapce) with `lapce -n -w`
- [sublime-text](https://www.sublimetext.com/) with `subl -n -w`
- [marker](https://github.com/fabiocolacio/Marker) with `marker`
- [vim](https://github.com/vim/vim) with `vim -g -f` or `gvim -f`
- [vscode](https://github.com/microsoft/vscode) with `code -n -w`

When the external editor process ends (closing the window or quitting terminal
editor), the composing box will be updated with the new message content from
the temporary file.

## Zulip-term crashed!

We hope this doesn't happen, but would love to hear about this in order to fix
Expand Down
1 change: 1 addition & 0 deletions docs/hotkeys.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
|Autocomplete @mentions, #stream_names, :emoji: and topics|<kbd>ctrl</kbd> + <kbd>f</kbd>|
|Cycle through autocomplete suggestions in reverse|<kbd>ctrl</kbd> + <kbd>r</kbd>|
|Narrow to compose box message recipient|<kbd>meta</kbd> + <kbd>.</kbd>|
|Open the message in external editor|<kbd>ctrl</kbd> + <kbd>o</kbd>|
|Jump to the beginning of line|<kbd>ctrl</kbd> + <kbd>a</kbd>|
|Jump to the end of line|<kbd>ctrl</kbd> + <kbd>e</kbd>|
|Jump backward one word|<kbd>meta</kbd> + <kbd>b</kbd>|
Expand Down
5 changes: 5 additions & 0 deletions zulipterminal/config/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,11 @@ class KeyBinding(TypedDict):
'help_text': 'View user information (From Users list)',
'key_category': 'general',
},
'OPEN_EXTERNAL_EDITOR': {
'keys': ['ctrl o'],
'help_text': 'Open the message in external editor',
'key_category': 'msg_compose',
},
'BEGINNING_OF_LINE': {
'keys': ['ctrl a'],
'help_text': 'Jump to the beginning of line',
Expand Down
30 changes: 30 additions & 0 deletions zulipterminal/ui_tools/boxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
UI boxes for entering text: WriteBox, MessageSearchBox, PanelSearchBox
"""

import os
import re
import shutil
import subprocess
import unicodedata
from collections import Counter
from datetime import datetime, timedelta
from tempfile import NamedTemporaryFile
from time import sleep
from typing import Any, Callable, Dict, List, NamedTuple, Optional, Tuple

Expand Down Expand Up @@ -808,6 +812,32 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
elif is_command_key("MARKDOWN_HELP", key):
self.view.controller.show_markdown_help()
return key
elif is_command_key("OPEN_EXTERNAL_EDITOR", key):
editor = os.environ.get("ZULIP_EDITOR_COMMAND", os.environ.get("EDITOR"))
if editor is None:
self.view.controller.report_error(
"Configure $EDITOR or $ZULIP_EDITOR_COMMAND shell environment."
)
return key
editor_splits = editor.split(" ")
fullpath_program = shutil.which(editor_splits[0])
if fullpath_program is None:
self.view.controller.report_error(
"Editor program not found, check $EDITOR "
"or $ZULIP_EDITOR_COMMAND."
)
return key
editor_splits[0] = fullpath_program
with NamedTemporaryFile(suffix=".md") as edit_tempfile:
with open(edit_tempfile.name, mode="w") as edit_writer:
edit_writer.write(self.msg_write_box.edit_text)
self.view.controller.loop.screen.stop()
editor_splits.append(edit_tempfile.name)
subprocess.call(editor_splits)
with open(edit_tempfile.name, mode="r") as edit_reader:
self.msg_write_box.edit_text = edit_reader.read().rstrip()
self.view.controller.loop.screen.start()
return key
elif is_command_key("SAVE_AS_DRAFT", key):
if self.msg_edit_state is None:
if self.compose_box_status == "open_with_private":
Expand Down

0 comments on commit 2d4ecaf

Please sign in to comment.