So with Linux, `.XCompose` is half-broken. So I decided to make a simple means to turn arbitrary strings into unicode and copy to the clipboard, using a trivial Qt app. This uses the `jda_unicode_table.py` file to define strings, e.g. ```py jda_unicode_table = { "poo": "💩", "rr": "Never Gonna Give You Up, Never Gonna Let You Down", ... } ``` A random thought is that you can use this for arbitrary strings. Moreover, we could use `()` to pass parameters to functions. Essentially when we parse chars, if a char matches a regex `^\w+\(\S+\)$` then we look up in a functions table or something. But I'm not sure I need anything like that. Probably you'd replace the dict with a callable object that you call with what you want expanding. ## The Source ```py #!/usr/bin/env python try: from setproctitle import setproctitle setproctitle("qjda_unicode") except ModuleNotFoundError: pass import PySide6.QtCore import PySide6.QtGui import PySide6.QtWidgets import PySide6.QtNetwork from PySide6.QtCore import Qt import subprocess from jda_unicode_table import jda_unicode_table import re class Input(PySide6.QtWidgets.QTextEdit): def __init__(self,*xs,**kw): super().__init__(*xs,**kw) def keyPressEvent(self,event): modifiers = event.modifiers() text = event.text() key = event.key() if key == Qt.Key_C: #print("C") if modifiers & Qt.ControlModifier: #print("Ctrl") if modifiers & Qt.ShiftModifier: #print("C-S-c") self.parent().doCopy() super().keyPressEvent(event) class Win(PySide6.QtWidgets.QWidget): def __init__(self,*xs,**kw): super().__init__(*xs,**kw) self.resize(800,600) self.input_text = Input(self) self.input_text.resize(800,200) self.input_text.move(0,0) self.input_text.setAcceptRichText(False) self.output_text = PySide6.QtWidgets.QTextEdit(self) self.output_text.resize(800,400) self.output_text.move(0,200) self.output_text.readOnly = True self.output_text.setAcceptRichText(False) # make plain text, make output read only self.input_text.textChanged.connect(self.handleInput) def doCopy(self): src = self.output_text.toPlainText() print("copy",src) PySide6.QtCore.QTimer.singleShot(500, self.afterCopy) self.output_text.setStyleSheet("background-color: #070; color: white") subprocess.run(["pc"],input=src.encode()) def afterCopy(self): self.output_text.setStyleSheet("") def handleInput(self): src = self.input_text.toPlainText() words = re.split(r"\s+",src.strip()) out = [] for word in words: outword = [] for char in word.split(","): if char == "": pass if char in jda_unicode_table: outword.append(jda_unicode_table[char]) else: outword.append(f"({char}?)") out.append("".join(outword)) self.output_text.setPlainText(" ".join(out)) if __name__ == "__main__": app = PySide6.QtWidgets.QApplication() win = Win() win.show() app.exec() ``` ## Command Line Tool ```py #!/usr/bin/env python3 import sys import argparse import re from jda_unicode_table import jda_unicode_table def main(): parser = argparse.ArgumentParser(prog="print_unicode",description="print named unicode chars") parser.add_argument("-n","--newline",action="store_true",help="append newline") parser.add_argument("input_text",nargs="*",help="words separated by spaces, chars in words by commas") ns = parser.parse_args() words = re.split(r"\s+"," ".join(ns.input_text).strip()) out = [] for word in words: outword = [] for char in word.split(","): if char in jda_unicode_table: outword.append(jda_unicode_table[char]) else: outword.append(f"({char}?)") out.append("".join(outword)) print(" ".join(out),end="\n" if ns.newline else "") if __name__ == "__main__": main() ``` And (where `pc` is a cross-platform 'copy to clipboard' script, [see here](/aw/os/shell/CopyPaste)) this command, `copy_unicode` then runs the above and copies. ```bash #!/bin/bash print_unicode "$@" | pc ``` So e.g. `copy_unicode rr,poo` will copy `Never Gonna Give You Up, Never Gonna Let You Down💩`.