<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<atom:link href="https://dev1galaxy.org/extern.php?action=feed&amp;tid=2751&amp;type=rss" rel="self" type="application/rss+xml" />
		<title><![CDATA[Dev1 Galaxy Forum / customizable Unicode international keyboard]]></title>
		<link>https://dev1galaxy.org/viewtopic.php?id=2751</link>
		<description><![CDATA[The most recent posts in customizable Unicode international keyboard.]]></description>
		<lastBuildDate>Sun, 24 Mar 2019 11:05:23 +0000</lastBuildDate>
		<generator>FluxBB</generator>
		<item>
			<title><![CDATA[Re: customizable Unicode international keyboard]]></title>
			<link>https://dev1galaxy.org/viewtopic.php?pid=15026#p15026</link>
			<description><![CDATA[<p>I forgot to mention that <strong>the scripts assumes you are using a UTF-8 locale</strong>. The script just won&#039;t work if it finds itself in a non-UTF-8 environment. Here is a quick tutorial on locales:</p><p>To see your current locale, run <span class="bbc">locale</span></p><p>To see locales that are ready to use on your machine, run <span class="bbc">locale -a</span></p><p>If you want to switch to a locale that is not ready to use on your machine, you have to generate it:<br />manually edit <em>/etc/locale.gen</em> and uncomment the locale you want, then run <span class="bbc">locale-gen</span> as root</p><p>To change your locale, put the one you want in <em>/etc/default/locale</em> (for example, <em>LANG=en_US.UTF-8</em>) then reboot.</p>]]></description>
			<author><![CDATA[dummy@example.com (GNUser)]]></author>
			<pubDate>Sun, 24 Mar 2019 11:05:23 +0000</pubDate>
			<guid>https://dev1galaxy.org/viewtopic.php?pid=15026#p15026</guid>
		</item>
		<item>
			<title><![CDATA[customizable Unicode international keyboard]]></title>
			<link>https://dev1galaxy.org/viewtopic.php?pid=15023#p15023</link>
			<description><![CDATA[<p>I like using my own custom &quot;hotstrings&quot; for invoking Unicode characters (e.g., <span class="bbc">cx</span> for <span class="bbc">ĉ</span>, <span class="bbc">a&#039;</span> for <span class="bbc">á</span>, <span class="bbc">c,,</span> for <span class="bbc">ç</span>) so I decided to create a python3 script that does this easily for me. Thought I&#039;d post my solution here in case it is useful to anyone.</p><p>To use the script you need to install a few dependencies (some packages and two python3 modules). Run these two commands in a terminal to get all the dependencies:</p><div class="codebox"><pre><code>$ sudo apt install python3 python3-pip x11-xserver-utils procps libnotify-bin xclip yad
$ pip3 install pynput Xlib --user</code></pre></div><p>After that, all you need is the script and a config file.</p><p>Here is the script:</p><div class="codebox"><pre class="vscroll"><code>#!/usr/bin/env python3

# klavaro 2.0
# Copyright (c) 2019 Bruno &quot;GNUser&quot; Dantas &lt;klavaro@dantas.airpost.net&gt;
# This is free software, released under the terms of the ISC license:
# Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby
# granted, provided that the above copyright notice and this permission notice appear in all copies.
# THE SOFTWARE IS PROVIDED &quot;AS IS&quot; AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE 
# FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 

from pynput import keyboard
from pynput import mouse
keyboard0 = keyboard.Controller()
mouse0 = mouse.Controller()
import os
import sys
import time

def log_it(keystroke):
	&quot;&quot;&quot;High level function that logs keystroke, checks if last keystrokes 
	match a hotsring/trigger, replaces trigger with corresponding Unicode character&quot;&quot;&quot;
	global mappings
	global last_strokes
	del last_strokes[0]
	last_strokes.append(keystroke)
	last_strokes_str = &#039;&#039;.join(last_strokes)
	#print(&quot;last strokes = &quot; + last_strokes_str) # for debugging
	for trigger in mappings.keys():
		if last_strokes_str.endswith(trigger):
			character = mappings[trigger]
			backspaces = len(trigger)
			#print(&quot;replacing &quot; + trigger + &quot; with &quot; + character) # for debugging
			while backspaces &gt; 0:
				keyboard0.press(keyboard.Key.backspace)
				keyboard0.release(keyboard.Key.backspace)
				backspaces -= 1
			os.system(&#039;&#039;&#039;xclip -o -selection clipboard | xclip -selection secondary&#039;&#039;&#039;) # save clipboard contents to secondary
			os.system(&#039;&#039;&#039;printf %s | xclip -selection clipboard&#039;&#039;&#039; % character) # feed unicode character to clipboard
			keyboard0.press(keyboard.Key.ctrl) # press Ctrl+v to paste from clipboard
			keyboard0.press(&#039;v&#039;)
			keyboard0.release(&#039;v&#039;)
			keyboard0.release(keyboard.Key.ctrl)
			time.sleep(0.5) # don&#039;t restore clipboard too quickly (some applications, e.g. qterminal, need a moment to react to Ctrl+v)
			os.system(&#039;&#039;&#039;xclip -o -selection secondary | xclip -selection clipboard&#039;&#039;&#039;) # restore clipboard contents from secondary

def on_press(key): 
	&quot;&quot;&quot;Keylogger runs this function on each keyboard event&quot;&quot;&quot;
	global capslock_in_effect
	output = str(key)
	if output == &#039;Key.caps_lock&#039;: # if capslock pressed, toggle capslock state
		capslock_in_effect = not capslock_in_effect
	if not output.startswith(&#039;Key&#039;): # pynput calls special keys &#039;Key.foo&#039;
		output = output[1:-1] # remove quotes around alphanumeric key names
		if capslock_in_effect:
			output = output.swapcase() 
			# .swapcase and not .upper because pressing Shift during CapsLock should log a lowercase letter
	if not output.startswith(&#039;Key.shift&#039;): # log all keystrokes except shift (e.g., so that a~ is logged without an intervening Shift)
		if output.startswith(&#039;Key.&#039;): # log special keystrokes as a space
			output=&#039; &#039;
		log_it(output)

def on_click(x, y, button, pressed):
	&quot;&quot;&quot;Keylogger runs this function on each mouse event&quot;&quot;&quot;
	button = str(button)
	if pressed and button == &#039;Button.left&#039;: # log left clicks as a space
		log_it(&#039; &#039;)

def start():
	# 1. Build mappings from klavaro.conf
	global mappings
	mappings = {}
	abspath=os.path.realpath(sys.argv[0])
	dirname=os.path.dirname(abspath)

	with open(&#039;%s/klavaro.conf&#039; % dirname) as f:
		for line in f:
			(trigger, character) = line.split()
			mappings[trigger] = character

	# 2. Initialize an empty list to hold last few keystrokes
	global last_strokes
	last_strokes = [ &#039;&#039; ] * 5 
	
	# 3. Create taskbar icon
	os.system(&#039;&#039;&#039;yad --notification --image=keyboard --text=&quot;Klavaro&quot; --no-middle --menu=&quot;Exit!klavaro stop!application-exit&quot; --listen &amp; echo $! &gt;/tmp/klavaro-icon-pid&#039;&#039;&#039;)
	
	# 4. Get initial CapsLock state
	global capslock_in_effect
	exit_code = os.system(&#039;&#039;&#039;xset q | grep -q &#039;Caps Lock:[[:space:]]*on&#039; &#039;&#039;&#039;)
	if exit_code == 0:
		capslock_in_effect = True
	else:
		capslock_in_effect = False

	# 5. Finally, start keylogger
	with mouse.Listener(on_click=on_click) as listener:
		with keyboard.Listener(on_press=on_press) as listener:
			listener.join()
	
#####

def stop():
	os.system(&#039;&#039;&#039;kill $(cat /tmp/klavaro-icon-pid); rm /tmp/klavaro-icon-pid&#039;&#039;&#039;)
	os.system(&#039;&#039;&#039;pkill -f klavaro&#039;&#039;&#039;)

#####

if sys.argv[1] == &quot;start&quot;:
	try:
		os.stat(&#039;/tmp/klavaro-icon-pid&#039;)
	except: 
		start()
	else: 
		os.system(&#039;&#039;&#039;notify-send -i dialog-warning -t 2000 &quot;Klavaro&quot; &quot;Klavaro is already running&quot;&#039;&#039;&#039;)
		sys.exit()

elif sys.argv[1] == &quot;stop&quot;:
	stop()</code></pre></div><p>Here is my config file, which lists my hotstrings and corresponding Unicode characters (modify* it to suit your needs):</p><div class="codebox"><pre class="vscroll"><code>A` À
a` à
A&#039; Á
a&#039; á
A^ Â
a^ â
A~ Ã
a~ ã
A:: Ä
a:: ä
E` È
e` è
E&#039; É
e&#039; é
E^ Ê
e^ ê
E~ Ẽ
e~ ẽ
E:: Ë
e:: ë
I` Ì
i` ì
I&#039; Í
i&#039; í
I^ Î
i^ î
I~ Ĩ
i~ ĩ
I:: Ï
i:: ï
O` Ò
o` ò
O&#039; Ó
o&#039; ó
O^ Ô
o^ ô
O~ Õ
o~ õ
O:: Ö
o:: ö
U` Ù
u` ù
U&#039; Ú
u&#039; ú
U^ Û
u^ û
U~ Ũ
u~ ũ
U:: Ü
u:: ü
C,, Ç
c,, ç
Cx Ĉ
CX Ĉ
cx ĉ
Gx Ĝ
GX Ĝ
gx ĝ
Hx Ĥ
HX Ĥ
hx ĥ
Jx Ĵ
JX Ĵ
jx ĵ
Sx Ŝ
SX Ŝ
sx ŝ
Ux Ŭ
UX Ŭ
ux ŭ</code></pre></div><p>To use the script, save it as <em>klavaro</em> (it means &quot;keyboard&quot; in Esperanto), make it executable, and put it somewhere in your PATH. Save the config file as <em>klavaro.conf</em> and put it in the same directory as the script.</p><p>To start the script:</p><div class="codebox"><pre><code>$ klavaro start &amp;</code></pre></div><p>To end the script:</p><div class="codebox"><pre><code>$ klavaro stop</code></pre></div><p>While the script is running, hotstrings will magically be converted to their corresponding Unicode character in any application that supports Control+v to paste from clipboard. (For the magic to happen in a terminal emulator, you may need to go to emulator&#039;s settings and change the paste shortcut from Shift+Control+v to Control+v.)</p><p>The script is tested and working (hard and on a daily basis) on Devuan ASCII and OpenBSD 6.4, but should work on any Unix-like OS. I love this script so much, I wish I had cooked it up years ago. Hopefully others will also find it useful <img src="https://dev1galaxy.org/img/smilies/smile.png" width="15" height="15" alt="smile" /></p><p>-------------------------------</p><p><span class="bbu">How it works</span><br />Script waits for you to type one of the hotstrings. When you do, the script very quickly does the following:<br />1. Presses appropriate number of backspaces to erase the hotstring<br />2. Saves current clipboard** contents<br />3. Puts Unicode character in clipboard<br />4. Pastes Unicode character at cursor position<br />5. Restores clipboard contents</p><p>-------------------------------</p><p><span class="bbu">Footnotes</span></p><p>* Adding new Unicode characters to <em>klavaro.conf</em> may seem like a &quot;chicken and the egg&quot; problem, but it isn&#039;t hard. First, find the code point for the character you want <a href="https://unicode-table.com/en/" rel="nofollow">here</a> (for example, the code for <span class="bbc">ĉ</span> is 0109). Then, open <em>klavaro.conf</em> in a GUI text editor that supports the Shift+Control+u method of inserting Unicode characters (pluma, gedit, and geany support this, among many others). For my example, pressing Shift+Control+u, then typing 0109, then pressing Enter creates <span class="bbc">ĉ</span>. Easy peasy!</p><p>** Using the clipboard was a workaround due to the fact that all the &quot;typing&quot; utilities I explored (xdotool, xvkbd, pynput) either had no Unicode support or only partial support. The X clipboard, on the other hand, can handle everything.</p>]]></description>
			<author><![CDATA[dummy@example.com (GNUser)]]></author>
			<pubDate>Sun, 24 Mar 2019 03:15:25 +0000</pubDate>
			<guid>https://dev1galaxy.org/viewtopic.php?pid=15023#p15023</guid>
		</item>
	</channel>
</rss>
