add implementation of matching cursor pairs

This commit is contained in:
2024-10-31 11:07:52 +00:00
parent 1316cdfe13
commit 553d4605e7
3 changed files with 157 additions and 0 deletions

View File

@@ -123,6 +123,33 @@ struct
in helpMove (app, buffer, cursorIdx, count, fMove)
end
fun moveToMatchingPair (app: app_type) =
let
val {buffer, cursorIdx, windowWidth, windowHeight, startLine, ...} = app
(* move LineGap and buffer to start of line *)
val buffer = LineGap.goToIdx (cursorIdx, buffer)
val cursorIdx = Cursor.matchPair (buffer, cursorIdx)
val buffer = LineGap.goToIdx (cursorIdx, buffer)
(* todo:
* check if cursorIdx is visible on screen first,
* and only get new startLine if it is not visible *)
val startLine = TextWindow.getStartLineWithCursorCentered
(buffer, cursorIdx, startLine, windowWidth, windowHeight div 2)
val buffer = LineGap.goToLine (startLine, buffer)
val newApp = AppWith.bufferAndCursorIdx
(app, buffer, cursorIdx, NORMAL_MODE "", startLine)
val drawMsg =
TextBuilder.build
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
in
(newApp, drawMsg)
end
fun firstNonSpaceChr (app: app_type) =
let
val {buffer, cursorIdx, windowWidth, windowHeight, startLine, ...} = app
@@ -212,6 +239,7 @@ struct
* interpret as "go to line" command;
* else, interpret as a command to move to end *)
moveToEnd app
| #"%" => moveToMatchingPair app
(* multi-char commands which can be appended *)
| #"t" => appendChr (app, chr, str)
| #"T" => appendChr (app, chr, str)

View File

@@ -1575,4 +1575,133 @@ struct
fun tillPrevChr (lineGap, cursorIdx, chr) =
prevChr (lineGap, cursorIdx, chr, startTillPrevChr)
fun helpMatchPairNext
( strPos, str, absIdx, stl, origIdx
, openChr, openNum, closeChr, closeNum
) =
if strPos = String.size str then
case stl of
hd :: tl =>
helpMatchPairNext
( 0, hd, absIdx, tl, origIdx
, openChr, openNum, closeChr, closeNum
)
| [] =>
origIdx
else
let
val chr = String.sub (str, strPos)
val openNum = if chr = openChr then openNum + 1 else openNum
val closeNum = if chr = closeChr then closeNum + 1 else closeNum
in
if openNum = closeNum then
absIdx
else
helpMatchPairNext
( strPos + 1, str, absIdx + 1, stl, origIdx
, openChr, openNum, closeChr, closeNum
)
end
fun helpMatchPairPrev
( strPos, str, absIdx, stl, origIdx
, openChr, openNum, closeChr, closeNum
) =
if strPos < 0 then
case stl of
hd :: tl =>
helpMatchPairNext
( String.size hd - 1, hd, absIdx, tl, origIdx
, openChr, openNum, closeChr, closeNum
)
| [] =>
origIdx
else
let
val chr = String.sub (str, strPos)
val openNum = if chr = openChr then openNum + 1 else openNum
val closeNum = if chr = closeChr then closeNum + 1 else closeNum
in
if openNum = closeNum then
absIdx
else
helpMatchPairPrev
( strPos - 1, str, absIdx - 1, stl, origIdx
, openChr, openNum, closeChr, closeNum
)
end
fun matchPair (lineGap: LineGap.t, cursorIdx) =
let
val {rightStrings, idx = bufferIdx, leftStrings, ...} = lineGap
in
case rightStrings of
shd :: stl =>
let
(* convert absolute cursorIdx to idx relative to hd string *)
val strIdx = cursorIdx - bufferIdx
in
if strIdx < String.size shd then
(* strIdx is in this string *)
let
val chr = String.sub (shd, strIdx)
in
(case chr of
#"(" =>
helpMatchPairNext
( strIdx + 1, shd, cursorIdx + 1, stl, cursorIdx
, #"(", 1, #")", 0
)
| #")" =>
helpMatchPairPrev
( strIdx - 1, shd, cursorIdx - 1, stl, cursorIdx
, #"(", 0, #")", 1
)
| #"[" =>
helpMatchPairNext
( strIdx + 1, shd, cursorIdx + 1, stl, cursorIdx
, #"[", 1, #"]", 0
)
| #"]" =>
helpMatchPairPrev
( strIdx - 1, shd, cursorIdx - 1, stl, cursorIdx
, #"[", 0, #"]", 1
)
| #"{" =>
helpMatchPairNext
( strIdx + 1, shd, cursorIdx + 1, stl, cursorIdx
, #"{", 1, #"}", 0
)
| #"}" =>
helpMatchPairPrev
( strIdx - 1, shd, cursorIdx - 1, stl, cursorIdx
, #"{", 0, #"}", 1
)
| #"<" =>
helpMatchPairNext
( strIdx + 1, shd, cursorIdx + 1, stl, cursorIdx
, #"<", 1, #">", 0
)
| #">" =>
helpMatchPairPrev
( strIdx - 1, shd, cursorIdx - 1, stl, cursorIdx
, #"<", 0, #">", 1
)
| _ => cursorIdx)
end
else
(* strIdx is in tl *)
(case stl of
stlhd :: stltl =>
let
val strIdx = strIdx - String.size shd
val leftStrings = shd :: leftStrings
in
(print "match pair throw err\n"; raise Match)
end
| [] => cursorIdx)
end
| [] => cursorIdx
end
end

BIN
shf

Binary file not shown.