147 lines
2.8 KiB
Nim
147 lines
2.8 KiB
Nim
# multiline.nim
|
|
|
|
import line
|
|
|
|
type
|
|
Multiline* = ref object
|
|
lines: seq[Line]
|
|
x,y: int
|
|
|
|
# getters/setters
|
|
|
|
proc X*(ml: Multiline): int =
|
|
ml.x
|
|
|
|
proc Y*(ml: Multiline): int =
|
|
ml.y
|
|
|
|
# constructor
|
|
|
|
proc newMultiline*: Multiline =
|
|
new(result)
|
|
result.lines = @[]
|
|
result.lines.add(newLine())
|
|
result.x = 0
|
|
result.y = 0
|
|
|
|
# methods
|
|
|
|
proc lineLen*(ml: Multiline): int =
|
|
ml.lines[ml.y].len()
|
|
|
|
proc lineHigh*(ml: Multiline): int =
|
|
ml.lineLen() - 1
|
|
|
|
proc len*(ml: Multiline): int =
|
|
ml.lines.len()
|
|
|
|
proc high*(ml: Multiline): int =
|
|
ml.lines.high()
|
|
|
|
# internal setter
|
|
proc sety(ml: Multiline, target: int) =
|
|
ml.y = target
|
|
if ml.x > ml.lineLen():
|
|
ml.x = ml.lineLen()
|
|
|
|
# warning check before calling them if y lands in illegal territory
|
|
# these are unsafe!
|
|
proc decy(ml: Multiline) =
|
|
ml.sety(ml.y-1)
|
|
|
|
proc incy(ml: Multiline) =
|
|
ml.sety(ml.y+1)
|
|
|
|
proc left*(ml: Multiline) =
|
|
if ml.x > 0:
|
|
dec ml.x
|
|
|
|
proc right*(ml: Multiline) =
|
|
if ml.x < ml.lineLen():
|
|
inc ml.x
|
|
|
|
proc up*(ml: Multiline) =
|
|
if ml.y > 0:
|
|
ml.decy
|
|
|
|
proc down*(ml: Multiline) =
|
|
if ml.y < ml.lines.high():
|
|
ml.incy
|
|
|
|
proc home*(ml: Multiline) =
|
|
ml.x = 0
|
|
|
|
proc `end`*(ml: Multiline) =
|
|
ml.x = ml.lineLen()
|
|
|
|
proc vhome*(ml: Multiline) =
|
|
ml.sety(0)
|
|
|
|
|
|
proc vend*(ml: Multiline) =
|
|
ml.sety(ml.high())
|
|
|
|
proc insert*(ml: Multiline, str: string) =
|
|
ml.lines[ml.y].insert(str, ml.x)
|
|
ml.x += str.len()
|
|
|
|
proc delete*(ml: Multiline) =
|
|
if ml.x < ml.lineLen():
|
|
ml.lines[ml.y].delete(ml.x, ml.x)
|
|
|
|
proc backspace*(ml: Multiline) =
|
|
if ml.x > 0:
|
|
ml.lines[ml.y].delete(ml.x - 1, ml.x - 1)
|
|
dec ml.x
|
|
elif ml.x == 0 and ml.y > 0:
|
|
let cut = ml.lines[ml.y].content
|
|
ml.lines.delete(ml.y)
|
|
dec ml.y
|
|
ml.x = ml.lineLen()
|
|
ml.lines[ml.y].insert(cut, ml.x)
|
|
|
|
|
|
proc insertline*(ml: Multiline) =
|
|
# the default behaviour of command mode o
|
|
if ml.y == ml.lines.high():
|
|
ml.lines.add(newLine())
|
|
else:
|
|
ml.lines.insert(newLine(), ml.y + 1)
|
|
inc ml.y
|
|
ml.x = 0
|
|
|
|
proc enter*(ml: Multiline) =
|
|
# the default behaviour of enter in normie editors
|
|
if ml.x > ml.lineHigh():
|
|
ml.insertline() # when end of line, it's just an insertline
|
|
else:
|
|
let cut = ml.lines[ml.y].range(ml.x, ml.lineHigh())
|
|
ml.lines[ml.y].delete(ml.x, ml.lineHigh())
|
|
ml.insertline()
|
|
ml.lines[ml.y].insert(cut, 0)
|
|
|
|
proc clearline*(ml: Multiline) =
|
|
ml.lines[ml.y].clearLine()
|
|
|
|
proc removeline*(ml: Multiline) =
|
|
ml.lines.delete(ml.y)
|
|
if ml.lines.len() == 0:
|
|
ml.lines.add(newLine())
|
|
if ml.y > ml.lines.high():
|
|
dec ml.y
|
|
|
|
proc getLine*(ml: Multiline, line: int = -1): string =
|
|
if line == -1:
|
|
ml.lines[ml.y].content
|
|
else:
|
|
if line >= 0 and line <= ml.lines.high():
|
|
ml.lines[line].content
|
|
else:
|
|
""
|
|
|
|
proc getContent*(ml: Multiline): string =
|
|
for line in ml.lines:
|
|
result &= line.content & "\n"
|
|
result[0..result.high()-1] # cut finishing newline
|
|
|