max / makenotwork
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
- Claude-Session
- https://claude.ai/code/session_01MptwXZ8k65v19rFmdGAyki
3 files changed,
+84 insertions,
-61 deletions
| @@ -2875,7 +2875,7 @@ | |||
| 2875 | 2875 | checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" | |
| 2876 | 2876 | dependencies = [ | |
| 2877 | 2877 | "libc", | |
| 2878 | - | "windows-sys 0.52.0", | |
| 2878 | + | "windows-sys 0.59.0", | |
| 2879 | 2879 | ] | |
| 2880 | 2880 | ||
| 2881 | 2881 | [[package]] | |
| @@ -4811,7 +4811,7 @@ | |||
| 4811 | 4811 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 4812 | 4812 | checksum = "82cb6a9f675da968c63b6208c641b9dca58fc0133ae53375736b1767b0cab8bd" | |
| 4813 | 4813 | dependencies = [ | |
| 4814 | - | "windows-sys 0.61.2", | |
| 4814 | + | "windows-sys 0.59.0", | |
| 4815 | 4815 | ] | |
| 4816 | 4816 | ||
| 4817 | 4817 | [[package]] | |
| @@ -5329,6 +5329,7 @@ | |||
| 5329 | 5329 | "proptest", | |
| 5330 | 5330 | "quasi-axum", | |
| 5331 | 5331 | "quasi-basics", | |
| 5332 | + | "quasi-declare", | |
| 5332 | 5333 | "quasi-router", | |
| 5333 | 5334 | "quasi-type", | |
| 5334 | 5335 | "quasi-webview", | |
| @@ -5722,7 +5723,7 @@ | |||
| 5722 | 5723 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 5723 | 5724 | checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" | |
| 5724 | 5725 | dependencies = [ | |
| 5725 | - | "windows-sys 0.61.2", | |
| 5726 | + | "windows-sys 0.59.0", | |
| 5726 | 5727 | ] | |
| 5727 | 5728 | ||
| 5728 | 5729 | [[package]] | |
| @@ -6636,7 +6637,7 @@ | |||
| 6636 | 6637 | ||
| 6637 | 6638 | [[package]] | |
| 6638 | 6639 | name = "quasi-axum" | |
| 6639 | - | version = "0.101.0" | |
| 6640 | + | version = "0.101.1" | |
| 6640 | 6641 | dependencies = [ | |
| 6641 | 6642 | "axum", | |
| 6642 | 6643 | "http 1.4.2", | |
| @@ -6647,15 +6648,24 @@ | |||
| 6647 | 6648 | ||
| 6648 | 6649 | [[package]] | |
| 6649 | 6650 | name = "quasi-basics" | |
| 6650 | - | version = "0.101.0" | |
| 6651 | + | version = "0.101.1" | |
| 6651 | 6652 | dependencies = [ | |
| 6652 | 6653 | "makeover-layout", | |
| 6653 | 6654 | "quasi-router", | |
| 6654 | 6655 | ] | |
| 6655 | 6656 | ||
| 6657 | + | [[package]] | |
| 6658 | + | name = "quasi-declare" | |
| 6659 | + | version = "0.1.0" | |
| 6660 | + | dependencies = [ | |
| 6661 | + | "proc-macro2", | |
| 6662 | + | "quote", | |
| 6663 | + | "syn 2.0.118", | |
| 6664 | + | ] | |
| 6665 | + | ||
| 6656 | 6666 | [[package]] | |
| 6657 | 6667 | name = "quasi-http" | |
| 6658 | - | version = "0.101.0" | |
| 6668 | + | version = "0.101.1" | |
| 6659 | 6669 | dependencies = [ | |
| 6660 | 6670 | "form_urlencoded", | |
| 6661 | 6671 | "http 1.4.2", | |
| @@ -6664,7 +6674,7 @@ | |||
| 6664 | 6674 | ||
| 6665 | 6675 | [[package]] | |
| 6666 | 6676 | name = "quasi-router" | |
| 6667 | - | version = "0.101.0" | |
| 6677 | + | version = "0.101.1" | |
| 6668 | 6678 | dependencies = [ | |
| 6669 | 6679 | "makeover-layout", | |
| 6670 | 6680 | ] | |
| @@ -6687,7 +6697,7 @@ | |||
| 6687 | 6697 | ||
| 6688 | 6698 | [[package]] | |
| 6689 | 6699 | name = "quasi-webview" | |
| 6690 | - | version = "0.101.0" | |
| 6700 | + | version = "0.101.1" | |
| 6691 | 6701 | dependencies = [ | |
| 6692 | 6702 | "docengine", | |
| 6693 | 6703 | "makeover-layout", | |
| @@ -6763,7 +6773,7 @@ | |||
| 6763 | 6773 | "once_cell", | |
| 6764 | 6774 | "socket2", | |
| 6765 | 6775 | "tracing", | |
| 6766 | - | "windows-sys 0.52.0", | |
| 6776 | + | "windows-sys 0.59.0", | |
| 6767 | 6777 | ] | |
| 6768 | 6778 | ||
| 6769 | 6779 | [[package]] | |
| @@ -7326,7 +7336,7 @@ | |||
| 7326 | 7336 | "errno", | |
| 7327 | 7337 | "libc", | |
| 7328 | 7338 | "linux-raw-sys 0.4.15", | |
| 7329 | - | "windows-sys 0.52.0", | |
| 7339 | + | "windows-sys 0.59.0", | |
| 7330 | 7340 | ] | |
| 7331 | 7341 | ||
| 7332 | 7342 | [[package]] | |
| @@ -7339,7 +7349,7 @@ | |||
| 7339 | 7349 | "errno", | |
| 7340 | 7350 | "libc", | |
| 7341 | 7351 | "linux-raw-sys 0.12.1", | |
| 7342 | - | "windows-sys 0.52.0", | |
| 7352 | + | "windows-sys 0.59.0", | |
| 7343 | 7353 | ] | |
| 7344 | 7354 | ||
| 7345 | 7355 | [[package]] | |
| @@ -7419,7 +7429,7 @@ | |||
| 7419 | 7429 | "security-framework 3.7.0", | |
| 7420 | 7430 | "security-framework-sys", | |
| 7421 | 7431 | "webpki-root-certs", | |
| 7422 | - | "windows-sys 0.52.0", | |
| 7432 | + | "windows-sys 0.59.0", | |
| 7423 | 7433 | ] | |
| 7424 | 7434 | ||
| 7425 | 7435 | [[package]] | |
| @@ -8545,7 +8555,7 @@ | |||
| 8545 | 8555 | "getrandom 0.4.3", | |
| 8546 | 8556 | "once_cell", | |
| 8547 | 8557 | "rustix 1.1.4", | |
| 8548 | - | "windows-sys 0.52.0", | |
| 8558 | + | "windows-sys 0.59.0", | |
| 8549 | 8559 | ] | |
| 8550 | 8560 | ||
| 8551 | 8561 | [[package]] | |
| @@ -10759,13 +10769,21 @@ | |||
| 10759 | 10769 | "pkg-config", | |
| 10760 | 10770 | ] | |
| 10761 | 10771 | ||
| 10772 | + | [[patch.unused]] | |
| 10773 | + | name = "synckit-client" | |
| 10774 | + | version = "0.10.0" | |
| 10775 | + | ||
| 10776 | + | [[patch.unused]] | |
| 10777 | + | name = "synckit-config" | |
| 10778 | + | version = "0.2.0" | |
| 10779 | + | ||
| 10762 | 10780 | [[patch.unused]] | |
| 10763 | 10781 | name = "quasi-immediate" | |
| 10764 | - | version = "0.101.0" | |
| 10782 | + | version = "0.101.1" | |
| 10765 | 10783 | ||
| 10766 | 10784 | [[patch.unused]] | |
| 10767 | 10785 | name = "quasi-notifs" | |
| 10768 | - | version = "0.101.0" | |
| 10786 | + | version = "0.101.1" | |
| 10769 | 10787 | ||
| 10770 | 10788 | [[patch.unused]] | |
| 10771 | 10789 | name = "quasi-store" | |
| @@ -10773,7 +10791,7 @@ | |||
| 10773 | 10791 | ||
| 10774 | 10792 | [[patch.unused]] | |
| 10775 | 10793 | name = "quasi-tauri" | |
| 10776 | - | version = "0.101.0" | |
| 10794 | + | version = "0.101.1" | |
| 10777 | 10795 | ||
| 10778 | 10796 | [[patch.unused]] | |
| 10779 | 10797 | name = "kberg" | |
| @@ -10786,11 +10804,3 @@ | |||
| 10786 | 10804 | [[patch.unused]] | |
| 10787 | 10805 | name = "painhours" | |
| 10788 | 10806 | version = "0.1.0" | |
| 10789 | - | ||
| 10790 | - | [[patch.unused]] | |
| 10791 | - | name = "synckit-client" | |
| 10792 | - | version = "0.10.0" | |
| 10793 | - | ||
| 10794 | - | [[patch.unused]] | |
| 10795 | - | name = "synckit-config" | |
| 10796 | - | version = "0.2.0" |
| @@ -164,6 +164,10 @@ | |||
| 164 | 164 | # here is measured rather than argued. Not load-bearing for any shipped route. | |
| 165 | 165 | # See wiki look-wave-2, tier G. | |
| 166 | 166 | quasi-router = { git = "https://makenot.work/git/max/quasi.git", version = "0.101" } | |
| 167 | + | # The declared form. A screen written as `declare!` is compiled to the same | |
| 168 | + | # `quasi_router` constructors the hand-written shape called, at build time, so | |
| 169 | + | # nothing new reaches the binary and the macro is not in the request path. | |
| 170 | + | quasi-declare = { git = "https://makenot.work/git/max/quasi.git", version = "0.1" } | |
| 167 | 171 | # The description vocabulary quasi's screen types are built from. Pinned here | |
| 168 | 172 | # rather than reached through quasi-router's re-export because a described | |
| 169 | 173 | # screen names FieldKind and Tone directly; it has to track what quasi-router |
| @@ -30,8 +30,9 @@ | |||
| 30 | 30 | use std::collections::HashMap; | |
| 31 | 31 | ||
| 32 | 32 | use makeover_layout as layout; | |
| 33 | + | use quasi_declare::declare; | |
| 33 | 34 | use quasi_router::screen::{Cell, Cells, Column, Lexeme, Table}; | |
| 34 | - | use quasi_router::{Action, Document, Node, RegionKind, Run, Screen, Slot}; | |
| 35 | + | use quasi_router::{Action, Document, Node, RegionKind, Screen, Slot}; | |
| 35 | 36 | use quasi_webview::Webview; | |
| 36 | 37 | ||
| 37 | 38 | use crate::git::{BlameLine, Breadcrumb, RefInfo}; | |
| @@ -95,45 +96,27 @@ | |||
| 95 | 96 | .with(page) | |
| 96 | 97 | } | |
| 97 | 98 | ||
| 98 | - | /// The strip over the table: how long the file is, and the other two ways to | |
| 99 | - | /// read it. | |
| 100 | - | fn header(view: &View<'_>) -> Node { | |
| 101 | - | let base = format!("/git/{}/{}", view.owner, view.repo); | |
| 99 | + | declare! { | |
| 100 | + | /// The strip over the table: how long the file is, and the other two ways to | |
| 101 | + | /// read it. | |
| 102 | + | shape header(view: &View<'_>) -> Node; | |
| 103 | + | ||
| 104 | + | let base = "/git/{view.owner}/{view.repo}"; | |
| 102 | 105 | let count = view.lines.len(); | |
| 103 | - | let lines = if count == 1 { | |
| 104 | - | "1 line" | |
| 105 | - | } else { | |
| 106 | - | &format!("{count} lines") | |
| 106 | + | let lines = given count { | |
| 107 | + | 1 -> "1 line", | |
| 108 | + | otherwise -> "{count} lines", | |
| 107 | 109 | }; | |
| 108 | 110 | ||
| 109 | - | Node::Region( | |
| 110 | - | Slot::new("git-file-header", RegionKind::Group).across( | |
| 111 | - | Run::new(layout::Fallback::Wrap) | |
| 112 | - | .beside(Node::text(lines), layout::Priority::Secondary) | |
| 113 | - | .beside( | |
| 114 | - | Node::Link { | |
| 115 | - | text: "Source".to_owned(), | |
| 116 | - | action: Action::get(format!( | |
| 117 | - | "{base}/tree/{}/{}", | |
| 118 | - | view.current_ref, view.file_path | |
| 119 | - | )) | |
| 120 | - | .navigating(), | |
| 121 | - | }, | |
| 122 | - | layout::Priority::Essential, | |
| 123 | - | ) | |
| 124 | - | .beside( | |
| 125 | - | Node::Link { | |
| 126 | - | text: "Raw".to_owned(), | |
| 127 | - | action: Action::get(format!( | |
| 128 | - | "{base}/raw/{}/{}", | |
| 129 | - | view.current_ref, view.file_path | |
| 130 | - | )) | |
| 131 | - | .navigating(), | |
| 132 | - | }, | |
| 133 | - | layout::Priority::Essential, | |
| 134 | - | ), | |
| 135 | - | ), | |
| 136 | - | ) | |
| 111 | + | region "git-file-header" as Group { | |
| 112 | + | across Wrap { | |
| 113 | + | beside Secondary text lines; | |
| 114 | + | beside Essential link "Source" | |
| 115 | + | to get "{base}/tree/{view.current_ref}/{view.file_path}" navigating; | |
| 116 | + | beside Essential link "Raw" | |
| 117 | + | to get "{base}/raw/{view.current_ref}/{view.file_path}" navigating; | |
| 118 | + | } | |
| 119 | + | } | |
| 137 | 120 | } | |
| 138 | 121 | ||
| 139 | 122 | /// One row per line: who last touched it, when, and what it says. | |
| @@ -257,6 +240,32 @@ | |||
| 257 | 240 | Webview::new().screen(&screen(view)) | |
| 258 | 241 | } | |
| 259 | 242 | ||
| 243 | + | /// The header is the first declared shape in the tree, so what it must not | |
| 244 | + | /// lose is asserted here rather than left to the shape of the expansion: | |
| 245 | + | /// both addresses, both spellings of the count, and the two ways out of the | |
| 246 | + | /// blame view. | |
| 247 | + | #[test] | |
| 248 | + | fn the_header_says_how_long_the_file_is_and_the_two_ways_to_read_it() { | |
| 249 | + | let annotated = HashMap::new(); | |
| 250 | + | ||
| 251 | + | let one = vec![line(1, "abc1234", "fn main() {}")]; | |
| 252 | + | let html = rendered(&view(&one, &annotated)); | |
| 253 | + | assert!(html.contains("1 line"), "{html}"); | |
| 254 | + | assert!(!html.contains("1 lines"), "{html}"); | |
| 255 | + | ||
| 256 | + | let two = vec![line(1, "abc1234", "fn main() {}"), line(2, "def5678", "}")]; | |
| 257 | + | let html = rendered(&view(&two, &annotated)); | |
| 258 | + | assert!(html.contains("2 lines"), "{html}"); | |
| 259 | + | assert!( | |
| 260 | + | html.contains(r#"href="/git/ada/engine/tree/main/src/main.rs""#), | |
| 261 | + | "{html}" | |
| 262 | + | ); | |
| 263 | + | assert!( | |
| 264 | + | html.contains(r#"href="/git/ada/engine/raw/main/src/main.rs""#), | |
| 265 | + | "{html}" | |
| 266 | + | ); | |
| 267 | + | } | |
| 268 | + | ||
| 260 | 269 | /// The title names the file being blamed, as the template's did. | |
| 261 | 270 | #[test] | |
| 262 | 271 | fn the_document_is_titled_for_the_file() { |