From abca3eb39756aa298cfdc9c1cad207f38aaef6b4 Mon Sep 17 00:00:00 2001 From: Dustin Swan Date: Fri, 13 Feb 2026 22:58:26 -0700 Subject: [PATCH] more --- src/cg/01-stdlib.cg | 2 - src/cg/03-ui-components.cg | 244 +++++++++++++++++++------------------ src/cg/10-os.cg | 22 ++-- 3 files changed, 139 insertions(+), 129 deletions(-) diff --git a/src/cg/01-stdlib.cg b/src/cg/01-stdlib.cg index a7d08b6..be7d005 100644 --- a/src/cg/01-stdlib.cg +++ b/src/cg/01-stdlib.cg @@ -133,5 +133,3 @@ any = f list \ fold (acc x \ or acc (f x)) False list; # all : (a \ Bool) \ List a \ Bool all = f list \ fold (acc x \ and acc (f x)) True list; - -# split : String \ String \ String diff --git a/src/cg/03-ui-components.cg b/src/cg/03-ui-components.cg index 66ec996..2cad3b4 100644 --- a/src/cg/03-ui-components.cg +++ b/src/cg/03-ui-components.cg @@ -98,123 +98,133 @@ box = config \ ] }; -insertChar = text pos char \ - before = slice text 0 pos; - after = slice text pos (len text); - before & char & after; - -deleteChar = text pos \ - (pos == 0 - | True \ text - | False \ - (before = slice text 0 (pos - 1); +textInput = config \ + defaults = { onSubmit = _ \ noOp }; + c = { ...defaults, ...config }; + _ = debug "c" c; + + insertChar = text pos char \ + before = slice text 0 pos; after = slice text pos (len text); - before & after)); - -calcScrollOffset = text cursorPos scrollOffset inputWidth \ - textBeforeCursor = slice text 0 cursorPos; - cursorX = ui.measureText textBeforeCursor; - (cursorX < scrollOffset - | True \ max 0 (cursorX - 20) - | False \ - (cursorX > (scrollOffset + inputWidth) - | True \ cursorX - inputWidth + 20 - | False \ scrollOffset)); - -findPosHelper = text targetX index \ - (index >= len text) - | True \ len text - | False \ ( - widthSoFar = ui.measureText (slice text 0 index); - widthNext = ui.measureText (slice text 0 (index + 1)); - midpoint = (widthSoFar + widthNext) / 2; - (targetX < midpoint - | True \ index - | False \ findPosHelper text targetX (index + 1)) - ); - -findCursorPos = text clickX scrollOffset inputPadding \ - adjustedX = clickX + scrollOffset - inputPadding; - findPosHelper text adjustedX 0; - -textInput = config \ ui.stateful { - key = config.key, - focusable = True, - autoFocus = config.initialFocus, - - # init : State - init = { - text = config.initialValue, - focused = config.initialFocus, - cursorPos = 0, - scrollOffset = 0 - }, - - # update : State \ Event \ State - update = state event \ event - | Key { key = c, printable = True, meta = False, ctrl = False } \ ( - newText = insertChar state.text state.cursorPos c; - newCursorPos = state.cursorPos + 1; - newScroll = calcScrollOffset newText newCursorPos state.scrollOffset config.w; - newState = state.{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }; - { state = newState, emit = [config.onChange newText] }) - - | Key { key = "ArrowLeft" } \ ( - newCursorPos = max 0 (state.cursorPos - 1); - newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset config.w; - newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }; - { state = newState, emit = [] }) - - | Key { key = "ArrowRight" } \ ( - newCursorPos = min (len state.text) (state.cursorPos + 1); - newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset config.w; - newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }; - { state = newState, emit = [] }) - - | Key { key = "Backspace" } \ ( - newText = deleteChar state.text state.cursorPos; - newCursorPos = max 0 (state.cursorPos - 1); - newScroll = calcScrollOffset newText newCursorPos state.scrollOffset config.w; - newState = state.{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }; - { state = newState, emit = [config.onChange newText] }) - - | Clicked coords \ ( - newCursorPos = findCursorPos state.text coords.x state.scrollOffset 8; - newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset config.w; - newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }; - { state = newState, emit = [] }) - - | Focused \ { state = state.{ focused = True }, emit = [] } - | Blurred \ { state = state.{ focused = False }, emit = [] } - # | Key { key = k } \ { state = state, emit = [\ config.onKeyDown k ] } - | _ \ { state = state, emit = [] }, - - view = state \ - textBeforeCursor = slice state.text 0 state.cursorPos; + before & char & after; + + deleteChar = text pos \ + (pos == 0 + | True \ text + | False \ + (before = slice text 0 (pos - 1); + after = slice text pos (len text); + before & after)); + + calcScrollOffset = text cursorPos scrollOffset inputWidth \ + textBeforeCursor = slice text 0 cursorPos; cursorX = ui.measureText textBeforeCursor; - padding = 8; - - ui.clip { - w = config.w, - h = config.h, - child = ui.stack { - children = [ - ui.rect { w = config.w, h = config.h, color = config.backgroundColor, radius = 0 }, - - ui.positioned { - x = 8 - state.scrollOffset, - y = 0, - child = ui.positioned { x = 0, y = 12, child = ui.text { content = state.text, color = config.color } } - }, - - (state.focused - | True \ ui.positioned { - x = 8 + cursorX - state.scrollOffset, - y = 8, - child = ui.rect { w = 2, h = 24, color = config.color } - } - | _ \ empty) - ] + (cursorX < scrollOffset + | True \ max 0 (cursorX - 20) + | False \ + (cursorX > (scrollOffset + inputWidth) + | True \ cursorX - inputWidth + 20 + | False \ scrollOffset)); + + findPosHelper = text targetX index \ + (index >= len text) + | True \ len text + | False \ ( + widthSoFar = ui.measureText (slice text 0 index); + widthNext = ui.measureText (slice text 0 (index + 1)); + midpoint = (widthSoFar + widthNext) / 2; + (targetX < midpoint + | True \ index + | False \ findPosHelper text targetX (index + 1)) + ); + + findCursorPos = text clickX scrollOffset inputPadding \ + adjustedX = clickX + scrollOffset - inputPadding; + findPosHelper text adjustedX 0; + + ui.stateful { + key = c.key, + focusable = True, + autoFocus = c.initialFocus, + + # init : State + init = { + text = c.initialValue, + focused = c.initialFocus, + cursorPos = 0, + scrollOffset = 0 + }, + + # update : State \ Event \ State + update = state event \ event + | Key { key = key, printable = True, meta = False, ctrl = False } \ ( + newText = insertChar state.text state.cursorPos key; + newCursorPos = state.cursorPos + 1; + newScroll = calcScrollOffset newText newCursorPos state.scrollOffset c.w; + newState = state.{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }; + { state = newState, emit = [c.onChange newText] }) + + | Key { key = "ArrowLeft" } \ ( + newCursorPos = max 0 (state.cursorPos - 1); + newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset c.w; + newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }; + { state = newState, emit = [] }) + + | Key { key = "ArrowRight" } \ ( + newCursorPos = min (len state.text) (state.cursorPos + 1); + newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset c.w; + newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }; + { state = newState, emit = [] }) + + | Key { key = "Backspace" } \ ( + newText = deleteChar state.text state.cursorPos; + newCursorPos = max 0 (state.cursorPos - 1); + newScroll = calcScrollOffset newText newCursorPos state.scrollOffset c.w; + newState = state.{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }; + { state = newState, emit = [c.onChange newText] }) + + | Key { key = "Enter" } \ ( + # newState = state.{ text = "", cursorPos = 0, scrollOffset = 0 }; + # do we blank it out here? wish parent could decide.. + { state = state, emit = [c.onSubmit state.text] }) + + | Clicked coords \ ( + newCursorPos = findCursorPos state.text coords.x state.scrollOffset 8; + newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset c.w; + newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }; + { state = newState, emit = [] }) + + | Focused \ { state = state.{ focused = True }, emit = [] } + | Blurred \ { state = state.{ focused = False }, emit = [] } + # | Key { key = k } \ { state = state, emit = [\ c.onKeyDown k ] } + | _ \ { state = state, emit = [] }, + + view = state \ + textBeforeCursor = slice state.text 0 state.cursorPos; + cursorX = ui.measureText textBeforeCursor; + padding = 8; + + ui.clip { + w = c.w, + h = c.h, + child = ui.stack { + children = [ + ui.rect { w = c.w, h = c.h, color = c.backgroundColor, radius = 0 }, + + ui.positioned { + x = 8 - state.scrollOffset, + y = 0, + child = ui.positioned { x = 0, y = 12, child = ui.text { content = state.text, color = c.color } } + }, + + (state.focused + | True \ ui.positioned { + x = 8 + cursorX - state.scrollOffset, + y = 8, + child = ui.rect { w = 2, h = 24, color = c.color } + } + | _ \ empty) + ] + } } - } -}; + }; diff --git a/src/cg/10-os.cg b/src/cg/10-os.cg index 0fc20d8..6e9c7a6 100644 --- a/src/cg/10-os.cg +++ b/src/cg/10-os.cg @@ -175,6 +175,14 @@ os = | Defined name \ openWindow name (_ \ inspector { name = name }) | Err msg \ openWindow "Error" (_ \ ui.text { content = msg, color = "red" }); + handleFocusLeftEvent = state \ + newIndex = max 0 (osState.wm.focusedIndex - 1); + { state = state, emit = [focusWindow newIndex] }; + + handleFocusRightEvent = state \ + newIndex = min (len osState.windows - 1) (osState.wm.focusedIndex + 1); + { state = state, emit = [focusWindow newIndex] }; + ui.stateful { key = "os", autoFocus = True, @@ -184,16 +192,10 @@ os = update = state event \ event | Key { key = "p", meta = True } \ { state = state, emit = [openPalette] } - | Key { key = "ArrowLeft", meta = True } \ - ( - newIndex = max 0 (osState.wm.focusedIndex - 1); - { state = state, emit = [focusWindow newIndex] } - ) - | Key { key = "ArrowRight", meta = True } \ - ( - newIndex = min (len osState.windows - 1) (osState.wm.focusedIndex + 1); - { state = state, emit = [focusWindow newIndex] } - ) + | Key { key = "ArrowLeft", meta = True } \ handleFocusLeftEvent state + | Key { key = "h", meta = True } \ handleFocusLeftEvent state + | Key { key = "ArrowRight", meta = True } \ handleFocusRightEvent state + | Key { key = "l", meta = True } \ handleFocusRightEvent state | Key { key = "d", meta = True } \ { state = state, emit = [closeFocusedWindow 0] } | Key { key = "f", meta = True } \