Browse Source

Cleaned up the repository. Switching some settings.

No more extra files. I kept Kenji’s READMEs though.
Changed $KTJISHO for $jisho, the default kanji dictionnary is now
$home/lib/kanji.dict, and now switching back to latin is done through Ctrl+t
instead of Ctrl+e.
front
roy niang 3 months ago
parent
commit
3ca14273a4
  1. 4
      Kanji
  2. 33
      README.md
  3. 9
      kanjimerge
  4. 0
      kenji.kanji.dict
  5. 90
      main.c
  6. 467
      main.c.cinap
  7. 6
      mkfile
  8. 84
      pipefile.c
  9. 67
      pipekbd.c

4
Kanji

@ -1,4 +0,0 @@
#!/bin/rc
pipefile -r ktrans /dev/cons
rio -i $home/lib/windows </dev/cons

33
README.md

@ -0,0 +1,33 @@
````
-
ktrans 2000—? Kenji Okamoto
2014—? Cinap Lenrek
2021 roy niang
-
README
````
# ktrans
`ktrans` is an input method on Plan 9 to get somewhat direct access to non-latin graphemes. This version was updated by Kenji and Cinap but due to the lack of prior versionning, I can’t tell who did what and when.
I updated it with some light tweaks and cleaned up the unnecessary files.
## Changes
- `$jisho` replaces `$KTJISHO`
- Ctrl+t replaces Ctrl+e
## Usage
Run `mk install` and add start your next rio session by adding `ktrans` right before rio in your `$home/lib/profile`. The dictionnary to translate kana to kanji is expected to be `$home/lib/kanji.dict` but you can define a custom location with the environment variable `$jisho`.
Your next rio session will start with ktrans enabled. Refer to Kenji’s README for more usage informations, but keep in mind the list of changes. If Shift+Spaced doesn’t work for kanji translation, try Ctrl+\.
## Custom dictionnary
The jisho converted by Kenji is pretty complete. If you need to add missing kanji translations, the best way is to make your own `.dict` file. For convenience, I created the `kanjimerge` script that will merge every `*.kanji.dict` in `$home/lib` into `kanji.dict` or `$jisho`.

9
kanjimerge

@ -0,0 +1,9 @@
#!/bin/rc
# Dictionnary on 9fs://royniang.com/lib/royniang.kanji.dict
if(test -e /env/jisho)
dict=$jisho
if not
dict=$home/lib/test.dict
ssam ',x/;;.*\n/d' $home/lib/*.kanji.dict >> $dict

0
ktrans-jisho → kenji.kanji.dict

90
main.c

@ -8,7 +8,7 @@
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include <bio.h>
#include "ktrans.h"
#include "jisho.h"
@ -24,7 +24,6 @@ int natural = 1; /* not Japanese but English mode */
int changelang(int);
int dotrans(Dictionary*);
int noter(void *, char *);
int nrune(char *);
void send(uchar *, int);
Map *match(uchar *p, int *nc, Map *table);
@ -35,6 +34,61 @@ extern KouhoList *getKouhoFile(DicList*, char *);
extern void freeQDIC(Dictionary*);
extern void selectKouho(KouhoList **, KouhoList*);
void
kbdopen(void)
{
int n, kinfd, koutfd, fd[2];
char buf[128];
int kbd;
kbd = 1;
if((kinfd = open("/dev/kbd", OREAD)) < 0){
kbd = 0;
if((kinfd = open("/dev/cons", OREAD)) < 0)
sysfatal("open kbd: %r");
}
if(bind("#|", "/n/temp", MREPL) < 0)
sysfatal("bind /n/temp: %r");
if((koutfd = open("/n/temp/data1", OWRITE)) < 0)
sysfatal("open kbd pipe: %r");
if(bind("/n/temp/data", kbd? "/dev/kbd": "/dev/cons", MREPL) < 0)
sysfatal("bind kbd pipe: %r");
unmount(nil, "/n/temp");
if(!kbd){
in = kinfd;
out = koutfd;
return;
}
if(pipe(fd) < 0)
sysfatal("pipe: %r");
if(fork()){
in = out = fd[0];
close(fd[1]);
close(kinfd);
close(koutfd);
return;
}
close(fd[0]);
if(fork()){
Biobuf b;
long r;
Binit(&b, fd[1], OREAD);
while((r = Bgetrune(&b)) >= 0){
n = snprint(buf, sizeof(buf), "c%C", (Rune)r)+1;
write(koutfd, buf, n); /* pass on result */
}
} else {
while((n = read(kinfd, buf, sizeof(buf))) > 0){
buf[n-1] = 0;
if(n < 2 || buf[0] != 'c')
write(koutfd, buf, n); /* pass on */
else
write(fd[1], buf+1, n-2); /* to translator */
}
}
exits(0);
}
void
main(int argc, char **argv)
@ -50,20 +104,15 @@ main(int argc, char **argv)
USED(argc);
USED(argv);
dicname = getenv("KTJISHO");
dicname = getenv("jisho");
if(!dicname)
dicname = strcat(getenv("home"), "/lib/ktrans-jisho");
dicname = strcat(getenv("home"), "/lib/kanji.dict");
strcpy(jishoname, dicname);
jisho = openQDIC(jishoname);
in = _IO_stream[0].fd;
out = _IO_stream[1].fd;
if (rfork(RFPROC))
exits(0); /* parent process will die */
atnotify(noter, 1);
kbdopen();
if(fork())
exits(0); /* parent process will exit */
bp = ep = buf; /* bp = base point of input string */
/* ep = end point of input string */
@ -165,16 +214,6 @@ main(int argc, char **argv)
}
}
int
noter(void *x, char *note)
{
USED(x);
if (strcmp(note, "interrupt")==0)
return 1;
else
return 0;
}
int
min(int a, int b)
{
@ -283,7 +322,7 @@ changelang(int c)
return 1;
}
if (c=='') { /* ^e (English mode) */
if (c=='') { /* ^t (English mode) */
natural = 1;
llen = 0;
return 1;
@ -337,7 +376,7 @@ dotrans(Dictionary *dic)
res = lbuf;
for (j=0; *res != L'\0'; j += runetochar(v+j, res++));
v[j++] = '\0';
v[j] = '\0';
strcpy(tbuf, v);
strcpy(hirabuf, v); /* to remeber the initial hiragana input */
if (okuri && joshi != 1) hirabuf[strlen(hirabuf) - 1] = '\0'; /* verb mode */
@ -383,7 +422,7 @@ dotrans(Dictionary *dic)
for (j=0; j<lastlen; j++)
write(out, "\b", 1);
}
for (j=0, lastlen=0; *p != 0; p += j) {
for (lastlen=0; *p != 0; p += j) {
j = chartorune(r, p);
lastlen++;
}
@ -395,7 +434,6 @@ dotrans(Dictionary *dic)
write(out, (char *)okurigana, olen);
olen = okuri = joshi = 0;
okurigana[0] = 0;
nokouho = 1;
break;
}
}

467
main.c.cinap

@ -1,467 +0,0 @@
/*
* Mostly based on the original source codes of Plan 9 release 2
* distribution.
* by Kenji Okamoto, August 4 2000
* Osaka Prefecture Univ.
* okamoto@granite.cias.osakafu-u.ac.jp
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "ktrans.h"
#include "jisho.h"
#define LSIZE 256
Rune lbuf[LSIZE]; /* hiragana buffer for key input written by send() */
Map *table = hira; /* default language conversion table */
uchar okurigana[LSIZE]; /* buffer for okurigana */
char okuri = 0; /* buffer/flag for capital input char */
int in, out;
int llen, olen, joshi = 0;
int natural = 1; /* not Japanese but English mode */
int changelang(int);
int dotrans(Dictionary*);
int nrune(char *);
void send(uchar *, int);
Map *match(uchar *p, int *nc, Map *table);
extern Dictionary *openQDIC(char *);
extern KouhoList *getKouhoHash(Dictionary*, char *);
extern KouhoList *getKouhoFile(DicList*, char *);
extern void freeQDIC(Dictionary*);
extern void selectKouho(KouhoList **, KouhoList*);
void
kbdopen(void)
{
int n, kinfd, koutfd, fd[2];
char buf[128];
int kbd;
kbd = 1;
if((kinfd = open("/dev/kbd", OREAD)) < 0){
kbd = 0;
if((kinfd = open("/dev/cons", OREAD)) < 0)
sysfatal("open kbd: %r");
}
if(bind("#|", "/n/temp", MREPL) < 0)
sysfatal("bind /n/temp: %r");
if((koutfd = open("/n/temp/data1", OWRITE)) < 0)
sysfatal("open kbd pipe: %r");
if(bind("/n/temp/data", kbd? "/dev/kbd": "/dev/cons", MREPL) < 0)
sysfatal("bind kbd pipe: %r");
unmount(nil, "/n/temp");
if(!kbd){
in = kinfd;
out = koutfd;
return;
}
if(pipe(fd) < 0)
sysfatal("pipe: %r");
if(fork()){
in = out = fd[0];
close(fd[1]);
close(kinfd);
close(koutfd);
return;
}
close(fd[0]);
if(fork()){
Biobuf b;
long r;
Binit(&b, fd[1], OREAD);
while((r = Bgetrune(&b)) >= 0){
n = snprint(buf, sizeof(buf), "c%C", (Rune)r)+1;
write(koutfd, buf, n); /* pass on result */
}
} else {
while((n = read(kinfd, buf, sizeof(buf))) > 0){
buf[n-1] = 0;
if(n < 2 || buf[0] != 'c')
write(koutfd, buf, n); /* pass on */
else
write(fd[1], buf+1, n-2); /* to translator */
}
}
exits(0);
}
void
main(int argc, char **argv)
{
uchar *bp, *ep, buf[128];
Map *mp;
int nchar, wantmore;
int n, c;
char jishoname[64], *dicname;
Dictionary *jisho;
USED(argc);
USED(argv);
dicname = getenv("KTJISHO");
if(!dicname)
dicname = strcat(getenv("home"), "/lib/ktrans-jisho");
strcpy(jishoname, dicname);
jisho = openQDIC(jishoname);
kbdopen();
if(fork())
exits(0); /* parent process will exit */
bp = ep = buf; /* bp = base point of input string */
/* ep = end point of input string */
/* buf = unsigned buffer array */
wantmore = 0;
for (;;) { /* key board input loop */
getmore:
if (bp>=ep || wantmore) {
if (wantmore==0)
bp = ep = buf; /* clear all */
n = read(in, ep, &buf[sizeof(buf)]-ep); /* read from stdin */
if (n<=0)
exits("");
ep += n; /* ep => end point of input string */
*ep = '\0';
}
while (bp<ep) { /* there are input data */
if (table == hira && natural != 1 && (*bp>'A' && *bp<='Z') && ep-bp<2
&& !strchr("EIOU", *bp)) {
wantmore = 1;
goto getmore;
}
if (!fullrune((char *)bp, ep-bp)) { /* not enough length of input */
wantmore = 1;
goto getmore;
}
wantmore = 0;
if (*bp=='') { /* ^x read ktrans-jisho once more */
freeQDIC(jisho);
jisho = openQDIC(jishoname);
llen = 0;
olen = okuri = joshi = 0;
wantmore=0;
bp=ep=buf;
continue;
}
if (*bp=='') { /* Shift+Space (start translate comannd) */
c = dotrans(jisho);
if (c)
*bp = c; /* pointer to translated rune */
else
bp++;
continue;
}
if (*bp==' ') { /* ^l (no translate comannd) */
bp++;
llen = 0;
olen = okuri = joshi = 0;
continue;
}
if (changelang(*bp)) { /* change language mode OK */
bp++;
olen = okuri = joshi = 0;
continue;
}
if (natural || *bp<=' ' || *bp>='{') { /* English mode but not ascii */
Rune r;
int rlen = chartorune(&r, (char *)bp);
send(bp, rlen); /* write bp to /dev/cons */
bp += rlen;
continue;
}
if (table == hira && (*bp >= 'A' && *bp <= 'Z') && (*(bp+1) < 'A'
|| *(bp+1) > 'Z')) {
*bp = okuri = tolower(*bp);
joshi = olen = 0;
} else if (table == hira && (*bp >= 'A' && *bp <= 'Z') &&
(*(bp+1) >= 'A' && *(bp+1) <= 'Z')) {
*bp = okuri = tolower(*bp);
*(bp+1) = tolower(*(bp+1));
joshi = 1;
olen = 0;
}
/* BUG! we have to hit ^l at every beginning of the new line... sorry
if (table == hira && *bp == '\n') {
Rune r;
int rlen = chartorune(&r, (char *)bp);
send(bp, rlen);
bp++;
olen = okuri = joshi = 0;
continue;
}
*/
mp = match(bp, &nchar, table);
if (mp == 0) {
if (nchar>0) { /* match, longer possible */
wantmore++;
break;
}
send(bp++, 1); /* alphabet in kana mode */
} else {
send((uchar*)mp->kana, strlen(mp->kana));
bp += nchar;
}
}
}
}
int
min(int a, int b)
{
return a<b? a: b;
}
/*
*send UTF string (p) with length (n) to stdout
* and write rune (r) in global lbuf[] buffer
* or okurigana[] buffer if okuri (verb or joshi) mode
*/
void
send(uchar *p, int n)
{
Rune r;
uchar *ep;
if (write(out, (char *)p, n) != n) /* write to stdout */
exits("");
if (llen>LSIZE-64) {
memmove((char*)lbuf, (char*)lbuf+64, 64*sizeof(Rune));
llen -= 64;
}
if (table!=hira || natural)
return;
ep = p+n;
if(okuri) {
while (olen<LSIZE && p<ep) okurigana[olen++] = *p++;
}
else {
while (llen<LSIZE && p<ep) {
p += chartorune(&r, (char*)p);
if (r=='\b') { /* handle backspace */
if (llen>0)
llen--;
continue;
}
if (r==0x80) /* ignore view key */
continue;
/*
if (r<0x3041 || r>0x309e) { reset if out of hiragana range
llen = 0; we use this for okuri-ari entries
continue;
}
*/
lbuf[llen++] = r;
}
}
}
/*
* Romaji to Hiragana/Katakana conversion
* romaji shoud be input as small letter
* returns the matched address in table, hira, kata etc.
* nc: nubmer of character(return value)
*/
Map *
match(uchar *p, int *nc, Map *table)
{
register Map *longp = 0, *kp;
static char last;
int longest = 0;
*nc = -1;
for (kp=table; kp->roma; kp++) {
if (*p == *kp->roma) {
int lr = strlen(kp->roma);
int len = min(lr, strlen((char *)p));
if (strncmp(kp->roma, (char *)p, len)==0) {
if (len<lr) {
*nc = 1;
return 0;
}
if (len>longest) {
longest = len;
longp = kp;
}
}
}
}
if (longp) {
last = longp->roma[longest-1];
*nc = longp->advance;
}
return(longp);
}
int
changelang(int c)
{
if (c==' ') { /* ^k (Japanese Katakana input mode) */
natural = 0;
table = kata;
llen = 0;
return 1;
}
if (c=='') { /* ^n (Japanese hiragana mode ) */
natural = 0;
llen = 0;
table = hira;
return 1;
}
if (c=='') { /* ^e (English mode) */
natural = 1;
llen = 0;
return 1;
}
if (c=='') { /* ^r (Russian mode) */
natural = 0;
table = cyril;
llen = 0;
return 1;
}
if (c=='') { /* ^g (Greek mode ) */
natural = 0;
table = greek;
llen = 0;
return 1;
}
return 0;
}
/*
* write translated kanji runes to stdout
* and returns last charcter if it's not Shift+Space.
* if the last is Shift+Space, proceed translation to next kouho
*/
int
dotrans(Dictionary *dic)
{
Rune *res, r[1];
char v[1024], *p, tbuf[64], hirabuf[64];
int j, lastlen, nokouho = 0;
char ch;
KouhoList *fstkouho, *currentkouho;
if (llen==0)
return 0; /* not use kanji transform function */
if (okuri && joshi != 1) {
lbuf[llen++] = (Rune)okuri;
lbuf[llen] = 0;
}else
lbuf[llen] = 0;
okurigana[olen] = 0;
/*
* search the mached index to the key word from the dict hash table , and
* returns a pointer to the matched kouho if success,
* or returns 0 if failed.
*/
res = lbuf;
for (j=0; *res != L'\0'; j += runetochar(v+j, res++));
v[j] = '\0';
strcpy(tbuf, v);
strcpy(hirabuf, v); /* to remeber the initial hiragana input */
if (okuri && joshi != 1) hirabuf[strlen(hirabuf) - 1] = '\0'; /* verb mode */
if(!(fstkouho = getKouhoHash(dic, v))) { /* not found */
llen = olen = okuri = joshi = 0;
okurigana[0] = 0;
return 0;
}
currentkouho = fstkouho;
for(;;) {
p = currentkouho->kouhotop; /* p to the head of kanji kouho array */
lastlen = nrune(tbuf); /* number of rune chars */
if (okuri && joshi != 1) /* verb mode */
for (j=0; j<lastlen-1; j++)
write(out, "\b", 1); /* clear hiragana input */
else
for (j=0; j<lastlen; j++)
write(out, "\b", 1); /* clear hiragana input */
if (okuri) {
lastlen = nrune((char *)okurigana);
for (j=0; j<lastlen; j++) write(out, "\b", 1);
}
write(out, p, strlen(p)); /* write kanji to stdout */
if (okuri) write(out, (char *)okurigana, olen);
if (read(in, &ch, 1)<=0) /* read from stdin */
exits(0);
if (ch == '') { /* if next input is Shift+Space, once more */
if(currentkouho->nextkouho != 0) { /* have next kouho */
nokouho = 0;
strcpy(tbuf, p);
currentkouho = currentkouho->nextkouho;
if (okuri && joshi != 1) { /* verb mode */
for (j=0; j<nrune(tbuf); j++)
write(out, "\b", 1);
}
continue;
} else { /* the last kouho */
if (okuri) {
lastlen = nrune((char *)okurigana);
for (j=0; j<lastlen; j++)
write(out, "\b", 1);
}
for (lastlen=0; *p != 0; p += j) {
j = chartorune(r, p);
lastlen++;
}
for (j=0; j<lastlen; j++)
write(out, "\b", 1);
if(hirabuf[0])
write(out, hirabuf, strlen(hirabuf));
if(okurigana[0])
write(out, (char *)okurigana, olen);
olen = okuri = joshi = 0;
okurigana[0] = 0;
break;
}
}
else {
if(!nokouho) /* learn the previous use of the kouho */
selectKouho(&(fstkouho->dicitem->kouho), currentkouho);
olen = okuri = joshi = 0;
okurigana[0] = 0;
break;
}
}
llen = 0;
return ch;
}
/*
* returns number of characters in the pointed Rune
*/
int
nrune(char *p)
{
int n = 0;
Rune r;
while (*p) {
p += chartorune(&r, p);
n++;
}
return n;
}

6
mkfile

@ -10,13 +10,9 @@ BIN=/$objtype/bin
</sys/src/cmd/mkone
installfull: install
mkdir /sys/src/cmd/ktrans
dircp ./ /sys/src/cmd/ktrans
install:
cp ktrans.man /sys/man/1/ktrans
echo 'Notice: For a user to use ktrans they must have $home/lib/ktrans-jisho copied from /sys/src/cmd/ktrans!'
uninstall:
rm /sys/man/1/ktrans
rm -r /sys/src/cmd/ktrans
rm /$objtype/bin/ktrans

84
pipefile.c

@ -1,84 +0,0 @@
#include <u.h>
#include <libc.h>
#define TEMP "/n/temp"
void
usage(void)
{
fprint(2, "usage: pipefile [-r command] [-w command] file\n");
exits("usage");
}
void
connect(char *cmd, int fd0, int fd1)
{
switch(rfork(RFPROC|RFFDG|RFREND|RFNOWAIT)){
case -1:
sysfatal("fork %s: %r", cmd);
break;
default:
return;
case 0:
if(fd0 != 0)
dup(fd0, 0);
if(fd1 != 1)
dup(fd1, 1);
execl("/bin/rc", "rc", "-c", cmd, nil);
sysfatal("exec %s: %r", cmd);
break;
}
}
void
main(int argc, char *argv[])
{
char *file;
char *rcmd, *wcmd;
int fd0, fd1, ifd0, ifd1;
rcmd = wcmd = nil;
ARGBEGIN{
case 'r':
rcmd = EARGF(usage());
break;
case 'w':
wcmd = EARGF(usage());
break;
default:
usage();
}ARGEND
if(argc!=1 || (rcmd==nil && wcmd==nil))
usage();
if(rcmd == nil)
rcmd = "/bin/cat";
if(wcmd == nil)
wcmd = "/bin/cat";
file = argv[0];
ifd0 = open(file, OREAD);
if(ifd0 < 0)
sysfatal("open %s: %r", file);
ifd1 = open(file, OWRITE);
if(ifd1 < 0)
sysfatal("open %s: %r", file);
if(bind("#|", TEMP, MREPL) < 0)
sysfatal("bind pipe %s: %r", TEMP);
if(bind(TEMP "/data", file, MREPL) < 0)
sysfatal("bind %s %s: %r", TEMP "/data", file);
fd0 = open(TEMP "/data1", OREAD);
if(fd0 < 0)
sysfatal("open %s: %r", TEMP "/data1");
connect(wcmd, fd0, ifd1);
fd1 = open(TEMP "/data1", OWRITE);
if(fd1 < 0)
sysfatal("open %s: %r", TEMP "/data1");
connect(rcmd, ifd0, fd1);
unmount(nil, TEMP);
exits(nil);
}

67
pipekbd.c

@ -1,67 +0,0 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
void
main(int argc, char *argv[])
{
int n, kinfd, koutfd, fd[2];
char buf[128];
int kbd;
kbd = 1;
if((kinfd = open("/dev/kbd", OREAD)) < 0){
kbd = 0;
if((kinfd = open("/dev/cons", OREAD)) < 0)
sysfatal("open kbd: %r");
}
if(bind("#|", "/n/temp", MREPL) < 0)
sysfatal("bind /n/temp: %r");
if((koutfd = open("/n/temp/data1", OWRITE)) < 0)
sysfatal("open kbd pipe: %r");
if(bind("/n/temp/data", kbd? "/dev/kbd": "/dev/cons", MREPL) < 0)
sysfatal("bind kbd pipe: %r");
unmount(nil, "/n/temp");
if(fork())
exits(nil); /* parent exits */
if(!kbd){
dup(kinfd, 0);
dup(koutfd, 1);
Run:
close(kinfd);
close(koutfd);
if(argv[1][0] != '/' || strncmp(argv[1], "./", 2) != 0 || strncmp(argv[1], "../", 3) != 0)
argv[1] = smprint("/bin/%s", argv[1]);
exec(argv[1], argv+1);
sysfatal("exec: %r");
}
if(pipe(fd) < 0)
sysfatal("pipe: %r");
if(fork()){
dup(fd[0], 0);
dup(fd[0], 1);
close(fd[0]);
close(fd[1]);
goto Run;
}
close(fd[0]);
if(fork()){
Biobuf b;
long r;
Binit(&b, fd[1], OREAD);
while((r = Bgetrune(&b)) >= 0){
n = snprint(buf, sizeof(buf), "c%C", (Rune)r)+1;
write(koutfd, buf, n); /* pass on result */
}
} else {
while((n = read(kinfd, buf, sizeof(buf))) > 0){
buf[n-1] = 0;
if(n < 2 || buf[0] != 'c')
write(koutfd, buf, n); /* pass on */
else
write(fd[1], buf+1, n-2); /* to translator */
}
}
exits(nil);
}
Loading…
Cancel
Save