Set aliases for characters, strings or complete lines
UNLESS you are using wayland (Ubuntu 17.10, tested on Ubuntu Budgie 18.04, but Ubuntu Gnome 18.04 should be fine too), the snippet below will help you out.
How it works in practice
- Press Ctrl + J (or any other shortcut you set)
A box appears

Type your "alias" (e.g. jj for m), the result shows (m), and the text will immediately be inserted at cursor position (or, if you prefer, after tapping Ctrl).
This script provides a single solution to set aliasses for a character, a string or even complete lines, just set the "alias" in the lines:
replacements = [
["jj", "m"],
["aa", "q"],
["zz", "e"],
["mb", "monkey eats banana"],
]
In the latter case, typing "mb" will paste "monkey eats banana":

Setting up
You need to satisfy a few dependencies:
Log out and back in.
Copy the script below into an empty file, save it as replace_keys.py
#!/usr/bin/env python3
import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Wnck", "3.0")
from gi.repository import Gtk, Gdk, Wnck
import subprocess
import pyperclip
import pyautogui
import time
"""
depends on
- pyautogui:
pip3 install pyautogui
- pyperclip:
sudo apt install python3-pyperclip xsel xclip
"""
act_on_firstmatch = False
replacements = [
["jj", "m"],
["aa", "q"],
["zz", "e"],
["mb", "monkey eats banana"],
]
class KeyWin(Gtk.Window):
def __init__(self):
self.screendata = Wnck.Screen.get_default()
self.screendata.force_update()
self.curr_subject = self.screendata.get_active_window().get_xid()
self.currmatch = ""
Gtk.Window.__init__(self)
maingrid = Gtk.Grid()
self.add(maingrid)
self.set_decorated(False)
self.set_position(Gtk.WindowPosition.CENTER)
self.connect("key-release-event", self.check_key)
self.keyentry = Gtk.Entry()
self.keyentry.connect("changed", self.update_current)
self.label = Gtk.Label("")
self.label.set_width_chars(10)
maingrid.attach(self.keyentry, 0, 0, 1, 1)
maingrid.attach(self.label, 1, 0, 1, 1)
self.show_all()
self.connect("destroy", Gtk.main_quit)
Gtk.main()
def update_current(self, widget):
curr = self.keyentry.get_text()
self.currmatch = ""
for s in replacements:
if curr == s[0]:
self.currmatch = s[1]
if act_on_firstmatch:
self.replace()
self.label.set_width_chars(len(self.currmatch) + 4)
self.label.set_text(self.currmatch)
def replace(self, *args):
pyperclip.copy(self.currmatch)
subprocess.call(["wmctrl", "-ia", str(self.curr_subject)])
Gtk.main_quit()
def check_key(self, button, val):
typed = Gdk.keyval_name(val.keyval)
if typed == "Control_L":
self.replace()
KeyWin()
time.sleep(0.05)
pyautogui.hotkey('ctrl', 'v')
Set up your aliasses (KEEP THE INDENTATION!) in the section:
replacements = [
["jj", "m"],
["aa", "q"],
["zz", "e"],
["mb", "monkey eats banana"],
]
If you want, change
act_on_firstmatch = False
into
act_on_firstmatch = True
if you like to insert immediately without tapping Ctrl
Set up a shortcut key with Ctrl as modifier. I used Ctrl + J in my test to run the script by the command:
python3 /path/to/replace_keys.py
And you're done!