=== modified file 'ppio.nim' --- ppio.nim 2019-04-09 17:17:44 +0000 +++ ppio.nim 2019-04-04 20:28:23 +0000 @@ -4,8 +4,6 @@ import asyncfutures import asyncdispatch import strformat -import sequtils -import strutils const ERR_PERM = 100 @@ -32,10 +30,10 @@ ] proc posixParseArgs(): Args = var args: Args = ("\n", false, true, ["32", "36", "31", "35"], @[]) - let argc = paramCount() + var argc = paramCount() var n = 1 while n <= argc: - let a = paramStr(n) + var a = paramStr(n) if len(a) >= 1 and a[0] == '-': case a of "-h", "--help": writeHelp(0) @@ -98,9 +96,9 @@ libc_fatal("fcntl():") asyncdispatch.register(fd_to.AsyncFD) - let buf_size = 4096 # we could query posix.PC_PIPE_BUF, but this is common var future_result = newFuture[void]("copy_data") + buf_size = 4096 # we could query posix.PC_PIPE_BUF, but this is common buffer = newString(buf_size) buf_written = 0 reading = true @@ -129,7 +127,6 @@ future_result.fail(newException(OSError, osErrorMsg(lastError))) elif res == 0: # End of "file" - pp_cb("") # Flush buffer if any asyncdispatch.unregister(fd_from.AsyncFD) asyncdispatch.unregister(fd_to.AsyncFD) when DEBUG_OUT.bool: @@ -207,155 +204,46 @@ escaped: string, options: Args, ): proc(data:string) = - var - to_print = "" - dm: DisplayMode = DisplayMode.none - - proc write_out() = - ## Write out and empty to_print buffer. - if to_print.len() == 0: - return + proc pp(data: string): void = + var + to_print = "" + dm: DisplayMode = DisplayMode.none + for c in data: + case c + of ' ' .. '~': + if dm != DisplayMode.normal: + to_print.add("\x1b[") + to_print.add(normal) + to_print.add("m") + dm = DisplayMode.normal + to_print.add(c) + else: + if dm != DisplayMode.escaped: + to_print.add("\x1b[") + to_print.add(escaped) + to_print.add("m") + dm = DisplayMode.escaped + to_print.addEscapedChar(c) + # case c: + # of '\0': + # to_print.add("\\0") + # of '\r': + # to_print.add("\\r") + # of '\n': + # to_print.add("\\n") + # of '\t': + # to_print.add("\\t") + # else: to_print.add("\x1b[0m") - dm = DisplayMode.none + write(stderr, to_print) - to_print.setLen(0) - - proc add_char(c: char) = - ## Format character and add it to to_print buffer. - case c - of ' ' .. '~': - if dm != DisplayMode.normal: - to_print.add("\x1b[") - to_print.add(normal) - to_print.add("m") - dm = DisplayMode.normal - to_print.add(c) - else: - if dm != DisplayMode.escaped: - to_print.add("\x1b[") - to_print.add(escaped) - to_print.add("m") - dm = DisplayMode.escaped - to_print.addEscapedChar(c) - - case options.endl.len - of 0: - proc pp(data: string): void = - for c in data: - add_char(c) - write_out() - return pp - of 1: - let endl: char = options.endl[0] - if options.hideendl: - proc pp(data: string): void = - for c in data: - if c == endl: - to_print.add('\n') - else: - add_char(c) - write_out() - return pp - else: - proc pp(data: string): void = - for c in data: - add_char(c) - if c == endl: - to_print.add('\n') - write_out() - return pp - else: - if options.hideendl: - var ringbuf = "" - var ringpos = 0 - let endl_len = options.endl.len - var endl_chars: set[char] = {} - for c in options.endl: - endl_chars.incl(c) - - proc ring_check(): bool = - ## Returns true when newline was found. - for n in 0 .. (endl_len - 1): - let i = if n > ringpos: endl_len + ringpos - n else: ringpos - n - if options.endl[^(n + 1)] != ringbuf[i]: - return false - return true - - proc pp(data: string): void = - if data.len() == 0: - # End of stream, flush buffer - if ringbuf.len > 0: - let l = ringbuf.len() - for n in 1 .. l: - add_char(ringbuf[(ringpos + n) mod l]) - write_out() - return - - for c in data: - if c notin endl_chars: - if ringbuf.len > 0: - let l = ringbuf.len() - for n in 1 .. l: - add_char(ringbuf[(ringpos + n) mod l]) - ringbuf.setLen(0) - ringpos = 0 - add_char(c) - continue - - if ringbuf.len < endl_len: - ringbuf.add(c) - ringpos = ringbuf.high() - else: - ringpos = (ringpos + 1) mod endl_len - add_char(ringbuf[ringpos]) - ringbuf[ringpos] = c - - if ringbuf.len < endl_len: - continue - - if ring_check(): - to_print.add('\n') - ringbuf.setLen(0) - ringpos = 0 - write_out() - return pp - - else: - var ringbuf = "" - var ringpos = 0 - let endl_len = options.endl.len - - proc ring_add(c: char): bool = - ## Returns true when newline was found. - if ringbuf.len < endl_len: - ringbuf.add(c) - ringpos = ringbuf.high() - else: - ringpos = (ringpos + 1) mod endl_len - ringbuf[ringpos] = c - if ringbuf.len < endl_len: - return false - for n in 0 .. (endl_len - 1): - let i = if n > ringpos: endl_len + ringpos - n else: ringpos - n - if options.endl[^(n + 1)] != ringbuf[i]: - return false - ringbuf.setLen(0) - ringpos = 0 - return true - - proc pp(data: string): void = - for c in data: - add_char(c) - if ring_add(c): - to_print.add('\n') - write_out() - return pp + # write(stderr, "\x1b[" & normal & "m" & repr(data) & "\x1b[0m") + return pp proc main(): void = - let args = posixParseArgs() - when DEBUG_OUT.bool: - write(stderr, "args: " & repr(args) & "\n") + var args = posixParseArgs() + write(stderr, "args: " & repr(args) & "\n") if len(args.exe) == 0: echo "No arguments" @@ -363,7 +251,7 @@ # despite documentation it doesn't search local dir on unix # unless executable name contains / - let exe = os.findExe(args.exe[0]) + var exe = os.findExe(args.exe[0]) if len(exe) == 0: echo "Command not found: " & args.exe[0] quit(ERR_EXEC_ENOENT) @@ -385,7 +273,7 @@ if posix.dup2(pipeout[1], 1) == -1: libc_fatal("dup2():") if posix.close(pipeout[0]) != 0: libc_fatal("close():") if posix.execv(exe, allocCStringArray(args.exe)) == -1: - let exitcode = + var exitcode = if posix.errno == ENOENT: ERR_EXEC_ENOENT else: ERR_EXEC_OTHER libc_fatal("exec():", exitcode) @@ -402,6 +290,7 @@ # input: 0 -> pipein[1] # output: pipeout[0] -> 1 + # TODO: IO loop here var rw_stdin: Future[void] = copy_data(0, pipein[1], pp_writer( args.color_escapes[0], args.color_escapes[1], args,