Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
3077988
add fixed line numbers, need to work through styling for side-by-side…
Cryplo Sep 12, 2025
46de818
style line numbers to be on the side of code
Cryplo Sep 26, 2025
2501177
make line numbers adjust, instead of having them fixed like before
Cryplo Sep 26, 2025
178266c
add toggle to line numbers
Cryplo Sep 26, 2025
049d6d4
Make line numbers stick to left side (messy)
Cryplo Sep 26, 2025
8743096
add different paddings for code editor when line numbers are or aren'…
Cryplo Oct 6, 2025
bee6ed7
add z index to css, added slight padding-left for line numbers, make …
Cryplo Oct 6, 2025
0012464
fix line number z-index to be higher above the caret
Cryplo Oct 6, 2025
5e99272
add small border to line numbers, add a small negative margin to ensu…
Cryplo Oct 11, 2025
8694e5b
line numbers have padding when code is scrolled horizontally
Cryplo Oct 11, 2025
2de5ceb
add relative line numbers
Cryplo Oct 12, 2025
c2b905d
Add toggle for relative line numbers, and have current line number di…
Cryplo Oct 12, 2025
671fecd
Merge branch 'dev' into line-numbers, fix merge issues with CSS styling
Cryplo Oct 12, 2025
1125235
bold current line number
Cryplo Oct 13, 2025
508f6e8
make bold outlines match backgrounds everywhere line numbers appear
Cryplo Oct 13, 2025
38b59bf
set background color explicity to avoid transparency issue, change cu…
Cryplo Oct 13, 2025
bc85363
hide relative line numbers toggle when line numbers is off
Cryplo Oct 13, 2025
b5f6a82
Line numbers (#1972)
Cryplo Oct 13, 2025
95139ff
delete unused open Zipper
Cryplo Oct 13, 2025
977ccfc
make relative line numbers behave as absolute when the cell is unsele…
Cryplo Oct 13, 2025
aea50d5
make line numbers skip multiline cards - doesn't apply to livelits yet
Cryplo Oct 18, 2025
b1507ba
line numbers skip livelits and cards, but relative numbering is not w…
Cryplo Oct 18, 2025
508586f
kind of works, but sometimes doesn't. pushing to save progress and wi…
Cryplo Oct 19, 2025
2cf88c3
Relative line numbering works now, code is messy and unformatted
Cryplo Oct 19, 2025
b733369
Add a processed_line_numbers function to pre-compute what the display…
Cryplo Oct 19, 2025
0af0817
Add an index_to_text function to convert row index to what should be …
Cryplo Oct 19, 2025
caacb38
further refactor code by adding an index_to_span function
Cryplo Oct 19, 2025
7c83f01
delete uneeded check in skip_row_generic
Cryplo Oct 20, 2025
01a73d1
add a bit more comments
Cryplo Oct 20, 2025
f44f236
make release works now?
Cryplo Oct 20, 2025
e0dc15c
Switch to sets for better performance
Cryplo Oct 24, 2025
3b75add
Format code to be more clean
Cryplo Oct 24, 2025
b030ac9
prevent line numbers from showing up on explain this cells
Cryplo Oct 26, 2025
d65ebd8
Implement new skip set that only lokos at Measured.piece_rows. Not ab…
Cryplo Nov 7, 2025
2f17f1a
finally works, added linebreak to new lines to distinguish between ac…
Cryplo Nov 7, 2025
12c8750
rename variables, add comments, pass make release
Cryplo Nov 7, 2025
69cf6db
Merge branch 'dev' into line-numbers
Cryplo Nov 7, 2025
f87c054
fix issue with not showing last line
Cryplo Nov 7, 2025
3f04367
Make Secondary for non-empty rows a linebreak
Cryplo Nov 30, 2025
224ab86
Merge branch 'dev' into line-numbers
Cryplo Nov 30, 2025
334dbcb
npm audit fix, ensure make release works
Cryplo Nov 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions src/haz3lcore/derived/Measured.re
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,12 @@ let of_segment =
);
// add seg to map and reset seg
//TODO(andrew): decide if should actually add linebreak here
let map = add_piece_row(origin.row, seg, map);
let map =
add_piece_row(
origin.row,
seg @ [Piece.Secondary(Secondary.mk_newline(Id.mk()))],
map,
);
let map =
size.row == 0 ? map : add_n_empty_piece_rows(size.row - 1, map);
([], new_indent, size, map);
Expand All @@ -344,7 +349,11 @@ let of_segment =
? {
let g = DeferredLinebreaks.of_secondary();
add_n_rows(origin, indent, g, map)
|> add_piece_row(origin.row, seg, _)
|> add_piece_row(
origin.row,
seg @ [Piece.Secondary(Secondary.mk_empty(Id.mk()))],
_,
)
|> add_n_empty_piece_rows(g - 1);
}
: map;
Expand Down
1 change: 1 addition & 0 deletions src/haz3lcore/lang/Token.re
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ let bounding_box = (t: t): Point.t =>
/* Token Recognition Predicates */

/* A. Secondary Notation (Comments, Whitespace, etc.) */
let empty = "";
let space = " ";
let linebreak = "\n";
let comment_regexp = regexp("^#[^#\n]*#$"); /* Multiline comments not supported */
Expand Down
5 changes: 5 additions & 0 deletions src/haz3lcore/tiles/Secondary.re
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ let cls_of = (s: t): cls =>
| Comment(_) => Comment
};

let mk_empty = id => {
content: Whitespace(Token.empty),
id,
};

let mk_space = id => {
content: Whitespace(Token.space),
id,
Expand Down
17 changes: 16 additions & 1 deletion src/web/Settings.re
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ module Model = {
explainThis: ExplainThisModel.Settings.t,
assistant: AssistantSettings.t,
sidebar: SidebarModel.Settings.t,
line_numbers: bool,
relative_line_numbers: bool,
};

let init = {
Expand Down Expand Up @@ -56,6 +58,8 @@ module Model = {
panel: LanguageDocumentation,
show: true,
},
line_numbers: true,
relative_line_numbers: false,
};

let fix_instructor_mode = settings =>
Expand Down Expand Up @@ -113,7 +117,9 @@ module Update = {
| Sidebar(SidebarModel.Settings.action)
| ExplainThis(ExplainThisModel.Settings.action)
| Assistant(AssistantSettings.action)
| FlipAnimations;
| FlipAnimations
| ToggleLineNumbers
| ToggleRelativeLineNumbers;

let can_undo = (action: t) => {
switch (action) {
Expand Down Expand Up @@ -314,6 +320,15 @@ module Update = {
...settings, //TODO[Matt]: Make sure instructor mode actually makes prelude read-only
instructor_mode: !settings.instructor_mode,
}

| ToggleLineNumbers => {
...settings,
line_numbers: !settings.line_numbers,
}
| ToggleRelativeLineNumbers => {
...settings,
relative_line_numbers: !settings.relative_line_numbers,
}
}
)
|> Updated.return(~scroll_active=false);
Expand Down
2 changes: 2 additions & 0 deletions src/web/app/editors/Editors.re
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ module View = {
editors: Model.t,
) =>
switch (editors) {
// Add in the line numbering for Scratch editor
| Scratch(m) =>
ScratchMode.View.view(
~signal=
Expand All @@ -372,6 +373,7 @@ module View = {
~inject=a => Update.Scratch(a) |> inject,
m,
)
// Add in the line numbering for Documentation editor
| Documentation(m) =>
ScratchMode.View.view(
~signal=
Expand Down
2 changes: 2 additions & 0 deletions src/web/app/editors/cell/CellEditor.re
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ module View = {
~caption: option(Node.t)=?,
~result_kind=?,
~locked=false,
~lines=false,
model: Model.t,
) => {
let (footer, overlays) =
Expand Down Expand Up @@ -228,6 +229,7 @@ module View = {
: (action => inject(MainEditor(action))),
~selected=selected == Some(MainEditor),
~overlays=overlays(model.editor.editor),
~lines,
model.editor,
),
]
Expand Down
16 changes: 14 additions & 2 deletions src/web/app/editors/code/CodeEditable.re
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ module View = {
~inject: Update.t => Ui_effect.t(unit),
~selected: bool,
~overlays: list(Node.t)=[],
~lines: bool=false,
model: Model.t,
) => {
let edit_decos =
Expand Down Expand Up @@ -289,10 +290,14 @@ module View = {
| _ => Effect.Ignore
};

let display_line_numbers: bool = lines && globals.settings.line_numbers;

Node.div(
~attrs=[
Attr.classes(
["cell-item", "code-editor"] @ (selected ? ["selected"] : []),
["cell-item", "code-editor"]
@ (selected ? ["selected"] : [])
@ (display_line_numbers ? ["has-line-numbers"] : []),
),
Attr.on_pointerdown(evt =>
move_or_select(Pointer.Event.mk(evt), Pointer.Event.id_of(evt))
Expand All @@ -303,7 +308,14 @@ module View = {
Attr.on_mousemove(evt => drag_select(Pointer.Event.mk(evt))),
Attr.on_wheel(evt => drag_select(Pointer.Event.mk(evt))),
],
[code_view],
display_line_numbers
? LineNumbers.View.view(
model,
globals.settings.relative_line_numbers,
selected,
)
@ [code_view]
: [code_view],
);
};
};
109 changes: 109 additions & 0 deletions src/web/app/editors/lines/LineNumbers.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
open Haz3lcore;
//open Virtual_dom.Vdom;
open Util;
open WebUtil;

/*
Used to display line numbering alongside cells
*/
module Model = CodeWithStatics.Model;

module View = {
let view = (model: Model.t, show_relative_numbers: bool, selected: bool) => {
let {editor: {syntax: {measured, _}, state: {zipper, _}, _}, _}: Model.t = model;
let num_rows = List.length(measured.piece_rows);
let empty_row = row => {
let result = List.nth_opt(List.rev(measured.piece_rows), row);
switch (result) {
| Some(value) =>
switch (value) {
| [] => true
| _ => false
}
| None => true // The row doesn't actually exist, hence it's empty
};
};
let Point.{row, _} = Zipper.Caret.point(measured, zipper);
let cursor_row_index = row;
/*
Recursively builds a list of line numbers for display, skipping empty rows.

Parameters:
- row_index: Current row being processed (0-indexed)
- line_count: The line number to assign to the current non-empty row

Returns: (line_numbers, cursor_line_number) where:
- line_numbers: List where 0 indicates skip this row, non-zero is the display line number
- cursor_line_number: The line number where the cursor is located (0 if not found yet)
*/
let rec processed_line_numbers =
(row_index: int, line_count: int): (list(int), int) =>
if (row_index == num_rows) {
([], 0);
} else {
let is_row_empty = empty_row(row_index);
let (returned_processed_list, returned_cursor_line_number) =
is_row_empty
? processed_line_numbers(row_index + 1, line_count)
: processed_line_numbers(row_index + 1, line_count + 1);
let current_line_number = is_row_empty ? 0 : line_count;
let cursor_line_number =
if (returned_cursor_line_number == 0 && row_index == cursor_row_index) {
line_count;
} else {
returned_cursor_line_number;
};
(
[current_line_number] @ returned_processed_list,
cursor_line_number,
);
};
let (processed_list, cursor_line_number) = processed_line_numbers(0, 1);
/*
Converts a row index to its display text.
Returns "\n" for empty rows, or the line number (absolute or relative) with newline.
*/
let index_to_text = (i): string => {
let line_number = List.nth(processed_list, i);
line_number == 0
? "\n" // if this is a line we want to skip
: {
(
if (show_relative_numbers && selected) {
string_of_int(
abs(line_number - cursor_line_number) == 0
? line_number : abs(line_number - cursor_line_number),
);
} else {
string_of_int(line_number);
}
)
++ (i == num_rows ? "" : "\n"); // Add a line break if this is not the last row
};
};
let index_to_span = (i): Node.t => {
Node.span(
~attrs=
i == row && selected ? [Attr.classes(["line-numbers-bold"])] : [],
[Text(index_to_text(i))],
);
};
[
Node.div(
~attrs=[
Attr.classes([
"code",
"line-numbers",
selected ? "line-numbers-selected" : "",
]),
],
[
Node.span(
~attrs=[Attr.classes(["code-text", "line-numbers-text"])],
List.init(num_rows, (i): Node.t => {index_to_span(i)}),
),
],
),
];
};
};
1 change: 1 addition & 0 deletions src/web/view/ExerciseMode.re
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,7 @@ module View = {
)
| _ => CellCommon.caption(caption, ~rest=?subcaption)
},
~lines=true,
cell,
);
};
Expand Down
26 changes: 22 additions & 4 deletions src/web/view/NutMenu.re
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,17 @@ let stepper_group = (~globals: Globals.t) => {
);
};

let dev_group = (~globals) => {
let dev_group = (~globals: Globals.t) => {
settings_group(
~globals,
"Developer",
[
("✓", "Benchmarks", globals.settings.benchmark, Benchmark),
(
"✓",
"Benchmarks",
globals.settings.benchmark,
Benchmark: Settings.Update.t,
),
("𝑒", "Elaboration", globals.settings.core.elaborate, Elaborate),
("↵", "Whitespace", globals.settings.secondary_icons, SecondaryIcons),
(
Expand All @@ -118,10 +123,23 @@ let dev_group = (~globals) => {
globals.settings.core.flip_animations,
FlipAnimations,
),
],
("l", "Line Numbers", globals.settings.line_numbers, ToggleLineNumbers),
]
@ (
globals.settings.line_numbers
? [
(
"r",
"Relative Numbers",
globals.settings.relative_line_numbers,
ToggleRelativeLineNumbers,
),
]
: []
),
);
};

//("l", "Line Numbers", globals.settings.line_numbers, ToggleLineNumbers)
let settings_menu = (~globals) => {
[
semantics_group(~globals),
Expand Down
1 change: 1 addition & 0 deletions src/web/view/ScratchMode.re
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ module View = {
| _ => None
},
~locked=false,
~lines=true,
List.nth(model.scratchpads, model.current) |> snd,
),
];
Expand Down
1 change: 1 addition & 0 deletions src/web/view/TutorialMode.re
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ module View = {
~inject=a => inject(Editor(this_pos, a)),
~result_kind,
~caption=CellCommon.caption(caption, ~rest=?subcaption),
~lines=true,
cell,
);
};
Expand Down
7 changes: 7 additions & 0 deletions src/web/www/style/cell.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@
#main .code-editor {
/* Only code in primary editor is selectable atm */
cursor: text;
flex-direction: row;
padding-left: 1em;
}

#main .code-editor.has-line-numbers{
padding-left: 0;
}


#main.Scratch,
#main.Documentation {
background-color: var(--ui-bkg);
Expand Down
Loading