Skip to content

Instantly share code, notes, and snippets.

@AdamGagorik
Last active January 2, 2025 20:58
Show Gist options
  • Save AdamGagorik/23e98e437e35da67ad07c6cadf56747b to your computer and use it in GitHub Desktop.
Save AdamGagorik/23e98e437e35da67ad07c6cadf56747b to your computer and use it in GitHub Desktop.
Convert clipboard contents from markdown to html
#!/usr/bin/env python3
"""
Convert the contents of the clipboard from markdown to html that can be pasted into editors expecting rich text.
# Read input from clipboard (default)
➜ echo "**TEST**" | cb
➜ mdclip
# Read input from command line
➜ mdclip ":smile:"
"""
import argparse
import logging
import subprocess
def main() -> int:
parser = argparse.ArgumentParser(
prog="mdclip",
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
usage="mdclip [-h] [text]",
)
parser.add_argument("--notify-error", action="store_true", help="send system notification on error")
parser.add_argument("--notify-success", action="store_true", help="send system notification on success")
parser.add_argument("--notify-error-timeout", type=int, default=-1, help="system notification timeout on error")
parser.add_argument("--notify-success-timeout", type=int, default=1, help="system notification timeout on success")
opts, remaining = parser.parse_known_args()
cb_text = " ".join(remaining).strip()
if not cb_text:
cb_text = get_cb()
if not cb_text:
notify(opts.notify_error, "Clipboard empty!", kind="error", timeout=opts.notify_error_timeout)
raise ValueError("clipboard is empty!")
out_text = md_to_html(cb_text)
if out_text is not None:
logging.info(out_text)
set_cb(out_text)
notify(opts.notify_success, "Clipboard transformed!", timeout=opts.notify_success_timeout)
return 0
notify(opts.notify_error, "Clipboard conversion failed!", kind="error", timeout=opts.notify_error_timeout)
return 1
def notify(trigger: bool, message: str, kind: str = "info", timeout: int = -1) -> None:
if trigger:
subprocess.run([
"/usr/bin/zenity",
f"--{kind}",
"--title",
"mdclip",
"--text",
message,
f"--timeout={timeout}",
"--no-markup",
])
def get_cb() -> str:
return subprocess.run(
["/usr/bin/xclip", "-o", "-selection", "clipboard"],
capture_output=True,
check=True,
text=True,
).stdout.rstrip()
def set_cb(out_text: str) -> None:
subprocess.run(
["/usr/bin/xclip", "-t", "text/html", "-selection", "clipboard"],
input=out_text,
check=True,
text=True,
)
def md_to_html(md_text: str) -> str | None:
try:
result = subprocess.run(
["/home/linuxbrew/.linuxbrew/bin/pandoc", "--from", "gfm+emoji+alerts", "--to", "html", "-"],
capture_output=True,
input=md_text,
check=True,
text=True,
)
except Exception:
logging.exception("can not convert text to rtf!")
else:
return result.stdout.rstrip()
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
raise SystemExit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment