The officially official Devuan Forum!

You are not logged in.

#1 2017-10-06 12:39:21

GNUser
Member
Registered: 2017-03-16
Posts: 561  

alternative to ibus? ibus suffers from vanishing characters [SOLVED]

I often use ibus to type in other languages. Especially when writing emails, I tend to edit a lot as I go along. The trouble is that in many applications when I click on the screen to move the cursor somewhere, if I'm using ibus then the last character I typed simply disappears.

For example, in mate-terminal, thunderbird, and pluma, if I type this (for example):

ho ho ho

Then click somewhere on the screen, the text turns into this:

ho ho h

Have any of you found a way to type in other languages--with or without ibus--without being affected by this?

I have considered using a keyboard layout with dead keys as a workaround, but I don't like having to type the diacritic before the letter.

--------------
My setup:
- Devuan Jessie with MATE
- ibus 1.5.9-1
- ibus packages installed: ibus, ibus-gtk, ibus-gtk3, ibus-m17n, ibus-qt4

Last edited by GNUser (2017-10-08 01:16:02)

Offline

#2 2017-10-11 17:07:44

GNUser
Member
Registered: 2017-03-16
Posts: 561  

Re: alternative to ibus? ibus suffers from vanishing characters [SOLVED]

I couldn't find anything suitable, so I rolled my own alternative to ibus. It's a simple bash script that allows typing diacritic either before or after the letter, user's choice. The script does not use "preedit text", so no characters ever disappear.

Getting the dependencies:

sudo apt-get install xvkbd python3 && sudo pip3 install pynput

You also need to install yad, which is not in the Devuan Jessie repositories but is easy to find (e.g., by clicking on your architecture at the bottom of this page).

pynput didn't work for me at first because one of its dependencies, the "six" module, was outdated. So, to be safe:

sudo pip3 install --upgrade six

Well, here's the script. It should "just work" once you have all the dependencies. You only need to alter it if you want to add or change the special characters section.

#!/bin/bash

# International keyboard (alternative to ibus for x11)
# Author: Bruno "GNUser" Dantas
# License: GPLv3
# Dependencies: 
#    sudo apt-get install xvkbd python3 yad
#    sudo pip3 install pynput
# Usage: 
#    - Change the triggers and unicode sequences in "watch_for_triggers" function to suit your needs
#    - Run this script as regular user to turn on the international keyboard
#    - Stop the script--via taskbar icon or, if running in terminal, Control+c--to clean up without a trace

main()
{
    create_pipe
    create_keylogger # writes to pipe
    create_taskbar_icon
    watch_for_triggers # reads from pipe, replaces user-defined character combinations with unicode characters
}

create_pipe()
{
    pipe=/tmp/international
    rm -f $pipe
    mkfifo $pipe
    exec 3<>$pipe
}

create_keylogger()
{
    # to troubleshoot the keylogger: 
    # 1. copy the python code below into a file foo
    # 2. comment out the three fifo lines, uncomment the print line in log_it function
    # 3. in a terminal: python3 /path/to/foo
    # 4. type stuff outside the terminal and watch terminal
    echo "
from pynput import keyboard
from pynput import mouse
import os

fifo_write = open('$pipe', 'w')

def log_it(output):
    fifo_write.write(output + '\n')
    fifo_write.flush()
    #print(output)

# get initial capslock state
exit_code = os.system('''xset q 2>/dev/null | grep -q -E 'Caps Lock: +on' ''')
if exit_code == 0:
    capslock_in_effect = True
else:
    capslock_in_effect = False

# this function runs each time a key is pressed:
def on_press(key): 
    global capslock_in_effect
    output = str(key)
    if output == 'Key.caps_lock': # if capslock pressed, toggle capslock state
        capslock_in_effect = not capslock_in_effect
    if not output.startswith('Key'): # special keys start with 'Key' and can be logged as-is
        output = output[1:-1] # remove quotes around character
        if capslock_in_effect:
            output = output.swapcase()
    if not output.startswith('Key.shift'): # don't log shift keys (e.g., while loop expects a~ not aKey.shift~)
        log_it(output)

# this function runs each time a mouse button is pressed:
def on_click(x, y, button, pressed):
    button = str(button)
    if pressed and button == 'Button.left':
        log_it('Key.mousebutton_left')

# start listening
with mouse.Listener(on_click=on_click) as listener:
    with keyboard.Listener(on_press=on_press) as listener:
        listener.join()
" >/tmp/tiny-keylogger
    python3 /tmp/tiny-keylogger &
}

echo "$(basename $0)" >/tmp/scriptname # so cleanup function can find this script's name when called from yad
cleanup()
{
    echo "Cleaning up..."
    pkill -f International # kill taskbar icon                     
    pkill -f tiny-keylogger # kill keylogger
    pkill -KILL "$(cat /tmp/scriptname)" # kill this script         
}
trap cleanup EXIT HUP TERM INT

create_taskbar_icon()
{
    export -f cleanup
    yad --notification --image='accessories-character-map' --text='International Keyboard' \
        --no-middle --menu="Stop!bash -c cleanup" --command='' &
}

replace()
{
    xvkbd -xsendevent -text "\b\b\[U$1]" # send two backspaces then desired unicode character
}

watch_for_triggers()
{
    # endless loop (it reads from a fifo pipe, so never encounters EOF)
    while read current_char; do
        echo "${previous_char}${current_char}" # for debugging while running in terminal
        case "${previous_char}${current_char}" in
          # Portuguese
            'A`') replace 00C0;;
            'a`') replace 00E0;;
            "A'") replace 00C1;;
            "a'") replace 00E1;;
            'A^') replace 00C2;;
            'a^') replace 00E2;;
            'A~') replace 00C3;;
            'a~') replace 00E3;;
            "E'") replace 00C9;;
            "e'") replace 00E9;;
            'E^') replace 00CA;;
            'e^') replace 00EA;;
            "I'") replace 00CD;;
            "i'") replace 00ED;;
            'O`') replace 00D2;;
            'o`') replace 00F2;;
            "O'") replace 00D3;;
            "o'") replace 00F3;;
            'O^') replace 00D4;;
            'o^') replace 00F4;;
            'O~') replace 00D5;;
            'o~') replace 00F5;;
            "U'") replace 00DA;;
            "u'") replace 00FA;;
            'U;') replace 00DC;;
            'u;') replace 00FC;;
            'C;') replace 00C7;;
            'c;') replace 00E7;;
          # Esperanto
            'Cx') replace 0108;;
            'CX') replace 0108;;
            'cx') replace 0109;;
            'Gx') replace 011C;;
            'GX') replace 011C;;
            'gx') replace 011D;;
            'Hx') replace 0124;;
            'HX') replace 0124;;
            'hx') replace 0125;;
            'Jx') replace 0134;;
            'JX') replace 0134;;
            'jx') replace 0135;;
            'Sx') replace 015C;;
            'SX') replace 015C;;
            'sx') replace 015D;;
            'Ux') replace 016C;;
            'UX') replace 016C;;
            'ux') replace 016D;;
        esac
        previous_char=$current_char
    done <&3
}

main

Last edited by GNUser (2017-10-22 01:36:19)

Offline

Board footer