Merge pull request #111 from paul-nameless/custom-cmd

Allow to open current msg with custom cmd
This commit is contained in:
Nameless 2020-07-04 14:28:52 +08:00 committed by GitHub
commit 73d3e535bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 23 deletions

View file

@ -230,3 +230,4 @@ For navigation arrow keys also can be used.
- `]`: next chat
- `[`: prev chat
- `?`: show help
- `!`: open msg with custom cmd

View file

@ -392,15 +392,14 @@ class Controller:
chat = self.model.chats.chats[self.model.current_chat]
return chat["permissions"]["can_send_messages"]
@bind(msg_handler, ["l", "^J"])
def open_current_msg(self) -> None:
msg = MsgProxy(self.model.current_msg)
def _open_msg(self, msg: MsgProxy, cmd: str = None) -> None:
if msg.is_text:
with NamedTemporaryFile("w", suffix=".txt") as f:
f.write(msg.text_content)
f.flush()
with suspend(self.view) as s:
s.open_file(f.name)
if err_msg := s.open_file(f.name, cmd):
self.present_error(err_msg)
return
path = msg.local_path
@ -412,7 +411,21 @@ class Controller:
return
self.tg.open_message_content(chat_id, msg.msg_id)
with suspend(self.view) as s:
s.open_file(path)
if err_msg := s.open_file(path, cmd):
self.present_error(err_msg)
@bind(msg_handler, ["!"])
def open_msg_with_cmd(self) -> None:
"""Open msg or file with cmd: less %s"""
msg = MsgProxy(self.model.current_msg)
if cmd := self.view.status.get_input():
return self._open_msg(msg, cmd)
@bind(msg_handler, ["l", "^J"])
def open_current_msg(self) -> None:
"""Open msg or file with cmd in mailcap"""
msg = MsgProxy(self.model.current_msg)
self._open_msg(msg)
@bind(msg_handler, ["e"])
def edit_msg(self) -> None:
@ -526,13 +539,16 @@ class Controller:
self.resize()
while True:
repeat_factor, keys = self.view.get_keys()
fun = handlers.get(keys, lambda *_: None)
res = fun(self, repeat_factor) # type: ignore
if res == "QUIT":
return res
elif res == "BACK":
return res
try:
repeat_factor, keys = self.view.get_keys()
fun = handlers.get(keys, lambda *_: None)
res = fun(self, repeat_factor) # type: ignore
if res == "QUIT":
return res
elif res == "BACK":
return res
except Exception:
log.exception("Error happend in key handle loop")
def resize_handler(self, signum: int, frame: Any) -> None:
curses.endwin()

View file

@ -15,6 +15,7 @@ import sys
from datetime import datetime
from functools import lru_cache
from logging.handlers import RotatingFileHandler
from subprocess import CompletedProcess
from types import TracebackType
from typing import Any, Optional, Tuple, Type
@ -63,7 +64,7 @@ def setup_log() -> None:
handlers.append(handler)
logging.basicConfig(
format="%(levelname)-8s [%(asctime)s] %(name)s %(message)s",
format="%(levelname)s [%(asctime)s] %(filename)s:%(lineno)s - %(funcName)s | %(message)s",
handlers=handlers,
)
logging.getLogger().setLevel(config.LOG_LEVEL)
@ -71,10 +72,11 @@ def setup_log() -> None:
logging.captureWarnings(True)
def get_file_handler(file_path: str, default: str = None) -> Optional[str]:
def get_file_handler(file_path: str) -> str:
mtype, _ = mimetypes.guess_type(file_path)
if not mtype:
return default
return config.DEFAULT_OPEN.format(file_path=shlex.quote(file_path))
caps = mailcap.getcaps()
handler, view = mailcap.findmatch(caps, mtype, filename=file_path)
if not handler:
@ -181,17 +183,27 @@ class suspend:
def __init__(self, view: Any) -> None:
self.view = view
def call(self, cmd: str) -> None:
subprocess.call(cmd, shell=True)
def call(self, cmd: str) -> CompletedProcess:
return subprocess.run(cmd, shell=True, stderr=subprocess.PIPE)
def run_with_input(self, cmd: str, text: str) -> None:
subprocess.run(cmd, universal_newlines=True, input=text, shell=True)
def open_file(self, file_path: str) -> None:
cmd = get_file_handler(file_path)
if not cmd:
return
self.call(cmd)
def open_file(self, file_path: str, cmd: str = None) -> str:
if cmd:
try:
cmd = cmd % shlex.quote(file_path)
except TypeError:
return "command should contain <%s> which will be replaced by file path"
else:
cmd = get_file_handler(file_path)
proc = self.call(cmd)
if proc.returncode:
stderr = proc.stderr.decode()
log.error("Error happened executing <%s>:\n%s", cmd, stderr)
return stderr
return ""
def __enter__(self) -> "suspend":
for view in (self.view.chats, self.view.msgs, self.view.status):

View file

@ -102,7 +102,7 @@ class StatusView:
self.win.clear()
if not msg:
return
self.win.addstr(0, 0, msg[: self.w])
self.win.addstr(0, 0, msg.replace("\n", " ")[: self.w])
self._refresh()
def get_input(self, msg: str = "") -> str: