diff -urN v2/dbg.py v3/dbg.py --- v2/dbg.py 1970-01-01 09:00:00.000000000 +0900 +++ v3/dbg.py 2018-10-04 22:37:00.000000000 +0900 @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +import sys + +fifo = open('/tmp/fifo', 'w') + +def out(s): + fifo.write(s + '\n') + fifo.flush() +# EOF diff -urN v2/idt.py v3/idt.py --- v2/idt.py 2018-10-02 22:53:13.000000000 +0900 +++ v3/idt.py 2018-10-04 22:37:00.000000000 +0900 @@ -1,22 +1,10 @@ #!/usr/bin/env python -import sys import nkf - -def get_opt(k, def_val=None): - n = len(k) - argv = sys.argv[1:] - typ = type(def_val) - for i in range( len(argv) ): - s = argv[i] - if s[:n] == k: - next = lambda : argv[i+1] if argv[i+1:] else '' - v = s[n:] if s[n:] else next() - return typ(v) if def_val != None and type(v) != typ else v - return def_val +import opt def get_tn(): - return get_opt('-tn', 8) + return opt.get('-tn', 8) def del_tail_spc(s): while s[-1:] in (' ', '\t'): @@ -42,21 +30,30 @@ s = del_tail_spc(s) s = untabify(s) - s = s[ max( get_opt('-d', 0), 0 ) : ] - s = ' ' * max( get_opt('-s', 0), 0 ) + s - s = get_opt('-a', '') + s - s = tabify(s) if get_opt('-t') != None else s + s = s[ max( opt.get('-d', 0), 0 ) : ] + + if opt.index('-s') < opt.index('-a'): + s = ' ' * max( opt.get('-s', 0), 0 ) + s + s = opt.get('-a', '') + s + else: + s = opt.get('-a', '') + s + s = ' ' * max( opt.get('-s', 0), 0 ) + s + + s = tabify(s) if opt.index('-t') >= 0 else s s = del_tail_spc(s) return s if __name__ == "__main__": b = nkf.get_stdin() - (s, opt) = nkf.to_str(b) + (s, nkf_opt) = nkf.to_str(b) - s = '\n'.join( map( cv, s.split('\n') ) ) + (s, tail) = ( s[:-1], s[-1:] ) + if tail != '\n': + (s, tail) = ( s + tail, '' ) + s = '\n'.join( map( cv, s.split('\n') ) ) + tail - o = get_opt('-o', '') - b = nkf.str_to( s, '-' + o if o else opt ) + o = opt.get('-o', '') + b = nkf.str_to( s, '-' + o if o else nkf_opt ) nkf.put_stdout(b) # EOF diff -urN v2/ins.py v3/ins.py --- v2/ins.py 1970-01-01 09:00:00.000000000 +0900 +++ v3/ins.py 2018-10-04 22:37:00.000000000 +0900 @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +import sys +import subprocess as sp +import os +import nkf +import opt +import view + +def bak_fn(fn, i=0): + bak = '{}.{}'.format(fn, i) + return bak_fn(fn, i+1) if os.path.exists(bak) else bak + +def insert(fn_i, b_i, nkf_opt, pos, ins_str, fn_o): + ins_txt = nkf.str_to(ins_str, nkf_opt) + + if fn_i != '-' and fn_i == fn_o: + fn_i = bak_fn(fn_i) + sp.call( 'mv {} {}'.format(fn_o, fn_i), shell=True ) + if pos > 0: + cmd = 'head -{} {}'.format(pos, fn_i) + if fn_o != '-': + cmd += ' > ' + fn_o + proc = sp.Popen( cmd, shell=True, stdin=sp.PIPE ) + proc.communicate(b_i) + + cmd = 'cat' + if fn_o != '-': + cmd += ' >> ' + fn_o + proc = sp.Popen( cmd, shell=True, stdin=sp.PIPE ) + proc.communicate(ins_txt) + + cmd = 'tail -n +{} {}'.format(pos+1, fn_i) + if fn_o != '-': + cmd += ' >> ' + fn_o + proc = sp.Popen( cmd, shell=True, stdin=sp.PIPE ) + proc.communicate(b_i) + +def help(): + msg = [ + 'Usage: {} [-o view_enc] [-s ins_str] [-i] fn_i'.format(sys.argv[0]), + ' if no -s xxx, use stdin', + " fn_i == '-' use stdin (need -s xxx)", + ' -i : in place fn_i (over write)', + ] + sys.stderr.write( '\n'.join(msg) + '\n' ) + +if __name__ == "__main__": + if opt.get('-h') != None: + help() + sys.exit(0) + + argv = opt.not_opt_argv( ['-o', '-s'], ['-i', '-h'] ) + fn_i = argv.pop(0) if argv else '-' + + if fn_i == '-' and not opt.get('-s', ''): + help() + sys.exit(1) + + f = sys.stdin if fn_i == '-' else open(fn_i, 'r') + b_i = f.read() + if fn_i != '-': + f.close() + + (s, nkf_opt) = nkf.to_str(b_i) + o = opt.get('-o', '') + view_opt = '-' + o if o else nkf_opt + vw = view.new(s, view_opt) + + lst = [ '\n', 'q', chr(0x1b) ] + k = vw.get_key(lst) + pos = vw.cur + vw.fini() + + if k == '\n': + fn_o = fn_i if opt.get('-i') != None else '-' + ins_str = opt.get('-s') + if ins_str == None: + (ins_str, _) = nkf.to_str( sys.stdin.read() ) + elif ins_str[:-1] != '\n': + ins_str += '\n' + + insert(fn_i, b_i, nkf_opt, pos, ins_str, fn_o) +# EOF diff -urN v2/key.py v3/key.py --- v2/key.py 1970-01-01 09:00:00.000000000 +0900 +++ v3/key.py 2018-10-04 22:37:00.000000000 +0900 @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +import os +import term + +esc = term.esc +ctl = lambda s: chr( 1 + ord(s) - ord('a') ) + +def init(): + term.stty('echo', False) + term.stty('icanon', False) + +def fini(): + term.stty('icanon', True) + term.stty('echo', True) + +def get(): + s = os.read( term.tty_r.fileno(), 10 ) + if type(s) != str: + s =''.join( map(chr, s) ) + return s + +def allow(k): + tbls = [[ + [ 'u', 'd', 'l', 'r' ], + [ esc('A'), esc('B'), esc('D'), esc('C') ], # allow + [ ctl('p'), ctl('n'), ctl('b'), ctl('f') ], # emacs + [ 'k', 'j', 'h', 'l' ], # vi + ],[ + [ 'pu', 'pd' ], + [ esc('5~'), esc('6~') ], # allow + [ chr(0xf6), ctl('v') ], # emacs + [ 'b', ' ' ], # less + ]] + for tbl in tbls: + for lst in tbl[1:]: + if k in lst: + return tbl[0][ lst.index(k) ] + return '' +# EOF diff -urN v2/newton.py v3/newton.py --- v2/newton.py 1970-01-01 09:00:00.000000000 +0900 +++ v3/newton.py 2018-10-04 22:37:00.000000000 +0900 @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +def get_int(f, l, r): + c = int( (l + r) / 2 ) + if l == r: + return c + + (vl, vr) = ( f(l), f(r) ) + if vl * vr == 0: + return c if vl + vr == 0 else ( l if vl == 0 else r ) + if vl * vr > 0: + return c + + while abs(l - r) > 1: + c = int( (l + r) / 2 ) + vc = f(c) + if vc == 0: + return c + if vc * vl > 0: + (l, vl) = (c, vc) + else: + (r, vr) = (c, vc) + + (al, ar) = ( abs(vl), abs(vr) ) + return min(l, r) if al == ar else ( l if al < ar else r ) +# EOF diff -urN v2/nkf.py v3/nkf.py --- v2/nkf.py 2018-10-02 23:07:15.000000000 +0900 +++ v3/nkf.py 2018-10-04 22:37:00.000000000 +0900 @@ -2,16 +2,14 @@ import sys import six -import subprocess - -PIPE = subprocess.PIPE +import subprocess as sp enc = lambda s: s.encode('utf-8') if six.PY2 else s.encode() dec = lambda b: unicode(b, 'utf-8') if six.PY2 else b.decode() def do_cmd(cmd, in_b): cmd = enc(cmd) - proc = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE) + proc = sp.Popen(cmd, shell=True, stdin=sp.PIPE, stdout=sp.PIPE) return proc.communicate(in_b)[0] def get_stdin(): @@ -61,6 +59,9 @@ def str_to(s, opt): return utf8_to( enc(s), opt ) +def str_width(s): + return sum( map( lambda c: 1 if ord(c) < 0x80 else 2, s ) ) + if __name__ == "__main__": b = get_stdin() opt = guess(b) diff -urN v2/opt.py v3/opt.py --- v2/opt.py 1970-01-01 09:00:00.000000000 +0900 +++ v3/opt.py 2018-10-04 22:37:00.000000000 +0900 @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import sys + +def get(k, def_val=None): + n = len(k) + argv = sys.argv[1:] + typ = type(def_val) + for i in range( len(argv) ): + s = argv[i] + if s[:n] == k: + next = lambda : argv[i+1] if argv[i+1:] else '' + v = s[n:] if s[n:] else next() + return typ(v) if def_val != None and type(v) != typ else v + return def_val + +def not_opt_argv(ks_v, ks_0): + # ks_v : key list , key value or keyValue + # ks_0 : key list , key (only) + + argv = sys.argv[1:] + argv = list( filter( lambda a: a not in ks_0, argv ) ) + + def f(a): + for k in ks_v: + if ( lambda n: a[:n] == k and a[n:] )( len(k) ): + return False + return True + argv = list( filter( f, argv ) ) + + for k in ks_v: + while k in argv: + i = argv.index(k) + argv = argv[:i] + argv[i+2:] + return argv + +def index(k): + n = len(k) + argv = sys.argv[1:] + for i in range( len(argv) ): + s = argv[i] + if s[:n] == k: + return i + return -1 +# EOF diff -urN v2/term.py v3/term.py --- v2/term.py 1970-01-01 09:00:00.000000000 +0900 +++ v3/term.py 2018-10-04 22:37:00.000000000 +0900 @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +import subprocess as sp + +tty_r = open('/dev/tty', 'r') +tty_w = open('/dev/tty', 'w') + +def get_sz(): + w = int( sp.check_output('tput cols', shell=True).strip() ) + h = int( sp.check_output('tput lines', shell=True).strip() ) + return (w, h) + +def get_pos(): + cmds = [ + #'echo -en "\e[6n"', + 'echo -en "\x1b[6n"', + 'read -sd"[" dmy', + 'read -sd"R" row_col', + 'echo -n $row_col >&2', + ] + cmd = "bash -c '{}'".format( '\n'.join(cmds) ) + + proc = sp.Popen(cmd, shell=True, stdin=tty_r, stdout=tty_w, stderr=sp.PIPE) + s = proc.communicate()[1].decode() + proc.wait() + + (row, col) = map( int, s.split(';') ) + (x, y) = (col-1, row-1) + return (x, y) + +def stty(s, v=True): + if not v: + s = '-' + s + cmd = 'stty {} < /dev/tty'.format(s) + sp.call( cmd, shell=True ) + +def out(s): + tty_w.write(s) + tty_w.flush() + +esc = lambda s: chr(0x1b) + '[' + s + +loc = lambda x, y: out( esc( '{};{}H'.format(y+1, x+1) ) ) +rev = lambda : out( esc('7m') ) +uline = lambda : out( esc('4m') ) +reset = lambda : out( esc('0m') ) +cls = lambda : out( esc('2J') ) + +def scroll(m): + am = abs(m) + sm = m / am + v = 'S' if sm > 0 else 'T' + out( esc( '{}{}'.format( am, v ) ) ) +# EOF diff -urN v2/view.py v3/view.py --- v2/view.py 1970-01-01 09:00:00.000000000 +0900 +++ v3/view.py 2018-10-04 22:37:00.000000000 +0900 @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +import nkf +import newton +import term +import key + +str_width = nkf.str_width + +def str_width_len(s, w): + f = lambda n: str_width( s[:n] ) - w + return newton.get_int( f, 0, len(s) ) + +class Empty: + pass + +def new(s, nkf_opt): + key.init() + + (w, h) = term.get_sz() + (x, y) = term.get_pos() + + lines = s.split('\n') + vw = min( max( map(str_width, lines) ), w-1 ) + + def cvt(s): + if str_width(s) > vw: + s = s[ : str_width_len(s, vw) ] + s += ' ' * ( vw - str_width(s) ) + return nkf.str_to(s, nkf_opt) + + lines = list( map(cvt, lines) ) + + n = len(lines) + vh = min(h, n) + vy = max( y - max( y+n-h, 0 ), 0 ) + + e = Empty() + e.vh = vh + e.sc = 0 + e.cur = 0 + + top_tail = lambda : (e.sc, e.sc + vh - 1) + + def show(i): + (top, tail) = top_tail() + if top <= i and i <= tail: + term.loc( 0, vy+i-e.sc ) + if i == e.cur: + term.rev() + term.out( lines[i] ) + if i == e.cur: + term.reset() + return + + bak = e.sc + e.sc = min( max( i-int(vh/2), 0 ), n-vh ) + (top, tail) = top_tail() + m = e.sc - bak + am = abs(m) + + if am < vh: + term.scroll(m) + else: + term.cls() + (m, am) = (-vh, vh) + + for j in range(am): + show( top + j if m < 0 else tail - j ) + + def move_cur(dy): + bak = e.cur + e.cur = min( max( e.cur + dy, 0 ), n-1 ) + if bak != e.cur: + show(bak) + show(e.cur) + + def get_key(lst): + while True: + k = key.get() + if k in lst: + break + + d = key.allow(k) + if d == 'u': + move_cur(-1) + elif d == 'd': + move_cur(1) + elif d == 'pu': + move_cur(-vh) + elif d == 'pd': + move_cur(vh) + return k + e.get_key = get_key + + def fini(): + term.loc(0, vy+vh) + key.fini() + e.fini = fini + + term.out( '\n'.join( lines[:vh] ) ) + show(e.cur) + return e +# EOF