~aren/zig-input-method

a450d0f84a4a51b44e89be6de4ee6656c502eead — ArenM 8 months ago 303efa1 main
handle gestures and prediction at the same time
3 files changed, 71 insertions(+), 31 deletions(-)

M README.md
M input-method.zig
M scripts/manager.sh
M README.md => README.md +13 -9
@@ 21,16 21,20 @@ zig build

# Usage

## Word completion using the input-method protocol
The entire system can be run with the following. This supports both swipe-typing
and prediction based on the current word.

The input-method binary implements the input-method protocol, and uses an
external program to to complete words. This can be compiled and run with
`zig build run-im`.
```
wvkbd-mobintl -O | ./scripts/manager.sh
```

Note that currently only applications that that support the `text_input_v3`
protocol are supported, I've been using gedit for testing. Also for this to be
fully correct wvkbd needs to be patched to *only* output typed characters to
stdout, and not attempt to send them to the compositor.

Currently it only works with text fields in applications that support the
text_input_v3 protocol. I've been using gedit for testing.

## wvkbd swipe-typing
## Using the selector for just wvkbd swipe-typing

The selector program in this repository can be used as a menu for swype-typing
with wvkbd.


@@ 39,7 43,7 @@ with wvkbd.
wvkbd-mobintl -O -L 240 |\
  swipeguess wordsSorted.txt 20 |\
  stdbuf -oL sed -e 's/^/\x1Bclear\n/g' -e 's/\t/\n/g' |\
  ./zig-out/bin/selector | 
  ./zig-out/bin/selector |\
  completelyTypeWord.sh
```



@@ 76,7 80,7 @@ In Scope:
 - provide current word
 - provide surrounding words
 - provide input field type
 - send send selected text to the compositor
 - send selected text to the compositor
 - change the current word (for autocorrect)
 - send partial words, only possible sometimes
   (with input-method but not virtual-keyboard)

M input-method.zig => input-method.zig +7 -2
@@ 122,12 122,17 @@ fn typedText(ctx: *InputState, line: []const u8) void {

fn processLine(ctx: *InputState, line: []const u8) void {
  // We must have at least an operation, and a char
  if (line.len < 2) return;
  if (line.len < 2) {
    print("Input command too short: {s}\n", .{line});
    return;
  }

  switch (line[0]) {
    't' => typedText(ctx, line[1..]),
    'w' => predictedLine(ctx, line[1..]),
    else => {}
    else => {
      print("Unknown input command: {s}\n", .{line});
    }
  }
}


M scripts/manager.sh => scripts/manager.sh +51 -20
@@ 1,5 1,9 @@
#! /bin/bash

# NOTE: The shebang is set to bash becaues this requires string indexing

cd "$(dirname "$0")"

# Cleanup
finish() {
  trap - TERM INT EXIT


@@ 10,33 14,60 @@ trap 'finish' TERM INT EXIT

# Create fifo file to talk to the input-method
TMP=$(mktemp -d)
mkfifo "$TMP/3"
exec 3<> "$TMP/3"
mkfifo "$TMP/4"
exec 4<> "$TMP/4"
for fd in $(seq 3 5); do
  mkfifo "$TMP/$fd"
  eval "exec $fd<> '$TMP/$fd'"
done

# Since we have file descriptors, we don't need the files anymore
rm "$TMP/4"
rm "$TMP/3"
rm -r "$TMP"

# Process the key events before sending them to the input-method
# Reading from fd 0 is required so we can put this in the background
# TODO: how does swipeguess fit here?
# swipeguess needs to:
#  - send the first char
#  - send it's words to the selector
stdbuf -o0 sed \
  -e 's/^/t/' \
  <&0 >&3 &
  # -e 's/^$/\n/g' \ # Empty lines are a return char

../zig-out/bin/input-method <&3 >&4 &

# Process lines from stdin
while read -r line; do
  if [ "${#line}" -eq 1 ]; then
    echo "key: $line"
    echo ".i" >&4
    printf "t%s\n" "$line" >&3
  else
    echo "swipe: $line"
    echo ".s" >&4
    echo "$line" >&5
  fi
done <&0 &

# Send updates to the input method
../zig-out/bin/input-method <&3 | stdbuf -o0 sed 's/^/i/' >&4 &

# Run swipeguess
../swipeguess /usr/share/dict/usa 20 <&5 | stdbuf -o0 sed 's/^/s/' >&4 &

complete_swipe() {
  echo "Completing swipe" >&2

  [ -z "$1" ] && return
  printf '\033clear\n'
  [ "$line" = "" ] && continue
  # grep "^$line" /usr/share/dict/usa | head -n 30
  grep "^$line" ../wordsSorted.txt | head -n 30
done <&4 | ../zig-out/bin/selector | stdbuf -o0 sed 's/^/w/' >&3 &
  echo "$1" | stdbuf -o0 sed 's/\t/\n/g'
}

complete_word() {
  echo "Completing word" >&2

  printf '\033clear\n'
  [ -z "$1" ] && return
  grep "^$1" /usr/share/dict/usa | head -n 30
}

# Handle output from the input method
source="i";
while read -r line; do
  case "$line" in
    "."*) source="${line:1:2}" ;;
    "i"*)if [ "$source" == "i" ]; then complete_word "${line:1}"; fi ;;
    "s"*) if [ "$source" == "s" ]; then complete_swipe "${line:1}"; fi ;;
  esac
done <&4 | ../zig-out/bin/selector 2>/dev/null | stdbuf -o0 sed 's/^/w/' >&3 &

wait