use linenoise instead of GNU readline

This commit is contained in:
Araq 2015-06-21 10:04:26 +02:00
commit aa8b470cf6
10 changed files with 1351 additions and 66 deletions

View file

@ -9,13 +9,14 @@
## Low-level streams for high performance.
import
import
strutils
when not defined(windows) and defined(useGnuReadline):
# support '-d:useGnuReadline' for backwards compatibility:
when not defined(windows) and (defined(useGnuReadline) or defined(useLinenoise)):
import rdstdin
type
type
TLLStreamKind* = enum # enum of different stream implementations
llsNone, # null stream: reading and writing has no effect
llsString, # stream encapsulates a string
@ -27,42 +28,42 @@ type
s*: string
rd*, wr*: int # for string streams
lineOffset*: int # for fake stdin line numbers
PLLStream* = ref TLLStream
proc llStreamOpen*(data: string): PLLStream =
proc llStreamOpen*(data: string): PLLStream =
new(result)
result.s = data
result.kind = llsString
proc llStreamOpen*(f: File): PLLStream =
proc llStreamOpen*(f: File): PLLStream =
new(result)
result.f = f
result.kind = llsFile
proc llStreamOpen*(filename: string, mode: FileMode): PLLStream =
proc llStreamOpen*(filename: string, mode: FileMode): PLLStream =
new(result)
result.kind = llsFile
if not open(result.f, filename, mode): result = nil
proc llStreamOpen*(): PLLStream =
proc llStreamOpen*(): PLLStream =
new(result)
result.kind = llsNone
proc llStreamOpenStdIn*(): PLLStream =
proc llStreamOpenStdIn*(): PLLStream =
new(result)
result.kind = llsStdIn
result.s = ""
result.lineOffset = -1
proc llStreamClose*(s: PLLStream) =
proc llStreamClose*(s: PLLStream) =
case s.kind
of llsNone, llsString, llsStdIn:
of llsNone, llsString, llsStdIn:
discard
of llsFile:
of llsFile:
close(s.f)
when not declared(readLineFromStdin):
when not declared(readLineFromStdin):
# fallback implementation:
proc readLineFromStdin(prompt: string, line: var string): bool =
stdout.write(prompt)
@ -77,7 +78,7 @@ proc endsWith*(x: string, s: set[char]): bool =
if i >= 0 and x[i] in s:
result = true
const
const
LineContinuationOprs = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^',
'|', '%', '&', '$', '@', '~', ','}
AdditionalLineContinuationOprs = {'#', ':', '='}
@ -104,31 +105,31 @@ proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
s.rd = 0
var line = newStringOfCap(120)
var triples = 0
while readLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line):
while readLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line):
add(s.s, line)
add(s.s, "\n")
inc triples, countTriples(line)
if not continueLine(line, (triples and 1) == 1): break
inc(s.lineOffset)
result = min(bufLen, len(s.s) - s.rd)
if result > 0:
if result > 0:
copyMem(buf, addr(s.s[s.rd]), result)
inc(s.rd, result)
proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int =
proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int =
case s.kind
of llsNone:
of llsNone:
result = 0
of llsString:
of llsString:
result = min(bufLen, len(s.s) - s.rd)
if result > 0:
if result > 0:
copyMem(buf, addr(s.s[0 + s.rd]), result)
inc(s.rd, result)
of llsFile:
of llsFile:
result = readBuffer(s.f, buf, bufLen)
of llsStdIn:
of llsStdIn:
result = llReadFromStdin(s, buf, bufLen)
proc llStreamReadLine*(s: PLLStream, line: var string): bool =
setLen(line, 0)
case s.kind
@ -152,60 +153,60 @@ proc llStreamReadLine*(s: PLLStream, line: var string): bool =
result = readLine(s.f, line)
of llsStdIn:
result = readLine(stdin, line)
proc llStreamWrite*(s: PLLStream, data: string) =
proc llStreamWrite*(s: PLLStream, data: string) =
case s.kind
of llsNone, llsStdIn:
of llsNone, llsStdIn:
discard
of llsString:
of llsString:
add(s.s, data)
inc(s.wr, len(data))
of llsFile:
of llsFile:
write(s.f, data)
proc llStreamWriteln*(s: PLLStream, data: string) =
proc llStreamWriteln*(s: PLLStream, data: string) =
llStreamWrite(s, data)
llStreamWrite(s, "\n")
proc llStreamWrite*(s: PLLStream, data: char) =
proc llStreamWrite*(s: PLLStream, data: char) =
var c: char
case s.kind
of llsNone, llsStdIn:
of llsNone, llsStdIn:
discard
of llsString:
of llsString:
add(s.s, data)
inc(s.wr)
of llsFile:
of llsFile:
c = data
discard writeBuffer(s.f, addr(c), sizeof(c))
proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int) =
proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int) =
case s.kind
of llsNone, llsStdIn:
of llsNone, llsStdIn:
discard
of llsString:
if buflen > 0:
of llsString:
if buflen > 0:
setLen(s.s, len(s.s) + buflen)
copyMem(addr(s.s[0 + s.wr]), buf, buflen)
inc(s.wr, buflen)
of llsFile:
of llsFile:
discard writeBuffer(s.f, buf, buflen)
proc llStreamReadAll*(s: PLLStream): string =
const
proc llStreamReadAll*(s: PLLStream): string =
const
bufSize = 2048
case s.kind
of llsNone, llsStdIn:
of llsNone, llsStdIn:
result = ""
of llsString:
of llsString:
if s.rd == 0: result = s.s
else: result = substr(s.s, s.rd)
s.rd = len(s.s)
of llsFile:
of llsFile:
result = newString(bufSize)
var bytes = readBuffer(s.f, addr(result[0]), bufSize)
var i = bytes
while bytes == bufSize:
while bytes == bufSize:
setLen(result, i + bufSize)
bytes = readBuffer(s.f, addr(result[i + 0]), bufSize)
inc(i, bytes)