Add 'shf/' from commit 'b6c5a95b664aeb861d7b33ffc9eefe447ba99dd7'
git-subtree-dir: shf git-subtree-mainline:401408448fgit-subtree-split:b6c5a95b66
This commit is contained in:
274
shf/fcore/normal-mode/normal-search-mode.sml
Normal file
274
shf/fcore/normal-mode/normal-search-mode.sml
Normal file
@@ -0,0 +1,274 @@
|
||||
structure NormalSearchMode =
|
||||
struct
|
||||
open AppType
|
||||
open InputMsg
|
||||
open MailboxType
|
||||
|
||||
fun buildTempSearchList (searchString, buffer, cursorIdx, caseSensitive) =
|
||||
let
|
||||
val dfa =
|
||||
if caseSensitive then CaseSensitiveDfa.fromString searchString
|
||||
else CaseInsensitiveDfa.fromString searchString
|
||||
in
|
||||
SearchList.buildRange (buffer, cursorIdx + 1111, dfa)
|
||||
end
|
||||
|
||||
fun addChr
|
||||
( app: app_type
|
||||
, searchString
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
, chr
|
||||
) =
|
||||
let
|
||||
val {cursorIdx, buffer, ...} = app
|
||||
|
||||
val c = String.implode [chr]
|
||||
val searchString =
|
||||
if searchCursorIdx = String.size searchString then
|
||||
searchString ^ c
|
||||
else
|
||||
let
|
||||
val sub1 = Substring.extract (searchString, 0, SOME searchCursorIdx)
|
||||
val sub2 = Substring.full c
|
||||
val sub3 = Substring.extract (searchString, searchCursorIdx, NONE)
|
||||
in
|
||||
Substring.concat [sub1, sub2, sub3]
|
||||
end
|
||||
val searchCursorIdx = searchCursorIdx + 1
|
||||
|
||||
val buffer = LineGap.goToIdx (cursorIdx - 1111, buffer)
|
||||
val (buffer, tempSearchList) =
|
||||
buildTempSearchList (searchString, buffer, cursorIdx, caseSensitive)
|
||||
in
|
||||
NormalSearchFinish.onSearchChanged
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
, buffer
|
||||
)
|
||||
end
|
||||
|
||||
(* return to normal mode, keeping the same searchString and searchList
|
||||
* from before entering this mode. *)
|
||||
fun exitToNormalMode (app: app_type) =
|
||||
let
|
||||
val {buffer, cursorIdx, searchList, bufferModifyTime, ...} = app
|
||||
in
|
||||
NormalFinish.buildTextAndClear
|
||||
(app, buffer, cursorIdx, searchList, [], bufferModifyTime)
|
||||
end
|
||||
|
||||
(* save search string and searchList and return to normal mode *)
|
||||
fun saveSearch (app: app_type, searchString, caseSensitive, time) =
|
||||
let
|
||||
val
|
||||
{ buffer
|
||||
, cursorIdx
|
||||
, windowWidth
|
||||
, windowHeight
|
||||
, startLine
|
||||
, visualScrollColumn
|
||||
, ...
|
||||
} = app
|
||||
|
||||
val dfa =
|
||||
if caseSensitive then CaseSensitiveDfa.fromString searchString
|
||||
else CaseInsensitiveDfa.fromString searchString
|
||||
|
||||
val buffer = LineGap.goToStart buffer
|
||||
val (buffer, searchList) = SearchList.build (buffer, dfa)
|
||||
|
||||
(* move LineGap to first line displayed on screen *)
|
||||
val buffer = LineGap.goToLine (startLine, buffer)
|
||||
|
||||
(* move buffer to new startLine as required by TextBuilder.build *)
|
||||
val buffer = LineGap.goToLine (startLine, buffer)
|
||||
|
||||
val drawMsg = NormalModeTextBuilder.build
|
||||
( startLine
|
||||
, cursorIdx
|
||||
, buffer
|
||||
, windowWidth
|
||||
, windowHeight
|
||||
, searchList
|
||||
, visualScrollColumn
|
||||
)
|
||||
val drawMsg = Vector.concat drawMsg
|
||||
val drawMsg = DrawMsg.DRAW_TEXT drawMsg
|
||||
val msgs = [DRAW drawMsg]
|
||||
|
||||
val mode = NORMAL_MODE ""
|
||||
in
|
||||
NormalSearchModeWith.returnToNormalMode
|
||||
(app, buffer, searchList, startLine, mode, dfa, msgs)
|
||||
end
|
||||
|
||||
fun backspace
|
||||
( app: app_type
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchScrollColumn
|
||||
, searchCursorIdx
|
||||
, caseSensitive
|
||||
) =
|
||||
if searchCursorIdx = 0 then
|
||||
app
|
||||
else
|
||||
let
|
||||
val searchString =
|
||||
if searchCursorIdx = String.size searchString then
|
||||
String.substring (searchString, 0, String.size searchString - 1)
|
||||
else
|
||||
let
|
||||
val sub1 = Substring.extract
|
||||
(searchString, 0, SOME (searchCursorIdx - 1))
|
||||
val sub2 = Substring.extract (searchString, searchCursorIdx, SOME
|
||||
(String.size searchString - searchCursorIdx))
|
||||
in
|
||||
Substring.concat [sub1, sub2]
|
||||
end
|
||||
val searchCursorIdx = searchCursorIdx - 1
|
||||
|
||||
val {cursorIdx, buffer, ...} = app
|
||||
val buffer = LineGap.goToIdx (cursorIdx - 1111, buffer)
|
||||
val (buffer, tempSearchList) =
|
||||
buildTempSearchList (searchString, buffer, cursorIdx, caseSensitive)
|
||||
in
|
||||
NormalSearchFinish.onSearchChanged
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
, buffer
|
||||
)
|
||||
end
|
||||
|
||||
fun moveLeft
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
) =
|
||||
if searchCursorIdx = 0 then
|
||||
app
|
||||
else
|
||||
let
|
||||
val searchCursorIdx = Int.max (0, searchCursorIdx - 1)
|
||||
in
|
||||
NormalSearchFinish.onSearchChanged
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
, #buffer app
|
||||
)
|
||||
end
|
||||
|
||||
fun moveRight
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
) =
|
||||
if searchCursorIdx = String.size searchString then
|
||||
app
|
||||
else
|
||||
let
|
||||
val searchCursorIdx =
|
||||
Int.min (searchCursorIdx + 1, String.size searchString)
|
||||
in
|
||||
NormalSearchFinish.onSearchChanged
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
, #buffer app
|
||||
)
|
||||
end
|
||||
|
||||
fun update
|
||||
( app
|
||||
, { searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
}
|
||||
, msg
|
||||
, time
|
||||
) =
|
||||
case msg of
|
||||
CHAR_EVENT chr =>
|
||||
addChr
|
||||
( app
|
||||
, searchString
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
, chr
|
||||
)
|
||||
| KEY_BACKSPACE =>
|
||||
backspace
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchScrollColumn
|
||||
, searchCursorIdx
|
||||
, caseSensitive
|
||||
)
|
||||
| KEY_ESC => exitToNormalMode app
|
||||
| KEY_ENTER => saveSearch (app, searchString, caseSensitive, time)
|
||||
| ARROW_LEFT =>
|
||||
moveLeft
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
)
|
||||
| ARROW_RIGHT =>
|
||||
moveRight
|
||||
( app
|
||||
, searchString
|
||||
, tempSearchList
|
||||
, searchCursorIdx
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
)
|
||||
| RESIZE_EVENT (width, height) =>
|
||||
NormalSearchFinish.resize
|
||||
( app
|
||||
, width
|
||||
, height
|
||||
, searchString
|
||||
, searchCursorIdx
|
||||
, tempSearchList
|
||||
, searchScrollColumn
|
||||
, caseSensitive
|
||||
)
|
||||
|
||||
(* In Vim's search mode, the up and down arrows can be used
|
||||
* to scroll through the search history.
|
||||
* I don't find this feature too useful as it is often easier to type
|
||||
* the whole search string again, so I'm leaving it unimplemented
|
||||
* until/unless I find that I wish this functionality was there
|
||||
* while using the program. *)
|
||||
| ARROW_UP => app
|
||||
| ARROW_DOWN => app
|
||||
end
|
||||
Reference in New Issue
Block a user