Skip to content

Commit

Permalink
go down a cell on enter
Browse files Browse the repository at this point in the history
  • Loading branch information
bcpeinhardt committed Nov 2, 2024
1 parent 63c738e commit 664f39d
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 116 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ review:
cd squared_away_lang && gleam run -m birdie

dev:
cd squared_away && gleam run -m lustre/dev start
cd squared_away && gleam run -m lustre/dev start

clean:
cd squared_away && gleam clean
cd squared_away_lang && gleam clean
28 changes: 15 additions & 13 deletions squared_away/index.html
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="main.css">

<title>🚧 form</title>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="main.css">

<!-- Uncomment this if you add the TailwindCSS integration -->
<!-- <link rel="stylesheet" href="/priv/static/form.css"> -->
<script type="module" src="/priv/static/squared_away.mjs"></script>
</head>
<title>🚧 form</title>

<body>
<div id="app"></div>
</body>
</html>
<!-- Uncomment this if you add the TailwindCSS integration -->
<!-- <link rel="stylesheet" href="/priv/static/form.css"> -->
<script type="module" src="/priv/static/squared_away.mjs"></script>
</head>

<body>
<div id="app"></div>
</body>

</html>
154 changes: 89 additions & 65 deletions squared_away/src/squared_away.gleam
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import renderable_error
import gleam/dict
import gleam/int
import gleam/io
import gleam/list
import gleam/option.{type Option, None, Some}
import gleam/result
import gleam/string
import lustre
import lustre/attribute.{class}
import lustre/effect
import lustre/element
import lustre/element/html
import lustre/event
import renderable_error
import squared_away_lang as lang
import squared_away_lang/error
import squared_away_lang/grid
Expand All @@ -28,19 +30,28 @@ pub fn main() {
Nil
}

@external(javascript, "./squared_away_ffi.js", "focus")
fn focus(id: String) -> Nil

/// To start, our model will be a 5x5 grid of Strings
type Model {
Model(
grid_width: Int,
grid_height: Int,
formula_mode: Bool,
display_mode: DisplayMode,
active_cell: Option(grid.GridKey),
src_grid: grid.Grid(String),
value_grid: grid.Grid(Result(value.Value, error.CompileError)),
errors_to_display: List(#(grid.GridKey, error.CompileError)),
)
}

type DisplayMode {
DisplayValues
DisplayFormulas
DisplayGridCoords
}

fn init(_flags) -> #(Model, effect.Effect(Msg)) {
let src_grid = grid.new(initial_grid_width, initial_grid_height, "")
let value_grid =
Expand All @@ -50,7 +61,7 @@ fn init(_flags) -> #(Model, effect.Effect(Msg)) {
Model(
grid_width: initial_grid_width,
grid_height: initial_grid_height,
formula_mode: False,
display_mode: DisplayValues,
active_cell: None,
src_grid:,
value_grid:,
Expand All @@ -63,11 +74,11 @@ fn init(_flags) -> #(Model, effect.Effect(Msg)) {

type Msg {
Noop
UserToggledFormulaMode(to: Bool)
UserToggledDisplayMode(to: DisplayMode)
UserSetCellValue(key: grid.GridKey, val: String)
UserFocusedOnCell(key: grid.GridKey)
UserFocusedOffCell
UserResizedGrid(new_width: Int, new_height: Int)
UserHitKeyInCell(key: grid.GridKey, keyboard_key: String)
}

fn update_grid(model: Model) -> Model {
Expand Down Expand Up @@ -96,32 +107,29 @@ fn update(model: Model, msg: Msg) -> #(Model, effect.Effect(Msg)) {
Model(..model, src_grid: grid.insert(model.src_grid, key, val))
#(update_grid(model), effect.none())
}
UserToggledFormulaMode(formula_mode) -> #(
Model(..model, formula_mode:),
effect.none(),
)
UserToggledDisplayMode(display_mode) -> {
#(Model(..model, display_mode:), effect.none())
}
UserFocusedOnCell(key) -> {
#(Model(..model, active_cell: Some(key)), effect.none())
}
UserFocusedOffCell -> {
#(Model(..model, active_cell: None), effect.none())
}
UserResizedGrid(new_width, new_height) -> {
#(
Model(
..model,
grid_width: new_width,
grid_height: new_height,
src_grid: grid.resize(model.src_grid, new_width, new_height, ""),
value_grid: grid.resize(
model.value_grid,
new_width,
new_height,
Ok(value.Empty),
),
),
effect.none(),
)
UserHitKeyInCell(key, keyboard_key) -> {
case keyboard_key {
"Enter" -> {
let new_active_cell = grid.cell_underneath(model.src_grid, key)
case new_active_cell {
Error(_) -> #(Model(..model, active_cell: None), effect.none())
Ok(new) -> {
focus(grid.to_string(new))
#(Model(..model, active_cell: Some(new)), effect.none())
}
}
}
_ -> #(model, effect.none())
}
}
}
}
Expand All @@ -136,51 +144,28 @@ fn view(model: Model) -> element.Element(Msg) {
})
|> result.unwrap(or: html.div([], []))

let resize_menu =
html.div([], [
html.label([], t("Width")),
html.input([
event.on_input(fn(txt) {
case int.parse(txt) {
Error(_) -> Noop
Ok(n) -> UserResizedGrid(n, model.grid_height)
}
}),
attribute.value(model.grid_width |> int.to_string),
]),
html.label([], t("Height")),
html.input([
event.on_input(fn(txt) {
case int.parse(txt) {
Error(_) -> Noop
Ok(n) -> UserResizedGrid(model.grid_width, n)
}
}),
attribute.value(model.grid_height |> int.to_string),
]),
])

let rows =
model.src_grid.cells
|> list.group(grid.row)
|> dict.map_values(fn(_, keys) {
let cells =
list.map(keys, fn(key) {
let on_enter = event.on_keydown(UserHitKeyInCell(key, _))
let on_input = event.on_input(UserSetCellValue(key:, val: _))
let out_of_focus = event.on_blur(UserFocusedOffCell)
let on_focus = event.on_focus(UserFocusedOnCell(key))
let show_formula =
model.active_cell == Some(key) || model.formula_mode
let value =
case show_formula {
True -> grid.get(model.src_grid, key)
False ->
case grid.get(model.value_grid, key) {
let id = attribute.id(grid.to_string(key))
let value = case model.display_mode {
DisplayFormulas -> grid.get(model.src_grid, key)
DisplayGridCoords -> string.inspect(key)
DisplayValues -> case model.active_cell == Some(key) {
False -> case grid.get(model.value_grid, key) {
Error(e) -> error.error_type_string(e)
Ok(v) -> value.value_to_string(v)
}
True -> grid.get(model.src_grid, key)
}
|> attribute.value
} |> attribute.value

let styles = case
list.find(model.errors_to_display, fn(i) { i.0 == key })
Expand All @@ -189,34 +174,73 @@ fn view(model: Model) -> element.Element(Msg) {
Ok(_) -> [attribute.style([#("background-color", "red")])]
}

let input = html.input([
on_input,
on_focus,
out_of_focus,
value,
on_enter,
id
])

html.td(styles, {
[html.input([on_input, on_focus, out_of_focus, value])]
[
input
]
})
})

html.tr([], cells)
})
|> dict.values
|> dict.to_list
|> list.sort(fn(r1, r2) { int.compare(r1.0, r2.0) })
|> list.map(fn(e) { e.1 })

let grid =
html.div([class("table-container")], [
html.table([], [html.tbody([], rows)]),
html.table([attribute.class("tg")], [html.tbody([], rows)]),
])

let formula_mode_toggle =
html.input([
attribute.type_("checkbox"),
attribute.type_("radio"),
attribute.name("display_mode"),
attribute.id("formula_mode"),
event.on_check(UserToggledFormulaMode),
event.on_check(fn(_) { UserToggledDisplayMode(DisplayFormulas) }),
])

let formula_mode_toggle_label =
html.label([attribute.for("formula_mode")], t("toggle formula mode"))
html.label([attribute.for("formula_mode")], t("Show formulas"))

let grid_mode_toggle =
html.input([
attribute.type_("radio"),
attribute.name("display_mode"),
attribute.id("grid_mode"),
event.on_check(fn(_) { UserToggledDisplayMode(DisplayGridCoords) }),
])

let grid_mode_toggle_label =
html.label([attribute.for("grid_mode")], t("Show grid coordinates"))

let value_mode_toggle =
html.input([
attribute.type_("radio"),
attribute.name("display_mode"),
attribute.id("value_mode"),
event.on_check(fn(_) { UserToggledDisplayMode(DisplayValues) }),
])

let value_mode_toggle_label =
html.label([attribute.for("value_mode")], t("Show evaluated values"))

html.div([], [
value_mode_toggle,
value_mode_toggle_label,
formula_mode_toggle,
formula_mode_toggle_label,
resize_menu,
grid_mode_toggle,
grid_mode_toggle_label,
grid,
error_to_display,
])
Expand All @@ -226,7 +250,7 @@ fn error_view(re: renderable_error.RenderableError) {
html.div([], [
html.h4([], t(re.title)),
html.p([], t(re.info)),
.. case re.hint {
..case re.hint {
None -> []
Some(hint) -> [html.p([], t(hint))]
}
Expand Down
3 changes: 3 additions & 0 deletions squared_away/src/squared_away_ffi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function focus(id) {
document.getElementById(id).focus()
}
8 changes: 2 additions & 6 deletions squared_away_lang/src/renderable_error.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,5 @@ import gleam/option.{type Option}
/// me as just one person.
/// It will hopefully also help to keep error's looking consistent in the UI.
pub type RenderableError {
RenderableError(
title: String,
info: String,
hint: Option(String)
)
}
RenderableError(title: String, info: String, hint: Option(String))
}
11 changes: 9 additions & 2 deletions squared_away_lang/src/squared_away_lang/error.gleam
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import gleam/option.{None}
import renderable_error
import squared_away_lang/interpreter/runtime_error
import squared_away_lang/parser/parse_error
import squared_away_lang/scanner/scan_error
import squared_away_lang/typechecker/type_error
import gleam/option.{None}

pub type CompileError {
ScanError(scan_error.ScanError)
Expand All @@ -15,7 +15,14 @@ pub type CompileError {
pub fn to_renderable_error(ce: CompileError) -> renderable_error.RenderableError {
case ce {
TypeError(te) -> type_error.to_renderable_error(te)
_ -> renderable_error.RenderableError(title: "Compiler error", info: "Todo: implement this error description", hint: None)
ParseError(pe) ->
renderable_error.RenderableError(title: "", info: pe.context, hint: None)
_ ->
renderable_error.RenderableError(
title: "Compiler error",
info: "Todo: implement this error description",
hint: None,
)
}
}

Expand Down
Loading

0 comments on commit 664f39d

Please sign in to comment.