From b424164922842796619cb6894ec46d729a8a6826 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 11 Aug 2026 18:30:13 -0300 Subject: clipboard, n/N and the tty prompt: three things that were half-wired Three changes that all turned out to be the same shape -- a feature that worked in one direction, or for one pane kind, and quietly did not in the others. CLIPBOARD. Every register write emitted set_clipboard, so deleting one character threw away whatever the desktop was holding; multi-cursor yank took the join's early return and emitted nothing at all, so the same key reached the clipboard on one cursor and not on two. Nothing could READ the clipboard: the SDL shell had no SDL_GetClipboardText anywhere in it, and the tty shell never asked for OSC 52, so `p` from another application was dead in both. Now it is helix's split. y/d/c/p/P/R and the acme chords are the DEFAULT REGISTER and nothing else; the system clipboard is five words on helix's own letters -- SPC y, SPC Y, SPC p, SPC P, SPC R -- spelled as builtins so they land in Help and are executable like every other verb. The one exception is the tag `y` chord, which still mirrors out because a tag is always insert, so SPC cannot be pressed there, and copying the path out is the whole point of the chord. Reading is a new read_clipboard effect answered by an ordinary Event.paste, so the round trip is honest about being one: SDL and NSPasteboard answer inside the same drain, the browser answers a promise, and a terminal answers over OSC 52 or -- far more often -- refuses. A refused read is a paste that does not happen, and the request dies at the next keystroke rather than landing minutes late in whatever pane is focused by then. The tty shell also enables BRACKETED PASTE now and coalesces paste_start..paste_end into one event. Before this a paste arrived as a flood of individual key presses: plausible in insert mode, and in normal mode every pasted character ran as a command. n/N. They stepped the armed results buffer and immediately Looked each row, so you could not walk past a hit without opening it. They are a MOTION now: select the next look-able text, open nothing, and let Enter decide. What they step is the largest whitespace-delimited run look.resolve can act on (look.lookableSpan, wrapper punctuation peeled), over a RING of panes -- every pane that has performed a look, most recent first, then the output buffers that have not, newest first, and only if both are empty the pane in front of you. N is the exact inverse of n, computed rather than remembered: both directions ask the same question about the same spans and compare against the column the walk parks on, so x presses one way and x back land exactly where you started, pane boundaries and the ring's seam included. A ring rather than a list with two ends because a shell's cursor sits at the prompt, below everything it has printed, so a walk that could not come round would have nowhere to go on the very first press -- which is the case n/N were written for. One motion everywhere, no pane-kind or buffer-kind special case. The only thing a buffer may change is the GRAIN of what a step selects, and it does it with one flag rather than a branch: output_pane.Traits.commands (renamed from `executes`, which named one reader's behaviour rather than the fact) makes a row select WHOLE, because a ThemeSel line is a word to run and has no path inside it to pick out. `]d`/`[d` are not n/N -- they are helix's diagnostic motions, their job is to ARRIVE, and they still reach searchStep. THE TTY PROMPT. Leaving raw tty blanked the prompt row, and the command you had typed at that prompt shares the row, so it went too -- a shell out of tty read as output only. OSC 133 marks the row CELL by cell, so the two are separable: config.tty_blank = .prompt cuts the prompt's own columns and leaves the command, left-hugged at column 0 in line with the output under it rather than in a bay of blanks. .prompt_and_input is the old behaviour, kept. Because the row is now something you can put a cursor in, enterTty adds the hidden prompt width back before asking ghostty to walk the shell's own cursor to it -- the modal column on a cut row is short by exactly that much. Verified: unit-test 186/186 (nine new), snap 87/87 (new ttyprompt.snap), hxdiff 481 and hxparity 561 with 0 mismatches, tty and gui both build. And against the real binaries rather than the harness: in a pty, SPC y emits OSC 52 carrying exactly the selection while plain y emits nothing, SPC p issues the read and pastes the reply, and a bracketed paste of "dd..." inserts text instead of deleting two lines. In a real SDL window, SPC y then SPC p round trips through the system clipboard while the default register holds different text. Setting tty_blank back to .prompt_and_input reproduces all 86 old goldens byte for byte. --- docs/design.pdf | 1537 +++++++++++++++++----------------- docs/design.typ | 19 +- docs/helix-keys.md | 31 +- docs/lsp.md | 17 +- docs/macos.md | 73 +- src/builtins.zig | 70 +- src/config.zig | 42 +- src/gui/gui.zig | 39 +- src/look.zig | 76 ++ src/macos.zig | 15 +- src/macos/Sources/AppDelegate.swift | 22 +- src/macos/pardes.h | 7 +- src/output_pane.zig | 36 +- src/pardes.zig | 993 +++++++++++++++++++--- src/term_pane.zig | 76 +- src/tty/tty.zig | 85 +- src/tutor.txt | 44 +- src/web.zig | 4 + src/web/app.mjs | 5 + test/macos_e2e.swift | 14 +- test/snapshots/argv.golden | 2 +- test/snapshots/boot.golden | 2 +- test/snapshots/builtins.golden | 216 ++--- test/snapshots/builtins.snap | 23 +- test/snapshots/chordcut.golden | 44 +- test/snapshots/cmdword.golden | 30 +- test/snapshots/cornerdrag.golden | 30 +- test/snapshots/cursorline.golden | 8 +- test/snapshots/doccol.golden | 10 +- test/snapshots/dump.golden | 12 +- test/snapshots/edit.golden | 4 +- test/snapshots/exec-bigdrag.golden | 60 +- test/snapshots/exec.golden | 14 +- test/snapshots/fileedit.golden | 12 +- test/snapshots/filewatch.golden | 16 +- test/snapshots/find.golden | 152 ++-- test/snapshots/find.snap | 63 +- test/snapshots/fsearch.golden | 44 +- test/snapshots/fsearch.snap | 25 +- test/snapshots/ghostty-mid.golden | 6 +- test/snapshots/grep.golden | 68 +- test/snapshots/grep.snap | 32 +- test/snapshots/hscroll.golden | 20 +- test/snapshots/images.golden | 12 +- test/snapshots/jumps.golden | 46 +- test/snapshots/jumps.snap | 50 +- test/snapshots/layout-close.golden | 32 +- test/snapshots/layout-open.golden | 30 +- test/snapshots/leader.golden | 74 +- test/snapshots/load.golden | 4 +- test/snapshots/look-center.golden | 12 +- test/snapshots/look-dir.golden | 6 +- test/snapshots/look-file-1col.golden | 2 +- test/snapshots/look-file.golden | 4 +- test/snapshots/lookloaded.golden | 16 +- test/snapshots/lookpanes.golden | 20 +- test/snapshots/lookrange.golden | 6 +- test/snapshots/lookrange.snap | 12 +- test/snapshots/lsp.snap | 5 +- test/snapshots/lspcomplete.snap | 6 +- test/snapshots/lsprelpath.golden | 24 +- test/snapshots/lsprelpath.snap | 10 +- test/snapshots/modal.golden | 116 +-- test/snapshots/multicursor.golden | 16 +- test/snapshots/nested.golden | 2 +- test/snapshots/psearch.golden | 20 +- test/snapshots/psearch.snap | 29 +- test/snapshots/respawn.golden | 2 +- test/snapshots/restore.golden | 4 +- test/snapshots/rsearch.golden | 36 +- test/snapshots/scroll.golden | 20 +- test/snapshots/scrolloff.golden | 28 +- test/snapshots/selarg.golden | 12 +- test/snapshots/shellset.golden | 2 +- test/snapshots/shrinktag.golden | 18 +- test/snapshots/splitparent.golden | 18 +- test/snapshots/syntax.golden | 8 +- test/snapshots/tag.golden | 20 +- test/snapshots/tagalign.golden | 10 +- test/snapshots/tagalign2col.golden | 10 +- test/snapshots/tagbottomimage.golden | 8 +- test/snapshots/tagnav.golden | 68 +- test/snapshots/theme.golden | 24 +- test/snapshots/themesel.golden | 50 +- test/snapshots/themesel.snap | 51 +- test/snapshots/tinywin.golden | 18 +- test/snapshots/topbarexec.golden | 12 +- test/snapshots/tty.golden | 28 +- test/snapshots/ttyclick.golden | 16 +- test/snapshots/ttyedit.golden | 40 +- test/snapshots/ttyfollow.golden | 8 +- test/snapshots/ttyhelp.golden | 88 +- test/snapshots/ttylook.golden | 40 +- test/snapshots/ttylook.snap | 12 +- test/snapshots/ttyprompt.golden | 93 ++ test/snapshots/ttyprompt.snap | 35 + test/snapshots/tutor.golden | 4 +- test/snapshots/winch.golden | 8 +- test/snapshots/windownav.golden | 38 +- test/snapshots/windowops.golden | 52 +- 100 files changed, 3530 insertions(+), 2003 deletions(-) create mode 100644 test/snapshots/ttyprompt.golden create mode 100644 test/snapshots/ttyprompt.snap diff --git a/docs/design.pdf b/docs/design.pdf index 83f97dc2..ab211161 100644 --- a/docs/design.pdf +++ b/docs/design.pdf @@ -2,783 +2,810 @@ %€€€€ 1 0 obj -<> +<> endobj 2 0 obj -<> +<> endobj 3 0 obj -<> +<> endobj 4 0 obj -<> +<> endobj 5 0 obj -<> +<> endobj 6 0 obj -<> +<> endobj 7 0 obj -<> +<> endobj 8 0 obj -<> +<> endobj 9 0 obj -<> +<> endobj 10 0 obj <> endobj 11 0 obj -<>/K[225 0 R]/ParentTree<>/ParentTreeNextKey 5>> +<>/K[234 0 R]/ParentTree<>/ParentTreeNextKey 5>> endobj 12 0 obj -[17 0 R 19 0 R 20 0 R 21 0 R 21 0 R 21 0 R 21 0 R 22 0 R 22 0 R 22 0 R 22 0 R 23 0 R 25 0 R 24 0 R 25 0 R 25 0 R 25 0 R 26 0 R 30 0 R 28 0 R 30 0 R 29 0 R 30 0 R 32 0 R 34 0 R 34 0 R 34 0 R 40 0 R 37 0 R 40 0 R 40 0 R 40 0 R 38 0 R 40 0 R 40 0 R 40 0 R 39 0 R 40 0 R 41 0 R 42 0 R 50 0 R 43 0 R 50 0 R 44 0 R 50 0 R 45 0 R 50 0 R 46 0 R 50 0 R 47 0 R 50 0 R 48 0 R 50 0 R 49 0 R 50 0 R 50 0 R 50 0 R 50 0 R 51 0 R 53 0 R 53 0 R 52 0 R 53 0 R 53 0 R 53 0 R 53 0 R 53 0 R 54 0 R 64 0 R 55 0 R 64 0 R 56 0 R 64 0 R 57 0 R 64 0 R 58 0 R 64 0 R 59 0 R 64 0 R 60 0 R 64 0 R 61 0 R 64 0 R 62 0 R 64 0 R 64 0 R 63 0 R 64 0 R 64 0 R 66 0 R 65 0 R 66 0 R] +[17 0 R 19 0 R 20 0 R 21 0 R 21 0 R 21 0 R 21 0 R 22 0 R 22 0 R 22 0 R 22 0 R 23 0 R 25 0 R 24 0 R 25 0 R 25 0 R 25 0 R 26 0 R 30 0 R 28 0 R 30 0 R 29 0 R 30 0 R 32 0 R 34 0 R 34 0 R 34 0 R 40 0 R 37 0 R 40 0 R 40 0 R 40 0 R 38 0 R 40 0 R 40 0 R 40 0 R 39 0 R 40 0 R 41 0 R 42 0 R 50 0 R 43 0 R 50 0 R 44 0 R 50 0 R 45 0 R 50 0 R 46 0 R 50 0 R 47 0 R 50 0 R 48 0 R 50 0 R 49 0 R 50 0 R 50 0 R 50 0 R 50 0 R 51 0 R 53 0 R 53 0 R 52 0 R 53 0 R 53 0 R 53 0 R 53 0 R 53 0 R 54 0 R 68 0 R 55 0 R 68 0 R 56 0 R 68 0 R 57 0 R 68 0 R 58 0 R 68 0 R 59 0 R 68 0 R 60 0 R 68 0 R 61 0 R 68 0 R 62 0 R 68 0 R 63 0 R 68 0 R 64 0 R 68 0 R 68 0 R 65 0 R 68 0 R 68 0 R 66 0 R 68 0 R 68 0 R 68 0 R 67 0 R 68 0 R] endobj 13 0 obj -[67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 68 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 76 0 R 72 0 R 76 0 R 73 0 R 76 0 R 76 0 R 74 0 R 76 0 R 75 0 R 76 0 R 76 0 R 77 0 R 78 0 R 79 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 82 0 R 82 0 R 82 0 R 82 0 R 82 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 85 0 R 85 0 R 85 0 R 85 0 R 85 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 89 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 92 0 R 92 0 R 92 0 R 92 0 R 92 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 105 0 R 103 0 R 105 0 R 104 0 R 105 0 R 105 0 R 105 0 R 106 0 R 109 0 R 107 0 R 109 0 R 109 0 R 108 0 R 108 0 R 109 0 R 109 0 R 110 0 R 112 0 R 116 0 R 117 0 R 118 0 R 118 0 R 118 0 R 120 0 R 121 0 R 122 0 R 124 0 R 125 0 R 126 0 R 128 0 R 129 0 R 130 0 R 130 0 R] +[70 0 R 69 0 R 70 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 71 0 R 72 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 73 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 74 0 R 80 0 R 76 0 R 80 0 R 77 0 R 80 0 R 80 0 R 78 0 R 80 0 R 79 0 R 80 0 R 80 0 R 81 0 R 82 0 R 83 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 85 0 R 85 0 R 85 0 R 85 0 R 85 0 R 85 0 R 85 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 88 0 R 88 0 R 88 0 R 88 0 R 88 0 R 88 0 R 88 0 R 89 0 R 89 0 R 89 0 R 89 0 R 89 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 93 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 98 0 R 98 0 R 98 0 R 98 0 R 98 0 R 98 0 R 98 0 R 98 0 R 98 0 R 98 0 R 98 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 103 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 104 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 105 0 R 109 0 R 107 0 R 109 0 R 108 0 R 109 0 R 109 0 R 109 0 R 110 0 R 113 0 R 111 0 R 113 0 R 113 0 R 112 0 R 112 0 R 113 0 R 113 0 R 114 0 R 116 0 R 120 0 R 121 0 R 122 0 R 122 0 R 122 0 R 124 0 R 125 0 R 126 0 R 128 0 R 129 0 R 130 0 R] endobj 14 0 obj -[132 0 R 134 0 R 136 0 R 136 0 R 136 0 R 138 0 R 139 0 R 140 0 R 143 0 R 152 0 R 144 0 R 152 0 R 145 0 R 152 0 R 152 0 R 146 0 R 152 0 R 152 0 R 152 0 R 147 0 R 152 0 R 152 0 R 148 0 R 152 0 R 152 0 R 152 0 R 149 0 R 152 0 R 150 0 R 152 0 R 151 0 R 152 0 R 154 0 R 153 0 R 154 0 R 154 0 R 154 0 R 154 0 R 154 0 R 155 0 R 155 0 R 156 0 R 157 0 R 164 0 R 158 0 R 164 0 R 159 0 R 164 0 R 160 0 R 164 0 R 164 0 R 164 0 R 161 0 R 161 0 R 164 0 R 162 0 R 164 0 R 163 0 R 164 0 R 164 0 R 164 0 R 165 0 R 169 0 R 166 0 R 169 0 R 169 0 R 169 0 R 169 0 R 167 0 R 169 0 R 168 0 R 169 0 R 170 0 R 172 0 R 171 0 R 171 0 R 172 0 R 172 0 R 173 0 R 178 0 R 178 0 R 178 0 R 178 0 R 178 0 R 178 0 R 174 0 R 178 0 R 178 0 R 178 0 R 175 0 R 178 0 R 176 0 R 178 0 R 178 0 R 177 0 R 178 0 R] +[132 0 R 133 0 R 134 0 R 134 0 R 136 0 R 138 0 R 140 0 R 140 0 R 140 0 R 142 0 R 143 0 R 144 0 R 147 0 R 156 0 R 148 0 R 156 0 R 149 0 R 156 0 R 156 0 R 150 0 R 156 0 R 156 0 R 156 0 R 151 0 R 156 0 R 156 0 R 152 0 R 156 0 R 156 0 R 156 0 R 153 0 R 156 0 R 154 0 R 156 0 R 155 0 R 156 0 R 158 0 R 157 0 R 158 0 R 158 0 R 158 0 R 158 0 R 158 0 R 159 0 R 159 0 R 160 0 R 161 0 R 168 0 R 162 0 R 168 0 R 163 0 R 168 0 R 164 0 R 168 0 R 168 0 R 168 0 R 165 0 R 168 0 R 166 0 R 168 0 R 167 0 R 168 0 R 168 0 R 168 0 R 169 0 R 173 0 R 170 0 R 173 0 R 173 0 R 173 0 R 173 0 R 171 0 R 173 0 R 172 0 R 173 0 R 174 0 R 176 0 R 175 0 R 175 0 R 176 0 R 176 0 R 177 0 R 182 0 R 182 0 R 182 0 R 182 0 R 182 0 R 182 0 R 178 0 R 182 0 R 182 0 R 182 0 R 179 0 R 182 0 R 180 0 R 182 0 R 182 0 R] endobj 15 0 obj -[179 0 R 186 0 R 186 0 R 186 0 R 180 0 R 186 0 R 186 0 R 181 0 R 186 0 R 182 0 R 186 0 R 186 0 R 186 0 R 186 0 R 183 0 R 186 0 R 186 0 R 186 0 R 184 0 R 186 0 R 185 0 R 186 0 R 186 0 R 186 0 R 186 0 R 187 0 R 197 0 R 188 0 R 197 0 R 189 0 R 197 0 R 190 0 R 197 0 R 197 0 R 191 0 R 197 0 R 192 0 R 197 0 R 193 0 R 197 0 R 194 0 R 197 0 R 197 0 R 197 0 R 195 0 R 197 0 R 197 0 R 196 0 R 197 0 R 197 0 R 198 0 R 204 0 R 199 0 R 204 0 R 200 0 R 204 0 R 201 0 R 204 0 R 202 0 R 202 0 R 204 0 R 203 0 R 204 0 R 204 0 R 205 0 R 207 0 R 207 0 R 206 0 R 207 0 R 207 0 R 207 0 R 207 0 R 207 0 R 208 0 R 218 0 R 209 0 R 218 0 R 218 0 R 218 0 R 210 0 R 218 0 R 218 0 R 211 0 R 218 0 R 212 0 R 218 0 R 213 0 R 218 0 R 218 0 R 218 0 R 218 0 R 214 0 R 218 0 R 215 0 R 215 0 R 218 0 R 216 0 R 218 0 R 217 0 R 218 0 R 218 0 R 218 0 R 219 0 R 224 0 R 224 0 R 224 0 R 224 0 R 224 0 R 220 0 R 224 0 R 224 0 R 221 0 R 224 0 R 224 0 R 224 0 R 224 0 R 224 0 R] +[182 0 R 182 0 R 181 0 R 182 0 R 183 0 R 190 0 R 190 0 R 190 0 R 184 0 R 190 0 R 190 0 R 185 0 R 190 0 R 186 0 R 190 0 R 190 0 R 190 0 R 190 0 R 187 0 R 190 0 R 190 0 R 190 0 R 188 0 R 190 0 R 189 0 R 190 0 R 190 0 R 190 0 R 190 0 R 191 0 R 206 0 R 192 0 R 206 0 R 193 0 R 206 0 R 194 0 R 206 0 R 206 0 R 195 0 R 206 0 R 196 0 R 206 0 R 197 0 R 206 0 R 198 0 R 206 0 R 206 0 R 206 0 R 199 0 R 206 0 R 206 0 R 200 0 R 206 0 R 206 0 R 201 0 R 206 0 R 202 0 R 202 0 R 206 0 R 203 0 R 206 0 R 204 0 R 206 0 R 206 0 R 205 0 R 206 0 R 207 0 R 213 0 R 208 0 R 208 0 R 213 0 R 209 0 R 213 0 R 210 0 R 213 0 R 213 0 R 211 0 R 213 0 R 212 0 R 213 0 R 213 0 R 214 0 R 216 0 R 216 0 R 215 0 R 216 0 R 216 0 R 216 0 R 216 0 R 216 0 R 217 0 R 227 0 R 218 0 R 227 0 R 227 0 R 227 0 R 219 0 R 227 0 R 227 0 R 220 0 R 227 0 R 221 0 R 227 0 R 222 0 R 227 0 R 227 0 R 227 0 R 227 0 R 223 0 R 227 0 R 224 0 R 224 0 R 227 0 R 225 0 R 227 0 R 226 0 R 227 0 R 227 0 R 227 0 R 227 0 R 228 0 R 233 0 R 233 0 R 233 0 R 233 0 R 233 0 R 229 0 R 233 0 R] endobj 16 0 obj -[224 0 R 224 0 R 224 0 R 224 0 R 222 0 R 224 0 R 224 0 R 223 0 R 224 0 R 224 0 R] +[233 0 R 230 0 R 233 0 R 233 0 R 233 0 R 233 0 R 233 0 R 233 0 R 233 0 R 233 0 R 233 0 R 231 0 R 233 0 R 233 0 R 232 0 R 233 0 R 233 0 R] endobj 17 0 obj -<> +<> endobj 18 0 obj -<> +<> endobj 19 0 obj -<> +<> endobj 20 0 obj -<> +<> endobj 21 0 obj -<> +<> endobj 22 0 obj -<> +<> endobj 23 0 obj -<> +<> endobj 24 0 obj -<> +<> endobj 25 0 obj -<> +<> endobj 26 0 obj -<> +<> endobj 27 0 obj <><>]/K[26 0 R]>> endobj 28 0 obj -<> +<> endobj 29 0 obj -<> +<> endobj 30 0 obj -<><>]/K[18 28 0 R 20 29 0 R 22]/Pg 253 0 R>> +<><>]/K[18 28 0 R 20 29 0 R 22]/Pg 262 0 R>> endobj 31 0 obj <> endobj 32 0 obj -<> +<> endobj 33 0 obj <><>]/K[32 0 R]>> endobj 34 0 obj -<><>]/K[24 25 26]/Pg 253 0 R>> +<><>]/K[24 25 26]/Pg 262 0 R>> endobj 35 0 obj <> endobj 36 0 obj -<>]/K[31 0 R 35 0 R]>> +<>]/K[31 0 R 35 0 R]>> endobj 37 0 obj -<> +<> endobj 38 0 obj -<> +<> endobj 39 0 obj -<> +<> endobj 40 0 obj -<> +<> endobj 41 0 obj -<> +<> endobj 42 0 obj -<> +<> endobj 43 0 obj -<> +<> endobj 44 0 obj -<> +<> endobj 45 0 obj -<> +<> endobj 46 0 obj -<> +<> endobj 47 0 obj -<> +<> endobj 48 0 obj -<> +<> endobj 49 0 obj -<> +<> endobj 50 0 obj -<> +<> endobj 51 0 obj -<> +<> endobj 52 0 obj -<> +<> endobj 53 0 obj -<> +<> endobj 54 0 obj -<> +<> endobj 55 0 obj -<> +<> endobj 56 0 obj -<> +<> endobj 57 0 obj -<> +<> endobj 58 0 obj -<> +<> endobj 59 0 obj -<> +<> endobj 60 0 obj -<> +<> endobj 61 0 obj -<> +<> endobj 62 0 obj -<> +<> endobj 63 0 obj -<> +<> endobj 64 0 obj -<> +<> endobj 65 0 obj -<> +<> endobj 66 0 obj -<> +<> endobj 67 0 obj -<> +<> endobj 68 0 obj -<> +<> endobj 69 0 obj -<> +<> endobj 70 0 obj -<> +<> endobj 71 0 obj -<>]/K[67 0 R 68 0 R 69 0 R 70 0 R]>> +<> endobj 72 0 obj -<> +<> endobj 73 0 obj -<> +<> endobj 74 0 obj -<> +<> endobj 75 0 obj -<> +<>]/K[71 0 R 72 0 R 73 0 R 74 0 R]>> endobj 76 0 obj -<> +<> endobj 77 0 obj -<> +<> endobj 78 0 obj -<> +<> endobj 79 0 obj -<> +<> endobj 80 0 obj -<> +<> endobj 81 0 obj -<> +<> endobj 82 0 obj -<> +<> endobj 83 0 obj -<> +<> endobj 84 0 obj -<> +<> endobj 85 0 obj -<> +<> endobj 86 0 obj -<> +<> endobj 87 0 obj -<> +<> endobj 88 0 obj -<> +<> endobj 89 0 obj -<> +<> endobj 90 0 obj -<> +<> endobj 91 0 obj -<> +<> endobj 92 0 obj -<> +<> endobj 93 0 obj -<> +<> endobj 94 0 obj -<> +<> endobj 95 0 obj -<> +<> endobj 96 0 obj -<> +<> endobj 97 0 obj -<> +<> endobj 98 0 obj -<> +<> endobj 99 0 obj -<> +<> endobj 100 0 obj -<> +<> endobj 101 0 obj -<> +<> endobj 102 0 obj -<>]/K[79 0 R 80 0 R 81 0 R 82 0 R 83 0 R 84 0 R 85 0 R 86 0 R 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R]>> +<> endobj 103 0 obj -<> +<> endobj 104 0 obj -<> +<> endobj 105 0 obj -<> +<> endobj 106 0 obj -<> +<>]/K[83 0 R 84 0 R 85 0 R 86 0 R 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R 102 0 R 103 0 R 104 0 R 105 0 R]>> endobj 107 0 obj -<> +<> endobj 108 0 obj -<> +<> endobj 109 0 obj -<> +<> endobj 110 0 obj -<> +<> endobj 111 0 obj -<><>]/K[110 0 R]>> +<> endobj 112 0 obj -<> +<> endobj 113 0 obj -<><>]/K[112 0 R]>> +<> endobj 114 0 obj -<><>]/K[]>> +<> endobj 115 0 obj -<> +<><>]/K[114 0 R]>> endobj 116 0 obj -<><>]/K[314]/Pg 254 0 R>> +<> endobj 117 0 obj -<><>]/K[315]/Pg 254 0 R>> +<><>]/K[116 0 R]>> endobj 118 0 obj -<><>]/K[316 317 318]/Pg 254 0 R>> +<><>]/K[]>> endobj 119 0 obj -<> +<> endobj 120 0 obj -<><>]/K[319]/Pg 254 0 R>> +<><>]/K[317]/Pg 263 0 R>> endobj 121 0 obj -<><>]/K[320]/Pg 254 0 R>> +<><>]/K[318]/Pg 263 0 R>> endobj 122 0 obj -<><>]/K[321]/Pg 254 0 R>> +<><>]/K[319 320 321]/Pg 263 0 R>> endobj 123 0 obj -<> +<> endobj 124 0 obj -<><>]/K[322]/Pg 254 0 R>> +<><>]/K[322]/Pg 263 0 R>> endobj 125 0 obj -<><>]/K[323]/Pg 254 0 R>> +<><>]/K[323]/Pg 263 0 R>> endobj 126 0 obj -<><>]/K[324]/Pg 254 0 R>> +<><>]/K[324]/Pg 263 0 R>> endobj 127 0 obj -<> +<> endobj 128 0 obj -<><>]/K[325]/Pg 254 0 R>> +<><>]/K[325]/Pg 263 0 R>> endobj 129 0 obj -<><>]/K[326]/Pg 254 0 R>> +<><>]/K[326]/Pg 263 0 R>> endobj 130 0 obj -<><>]/K[327 328]/Pg 254 0 R>> +<><>]/K[327]/Pg 263 0 R>> endobj 131 0 obj -<> +<> endobj 132 0 obj -<> +<><>]/K[0]/Pg 264 0 R>> endobj 133 0 obj -<><>]/K[132 0 R]>> +<><>]/K[1]/Pg 264 0 R>> endobj 134 0 obj -<> +<><>]/K[2 3]/Pg 264 0 R>> endobj 135 0 obj -<><>]/K[134 0 R]>> +<> endobj 136 0 obj -<><>]/K[2 3 4]/Pg 255 0 R>> +<> endobj 137 0 obj -<> +<><>]/K[136 0 R]>> endobj 138 0 obj -<><>]/K[5]/Pg 255 0 R>> +<> endobj 139 0 obj -<><>]/K[6]/Pg 255 0 R>> +<><>]/K[138 0 R]>> endobj 140 0 obj -<><>]/K[7]/Pg 255 0 R>> +<><>]/K[6 7 8]/Pg 264 0 R>> endobj 141 0 obj -<> +<> endobj 142 0 obj -<>]/K[115 0 R 119 0 R 123 0 R 127 0 R 131 0 R 137 0 R 141 0 R]>> +<><>]/K[9]/Pg 264 0 R>> endobj 143 0 obj -<> +<><>]/K[10]/Pg 264 0 R>> endobj 144 0 obj -<> +<><>]/K[11]/Pg 264 0 R>> endobj 145 0 obj -<> +<> endobj 146 0 obj -<> +<>]/K[119 0 R 123 0 R 127 0 R 131 0 R 135 0 R 141 0 R 145 0 R]>> endobj 147 0 obj -<> +<> endobj 148 0 obj -<> +<> endobj 149 0 obj -<> +<> endobj 150 0 obj -<> +<> endobj 151 0 obj -<> +<> endobj 152 0 obj -<> +<> endobj 153 0 obj -<> +<> endobj 154 0 obj -<> +<> endobj 155 0 obj -<> +<> endobj 156 0 obj -<> +<> endobj 157 0 obj -<> +<> endobj 158 0 obj -<> +<> endobj 159 0 obj -<> +<> endobj 160 0 obj -<> +<> endobj 161 0 obj -<> +<> endobj 162 0 obj -<> +<> endobj 163 0 obj -<> +<> endobj 164 0 obj -<> +<> endobj 165 0 obj -<> +<> endobj 166 0 obj -<> +<> endobj 167 0 obj -<> +<> endobj 168 0 obj -<> +<> endobj 169 0 obj -<> +<> endobj 170 0 obj -<> +<> endobj 171 0 obj -<> +<> endobj 172 0 obj -<> +<> endobj 173 0 obj -<> +<> endobj 174 0 obj -<> +<> endobj 175 0 obj -<> +<> endobj 176 0 obj -<> +<> endobj 177 0 obj -<> +<> endobj 178 0 obj -<> +<> endobj 179 0 obj -<> +<> endobj 180 0 obj -<> +<> endobj 181 0 obj -<> +<> endobj 182 0 obj -<> +<><>181 0 R<>]/Pg 264 0 R>> endobj 183 0 obj -<> +<> endobj 184 0 obj -<> +<> endobj 185 0 obj -<> +<> endobj 186 0 obj -<> +<> endobj 187 0 obj -<> +<> endobj 188 0 obj -<> +<> endobj 189 0 obj -<> +<> endobj 190 0 obj -<> +<> endobj 191 0 obj -<> +<> endobj 192 0 obj -<> +<> endobj 193 0 obj -<> +<> endobj 194 0 obj -<> +<> endobj 195 0 obj -<> +<> endobj 196 0 obj -<> +<> endobj 197 0 obj -<> +<> endobj 198 0 obj -<> +<> endobj 199 0 obj -<> +<> endobj 200 0 obj -<> +<> endobj 201 0 obj -<> +<> endobj 202 0 obj -<> +<> endobj 203 0 obj -<> +<> endobj 204 0 obj -<> +<> endobj 205 0 obj -<> +<> endobj 206 0 obj -<> +<> endobj 207 0 obj -<> +<> endobj 208 0 obj -<> +<> endobj 209 0 obj -<> +<> endobj 210 0 obj -<> +<> endobj 211 0 obj -<> +<> endobj 212 0 obj -<> +<> endobj 213 0 obj -<> +<> endobj 214 0 obj -<> +<> endobj 215 0 obj -<> +<> endobj 216 0 obj -<> +<> endobj 217 0 obj -<> +<> endobj 218 0 obj -<> +<> endobj 219 0 obj -<> +<> endobj 220 0 obj -<> +<> endobj 221 0 obj -<> +<> endobj 222 0 obj -<> +<> endobj 223 0 obj -<> +<> endobj 224 0 obj -<><><><>222 0 R<><>223 0 R<><>]/Pg 256 0 R>> +<> endobj 225 0 obj -<> +<> endobj 226 0 obj -[/ICCBased 275 0 R] +<> endobj 227 0 obj -[/ICCBased 276 0 R] +<> endobj 228 0 obj -[253 0 R/XYZ 62.362206 729.37256 0] +<> endobj 229 0 obj -[253 0 R/XYZ 62.362206 576.02637 0] +<> endobj 230 0 obj -[254 0 R/XYZ 62.362206 679.2434 0] +<> endobj 231 0 obj -[254 0 R/XYZ 62.362206 288.38 0] +<> endobj 232 0 obj -[255 0 R/XYZ 62.362206 706.6116 0] +<> endobj 233 0 obj -[255 0 R/XYZ 62.362206 463.47986 0] +<>230 0 R<><><><><><><><><>231 0 R<><>232 0 R<><>]/Pg 265 0 R>> endobj 234 0 obj -[255 0 R/XYZ 62.362206 343.90167 0] +<> endobj 235 0 obj -[255 0 R/XYZ 62.362206 252.28497 0] +[/ICCBased 284 0 R] endobj 236 0 obj -<>/Font<>>> +[/ICCBased 285 0 R] endobj 237 0 obj -<>/Font<>>> +[262 0 R/XYZ 62.362206 729.37256 0] endobj 238 0 obj -<>/Font<>>> +[262 0 R/XYZ 62.362206 576.02637 0] endobj 239 0 obj -<>/Font<>>> +[263 0 R/XYZ 62.362206 659.4719 0] endobj 240 0 obj -<>/Font<>>> +[263 0 R/XYZ 62.362206 268.60852 0] endobj 241 0 obj -<> +[264 0 R/XYZ 62.362206 675.4436 0] endobj 242 0 obj -<>/FontDescriptor 243 0 R/DW 0/W[0 0 280 1 1 786 2 2 559 3 3 474 4 4 639 5 5 527 6 6 454 7 7 319 8 8 383 9 9 869 10 10 800 11 11 607 12 12 447 13 13 756 14 14 639 15 15 607 16 16 319 17 17 575 18 18 958 19 19 1189 20 21 639 22 22 319 23 23 639 24 24 607 25 25 510.99997 26 26 831 27 28 639 29 29 351 30 30 671 31 31 607 32 32 882 33 33 575 34 34 319 35 37 575 38 38 818 39 39 692 40 40 319 41 41 1092 42 42 831 43 44 447]>> +[264 0 R/XYZ 62.362206 432.31186 0] endobj 243 0 obj -<> +[264 0 R/XYZ 62.362206 312.73364 0] endobj 244 0 obj -<> +[264 0 R/XYZ 62.362206 221.11694 0] endobj 245 0 obj -<>/FontDescriptor 246 0 R/DW 0/W[0 0 500 1 1 556 2 2 444 3 3 394 4 4 278 5 5 500 6 6 556 7 7 333 8 8 306 9 9 500 10 10 392 11 11 389 12 12 556 13 13 722 14 14 1000 15 17 500 18 18 333 19 20 500 21 21 681 22 22 500 23 24 528 25 25 833 26 26 444 27 28 278 29 30 556 31 31 278 32 32 556 33 33 528 34 34 278 35 35 556 36 36 278 37 37 722 38 38 686 39 39 528 40 40 681 41 41 528 42 42 361 43 44 389 45 45 556 46 46 764 47 47 625 48 48 500 49 49 514 50 50 750 51 51 917 52 52 500 53 53 722 54 54 444 55 56 750 57 57 778 58 58 278 59 59 583 60 60 500 61 61 750 62 62 778 63 63 750 64 64 306 65 65 736 66 66 785 67 67 708 68 68 556 69 69 500 70 70 611 71 71 778 72 73 500 74 74 778 75 75 750 76 76 1000 77 77 653 78 78 1028 79 80 750]>> +<>/Font<>>> endobj 246 0 obj -<> +<>/Font<>>> endobj 247 0 obj -<> +<>/Font<>>> endobj 248 0 obj -<>/FontDescriptor 249 0 R/DW 0/CIDToGIDMap/Identity/W[0 79 602.0508]>> +<>/Font<>>> endobj 249 0 obj -<> +<>/Font<>>> endobj 250 0 obj -<> +<> endobj 251 0 obj -<>/FontDescriptor 252 0 R/DW 0/W[0 0 500 1 1 527]>> +<>/FontDescriptor 252 0 R/DW 0/W[0 0 280 1 1 786 2 2 559 3 3 474 4 4 639 5 5 527 6 6 454 7 7 319 8 8 383 9 9 869 10 10 800 11 11 607 12 12 447 13 13 756 14 14 639 15 15 607 16 16 319 17 17 575 18 18 958 19 19 1189 20 21 639 22 22 319 23 23 639 24 24 607 25 25 510.99997 26 26 831 27 28 639 29 29 351 30 30 671 31 31 607 32 32 882 33 33 575 34 34 319 35 37 575 38 38 818 39 39 692 40 40 319 41 41 1092 42 42 831 43 44 447]>> endobj 252 0 obj -<> +<> endobj 253 0 obj -<> +<> endobj 254 0 obj -<> +<>/FontDescriptor 255 0 R/DW 0/W[0 0 500 1 1 556 2 2 444 3 3 394 4 4 278 5 5 500 6 6 556 7 7 333 8 8 306 9 9 500 10 10 392 11 11 389 12 12 556 13 13 722 14 14 1000 15 17 500 18 18 333 19 20 500 21 21 681 22 22 500 23 24 528 25 25 833 26 26 444 27 28 278 29 30 556 31 31 278 32 32 556 33 33 528 34 34 278 35 35 556 36 36 278 37 37 722 38 38 686 39 39 528 40 40 681 41 41 528 42 42 361 43 44 389 45 45 556 46 46 764 47 47 625 48 48 500 49 49 514 50 50 750 51 51 917 52 52 500 53 53 722 54 54 444 55 56 750 57 57 778 58 58 278 59 59 583 60 60 500 61 61 750 62 62 778 63 63 750 64 64 306 65 65 736 66 66 785 67 67 708 68 68 556 69 69 500 70 70 611 71 71 778 72 73 500 74 74 778 75 75 750 76 76 653 77 77 1000 78 78 1028 79 79 750]>> endobj 255 0 obj -<> +<> endobj 256 0 obj -<> +<> endobj 257 0 obj -<> +<>/FontDescriptor 258 0 R/DW 0/CIDToGIDMap/Identity/W[0 80 602.0508]>> endobj 258 0 obj +<> +endobj +259 0 obj +<> +endobj +260 0 obj +<>/FontDescriptor 261 0 R/DW 0/W[0 0 500 1 1 527]>> +endobj +261 0 obj +<> +endobj +262 0 obj +<> +endobj +263 0 obj +<> +endobj +264 0 obj +<> +endobj +265 0 obj +<> +endobj +266 0 obj +<> +endobj +267 0 obj <> stream xœ๛�����?๊๔ endstream endobj -259 0 obj +268 0 obj <> stream xœm”Oข@ล๏|Šฺ‰spq4ฦDQ๓'ใd๗Œt้’HC8๘ํ7๔+วษfj^WUฟ๚Uw๋�x?N7บ9๑4�าwอ`Kžf/E๋๙�ฎ)‡šM�สฌY฿ฃ�’Z�”๗”vS๕ž๏Ly4฿s�—ฒๅKe ฃeCื7ต็๛ŸUๅ%Mฐ@ฎ':h6}ี฿(|๒|��ฎjฬ’"ฯ๗๗FgM=6ืyxP๐n›๒ศ=+ฃญ8ัi๔๕"Eบ*{Q๎ปฌ‹ึo]ฯ๕มœŠ‘ฅ‡V2‰ˆ‚พT]oo4q=‘ๆ3"oVณญฬ…&๗fฟC�^yl’BทสFป฿`„-jฆ@€ฟV…’ขวา็ญeู ๘�า่ปˆะbูh๎ฺขd[˜ {ซ0 ร5ญ๒<ฯืฃใ?๑$Aู้\�)ฌKึด @@ -786,7 +813,7 @@ x Œ1\zU`Œฑ‹cŒฮ•œกิ1‘ูEฮ๓Vr†˜ขc*F…)*0ช…ปŒr๋ฦk9พพฏwPึฒ้�ใs—~ผแ•แฏW�6ํXๅ>๎๙฿�IF๕–�จs?๔ endstream endobj -260 0 obj +269 0 obj <> stream xœXiXืถญฆฉชƒFบlLิTƒApBpบIŒฦข&Fโุ(((eZกฑ›�4๓$3ŠA@ZQJŒc4ฦ!1ื›่IฎC5&!<�v‘C๎}_ใ๐rอ}๏{ชฟ>็๔9{๏Zkต[มุ�3 @@ -819,142 +846,146 @@ w1 ๛66> +270 0 obj +<> stream -xœ๛�AJ -w +xœ๛�6ำ ๗ endstream endobj -262 0 obj -<> +271 0 obj +<> stream -xœm•Ioโ@…๏�=Kษ!CoถBH,ฑฤ!‹B4s&๎‚ฑฺ–—�~ิ� -ˆFsHข็*Wี๗Š้ท�รา5Ÿ๔`~J๑N}3v=ฌŸ๗m’ฆ›ฆOไ‡"G๎ํgขํšชงAฌท›ญฏ‡$Mทพ๚]r�—ฒขcํo ก‡X�ะœ’4�จ‡/š‰;<q&ฑuไ‡z8 yŸค้/๊๚บ๑3ก’4}๒n�œยp}2แb๒ึ5ีŽqจฝ๋ธ“๘ }ฅ…ซซU�]๖m|yw๎:m�กYnl9S!&๏tฌ๛ก;‹ป8ุฝpt@ไตsิี�(๎.ร~ ๎ฦถ�ข0ค๑)y�N�ห�DbยภืงL)ิํัวน%.0๙��ธ‹Pฑj๕ํพขn๏”ฬฅ”r!ๆeY–‹ะ๑Ÿ๘ฃฤkŸ‡๊ฯพ‹้j!ๆRๆv•†ส LT…ฒˆMก2จ*‡z‚*ขา๊ฑj -UB-ัACญ x–52ก6ˆqฟง…˜kฉ8ณŒ1ƒ** ฅAw>ƒ๎ -|z>ƒš -|์ -|Wa>พ“)๐�๙ธ๘r8จภg–Pฬท†b>๎๘ค,ธ;๘425๘rะj๐ุŠŸYA/ฯฏ[ำ`ิุ“fFธจ™1ฟn@ƒ3็jเด˜Pƒณ€#œ–ป€Sร Nอ1pfpDƒำr?pZp�#2 8-ผ3เด่`ภiแนaF|ย -WcมUภ—ศ0ผ1เณ\%๐้ฐ�จV7_ฑuFร๓0#ว˜.f„o–w‰y,3lึ2#>–9foภ- Nรuม™q]�ฤœž[pY์ัภI ฮ ุภจี”'ฃฃcฦณ‚1ƒณiu�ฦฟ“�บ;9š0๐๕)S’ผ=๚<ทŽ L~ฟ4๖"$Fฌ๋๚vWนn็.™ !ฤœfeY–๓ะ๑Ÿx1ลk_๛๊ฯฎ‹้rN3!r3JAeP:ชBCฤฆPT•CญกŠจ”€zD,‡šB•Pฯ่  P<ห™P+ฤธ฿zN3%$g–1ฆQE„ะ่.มงั]‚Oญ ภงQS‚Oƒ]‚/ใ*ฬ'กภW`2 พ‚;0w_%๘๔3๓-ก˜ป>! +๎>…Lพด +|ถขภงPเห๓๋ึ๖ค˜.*fฬฏPเฬน8 &Tเ,เˆงแ.เT๐GSq œQเ4�œœš๗ˆL N๏48 :hpxฎ™Ÿ0 FรUภXp๐e าฬo4๘ W |*,7ชลอWl]ƒQ๓<ฬศ1f„‹šแ›แ]bฦ ›5ฬˆOงaFŽ™�pห€Ss]pf\—ฟ˜ภ€SรsN 2ƒ=j8iภ™มF*•œ๒<`ฬxV0fำx‚๘ึ„cn๎๕๚Ucื9?ฤ“O]ธkตwื��6mx+�ฤฃ๙�ิ[๙lGข endstream endobj -263 0 obj -<> +272 0 obj +<> stream -xœ}zw\ืื๗]`wFิ5ฒฎ%๊ ฦ�5อฑk์ฑk,ˆ ่JP„ฅ๏๎ู]z•‹ฒˆˆb‹ 5j์-‰ฦฎฑEฃมz/z�ฯ`~ฯ๛|�็๙ผ�q๙ฬ์ms๎น็|ฯ๗qr" -…โณiž!cฆะ๗ฯ•ม:๗ต๒ป๑R{ฉ4คŽ -ม™ˆŸฺf\–�ae•ฅƒSฒ#! -s น}ึฒ#!ˆอพฎ4๋"�;ำฌ+qt -ข"j…0j…฿rฯI+<}ƒ|‚ยzŒ๑๓ำyz๕t�rภภ!}ฟ๐ๅทฎฃ|ƒ�|}]g๚้�ึ๘๙๖sužํํ่โทvตซO ๋ZOง{ ็ -ื`฿žk]ƒผ=]'ฬ˜๒U๏๑ใ\๛๖u ๔๔t๕ -๒ฺฟHHHฟ•พม��ึฎ์ฏ๓๑๐๔ ๔ ์ฟา_ืืห= Ÿwะ]็๑~พAใB=<�ƒ|�|]ว๚ญ๕Y�๘๔฿๗;ฎงผฒ๛Šž+\}|]gyz4�0ศีฯหuยด9}ๅ ๔sๅ้้:ๅำ:ฎ^>:Oื o๗ Wฟ5žฎ!>A�ฎฮAžฎ+�๛~^๛๗๒๓ -์Gˆ,ง้’กU}Gmp‘4&—๚f$ฉgงู~อš$7s†fMํฮEf‹ูb1งX,อš]lZZcMถ$[ญึคfอ‰‚BfสGืส `–ช#!dจ|ษ.dฆผภไ€ข—ƒ—ร ง N�8ฝRฮWžVUUq›šดoาป sžไ�ป๓ณฆ{šy4ป��ทลฺฯ†ท$-u-‹[�wYขqิฬm๕EซฺVฺ3ฺฟZฯl�ถMU�^mOถsmw๗๓o�—vp๊0ฏcวŽgฑน่.�p์zฐำ๔N๙��โX็%ฯt)ํš�mP๗v�๏๕๐ู้ฝ็ึ^_๗Z฿๋ฯ�žฝฯ๖พูgtŸ›�š๖2 ”&Tˆ˜S6ษฺ+ -As ฅH๋9%ซv„Wร}ฐ™๎)ฺwฐ๒ †š5ฅ yหล/0x5sฒQ]!u+V”�กั็ฅถ”ำฎ๎?":ผ!0+8ฯ}[ศQธษ็ะ�&‹5—r฿฿b*ฆ�ฦ•5gยป~”ฃฮ?QEaฒ!9ZŒ…„„„Hž๕ฅgดuYฌต‡h`Q)\*m๛{ๅNyติจb้ซ—ญ•Rซ-๐€ๆ๚ง4Vห8nฃ1!*า˜œ‘�œ)†ฌ^นB€ๅ•กๅัH๚I๏_>‰Fา–S!Qด‰ุฮk YHŸžฎEาyA<๗ฬ‚‰žฃูgฐ|6๙—!�=;๑ฎFฌฟ(�ุ‹๘NŒ๑�Š๙ˆ w— q๔ฮFา๒ภX‘Š’–xสŠฤ‘ J4S‰CjฤO‘8่ พี~H]‰ค้ยๆˆwฟ\€คนืkฤง็6#qIๆ#้ี#I‡ˆkp๖ูแ$์[Uบ,๑A] $�…\ฤ}-^"Q Xแ^ยkžฌส_ณ๖Aํึหด์†ฒศโ ถR$Ž{�ฌHธ ตภ''™ยEuvIYžB;ฝvน๚f�9อฏ[[�น_r‘‰nHบ์ฉi%‡คO‚›‰*ดvŠvฅฆ†บf@ƒณ๑Fƒ*฿t\,ณฎ�&ิjฒ์…E๖J�ผ€€€๕�ks�ชE5[^Bgœผ]LกX_ไฒ๙pศ๏3ส้า฿ท^z\๓T/“hWยฒะ?^๓JPเณ้G่ SFร(XVธบฤื�ฅ_ฟ6าt0g›.อภk�ฎE�q( ๑ัศฤ—ฃฏ��๏ฑD~า�iด=’ธ)nHๆํฌE2,ฟษ8๗9์ุh*ž`ˆy๐ำUšฟ -u๖ํ"ไฆไฆgุ6lูธรๅspถmฌ๒ท!i!�๘ท้Lื isฏ+’ฎํ…$H6๐ั†ุhุภoศŽฬ.Hฯ�$ q9๚5โซศH„g�ะป์3๖ฅๆว„ฌ X้๒G"๎2G|8 ษไGH๚ทหแPŠญ 0;;?s ๙~y( qฮ3 Vท๘/ืu็5jฉCƒณvัดูL1p๘ฎ“์฿Vพ+•งผ๊ง1฿‰๊~๒๙ฺ#J\จรE๊yQณWZLj๋~�ั_?.œอรฅๆ๋ค](ฯ˜_Tฤ฿g‘p๎zำDAวรYk ไม-C๐vnR$s<’n๋E:ำ์ญปxโ�พอˆ๗*�๗ฬ.X‡xm`m$โว๓n“ไ9ฬG-{ ฎณLผ=Œ›‡คi‹�Hฺึ�&ชูE5{ึจ‹4ฉXAฮ?น็Hว_ึา[TegMh๎�ม�;‹ฒbAH0DŽJ\ตc๓ฆ<�N๒ฃ†�ะM`�p�uvƒ[aX „๋T%๐“u์รฆr#o฿ศังlีQ6ฉ_‘l–ถ�qคึlํtX\v@oOุgเL๊ฎฒJ$ฺ!|�ำ6$]Ot@าn�ป`์ ส๓-๓Iu‡ษx@ิาV�฿ฒๆฌe/ฆ`-™๖uoฺ„6ฏ{N5‚šฅ7žพศๅํนท๗4{฿�ฆ]eœ ่8์m�แ)C,ึ^tHผฬมH7งๆะnืฒ‹! ฌdฺ !ผaxัฆฒ๔สสUeห…ษเ1/t&ิA>?๑ำ๙0dW™ใatๅี,+ส&ต*ชpyuim)�ผTณ•žคjํ‰า�(ฤป‡jg nkh๛qํogZสiฮ~[ค๚ำบ๓ฑ๙9_ชาle“i็ีœฆ†u–ชธyyฒ5บฒO@20jM๙๙ะ'=k[Lฝ*าC\จโ๕พค๙ฃ4KQ๑“SO-’EOุ๘G๚8 ^yู‹O๐,†Cผ3ดถ๑ใqทใ‚Ž „ฌห ฦ"dฑ qpj -H4K‰โ™๐H†u}RHzฮ�Jคแ�ภญ ฯ 'ˆ•?“™R`“8ฤ_e)ˆ>.ผ,่ธi ƒฅ0฿$ฏ๐[bโnQส็๖๊S&6šท›ดKฐ:3(๗\๘ิณ?ลIฮC�Q&�bศํpฤZ ผŽำ๙#ฒษˆjฯYนYผGใยไU้�$ญ\G|�ั‰ใ˜nหๅ๑นฆ�ฦR(†รึอ๒xฤ;ส๓ˆพศš\B|บ�Z�DBnD!ฒุ0$Š+ว฿?T๐uฌ๚ อQ"QผR Qn๘ˆ„<ท#QฎšH”ƒบ๒Hฺ=ู๘W๋ -$ญ๊/#�jb์\ ำAo@า๒O=ุกฤ’cๆu�2@| pC�s—โ›ตˆ๗พฏๅY ๖L–œ฿็ˆาตžˆo“!~์~ี(K.ม ฿^+Aข๐ฉG�Pุ‰*ƒใี๔5M+Rะ4ง๗แEรUj๘ƒพ}Ugw9๘†.}`ำผ‘†ดถๆ—า��Z@ฤเจXD๖x9โ‡Nโ?m๓ูm� x6~9กDR’�I�จ|$๎๎ฮHพฎฝHย?่y๊ŒX์0๛*ข๑รVฆ๕eฟeๅ‘ล6[~ฅ=ฐะ_ˆ‡xˆ7U>บœQผFข\.b”ื:ฤู&Yภ[๖&"ž่;q�้Bฤ—ซw…_โู6O‰(-@ค™ˆ›ผWA0ฏ.ฎoSคุq—&�uคjzMKฟฑะฏจ u1ณฏุ7์๛–น0#�–~# nอzฺู:‘Nดำด'ํฉฃsุD6Qวๆฐž‚:xณ๔Eัวี6—šGิ๋แ๗5 ๔x}+ญŒ - -�ฬ ภGzว/๗-X_fูm�weึ๖ัฌkฮzณE์<�2๐ จyO[�xK›ัฯฟ`ฮโlXพสoŸสกBป$I๘วfH>/ZŽd€โภF6 า�นํ้}๊ฌอฐ9ภฺฑ&#=nะ๖‚š]คำN(2hพcฆฅ๙'XพJ-�ckˆโจ-ูv๚‘ใƒ๚มฺRUโj;ะ%ภำฯUฐวฎG�Pp‘๎G|ณ์+žตcำ•ˆวชkํ/�_NsCŒw!€ธขก–G<—DLˆw�ษฤ๛ z"�SvIห‡‘tฝ:J$>ฎำ|qn ’ไห็,๙2I|ณ‡�kฺƒ๑ D\๐} �ณkฤล ึ�ใ†๘ืJ๙†V‹XQ ˆ๘นo -0sๆญtศาฆNฯ่”bฺ๚ถหม็‹หi่Cอ;ฺVRj้<ฎ,zKยfเi›ำOำ’Œษ1b4ฬ_=มb๛zเใŒ ั"ปภE$ฦง)hNJMษจ>qสก<$wUพWาj˜Cฃญ\๎ =๘ฺQ๊J/jiณWHfฝซEฒด‰uf๊KฬQdc€} ซๅ‰ ฝŸุPษนGพ6๊T•pฺzŽรรเํ��wแ)U"ฟฯํทiY{บYU‘iญฉ่Wะiแภ๛JTGำะยฒG{‹].?ขƒ/N?uฅT๓Arฅ�ดP“PํปลkปGแเgZ1Zิๅญ฿ผ9/oKษ๚Bกค|๏ฆ*เ]6T\ฮฑตqS๛รD๔,่ƒฃ[ŠŽ›C7M9|๙กข+โฯkเๆ้#CยฒŽ ใ๗iฟ๚~๙�ู>HzตฏEา๛›๛ซ�ค#Sx5k�ˆ=ด”ฆiGิษWs๔C$ฮส ˆS�#q<2Dถ| Q/ื#iqy -พต+อผ$ไๅ]�ฮภ/๐Kฐl๖๖’6w�!โใ9Hฺธ:#�o[ค็š"ฤำkА๔จYŠxบf)’žท โ้�„_2S9๗{0ลฤ">˜๕๑๑ฉฤ_ท: >�6z‰Qถๆฤe%AB’๎ฉฏ‘8$$”อ‰ห75€ค�ะ:ฤ†z†ค�Iูu๖๊)ทŸ�Œ„(^"Q4ู‚„8ต’ฝ+พ˜บ‰รฤtฤ7ืฏ qž?|๖E iๆ๚ ‰jส็HZxญCข† $-w}ฦ_ผ๓ˆ5W"q„ ˆlาB$]}฿o"๎ฟ็๑ˆ�x#>์xฑ>b"8NะqepฬZ �a‡กH๖R?b]?ŠฤกsโใKMˆ7"�๚๘-’!)2L๘๓ ’มVฤ+_OC2่ถฤ_{ฆD๒อ=’1_$�พำห“TZy;fZe\ซภำ$ห‰zVD\0‰๚ํ5ฤทNร๑yุc๙VGี ๎ุำ1ฟ์œฌฒ_งP้HGJD‹๘ฎ)Aาvฏ‰ห[‚ค้�^yื0ีเaฐศผึย๋’นฝ€คล#"{vI“!ˆOZน๒ดWƒR‰ฤแ๖gˆาซฏ‘8vชCฌo~6า‰*�/$็์Hœbฺ i๚ๅ\žถง*‘4ูS…คmว.Hดg"้z�ๆ yูPc€i „รkด์าwศ‡๔�โ]‡ๆˆo”๏}xอwfYJ5าจอ๚"๊p‰z\ฆห/ต๊ น)ตฅ'ตl#‡x�iž๑=+Ÿ/lะฉฒเšตถภIC ๐๖๕�}าv‘ฮเ�>w๊โ~�ชQ‹ๆ<๔ �๖ฝdอƒ=๐ณกX�ิ|ฐ‹4ž{5w�a�ธยwfิูEฃม ป๛Nๅแucdกผ’ฝDdๅœ๗รbyš8aอ‡�pฌqInR$์•‰งgO_–ฌ*~โ*Uู\ถ�ก๓žl,ึH4Iฏฅ.�ฉ*79�-ฦ€ัhŒ พb๑h˜Cํ7๓๖WีgVย^ุตฑ(˜_aŒ๑ƒp�?7ค�–ŸW~~๘ŽQL๛%S1g)n3gฺAฃเทิ๏ญโ�[G:[Rkท–๘๚๚๚–nูRRฒE`8�wฑsฝข๐:žำ\คใฎi—ฆexน~ดz€,1ฌ•ฟ๎|†uป(mแ~ -ถฬj„—�i— ฅบ_Tqค]rชXฝห…*.Qฏ š>REkึE•๋yธOžต E2แฐ’qnต"]ฬˆKŸ!DุUš\ฺ=ุๅ‚ดeืŒ ะ#dี#rฆ‰๛ืnฦU‡ฆ.4}ไ๎ปฟW.O<)คซิ�ุ\;ํS,ตต‡�\�\ข9w4o–บh/ฅฦ�(6ฌโ<"L฿7ฦ}ฟ[ณ!ฎ๒ไ™จ‡}"หๅฌ<์sTFเks๔Hึx๊‘,xู‰U�Vิ�คM‹ฟq{h9]+ฌ€1๓f๒pNฉ๙›uั+iwvKK#8ออ’={ซ~�ิฅ๑ฌ-โ:ึjโAงฟง‹รม๋JB>/ ๘ต‚N,vคNlŽ6๓:’iป๗! ˜4aWิู9^|ƒณt;ฤ<ศNIKใใ8๎;c้bฤM๕ˆ�ิสฑกฉ๙Klช หcV\b 96˜ูn�ฤN� ๊”rฯd$_ญeัHบX”ภS%Oikฺบวsๆ$"^๗–ม™Lท่Eณx๚Yƒƒ๑๑…€๘�‡dO$_ ข4ก‰๓V7Dบื ‰๓้ZศๅiฬE๏C2pp’๑' ™~2I�็o‘ฬui๊ม๚ ฐิ่ถ|qPภ๊ ฅ2๏ีœ น#�7ฅv๔‘ถ KdญPš,&+$๒ูYปู\1ฤ€'x|๒I๛!ฒฝe๋ค]ข\3ฮยd…ฐด่ดkฮ&(โ+3ย6Dญr฿พโจpjŽ•็้iธ2o๗Ž’ํฒฤ˜#`5,ต†ส–จ๒t:๙ธ˜�::็�“Bต€zษm,โีำ3๑ล ->6)!)ใส สo1�6ว;ฬ? ืฟJ@าฒ… แ๋j“R“๙Od†LVuxผตศๅอy:๕๑ค๓š�›[�น ้–‘^nฟN•u ฮ‡�B2ee-’ฏณ�–ฮZš_&@šฅjฏ๑m{Y๔j>จEาบฝ�"เ' v๏!2Gฺ�o>šX“ย78pหR Ÿฎ๔R๋rXK ฒ4ท.ฅZ๖ˆด„�ท1๙G๕bn*ึ‡[–jผ$่ธ€ฦฮ�rX,ำ`ๆๅ“Dj�ง@ิฟ‚]bvล6M}@SmŽญำ๏Z๏€[ึK๐.6oๅX“่ิjQ*ใ*ญIG„Bํ ™ูฌoƒ�@!„�@™MdVำ�ภชjใ}ฤ†2ฮ3:†5BU๊ํ๚า2A“Š\จำนว๗๗\�ฤ ิำณา-๋HyีŸ๛๗๏ฌ9ฑ‘ aฐ–ฺRถ%ง dปืึนใพ�I`œLณ\ใ–่aข:ชฒ*wยOฐำ ‹eฃ~j”1ฃJคฟำ@ถ…c-žDV]�|๙Œ๐๓ฺู�จ5ž^‚ๆ~"<สฉvถณฮtสZฮ4$ฐ+#*�H•ะ{Fˆห�sškRช]ปB’ึ์`m่”่์ฬฌsว๖l?Pะจ‹‘F“tฐศผสย๋นcZl„ˆ๘hฝ>มเณฦs5?n*HAJอูฒ๊”วŠŒ?Š [8/ฝAfถJaฏu'์„=†Ryบฑฑ–="ผRฝVi>bฉ†MPkL3}ยา'ํดฒ\A�?ค mด—อbs”†ัญๆจฟฦฤš ‹h‚ช*ำ\%ะv*ฺ ถฯหa_๐ฅเGƒN่”๗7™–Š ฅœ—)ฆซ “~็vัŒP๚ณ‰‹d�€gี\CาV‘ํ็hSป‘qขlๆฺi฿"ฉ‡Mฑ๕อนไ(อaอดา‰`ภ๋K“)xฯฒ}cๅh9๔gํYOฺ|ฤ}๑์จฺฒg“9Ÿุ่๙B˜Neƒ}ึจฝ›,Šq1ึโ$šฎ�๑ศึฺ๑ˆgน!n๏S‹xโŠ’%M ๘พqGโฏ�†ไ;�V$๓R@๒Cไlแ2l›’3ƒWณšF'ฉ 8าSvm‰Nๅc™bžณ`ชษวศ�m�ukF•4hฎฒา9Tดซส็LGก^š‹,ผ.๛.6ฺK– ,Wนาชฟ)จYึ?'้@jี�v/พDโRฆGา>… ั.ะ#i็KJŠ‘4O4�ซG|๗Aโ2Aถx%โ๕Žzฤ+๓�๏�ื#ž�R;ฝวjึ˜Lจ`-N๖เ‘ˆ๒Oทe"w�b฿สโ0$Mฦ;หS™_ํ{'OXŒ๘T�@;_‚๘|มฟ[ม�Dƒฤ‹4Gผ‰ฯ‘˜๐5ะoenŽYฒ4๔ค#]�้#ผฉ8�e่ๆuฅลYiyลa๛VV/ฑฯ?ูฃโ?›ZอZL๏ม๋ๆ{.Yผ2(,:/+ซคธฐ4๓ล—�จุ8kฟเŠ๚e.Gmg้๙ณsK5ืŽัฺN0'H0- c2$Bc๊ฬœ–™วV*w/;้xž$ณrพEฒิฌ$� žOพ๙]!bCœ yU‹ธnฝIงๆnqฤ ›ใ|ึ1๑ท๙๔ป งเู๊#dpZ= ›ถw`6kŠDกพ‰H;‘(^vAl๘85 R ัbIไi(—k‰๑รฯqC�8Uvใj +งผIๅSแฝฝ Z๗ษฬะฮ๑ต=` ‚n"’ฉตO�พษท# พ8ธ /–ถ๒ห‰Eาga -โ?Kš ้a๓E<ฟ{ ๎๖# ึ��๑๊�ˆี#–”Ožฉแห๓1ดฏybสS"โฺAHšHฎˆฬr -‰w7xฝ)6RTำOPA;�)นิ9nณku’Šฃ#i[๚ Gงฐ๔[6Fd#€อXญผVj๒๖sพq_ -๔๗ึ฿จ–ำสEi?gหHฒ oT๔ปsฌ›�}#sgzQ๘๏๔ําป6G้:อะฎUm`รๆNg€ฆZm�%Jฅ�ŽิดGยปj…q‚i&ฬ„)f ฏซไNฆm\'6Ts�๑Qฃ„@”งRoพJiืสื*uฉกŽƒ๋่ฐวnฏZqDSOจBบชญ8x!ณ -*แฤ:๘ฦ๘™Š๘ชe-โ๛ zฤื/�q€~•๑๑_yˆ.ฌF|ืฺ‰ำ€t‡sBข‘ท˜v@ฑฬE่on�›uฑฮS\ -ฃ -WM4Yม -ผฝดจrkPฑwHะสฏงŽ”ผนFEธ:๓S฿(=yn๐ทพ:ึปำุษcWฌ+ฏฬ+�"”F–,ิฌ}p๑ฯิQ -ฉPิP'ฺ๓พc uะfsษถ��ญภW๊V๙ˆ *$Nฯk฿uษBา้poฤ‹7ผ‘L˜ีIึะ‘3"้พm ’๏ณ ท•D”ผธ๊จิ>‚ฏ]ตอxตั�ฑๆฏ�ภน‡ฝลO1z…"4IBผดฉ๑๐;ฑzx= Vฮ ้ฝk6":ษ�๏ท๒๊:ฐำSvZi—ญ =�ษ5ศ^2‡f9�Jƒ~ธฐNงชด�l>วเธฉา({�ฦ>@ํ@S”[ฌY7…|ป*ุุหดfร4๓ ฏห็nZ#}Dษำ๎��็?ึ๓]‹Sำย•M,งF;ต�tฌŸ\฿Y�pž›c.วl›เ’๕4…ZC9๐๖pnhฌ๕(esป’Ro 9v6^C�ž๙5œ`ซฅƒส(›ั<๛N—ญบž็)6คrsๆF.S–�ๆ�ฐ๖›l๒๒‹ๆคฅ=�-ถ๒&๓บลVZcR’!’ญฉผš…ญ{ข Mw:>cAZ๚๔�0%ง_*‘4oี‰jะ,$-Ÿ�šš‚X�K%โ‹Vฝู Yˆฏž�ฦณง‡)ใ#โย๒c๓c“๓’ฒx๕ฏม๕}์ŠฃฏฅเRGฉG�-›ฮพa_ฑeฬƒb้4:๐mK›gArdฤDสzณo#‘ F*ศ฿t=อข�ฏQ…H๐`@๋fู†lเ7ตPคQ\.ค่…H€˜H~ม(ฅWี�ƒฝำใ`“Z+jl๔tฉใๆ,-$#qr_‹Duิ‰Sพ‰jฤ žVHอYSPฒ&;;nฟ2่7๔&(7YโcDH0Mฦ>r�^�‡ตโฉซY๙ฤ\z"นŽ/… l:{สˆ„ฤ4Q]lฏo๓ษŒผ/w”๊iฐ–พไvฅV=์�za‚U0ี(ƒ๙ฟ“—{‹์วบv9`r๗]tฌ }ฦmณค฿r์*ใtำ˜3 L6wฯๅ#6ดๆ˜†:ฐ&ดm๑๊ud�dธสฅม[ฅz้WmรQncBBด 'Eฐ๗ $Š~:ฤ†_‡"qธ”ฺ๐ตTfพaง3/yูขY—ม2X๔ q�ผs›(ฅpฦD7!ภNgจRbS#้fๆ้D– าๅถธฝ;gƒ�†Fีฒฺไ/๊jZขีTlซ\ช8๚JZ๖สQjฌฅใi:zP6€`ใูx6€ `ฬƒd้xัๆิตzB3iี>�็ชศ"X&kีฏ›œ7ฏ�>Dqทพ•VŸ๊พW(„ดด์ K˜ ๎ฑ๎<�}B#ใ!โSb“ ’“22๘�ตฅ'แ<ฺ—ว๊เภ5‚zาๅ;฿œง+ฯ9ถ๊@n]s‚‡oื฿ทuEโ„[e๑.’๎d6O� ผ5•c‚dDมŽDผr_ศŒ„CDย๚ศ‡KH๚~่_’›g�นผ|ฑฐV†๘ฏ+๓ฬ™ |—.SŠฌน ่ฏrK๔ฆ�$%?มภFD<)RŽ๙ฏR/v๓ˆ4L�าดฬ‰๙PŽ{t{฿Iกชโ‹6ฎ‹฿”™•`Œ1ล6ๆ16ืท(uฉ9ผ—–์ >คนHOัฺ#ฅ็มM�๏nGt6บฏN{m ๆ 7ฦ$(Y๋ษqมŸ�๖๚ืดี ชธL› ฐ{��ี[๙ ŸBwธI;ณZู๏— 8ฤ?ฝ็ฒ น๖๋™๙ฃE˜ตdึl~ไL-ํึWฉ๙น"จภผ๙‘฿อ1๘ปใ -Pป๙ภ�ช�ฌฒ\^]W๏Zก tงฃtOบฃeSึณ9RŠ26฿P๘ง™ทsซL3 ม&Z}d: ฦฬU<ีP*ญัษ๑ู IVk*Oรค:efEUูqYV0ี !0ร๊-:`ช๔๐ๆีT๛_~�‘�EQ &${ปvภ�ด Gขธ�ฑแIlr”5byฝ)๔Aว•›[A!�3fšฉา Iซ๖็�1ํฯ”tจ€NคฃาR -s๗T]๘–ฯ6z;ธ[�ไ@K๎†๕"„GGGGวฦฑฃฌฦ`ไMF —•ีษฉท�ท�|71zฅุPภ-ŒIฺศ์[N˜ภ8ู่"ยนฏMHšฌ™ƒค{J…HGqŽm]Zข Rตc�rปvœLฏ^๘‰รฬ:ฤ7ฮ"้ฐํ3žึทQ"6luCา$ญ๑อฌZ$Šีnqˆo8™ซูN$™™Axฆ๛@”a�บ๕ |ŒNญป„8a,•…17ธฌT$M,ุ$กฌง Bโโ๓๑”!Iืฌ_ณยศษื‰อyฤวบอˆฟw|)๓ี‘ˆw๎Œข?yมƒpŽสทeัL- VUSฒ*ถSย›JˆOŽ~หN๑j๖ŒนKืํ!ดำ—ทo&žื�šหพำZLE‘ภ*8L”พๆช‚R�S"ำ'b”_O๙~4b%+Dผ๓ศIฏํz$�บน!ikฎEาrภ"$ญr๕H:>ˆD˜�๕�ฉˆOJjŸ\ี ฒH;ศ2ซื#>๗&ฑ<__ฆ- ฒญ4Y>!~k�‹ส+ 6—Š๊๛มล&;=\L�]จpn{�ฬฆ‰&า'ฺ+น/ร฿�ŸŒ<`}v^Wก:‘๙o.'�0๊ำ‰�b–s9ปL;Œr.gฒ!{‹hขi็A๙+$@ฆq_ิฏด%ึH0›งมdฐX7๒šCh‹„|8 ‡,'๘LcR”�นิ™งเแล๚รัีัOฃ ๙ˆcsทฯหๅ/ัมZ˜้ต&๑ผฝยK†ไ_สะฉ 3๐3h‘ส\lI9�yํ‹(�—)๛ฌ‡rษห๕Aฯx5ํlฯ\Gใ์R7ปหัืา7W—kิQ?G+ว {?�ด๑}๎$Diœ‰Ÿ;R9๎ฺ่Tนศm๋อFฑฺุŸ ฃsล[pmK๙ฯผ&<-lืโ,เ“,ู"ฤmฑไlส+TLmPฮ2ทx™y�O�ฅิศตโ -Aฌ1†ื�ณ`สฒมภ{ณu›่yZKn;.R-�มZd2gK$˜ฒ! ฌ`ฑ๐š–DHฺšง-ธ\ฃ5JPŸ€ -zถˆ๎จpกย๚๓๓1uIZB๋ตฯ -.€k�ใ~ืู{ซS]จ„ีbร).aCtด๐utนІภzศทRe๎๙;๐7‡฿fช žEา2mVFZ‘@ปซฮ�o๘@‡’Ž€ญทRhoูัะ ;’rงฃคคดฌš NOOOO*h5ญๆŠ’าำำใำƒEVMซUEQIQQQ๑มซ–{ฦGEE%E‰jฐำvาบ=|ล‘ึJ็ด M˜“ฐ๙Z๛zn„1}ปx�{wi—•จ"๑ฃ_%".9๘.iโหขก<;�เ:š๐•าว9J:Jแค๕“นตƒŒถ?บS$uฑนิ<�^ฎMะผ’าm—E฿aJ ํฯ5ำฎด™ฐถ๚ไ.แ3W'Nลrบธ์า>ุฬ‚ื‚2ŒŠAGY/เปซฆGƒ—ศาŽpฯw&>sm,/`“<ว๒๙๙ˆ77ํABถ Gฬ^1 ‰ขพ?‡%ชVnŠฝ&lSฉฅ2�ช๗ฃฮZ$9;*nถญ•kปจ�ผ–ํC;๑H>?ƒx;ฤIปวๅˆงฏr‚+€S†rุ�ฉAฮn�ธ”g๓ž)" ๑‘ฐQ๖แ‹4๋1‘ลุ4ฟZรณAฐ yJSB\B D™ใ-ฦžyิซ•ฑลแ)๓€ฐซlpุฐ๖ร1Kฅ™ืษฉาำƒž �sงb]�ฤ?N๙๕EB6MGlจ€D1ตฑม)‚ง฿4่ฉ(ŠฌV†ทฆปeWm2�0–ม8c�,๏๑ฐ๊5โ๓อ_w}…๘ทtKž“=๘ ูy‘บD‘า‘}I๙>–ดถsฟ’�ฦj$mŸ~Dาa�t$ฝด<DใุLบ]‰๘OปฑHฺyš๏?:€ฤ!'hš hํpิpชเ‚e› Wหค้UˆuฃŽ#iนj&โรCรxฺ†อWZฌTEG ั๎ž‡ฤu`%โํIๅH:ŸตL6พ[L‡Œrˆ๒“ตD6กฒ๏พ1๑ๆฬŽˆE�Œx{�Ÿrฮ๊ลฎ(‘ด๖1 �zณษ็กr~.�Œ๏๓|^�ธ|f๖ถ9๗�sพ็{Ž‚89…B๑ีฯ‘“๛๖้๙“็Š`๛๙�ฉติ R[…เLD€/m#ฎ K�ดขสาฦฉJู–…น‰�พhฺ–ฤF฿ศWu�mิ‘8:QตBฑ�o™็๘ๅžพA>Aa]F๚๙‡้<ฝ‚บบ๖๋ำwpฯ~}๚ pแไ็๋่:3ะO็ทฺ'ศ'ฐ—ซ๓LoŸ@ืฟ5ซ\}]ืx๊<�=—ป๛.๗\ใไํ้:vฺคoปํฺณงk งงซwPเ�ฝCBBzญ๐ ๎ๅทfEo‡งo g`๏�บž^๎ฝผƒVฺ๋๑๓ ๊แ้ไใ็๋๊<ส'0hฯฒเ๚ง�๛พหจั]ๅ•�—/๗\๎๊ใ๋:รำฃ�‡ฎ~^ฎcงฬ๊)o —๋ OOืI_ึq๕๒ัyบyปนz๘ญ๖ t ๑ ๒vu๒t]�฿ื๐๓ช฿ฟ—ŸoP`/Bd9M‘ อj�jƒ ฅ‘9ิ7=นP%8;อ๔kิ น‘34jhw.4[ฬ‹9ลbiิ่Rร’*kฒ%ูjต&5j์H„2M>บffณ|Tm !Cไ“Hv!ำไพ!�ผn9u๚ว้rฎ๒Œj”j;ทฉA๋�0็๑ฮ8ฟhธท‘Gฃป}›ฌ๙jhSาTืดจ้C—ลGอ์f฿4�ฉmฆ=ซ�ซ๙๔ๆ๏[loูญๅฉVฎญ๎= uIง6sฺถm{V๐‹๎โ-ื‰ฎ‡ฺMm—ื๎ฯoŽท_��l‡’Žษvnี๙AŸฎปnํึฟ�บnv๗์~ฎ๛ํk{�๎ีฐื+8$?ค8tˆVr<ิ\๊ UิuPช[ฏ•ฦำ๊บ๑œบ—พPo—Zาค—Šปtำ%อAjิkŸย๎sf3?>‘ำ„ำอ‚ีฎW�•พK”$หฺ่Aิep‡ณฃผDฤญ�ตธ`๐ฌYF˜ณˆ=๏0’ฅ=1ป๔G$kฎ*อม”Bญdฏ�^ มf>^ฐทp�กŠCpชV—ฬ็Y,ผd์pเีฬ=สFuิญHQzFŸw”ZRNปช๗ฐ่@๐†ภฬเ\๗m!วเ6ŸMwr›,ึสMธรTL�+kฬ„ฝ(GฆŠ‚dCrด ‘<๋Iฯjk2YsัภขRธTฺ๒Š]๒jฉQEาท๙.[.(กV[เAอฏ๔Oi”–q�cBTค19=;�%S ^ตbนห*Bหข‘๔’>"พ~ค%งBขhฑ/œื?Sค�R‚x�;7˜ใ<d_ม๐ูไ_Šx��Dฤ[ธ +ฑ๖bขtkโ1 +xฤห็"ึ�_Œฤั; IำƒฃD*rHšโi+G2pฃ น” +HR� ~z๎ˆฤA๗๑ฝ๖S๊ +$ ็7Fผ฿o’ฦ^oŸŸ฿Œฤu8™‹คWT—8$m"ฎรุo‡Sฐeษา,ฤG5M๐s๗7yDีgน{1ฏyถ2o๕Vุี[ฏะfฐJ#‹ึ�J8๎sณ"แฦVŸœd +ีuุ%eYFm๗ึๅฺปั็5ฟmmn็~อABฦน!้ฐทZค’ nz$ชะ๊Iุ•š*๊šuฮJฤ[uชlDt�xLะqAฐิบxo˜g�…tJซษดฺ+�sึyฏษ๖ซีlY1v๊n…"}กหๆ#!L+ฃK�ุvdษ อsฝ4Zšง]KC�xอ}@พฯฆ…ะ&�#`iมชb?^๓—~�šHะมฌmบ4ฏ๙ปq็แ0ฤ'ร#_H@ผ๚ห[@|ภ๙๑งะึHโ&น!™ณซษ๗yๅHFปฯ`็{Pั�ƒƒอร€Ÿชา�U  ฐ๏!'%gcบm�– {เ)\9ท`�†ํ�6$M„[�6ํ้j$-tDา๑ฏ}ษ&>ฺ ๋๙๕Y‘Y๙ณ6 H\Ž๕G|๙ +‰0์โ ฝ‹ภพb�ด07& dmxฤบH??qท๙โปภ๏‘L|โคwซ\งุ๒ ฒฒ๒2ถ’ หB‰sฎฑฒษ @ผRำ™ื<ชฆuฮฺSf2E฿กปO p`[ู๎Tž๒ชŸ_ล� ช{ษ็k(vก—จ็%อ>i=ฆญYธณท0ฮ œษร;ฅๆ:kง]&(ฯš_m'ˆL'"ห็�๕ฆq‚Ž+‚sึbศ…;†Lเํ�๘H$ๆx$ื‰t +งูWs้ไ๙�›”ป#๎™/ฐ๑z฿๊Hฤฯ�ฦหs˜Y๖B.\5fšx{7+Iร&�‘ดฌ๙]TณKj๖ข^iR‘‚:\x๖ภ‘Žนขฅwจสฮะ�รCvfฦ‚` +ˆ•ธr็ๆMนถ]e๓F ๙ฉ“ภ๘กบ›์ท<ย0OืฉŠแg๋^ุ GLeF�พฉOู*ชฃlRฏBู,mน็HญYฺฉฐจ*์ �žฐ ฮยูิ�ฅHดƒ!๙๚็mH:žlƒคี่Ÿvรnุ”๋[๊“๊y˜˜เญื…อ_ผl*๐4€.ิาf฿ณฦฌi7ฆ`M™๖mwฺ€6ฎyI5‚šmฌ?}กห๛๓๏h๖ฝ�]ป,ส8Vะq6ุWฟรำ†|Yฌ� ้ฐx…ƒ{ฐัœšM;]ฯ*‚$ฐB’iCLt$„๐�แ…›J7VTฌ,]&L9กำy ๒๙‰_ฮ๏ !�ธา  #ฏf™Q6ฉYQPนห›หkJ่ื%šญ๔UkO–LใF �?\= q[�ˆถQŸื�~N %œๆ�€BีŸึ]Oอ/๙•f+›H�ฏโ4Uฌฝ�ฐ›“+[ฃซ๛$}ฃฦ"ั”“_ัณ–Eิซ|cˆ Uœง�—5ฃb„f *~v๊ชEฒเ™๋�Hง|ฤซฏ›b‘๓Ižลpˆ๗†T็#~>แvBะq๐“u)„มhC„,$N ‰‚fสใ/ Qผ๐ษ`ABขฎญCBสIื™฿Š4œปธuโูกฑโฒ)6žC�MQš‚๘้๓�+‚Ž‹€แึ0Xs A๒ +ฟ'&๎ฅe\ฝyปM;คซ1ƒr๏S$I$NN]‘ดา ^�›ิก\!y•;J^m;๚๓7lฟ๑ำjฤฺƒฑv”โงQ$>ฤซR(�!ึฅ™‘4H*ๆY+‰W"~ศพŒไ๋Aตˆฯ={#Qœโ<ไeภฏ†lุGญEภ๋8?"›€๘จ*ั๘’•™ล4.L^•>ฬGา์เMฤ—m�‘8Ž์ดLŸc:`,"8b�,Gผงผ€๘dย+Dึเ2โ๓u7D@ฌkz น…ศbร(ฎG�๘Xมืฐสg4[‰D๑FDน�3๒าŽDนr Q์ศ#i๕์โ_อห‘4ซฝ‚xง]ฐs้€ddฝIำ?๕`‡bKถ™ืqK๑‘ย ๑ฯ�nˆ๏>W#>˜Pอณ&์…,9ฟฏฅ๋]฿'=A��๙šQ–\‚ พฟ^ŒDแS‹๘ฉ -U:วซ้[šVจ iNร ?‡ซิpƒพScw9๔Ž.y`ำผ“7ทๆ•ะ��@ฤ จXD๖tโงvโ?-๓ู]� x6~=ฉDRœ๗I�ˆ<$๎๎ฮH๚W?$แŸ๔ชค-Q%ฎฒ] <�Zkqิ:ฤO๙็้xฤwKฟๅY+6U‰xผฒั�ฺ ๑๕7ฤxˆห๋ชyฤ๓Iฤ„x฿Ÿ,F|8ฏ+โ?ฅื4ํrIวk#@โใ:ษ7็W#Iพrษโ~ฉHโ=ๆ฿า.Œ%โผ ๅ€๘ฯ๎YƒX๓โ_+ไ�U5buD5 โืnผ)ภฬ™ทาฅ K›:ฝ “Šh๓ป.‡^.*ฃก5hKIฉฅsธา่- ›ง-ฮFโฌ‹๘9ต5วฃƒeหw‘๕2=’&W&!แ›ป"ัฬฉBB^฿็ํ\,4x๘X‚eณทดธ๗ŸฮBายี๑aหr$]W"žY]ˆคKีฤ3UKtฝKฯ�%�โ้สูภ‹๘hฦgฤงง#�๊€๘|@๔bฃlอ‰ห +‚„$S฿"qH$Hฺ(—๏ชI๏!5ˆuต I ทSฒ๋์ึUnฟ� QผFขhฐ qj&{W|5y‡q฿�ผŠฤy๎L@๒ี7ฅ€ค‘๋ $ชI_#iโต‰า‘4��้�ึX‰ฤึ#ฒ๑๓‘8t๔E�ธuฐlธ�žร#�“๏๘ธํฤฺˆmˆด๏hAว•ยqk์€†BูK�ˆ5ฝ(‡๖ฅˆO/7@"�ž๘�ำ๗Hงศ0แฯCHY}ฏ๖Ÿ‚dเ]‰ฟ�B‰ไปฃz$#๛$ฝ~ะห“TXy;fZi\ +มำ$ห‰zF Dœ7 ‰๚�uฤ๗NC๑eุS๙VGU ๎��1ฏ๔ผฌฒ_งPแH‡KD‹๘ก!AาrŸ‰ห{‚คแX�>yื0ูเaฐภผฦย๋’น}€คษH#"{qIƒƒ!ˆฯšน๒ด[R‰ฤแ๎Wˆา›�H�ี ึ6>—i€D�‡๓v$N1-4์7›งญ้ŸJ$ ๖nGาฒm$ฺqำ‘t|x๛คผlจ1ภดยa’5Zv้;ๅC๚x๑พCcฤwส๖ˆ>ฝๅ�ณLฅšNชืf}ก uธL=ฎะe—›ตั�–ZาSZถCผ้4G๘‘•อึ๋T™p�Z[เ”กx๛:nž>i‡HงqŸ?}้€mๅEs๚„๛^ถๆย^๘ลP$ojฎ?ุEฯฝ™ฝmฐ0.๗unA๙เ‹�}'๓๐ถ>ฒP^MŽ^,ฒ2ฮ{ฝa‘๖ษฤ๓sg. ‡ŠW ฟpๅOถ�\ถ�ฃsžm(าH4Iฏฅ.;จ*'9�-ฦ€ัhŒ บ|ั0 ฺn็ุ^UXX”Q๛`๗†ย`~น1ฦยy�œ2[^nู…ก;G0m?ฆbฮS�eฮด Gม๏ฉ฿{ลƒ๗Žtฆคึn ,๖๕ ๔๕-�ฒฅธx‹ภn8�w๕ฑsญข๐:žื\ขฃฏk—คexนZ=ภึศ_w!�บC”ถp?[fิรหดCบR�+ช(า.9•ฏฺํB—ฉืEMฉผ9๋ ‡วสต <�วฯZ…"{ฤ ษhทj‘.โNฦmœ&DุUšฺ9ุ#ๅผดฅื‘Œ ะ#hี#|ถ‰{7Nแ*CS šr๗6๕�?*—ฅFž6ชิฝุl;ํQ$ตด‡�\�]ฆู๗4o–:h/งฦ/๋Vrฆ ๕q฿ึ,ศ…๋†\๙Cฦ้aฟHGqู+Ž๘“๘šl=’ีžz$๓^7DbUฟ5ทiฤข๏��"ZฮT หa^ฬœ้<œWj�f๔Jฺ™�ัาNsปx๏พํฟ๚๒ึq-k6๑ำ฿Sลกเu5!—�VAว9R'6K›qษ”=๛‘Œป;๊�,ฏ๕พม™บb.dฅคฅ๑q ๕ถdโ็†zฤO๏ชๅFXืะ Œ|‚%6UežถVXHฝห2B\�งy๗4จ›ิXK/›ธX`Z},๐บLnฟ13.1ะœ๋อlobglฐ�ดr๏D$฿ฎaัH:X”ภS%ฯisฺผหKๆ$"�๔–มู ท่3x๚Uƒ๑้ลฯ€๘{‡dO$�Q[ฤyซ"�็†ฤ๙L5ไ๐4Hf‰ข๗#้;(ษ˜ c‘L=•ˆค๗ห๗Hfป4๔`ฝXbt[ถ((`Uะ™๗jฬ฿“‚ํŠ��ŽR+๚D�%2Ž–+M“๙ฌฬ๔=‚lฎFbภ<พ๘คY�ฒuR„.Vฎํ?v"„BXZtZฑ5{๒ๅ้a๋ขVบ๏X~L8Uว‹O๐tค4T™ปgg๑Y bL‹Œฐ +–XCeKT นบ|\ฬm-๕�ฟIกuŽZ@ ฝ์6 +๑ฺ™i€๘jน?›””~๕ๅทŸๅๆใฟ]@าด‰ แkช“R“๙/d†LVตyบตะๅ�:๙้๘ šป››�น‹-U"ฝ9ิ~“*9๊@�…dาŠj$�3�–ฬXšW*@še๛>3โ๛ึฒ่U#>~Tคykทภไ�EdŽด wภ|,ฑ*…ฏsเ–ฆพ\้%ึeฐ dh๎\Nต์i1ทC๒Bucn*ึƒ[šjผ,่ธ€๚ฮ�2X$ำ`๕ๆๅ‹Dช�ง@ิฟ]bvล6M}DSmŽอัš๏„;ึห๐.6oๅXƒ่ิJQ*ๅ*ฌIG…ํYฌoƒ\G!„�@™E๛dTา๎ภจชใ}ฤบRฮ3:†5BU๊๚’ 2A“ +]จำ๙ง๗^๚ย าำsาH-kKyีŸ์ฌ ูฑ‘ aฐ†ฺRบ%;ฟx‡ืึูฃฬn'0NฆYฎs‹๕0NUY•ปเgุeลฒAฟV5ย˜พ]คะ@ถ…cMžEnฟฒ๙สYแ—53นซ=ฝอa�8x’#R;mogํ้ค5œip`GF๊Uบž*ก๖๔—๗็5ืฅTปv„$ญ�ภZะIัY™็์�q0ฟ^#�&่`yฅ…ื%rูฦด(ุ๑ัz}‚มgต็*~๔d‚”šgฒeี)Šu[8/ฝAfถJ`Ÿu์‚ฝ†yบQฑ–ฝ"ผ>{์•H๘฿G|›9 Iรn��^Qz>RฝFi>jฉ„MPmL3}มาง์ดขLA[?ฆ๓mด›อbs”พงZอ P1~ต‰5ะี๖ ๓vถRัvฐcN6๛†/?\w +@ง|ธษดDฌ+แผL1๔ท›ฆ€าŸ[ดužiTณ I[EZx€ฃ ํFฦ‰ฒ˜mง= ฅ.6ลึ{4๛ฒฃ4‹5าJ'ƒ9ฏ~&S๐�ฅ๛Gษัs่อZณฎด๑ฐ‡โeุน}หžMไ|ขc็ +a:• ๖[ซ  +๖lฒ(FวXw‰ใ้FํOˆGทVA<4ร qGjฤ“W�,n˜ฤ๗;�6$?่ท"™“๚’Ÿ"g +W`�ค์iผšUี;Im๓ศ‘žถk‹u*ห$๓ ˜“M>F�nใnZำท‹@s€ๆ(+ C„@ปชฬx�t สเตนะย๋นbฃฝD`9ภr”+ฌ๚�‚še�sา‘๖ฅV-ะ�จx้5—R=’ึ)‰vžI+_R\„ค๑‚คั>=โ‡Ÿ —ฑ๚ ฐE+oถี#^ใ†x�ก๑�–๊ฉ]Vฑ&ภ`B9krช Dlk”บ+ใฐน๛7๛W…!i0ฦYžสŒ๘f�y๚ ภ"ฤ็๒Z๙ฤ—๓�� + $^ค1โm|‰ฤ„oน9fษTะะSŽt�—๐ฆโ˜ืก›ื–Edฆๅ…ํ_Qนุ>๗T—๒�ljk2ต ฏ›๋นxัŠ ฐ่�ฬฬโข‚’ผอ—^oฃb�ฌฝ‚หk๛”บณœฃฮอ.ั\?N—k�qภœ มlด$XŒษ๕‰3sZVF._Pก�ณ๔”�m@เyฬศ€d‰Y H�ผœx๛‡ฤบ8=๒ฆqํ:=’v�โ,ˆ7ว!๙ชmโ๏sื#้๕0NรตsG/สเ ดr ๙~สพพYฌ!…๚6"U์Bขx�ฑ๎๓ไ4HD‹%‘งก\Vฌ%^HฤO;e;๏ฆฃ้+n›eใ!�ฎ๒1N5อ‚Y0ญ�ภdqฌQ>b]sŽiจk@�ั&o>PWAึ๘/†ซLดลQช•~ำึใ6$$D rRปŸDข่ฅCฌ๛m‡หiัฉu�ฅZ0๓u›8y๑๋zฝภบ–ย‚/ˆ๛๏ไ]�D)…+7&บ v:M•›I‡13Oวฑ†)ทลํ๊&ุ90ิซ–ี&QGำbจฆฺ`[ํ ลฑ7าา7ŽRห`-C{ำพิƒzฐ>ดรฦฐ>ฌ๓`ด/๋Kวˆ6งNฌู3šA#จ๖๑?�Pm_ม2Xณ^ไผyํ„ล�ฺfZ}ช๛>กาาฒา-Q`6ธวบฏ๗๔๗ ŒŒ‡ˆO‰M‚DHNJO็T—œ‚ ���ซ‚W ๊๑�•๏|wฎ8๏ุฌ �ฅy1ฌฯ ฎฟe\o@�ุา‰n•yฤ๛H:“™<ฝAy;k(ว:ษฐ‚‰x๕ก ้ )†ˆ„u 7 !—=๔�ิป8'ืถkYู"a>ฌ๑^[๊™=๘&๕Ycะ_ใ๋M�IJ~๕ˆx|ค๓_ฃ^์&็i/�าดฬ‰๙PŽ{rw�)กถวnXพ (;23มcŠญฯclฎmRโRu(x-�|Xs‰žฆŸตGK.†��฿ ๋๘�=่sฦkk0_ฐ!&AษšOŒ๋ ��€›�iณWTq…6`ฯบ}ซถ๒Aล>๎6>p“vzฅฒืฏ!้p˜?qf๏As�ทณsaฦโ3�๙แำตดSOฅๆ—๒ |o๐ๆ‡�0wุ N�)@๕ๆƒ๛ถ็d–ๆ๐๊šZืrฅปฅา=-›\ทŽอ’R”ฑy†‚?อผ[išnœพ0ฮ๊#๋ะ9ศ7fฌไฉ�“RiNŽฯ‚ HฒZSy&ี(3สท—že“ มำฌ�๒จƒฆ +฿o^Mต�ๅว้_ต`Bฒฏc��O‹p$Š›๋žล&GYc –ื›Bt\™๙„ๅ0ภc†ฉž*]Ÿดrฏ!q๖)OxฆคC”t‘–Rณw๛ล/a๙LฃธƒปลO๔ทไฌ_'Bxttttl;ฦช F�dzEY™œz็ปอ๗ฃWˆu๙��˜„!๕ฬพๅค๙(…S๕."œ๋oBา`๕,$SสE:‚ซwl๓์าข•*k—ูตฃez๕b$ำk฿๕9‡คอถฏxX�B‰Xที Iƒดjฤw3ช‘(VนลA< พใdฎfAฌ“dZdแ™๎Q†y๋ึอ7๒1:ฒ๎ชเคฑDฦ์เา4˜ทเ’„าž‚ +‰‹ฯ{ฤำ†\$3Cฬ ๋#'_ว5ๆŸ๊6#�ั๖ตฬWG"�ป7Fˆ�โม!8&฿6–I3ด,XUIษชุA o6*!>9๚=;อซู ๆ^$�ดง‡ะv๏\�ฟwA๓[๛Ak1F–8�ยqQ๊ฯmJ�O‰Ltจ‹Q๖Ÿ4แGฤ +V€x๏‰+’n;๔H:urCาา\คiŸHšๅ่‘ด}๙‰0๑[$๊“ŸW#>ปฆd‘ถ‘eVซG|้Mcy:ทถT[d[-h2}B�ึ๘”Uไo.ีƒ‹LvzคˆฑปPแ�๖๖…M!ฃฯดWs^ฟ๙?yฤz +์‚ฎ\u2ใ฿\Nธaฤ—�ี,็rv›vๅ\ฮDCึัDำ.€๒7H€ ใ�จ^i‹ญ‘`6O‰`ฑnเ5‡๓�ั& ypส[N๒ฦค(ฝ!>r‰�ROมย‹๔Gข+ฃŸG๐วg๏˜“ร_ฆƒด0+าkuโ{น— ษ๛ษะ)ฟ=๐ำhกส\dI9 �ํ‰(=”)๛ฬวrษหอ/x5mlฯXKใ์R'ปหฑทาwW•iึ~S;K+วu{?�ผ๑cฮxDiด‰Ÿ=\9๚๚ฉr‘� ึ`?ฑyด7๛žฮ๏ภ๕-eฟ๐š๐ดฐ�‹2OLฒd‰t<ทล’ฝC(+W1ตA9ร4ฦโeๆu?s—S#ืˆห9Xฑฦ^๓sฬผIK๏อึnขh5ฟํ„Hตpƒ5ษ`ฮ–H0eAXมbแ5-‰ ด9O›p9Fk” > ๅ๔\!�Y๎B…{๔——#k4’ด˜ึj_ไ_> ื๙งฝnฒo๖^งบXซฤบำ\ย๚่h7เ7่่2 ugฅสœ ๗เท‡�eชtžEาRmfzZก@;ซฮ�2iุะQใพYO๛ี‰๎ค?q๗4lสˆž"kฉ +XŸX๔Ÿ +!บ)$M.PกSžŒ?ฏน)idFh%uTฝบท๛ผ yžฅฐ9šื�ŽNXผๆ&„ฅ†็ฤ๑lŽป๓�ฒ)?�76E๓คOซใๅ<�š\DL�๑“ลuOŒภknฦษ +๎ุ+๑`�เ{ฒFs™ƒศ”ฒWบษ�[*S�/9ฑ๗?ไ„eHฏsjฐK;์gCิ�wGi`s9Ÿe—“cัnˆc '/9gืฃE5/็2 Iz!ZตฺฉSศ6ZŽ{;฿ธ‹Dใฑ‰sงop9Y|]6'ณถOๅ4Jฎ๋ศฎFŒ‹CŸ ีผŽ+„WVœ†›†ํภซ=กB๚\ฎธd“&•8Jๅ4_[ข2ึณ`เ๊–rkใ K„L$ +ฉƒ\อ๒‰’ป„cx:ƒง๓้9๖-(Y๐๘1–5ฎGzมาB้ลลˆ‡ˆ้Gู๑ˆฬg8ขth_๗u�'๚=(้0ุz'…v— ]ฟK!)w9JJบ^ห*นเ๑7nL*h%ญไ +“6n�ฟ1Xd•ดRU•,ฐJนg|TTTRTกจ;mU.ญ Qะ#Wiตt^[ื€8ฉ›ซตฏใ†7๎�c๏,-็2๕B$ ~๖ซ@ฤล'?$อ@|]8„g'๊ผ@G๓พU๚#GศAG œฒ~1ทv๑มŽ'๗ +ฅ6—ชวไฺอI! ึvX๐รHฆฺ๚�13ํH ๛aซOฮb>cUโ$Xฤ355j5�wํศ8ฆน�ž๒โEุy �ฟžciํ‹KHŽOŒต๒Ÿซ๔ qqลณูN•ปัภื6VฅX““๙,ฮ˜Ÿo5š ภ.ฯฎจขbใAฯซk˜`SิF3Ak๛ภฉมNถำŸฟ…3m๔›#}฿|นeฌน>|ฏ'ฦฒธ฿ณๅ๐�ฮ’6ŽฉQHœiษ4$ฤฑ๏#'rซม.ํ‡อ,x (รจtŒuพณjj4x‰,ํ(๗rWโ 1วฦr6ษs,››‡x{ำ^$d�Pฤฌๅใ‘(j;๑ณXขjลฆุ๋ย6•šพ-\Kรช<ชhXˆ‹ฆฯว‘4Q•ฌOŒJ๊}t๚ญ�C•๑��'็'ว%ลง$๐ทO &edธ1Lิธ†e3Mum‚Iน.*tํ๚P๗yบ‰Q๘]ช�šทžๅ7&ฅ'nLๆีR~ี๚Qg-’์ท[Vหต]Tn�ส‰๖!ํx$_ŸˆAผโ€คีำ2ฤ3ื8มฮๅรiC์„๕ิ ็๓7lXยณ9u/” ‘†๘Hุ {๐Hu™„ศblH_ซโู@ ุฐบ\ฅ)!.!ขฬ๑c +ฯ�{เH๏]ำา๙โพK‘~ฝqฟƒ7’ภ9‡๗„$ะbAฌ๙ปIหไ฿jฆ"แ| •ญfฎ้พq3†๓ๆ2y#ไ �žงˆฎ|@ยo…๘ฎง3O'ฒCt(-Q"Qw๊Œค๙3ฤบ7tm‘4Ežงะxฤด +แฌ%SFšr็w๗aˆอwG�+๏8โ-[>ฯๆฑ฿€-Q"�ุAJqน!่8๓Tหl˜ Sซd,๗(หผWT�(Y— endstream endobj -264 0 obj -<> +273 0 obj +<> stream -xœ๛�6ำ ๗ +xœ๛�AJ +w endstream endobj -265 0 obj -<> +274 0 obj +<> stream -xœm•MOใ0†๏๙�C$8ฐMl'„*•–H=๐!Švฯ%qป‘hๅใะฟฒŸ) ีฝ™๑ผ๓Œญ!�๑ฒฝZVํปป2?๕๊†v๊Kwตz�uQฏ�r:บf|rฎrี9:�ชฎoหมjตYošzŒโxำ”Sๅฮ9�Kนw‡บ๙J๐j5 c{Œโ๘ญ?�ญบเƒ -=ฉMๅšฑO*นŒโ๘—๋‡บmnUล๑CSญฺฃonˆfโกf/}[n�จ๖uS๕โค�ฝo”jUีๅ(*�.ป.�ž†ั7อพU†ฌj๊$S)ฅfฏ๎PcRกฑKUน=‘็พr}�ิลนูoมํิuฮ7ฉ’๐ี5U๘;๓๐OปฃS3��*”*�๚๔v๊œ˜�~lซณHiฑl+7tปา๕ปๆเขป$I’…บ+ŠขXxวโ๓Žฝ๏ห?ป>คง u—$๓l”F%(TnQ•ข22%–“*๓ ๔5๊šฬuCๆjIๆ ๊žLƒZก4jอ9ฉ๒€’ฬ‚*t๚$‰^ฃเหW(๘4๎)|๓%J๘ -”๐อQยw‚oNืฉ๐A› -Ÿธร—K พ\ฮ Ÿิ„OKŸ๐อฅ -|9“ะ๐e๔ฉๅ�ธ _NืพŒนh๘ 55|w Ÿ–š๐ๆขแห$พLชภgน Ÿ–L๘,ด>ห{ัยญ†ฯภgเ3ฬฬภ—แ`เณผŸๅี๘2 |Ÿ‘*๐eโŸef>+1แcบพL�แหไ|†—eเ3L�ศ๛ค3 Ÿ…ฯยg™ผ>ฆkแ3ธ[๘4~ึ๓้ฬโg=Ÿฮ„ึยgqท๒>%S๘Dษ๛ไฆญ๐IL๘˜ฎ>q€ฯrำV๘–aๅศn๑หว๏ุฯmWN}๏š1ฌุฐฺ�ซ๗นซปถ๓งยOX๒็�^=g๓ŸU +xœm•หNใ@E๗�Šž…%X0ฑ๛แB‘B‚ฅ,xˆ ™uฐ;Kฤถ�Xไ๏G๎S4šEˆnwu�:ี"�๑ฒฝZ–อปฟ2?๕๊๛f์ +ตz�ตQฏ›b<๚zx๒พ๔ๅyทฟUmืฝิjณ�ิีล๑ฆ.>ฦาŸc�r๏U�0yจีุอ1Šใทj๘๐ท๊‚jR›าืC5œTrล๑/฿๕US฿ช4Šใ‡บ\5วฉธ>š‰‡šฝtMฑ๕ƒฺWuู‰“zŸ|ฃTซฒ*Qแoq�ตแ๐๖ิ�ธฉ๗2D•c+‘J)5{๕‡ชบ“บ…]ชา๏ูy๎J฿U๕A]œ‹�ถน�๖รOEช$ฌ๚บ ฿ณ �iw๔j&ภŸซBฉาฏฅทS๋%ม์๗cSžEJ‰ES๚พ�พ�ี�%I’,ิ]ž็๙br�g�:แุ๛พ๘ณ๋BxบPwI2w‹ 4*A™ 2‹ฒจๅˆ”ฝŒ=ษ2J_ฃฎ‰ฬP7D> –D� ๎‰4จJฃึœ“,(‰ฬษBี้ิ€$ัk|ู +Ÿฦ=…oพD _Žพ9J๘๎Q๐อฉ:>hSแw๘2ูƒ/“sย'9แำR'|sษ_F'4|Ž:ต�ทขแหจZร็่‹†ฯSรgpื๐iษ Ÿก/>'‘๐9ษŸๅ4|Z"แณะj๘,๏E ด>Ÿฯะ3Ÿรมภgy>หซ3๐9 |Ÿ‘,๐9๑ƒฯา3Ÿ•=แฃป>'๎๐99Ÿแe๘ 7๒>ฉฬยgแณ๐Y:o…๎Z๘ ๎>Ÿ๘ดณ๘ู‰O;กต๐Y�ญผO‰>Q๒>นi+|ฒ'|tืย็ธM+|โŸๅ���–aษค™Fั4q?g_1vฏ‡0pร ›ฆZU๛ฯษ�6ํt*|ยศ?�๗˜ิs�Fsก� endstream endobj -266 0 obj -<> +275 0 obj +<> stream -xœ�ผ TTWถ?ผฯt๏ญขnQE1CdDQJ็จQ4qFฤ1**าFmŸQJา&เ”H|i�ะvด!m4ŠIิคQ’๎ ไiบ�„_žšD‹ใ{‹A3tฏ๏}฿๚ฏ๕AŠบu‡}๖�ํyŸ2€ภk€@สฌeKฃฎึสf8€SŠอ)yฯ�ทภ�9 ส‹�๛ุขมdภญลณg๖(๛ํT€ค�€�ลลณg( ˜$€nล%KWธž�๔์YP:kฦหง_ -,๎฿S2cล"v‹ๆคt€จ…3Jfฺ๘ค plYTบd้จ9ซ€ผฟภ{‹ฯ^”๕ๆ `๐~9แœ๖ชGOA#@#lภซw�6ย)8XปฏC›ะkp๖‚ฮม:๘ษ›(ึAPœƒjุฅ=YM�eไ\„3๐”‘ L๒œCม…>…Fุิน -i‚MpŠ4Ai"(•ภ ่%จ€FT -ซq4โฑP ๏ะ ๐l€ ฐ^€RxGใlz ->รP 7`พ -“แ0ผงฉ 8X๔5P �‚ีธ๗รEP งกvภดZ` dŸณœ/ภaุ3aka�ฌ…ตฐ๋๐„K’]ŽA5�๖ขcจ'‘*`B๋i ]NฎB52ๆมyึ"ูกZށjฉ•ำฺ้o…/งำQ=\•์๒L๒=T`œ†]šฤ‡๑X6Šข vม.ํoต�Wฒย;ไ6ฌƒง0GC้`’ีPAGภ6ุqP -ฅ$ๆA)Tฐอ๚/ิC=$ฒอคW่h 4�vแ"T ี๘ผฅdd@„ณkฐ–์๒*XยZ์๐ช,1J0‚Qึƒุ_xะ๓`Aิ[“\‰=๎๛e•ฃย˜ƒ~ๅQw๏Ž) กlาAvธ•ƒิ๓๙ฯ]�<ฑว๐1Qศ™7ศG6o๚ ฤรวฤn๑iะ$—+ฑG� ํšX๕ sd๎�้ฃfG=a}"&๋ ๋์ฌDภPฬkh1{ศy (ฒ€„์ Ha๋0…ไๆKญ=มzฉ๕RkJ€๊R�.ีULมป„„zฟเ5ฒๅ๛oK๑N�ฝLC้T€ž ƒ…AR•บ�ˆNš� ’i–`ฐ�zฃี�šฺ’ฏค�hU™™)jšjLKํฎฆฉ1้{ชq�ข_?qไHฯ�ฟํร mรjทผ๚{\~gฯพ…Ÿ‹๕04๑ t<ญ+„Aš'Œ=คสbฏRš,�ั)r2\ต™†8)Hxpธ๕FkjชWHrๅส•ญึkjffŠ[Qำ�QZชMตโ˜่Xิ+6&Zrhฬ ๅGŽ$m/<๗ž-ฺŽฎoX�๘O<พ~รๆถ3’ฑz�D��’รฯLD7฿�๐ฃ–Kจ๓Tq๗2ตIvงOHO�-Mh'ัธขฺLCG�ึTDkCจฌZmiฉHวEc‹Lnl ]�๒์์�ใ๚๕••๋ืo$๐ภZ7›ˆ๚"RQฦDnz�ร/ต|๔กเg��ห4†V€ โaก็ฃ !Qๆ ‚ไ*›ซ2๊xxUท&�๖ ?Dƒ-Fษ<(ŠJŽ�Xoด6 ีฬฬž�|ๅ†Wp)๘T3m™ช-3ลž™•โJ‰ฎƒ:T‡๋Œuฆ=uฮบ บเบหิeFzFปbำ{๕๎‹า“ฤ59]@่Œ@ธฉ฿๓�นrมถ—ะ‘#}_^๓๛ท๏�ฯw่๑ญSO<\tด ๒tฟุ(œ๖่ขู‹.พ?ขmํ�ยiฏ๏9z2�๑๒�ฝใโฦŽM�ช�฿:ชฐ็ zz‚,L๑'  ข“JƒQ10ษjณุญ—ฒ›ฝูอฉšXญ7ฒ›[…ˆ)Hu9\ช=ฐ/r.UWบKลEhŸ:ต์�็็๋y J`ฯ๑“ีmuฟšนu๏9<ฝ๕๗้ป€V€ย ฯ + ›ฅภ$U๙กืƒซš�ถ‡f5Jfณ๚t฿ฌฺึ+7Zฏ`ญ7ฎู2ีฬไp๙PsXPLจVHKตษ:dดภ{๙๘K'Jๆžz˜฿แขจ๋๏ืHŸฺธ~ฟO,ฝ๚VŸฬWP& -@fไแ;ฝ็ลƒปกz�-)“lเ‘i์ด๘ษ@l-ึKญฉญšžญ�ึ$a‡�ๆŒ‰ล้ฝlคl�บu๋๋jŸ~บVฒ]แ}��ฯ๚๛5t๊ณOQs+ ( %t:H0�Oœ”Q์D˜‰7‚%@สลN2‰Œอ‡<ูzฃี)๐ฟ’š™2|\le_หVล๗b_OŠ>‡L๑Xd‘BJvc<M H3 4Sxๅกมว๙โฏ้t๏xฒ�Nˆ?4”V�šฬ'K0Lฤ -�h 9๛Š/� 5Fีฟ#าะ#๓][ูุุs฿’฿ฟ(ยnจmพo๚,€z„Kโฺ1•ฆ22)Dm&‹๕’W3,ฆi6‡ห1ฝm้ฝ0zDรณn�บu’ญ•g๚9ฯn�'zใ๒๔†ฐใ–ป—ฉD+ ส<?3ถ˜œ‘ŠหFgDdDnxDัIP‰NP{ฅใDP•Jซ�M๊๖๎แFSdจ ฃC%Kพ,ูฃ๓บ[o4ทz[ฏck77+ฟyอz๓šอฉนฑ†ฟๅkี™)k'E#‡fl{`$Š@ป—ดP”Œ“Pzฏ�iฉไัuใVU<๒๊ฐM›[฿ื0oฮฑ๑+ฟฉไํ�อ‡g'๏ฅ™‡“’7|XŒ%dืชฝGcbšาำgMZำ["ทฎ~�€Kรp]G+@…ัžI6PIญฅษpR6J(6๋ฅf=[�hฝ๔ถˆ=)ทฌศชFAŠRS ฅYSTxะ@ซGcะ๋ี6้Bt๊ิIื๕]™ฟฟแศ‘คใ๋-๋Mส“๘ห�m้๔–ฏŽ๎ๆหa4NฒC๔๒„0+2+ ช‚้คศ``’Ÿฟ้�(r%ี�jฝ–jถไˆ‰–ย‘ˆ%1"†คh�…Y#ัZพบQ‘_–์�œ3ซฺ›L.Tj|ฉ3wบiCฒ'ฤ\้wย -•ม'ซˆตสะDถ‡ุฬ ฑ�hNmmืโ กลw{”pฅ:;4'โu{v,๗๒ัwŒส฿:ๅฏ�?}�€ฬ„ิู‘๕y ว๋ฒ>{๗�็}๛ }ขOI ^ิจรต^jึ*€!*ฤ†ถ๏๐บA5J‘เฑžcƒ๙4i`Dข ™FD\๑พญวYฏˆ/)่ž๘ŠW?<้ƒซฟ}…�}Šj~๕ุฎK'ษOBW๐จ'ฐ6ภŒยยe…#ฉ1่ชื‹z๒๓n็จ•ฮxยˆSVdล‰ ฮUเ$i` -Š๒Aส3 -?๐%ณึญQG‹6}„ฆxฝI% S&’e6™ง”‘•ŠqJ€ห!$OGฎห$ฑm^็=Šืต=Cg๎๓~\SO�Z�฿t๗2ชๅY'ฤxค*T™E^5ุ�›ฃ๔}ชป–‚ฺต”�+6ฮWˆค‹ซž|ฒj๓“Onพ๚�ญ/ฏ�บE>�๐�–>jy�ร]�=�_�s~%"แ˜IB~ ่t0#ี“gย FBฐัdคŒฃ’ภ„9)SYฤd3˜‘ฬนF†‰B$8iRฬ&ฃAัซV“ ษokก9๛Fvณ๊ิรรฝัYถฒ3ฒU๑ฝุ™Iั‡�"ZW™ ิ ‘(‡0ฬย กฦSค9bQ<Že๑Rผฃ๔0gโ�,Sส”ำ”lsž’olfž &š&™‹๐\RD็ฒy†ูฆex%[ก�สฐุ”่o ฦ‘$’ณHcค1'ฐ�ธ?ห65N2ฮรsYฑฑฏ&ๅt5]ษ~e\m š‚ฆจiกH�‡bL(ฆแT�ณ{N5๐�_>tN๗.วนmMdำ:\ิถC๗มVzHฒƒ N{ฒงAa“’ฤ N‚งฌฬœรS'6ฦ0!'aงQR%’Iา ศ3[oดถฆช:ˆญWœ๗f8ๅk™๚PT„ๅ)ฒฐผฑV”@ฤ‚”t�‹๕Vใ"\†—1ณ(J0qา ,…ศAJwวบห}I_šม2ๅ eษ—'I“ไ๙d.+อ•หษ -V.•หaS`J@šŠา (ษjLkบ�‚๘็|ๆฆ&ษ๎ญ@๘ไถม8w-ฯล|]Kงƒ ๊jพšo›ไgœS$cู‚PบrBย429iศฌ่ค'yบไมG†๐ังะ4ไ*.;ฮฟฯ5jวิf:ส๛4Y ๋y]Oงƒ ^๔ eNI–จ“PYผ1Š0"NŒ‘ษ ŒNƒ‰7“QVdƒSQไ\ฃLUเ$รพ#œฏHB๋อ^]�ไ์+ฉฮŸ•๕พ:Gึ<'ย€$นอ•—กrY’‘,KF‡1‹๖2NฆŒส4ล€c (ฦ คฅSy)jlแ�H jไฅoฃxGงท�ณญฝฮs๐Pฤ็ฃgtYKh)ญ€h๘OO\อ฿@e•d‡น*Š4…ž ถส ๚+#ฅQ๊H�QaA#C๒bฌ7†4~P�pมน{ขฯ$oถWฤp›&^๖•ู"–ช™™"Bx†คะ–"ฅศ)JŠ!ล˜bส ฬqๆๅ็„ไ„ๆ„ๅ„็Dฌ!k่ถFZ#ฏQึึื˜ชซีAีมี!ีกีaีแี1h -าu0๊R�_™แข็�Pบ/}๐˜พ๛2‡ๅg�๎wฎY9#f“kC๓.๐O�–ใต_/ฉ๘ขm5^{}‘xงำงg็ nฯํกZnฟท>�๙ำ๕a๋Oึ‡๊ฟจ%{� Zˆแ$ูม~ไ Vภ�l� '%�@ษ’ุn”-ึKูWZฝูZ†Kฝ"j‰ไ�HบKuก4G ๔*๑.D%�sูุHง{“ซซI.xUศ๕ ?DnHv่Ež๔`‡IrBฌŽp‹r05 ฝaxำั๐Š�l0ฒnมndุQม�Œ�ฬ�YฮจZoงฝดาUหV6งh๙:.ฆ0‘ร๛ก^ฑบ๖Cขฉำ+ป$G pัท’ž^œ_ีฟ�ๆy/�เ\๕ะร K'?Tี๔ไำŸ|Sปดzqอ๕OถVO�๒�ณ[‚Cท์๚พz‚VnๅŸใoQ20๒˜ศย‰P’˜@ผ�^L;HLบๅ=ฝcJ>ฯืขีบญwโ0ฯ“้ 4๛+ก&Gฐ?eQ‚Bก!ๆะ7�ิW�aม!DA qฤุ(„D:๚YมD5$RฝูZs๖sXh'}xค8}d$กDˆ$ Omž0นtแร6๊�รพ๙›=žอ๓๗�ะฟฉ`๓๗ปถ„oy๖๛อี[?น^ณธziํ7Ÿ<ญฯ^ฝฅ–ดYBู@ช� UŽํ�Mก;ƒมfd–ค.ำฎณ„ฎณŒ.3Ž8GŒšFj6๊๓Œm—{์,:๛ฯซ็ -ท'56โd฿0ฏ[ภฯ๐o๘W�๔ฤq›ลˆ ๐pz—�W Qภษo๛*C‡+^ธ“ฬKฦŒัy฿ฤวาHบ\ใ=อึม{“�๖ะSม'ร5ฮ‡€อึฟsาu6ำu๒บLDœ้ขฑa�๚M›ึฏ฿€Cทฯ>s๕Ÿg ท'9‚๛-}ุ๖ฤธI(ฉ(eMW�ร-}6ร‡R›o2ิlŽ3[e@ ก*"ฐสŸTukŠ๐?ี�ไqม ™‡H6›k่zๅใฏY‚X[ฎ้Fp/ฮv�ู*๕ร๗ฒM&oXปaK๕ฦีฏ�cฤ�q3๋>ณฑวถ’ๆ/ฟl^P“�ˆ3ฯ๐ม๙๓�โๅ�ฐะ†ค{*ซฆ>‚ฒŒ”5a๒S:ถงhk ม„jญPkุhณLฅ๚๕Q!ยfทzE$ำSา 1ฟCชRท+•:์4ฉ1จ๚หชgwmๆ#ะแ�๓ปwพ<ห’�ฮ?ฝ~�ึฝ—?๚ไฟฺ๖้k ้ดœ์ัๆ„ก3ญ“p(Lxๆ23Bั๚ธฎ๊บ๓ฉxa๓~œ[/h่พMใ€�žeค9๘~#กŽไpษhฝไฝไี��5W'Bๅšป๛yฝ>'o๒ ย&‹๎ๆา ึDฤ )ŠADร  .o4งˆ”7yฏg-?”ึ๛ ็“ล๏�tฤPธ.ŒึoŠA4ชฏแ๐ziฟภ3ตถ:ฯฟ%ห%;ศแ๑ง าซธ^Q"� ฏˆW#โ็pก๓h฿๕๋ผ@ฒW�เญึhLๆ฿�Nƒ4 W™ �$L๋%ฝัำiจ.a๖้๓‚๋ื%๛๗ซ–จF*๏^ฆ=ูu†$OH๐หp(ฐ–๘ฝl>dญ5ิˆถ1ี =ฅ”a พๆCX๐ญŸjuSํA{Ž�๓0�œŸB9(�แ=#‡ีO8��|บเล�๔๘xTƒก…h{|�๙~�.‡�™ฟ๋้ง๑RาrบL็ฑร๓Tวž—‰‡PSBŒ’Y€ซๅ9฿o๊ฆuส*>†�ฤ๎ใƒะ1บ•ช๕่ 8@%ึ&a5F\ Z+1”A"dศ0˜ล�JŸ)ทฆ�hMํฐA‘>ฯ~�M”้=…2๙›ฌฅ�ฮ๊๚zบึฃ่XอT่๎qHต†P๋/ฟA&ฉๆžr„5ลfี๊}vข…;ชทjuลจz๑HE‡แ๎ู3waz!š€๑cผž_ุ{ Eร๏�Yฮ’๙ำ| �5Fl lใแธI -ถWผBbฝนตz฿ึ* �ด_ -�ม" ุ@cุuƒ=๑ๆf -!ฮPท$ฑ\ซ๚;ฟZ{ …Z V#Fฦgด•t ทz›ฝญ'N่๕šๅฦ�ํ๕จVkณฏฉ“ข�ฃ�ั้qVศR‡]’-•แ—ผeGQPzแเญk~kัœ7g|„L“ -๛ดิืืŸFI�WึŽ^ต%wเ�=Sฏ�i๚‰ฅ�@`��หtป&ˆd่q™ก6NชHฌตีDl{1%ศ�ํGทC„#4šD๘ป"Sฌ�ๆVoณoพ,’ญžวฌืD€ํา)ป�gO‚G1šข1ั�า{๕่’-p๑†ญฯฌ฿ธ๕~vํS฿พ{แ�งึึ์ๆ�ส~w๗ศ5ๅ+ืฌฎ(_ƒOื>๑ฤ๖ฺชM�ฦปฏ>tแยกี‡]ฎทvŸฝr๙L�4sลcญXนFณ�ว†ฑ๋�แ้งอใ�พœ;22"W›ฦ!วห๖฿ีช่e๘ญuืจ�ปG่รธุะLKOปœา�๊C๕{†qบ;ถwฺพAœ�&ฺC,๚!ัU!#ั��7žฃ]วsฑษH`ิMฬ็nดพ-CรRไฎQš/ว{}๔”Z๚G#bdšY'ฉัผจหแ:M–ตว[ฺใใ�ๅ‚๒เ๚ถห"ฝ‚dบ‡ต€ a‹คqŠฒHd1EŒขD}ิbTW2]ยฯ๑ึRป…%่4> b'OิŸfD้ ฝ$ซทUธาš&๙เพเ-d-ท[๊ลsb�“มฎCwโ‰‡€Z‡ฑาฐืฏVŠฌŒฺVS#mwผฤk ั‘vCdผี��์mฝค'iอ่usฐ^หL๙ �๊ๅ๖�ฮJ”ญป๘W7็ผ?ง่™{ฺถcGๅฎงŸิT\�ง��D"ใ�|ๆฯ_ลv;“�ซf๓ฏท๏]Yฒคข{๗ืขข>zฅBlุŠh1Gb-a0ฯำว ศฤ(น %ฬM)ษ•(8uิ์ต~M”ฉ‰‰ -ab NฅjOป1ยœฎ๋NศฃŠ�Pี'Iญ—Zm™โทณ)n5G g@ IBขQตฒD๊(S๐๗ฃŽ=๗ืC#+fฝ~ี�Bา๓m๏~๒ิ–ฺ'๑๋๖าฝผ•??ฅmk๙�{Oล“ฺฎ�๚๑ต›ดšเ2รฎC8d{\ม!HBjร๎ษ‹กมf่*ฅGˆ฿,Lุ็�’จํิฬ_ศjLบ‹Žy๐�2~…7# -Ÿบฬƒ๕ำNŸ>�ฦภู๑E;*†DตจT$ส๔�็Gๆ๓๓�ฯ� o‰tกง๖‚ˆ“{่ฃพ��<1มPk4ิฺ6ขZใ#USpd€‚X"YjXODุR\zAงY‹žŽ4kัถ uภH—ฏ3Dฦ#๔่7kž�๗อWฟYท๖i> ฝ๖ล๗๋ึm�ฟลเƒ๑™ถO*6�f.โ�ญzดp๏ฏlzฮxพ๎�yภเ ๛Y `0ย6ฯp#{ขu๋#Zw—ํแŸัz~Dซfe}R;)๚PAภ8UŒP#ษ$™&sHํcœŒ'3“ำ‹ n๚๋ฎ$�ฆXs:ฮ"้4‹๕Uฒ ฝLฝอใa<šŒ ศD:=,=,U& -LSฬs”bs9YFห หL1S cๆJฤฬ๕tu�ล�ีง?=~๎์qึrg‰๖~L›n'ๅ^แงฐ™–ำๅ หcปƒภ่K่ฒ„ปSˆ“ญ�์Vล^aJ@:r tคตd,yฝO�หงพŠ๚ั๖ธGh5‡bัB~kฐีF˜kƒj"ถwsD„J.๖pEvQ�Rซ๕Z๛�าตฯ๛ษŒ’ฑ%™%Kษrฒ’lH6&›r ๅ`Sห‘rไ%วcฬ1†ัh4mmšำะ4<อ8อดvฃ�x7ูMwณ�าnyทฒ�ฐ�ธ�t ๘9@ฐา๙€rภpภxภtŽฃใ๘89Nณใาq๙ธr�p�x�4๘็˜๑-Eฆัilš4MžฆL3ˆ…ŽPท)h -jฏ•bขc|ัKŒบn8 ห#{๗3:ณฯ๐๕›++7oฉฌ�๒ออ›฿|sใพ–1fLFŸQ#๐.�.?รฯ๒wQ -๊2PJ_มื๒_๓h#z ญFต˜ึฤ/าษ’$๐ƒd(๔d*�ปD�๖dซ3น+ปm‰์^aฏ ุ‚ช-ฎ+•บ)=˜คะึ=สB@Žp๚9ลzษ™�๊L๕fทZฝWฎ๕„ไ7R›ตด๘ฦ-=8ซพอKคjลkœjA{ –IDบtชZก˜‘žๆŒ@"vวฉฺFฆŒ/�ีขฟ—•\*DEgfž›๕ึู‹ว ั่=ใz~ฬŸ�r๕ฤG‘ฅ…Sๆ\@ฯาES'�9YR�แ�นlจy๖จๅซฏXDศ’)0๒ไŽ6่ตƒ่'†jตMฌวฎิโ?Rุh”dมzPค่•ึจd‹=Cญ’ ฆ๊Rc6ร๑็ฮต}pŽตดํย…ท๐›m™zn.ป{™>าn฿žCญ?ฉuิ๘o‚Tso)ี–คu){KํบMKตt9&›6์ุพaร๖.~ืึv๋;o�w๘*สG!�๏�U�ศ�Ž‚Q>_ษื วะFดญแk4น&ะr-~ญ๗๔P0มฒุaB0FนFP61ƒ"v๘’D“ค๘้อ“o'$ต#Vi๛Gิ๗๊ฒิ)FƒงdˆE๑$V‰7๔F™คทาว`๑—�e#฿pจเP Rc& ยˆ"�ฃ�ึv~๓5ึาฆเ๏o'ฐ8๏ื$เ๖_ม-:˜ต€Q่…ˆš“m”กึ ฤHbษzI”ๅพV้RkŠ�ฅฒtทVๆ! สโ/ก1gQo๏[๕ดlDใ0ญโฝœ•ิใ&m๖ zน]z91uะzน—XK›๘ยœะ#โ'pฃ๔บ6w๑]ขฆฉ8จฎฎŽ, yg<๏�ฏ๋<ฯฃฯ@��€t—#-�ๅศFืหัu~พ๑}ภ๛‡$bK—นW็—{ดY—ธคNฝ3œU”อA-kๆฯ_ปv��5UOบื}�โล็ว<�ํเSท๘'hฒ๕^™’S‘ลw๒)hสพpปึ๎�น๖ื;w๒–ๆ ๚๖ุฑo๗หูีฤื๒#�Uพา๎ุ„�CU่q๔g~๋3‘SP+-'f…X ™จ?Xh]ฐ ๊La`‰ ณj…�%o๖ฅึT]0$พewฯw’B.Z>ผz๔ไGM#็ค�œ?๊7ใา ‡™Kง �Dฬ/๕อH3RWP฿œ—ฒ{F2cF?ั+๚lอ%ž0a„%Yส.rXa’ฑJ{ส*ค� บod๚b๛ขํฑŒ๖๗;�kRฒ@ฌ]ึž“Kxธจแ๏lผkgMzE฿ๅั P ง  *`=ฌƒ -T…p -=-hœ๛Žจ๊ะU8'๔ ญP # Nม!๘m…Oเuุp -ะV(BWัy4*กฮภ&lƒmฐ*แ*œ†d๘6i฿p� nัอ@ฌ๑�๐2˜ทฐA6„BTยk0ถBl�&ฤยTุืQชC7p.ยฯแณฤC6’fชP…Fะat:}~ฦ—จดRบ./“_’�Kช)6z–>4ฺฝำ+ปŒMฦฯLฑฆฑฆวLฆwอ�อฟ๑ณ๚๕๑+๒�่๗‚…ZๆYŽ๙[�W๘ฒ๖ทฮTcีฝ๊{6›mฑํ9[ƒํm�฿Š๖�ฒงฺว�wุO8บ;–๙t4wƒ˜`ฐยv1 e‘ - จ๖ฏžˆŠ’K|Ÿ^?FMพc -�อwLบœง]Žม฿}ว„๗+B|ว&ศBูพcฟ€Xดฬwlb๛.ฅฐสa1ฬ…9P K! -บร,ˆ‡(H…H4ˆ‚™PQ sa),ฅฐfร (๙ฐfADมX -ฦvะZข}š K`6,†e0 -! Œ0fร<˜  ข`ร Xsด;ฃ`†F? -ๆยBˆ‚EP3aฬ…Y…P -%0Cปv?qAa$”ยB(…\(…R˜ด๕—ภ\ํผ, า ใž็�Ÿn๖^ฺEฺY]ขฅ>้…„KadAฒ่|๗/ƒ2H‚%P -eฐfมlํูลštIฐfรR�…Zปดํจ�eqM (๎š ณa”ยrˆื0�IกใOฎฌ#7ข๎แ๙วVc„ฤ�ลฏX��†%F� ™็๚P:g„Žf‹a>DA)�K^„dc4z%ตNิikืf๛ไšฃญ"P� :Eฺีูซ้ึญI\_ -ฅ‡ ต็๙์\_กfยRŸ†ลkŽO–Y>ค�i.ีธธืฦgภ,ํพXไฃ�NA�ญ๓ฎ[าlอkt Ž๎b%ัšๆฤณ…ฺปฝfม\˜แ“OทมYP%ม๋า|Š`.,๐ูq๗;W�.๘_ -ห}v.V์ฤDœY‹ก -กLใณ“›BMกฑน0ส4~:q๘๙uร,Xe“ๅš k>ฟิ‡Œะ๗ฝตำ๏ด๐%�–i๖่ขq,p้ิuง�.bํฬOษัฃCฮd-๎Di”uะiฯ๕กzฏ๖Y๊vไtnu;ำ%ผื๊:%ZฎแQ๒oญะ๎ EZฬ\่“Pทšฐ!Iฉฦอ ‰y0fi๔๔{บฺ๑_”lื\H0ทCK K๓ฮ๑พงfภL(ี"CงบฦขN~ Dพt…•-น็�v_Y๔“1 ๋sB*แ�บฆDœฟืึt4๔H>ใ๔)(๋๑B่พD{๏Œ�Ž.–Bนฦo‘ํค{๚ฅg&ๅ�‹ีๆย—�#šเ]ุ้โŽ3:งำv)…>ปZ]{�ซ่x•มํSงDโY์Ÿ๊๒ฮš4ลพs‹ปฤP!ฮษ’Ž5๎วgษฟ”ฉkŒ+ผวย„ค?อม/sr๏z๗ใ๒S<๊(.ิV’�|Tืต$� -�J๎ก�~fI‡eถ๛อ�Ydถ/� Ž;WZฎIUจ=�y1บC๎๛Ÿ๗ทg�่.ึฆ๛ฮˆ๛๒ŒภEฯMํผ -kXะEห ๆ�bณa…†ณnฝ3`,๒e1แ�"�ด?ัU�:ฯฟ์1Bโšx_โใQฌ๓K๖ขK๗S1\\-ำ๎บแ่_ฌWข๏ัแ�SŸ1vAGฮ๎๔บv„๎{"/้๙ๅ~Šโ™Y0fh๗สz^V๕ใ๚ใ�‹ˆ๕๓R้•–Žขศ‹EH …@ฌฉ๓!๐Ÿะฑ๒8M�0BรVศ;N[!ภศบํถ3Dฃ ๘ึัxH“O๐—ฏI(hˆkE็ˆŽ;วvัŠะ้Mo‚s๑ผD 2๎'%iงvฏv~ส:ฺWด„�R#ดปวมศƒ%�Œn๙šฌ}ุ๊4uปืmBฟW็I่g”ฆูแ!฿:ฝ๛ฅะ=D๐฿)…ฎพฟป`ึฉ}AQ๐�ฮฐfae?FE๘ŸเD�%ฌ@|jGAุ˜ะ’ฮน๎/๚ํz|ศgŸํž7๊>|��จ�พ'v่ดฺืพWƒO“ฮกIF�[t๕ุ•+ดธทศ—ื–�(swญ;ซาฎ๕g.ฑถk% Gแ!ฺฝ%๗�ืyVฯzฮ๊์yบึp?•นฺปไ๗Uฟํี‡ป๕�จk๕[จี้z-ธคฃ*ั๓GiGe"ชฝbh๏ZD7(๒หฝ��m]]2}ญำา๋KqŸพฺ’Ÿ@๓—2ิ�ขเE`$(/ืŽล,Iฏfh๗ˆ{ล๙•๗uลบ �พฺe๙W๘‹ณKด,*jันยขžL๒ั]�ัŸub"ะง[%๗iฝำ๚ตฌีกƒ9]8�^cˆบBฌi�_ฬื’5ผ็ร\Hึxฯฎ€$ญ -_ษ๗U”bŸR๛น๛˜์›��๛#�1@Œƒ!0H‹[&˜‚&ภCƒลฟ๐„ั ย “a<ร#`*๘รtศƒ\รด Vุ ๚ƒbม= ฆBก7ฤCwศ€d„tx�ะ 2! \2$h30;ˆํj10zj๑ดDB๘ษe ็ฆฆ๗ส๓ฝ8‚ื วกงงฐaศ5@ึh�_ hm`‚Tํุช�๕‡@E;๖;๔ี6ภ�`d7d‚T ศจั3hw)`‚dํXา๎aฺ1ีฮํ ึฮ ฯ$N8'mซˆ—“;œ�N%?%฿ฏ"฿�ชb฿q๒� z๋ๆ$vซŠ�ZCo�ˆe7'‘›z#–�ฯทษ์n“o“ษsr“oRษ5;๙บ†ด~5„ตrาฺx๗‚็.�j๙๒j!๛ฒ†\-$�ไไe�เไ๏กไ Nฎฬ'—9๙ฏฃไ๓ฯ‚ู็ทษgมไำ๒7N>แไใ์cN>rkศ_�โ`ๅไ/›M์/๒ม*๒~iูlb-Yไ'฿3ฒ‹œผg$8y—“๓Oจ์|๙s y‡“ทkศนJ7;วษYNฮฌ"oq๒&'oprz‡kๆไ''9y“›M์„7“ฆ?eMœ�ุ้๖งฃไOk่ฑฃnvl -9ๆกG�ไ5NŽิฦ๊์UNชฐ†�ไ•~์0'/’C…ไrะFp๒๗ด‘?pฒŸ“฿�H='/๎ณฐSษ> ๙�^•�ฎ;ูซ’฿พศ~ปŠผH�““=œ<ฯI�๎`VWHv?geปƒษsV๒ฌ‘์โd็?ถ““~d๛ถ$ถ“mIคถzซญ!5ฯe5œ<๓๔๖ฬQ๒ฬ๚๔“n๖๔๒ด‡nๅไ7œ<๕ค›=u”<้&ี•nV=€lูlb[์dณ‰TUบYU!ฉ|Be•n๒„J6qฒ‘“ œ<พ^esฒ^%�มษ:N~ญๆฒ_#k9Yณ‚ฌ~l[อษcซศช๒+N*,d%'ห9YฦIูR3+๓'e<าฅfฒ๔]b#K8 kแ;d$ฏฃžฐ บแ,TยNํษJ๒(!Gแœ† „�eWเ,บn๔ิรฦ๖UHl„“คสHษC‘จžC/@ิฃbX…ห Jx‹ž€ท`=ฌ‡-๐ร[gkั๐ ‚rธ[๑˜‡เ8E�ภมขฏšเ&ฌยตธ.€r8•ฐถฃตะ‹) #p๘‚5แxมN˜;Y�*๐`Mฌ‰]ƒ็ Bช—์r บ แถE�๐Hธ€ŒPใศCไa๒ZGc่2r*1i0ฮฑ&ษ•r TJจ”Nำพห„|x†jแŠd—g  ปแ์ิ$8„วฐ‘l$=ฐvjฟ+๕฿’�"ท`-<9B‘lจ„2:ถยnˆƒb(&้0ŠกŒmาฟกj!‘m"UธLGฅแ>ฐ rจฤ7แ-(& '@ป +๋ะ!ษ ฏ„ลฌ ภ/หฃ#่e=€=น๙ผ๗็Eฝ1ัุ๕ž?ฃฌrิ}  4ช�ฮัy4œM<ภ: ๅ๕ฤ|๑KฟH์:lt^T=rเ';pฺ€ฤฎรฦๆภ๑ื€‰nwbืดkbีฬs€yrงˆšY๕˜๕ฑ˜ฬวฌณ2C!ฏข…์9 CไQ ศฒื!…ญล’/6w๋ลๆ‹อ)Aช[๕ธUw!฿b๎๛’Wษ–พ[$ล 8y็ งS บzC I๊6#:a0HฆกX‚Av๋๕f_sj7HพœzฝYufdคฉiช=8-ตGบšฆฦค[PLt์ษ๚y ๛ุแร�žx฿^ดืต ญ��๒q้ํ�{ง็!ึระภวำqด ฌะ าผุร*,๖ +ฅมฒ $'"T›iฐ“‚„EXฏ7งฆ๚„$—/_พ�lฝชfdคxิ5อัฅฅฺT+މŽE�ccข%‡ฦ Zv๘pาถ�ณ�๘็™‚mฺ่๚u>๖ุฃ๋ึoj9-+วNเฏ๑ฏ๘ท�๔tใฝ?jบ๘๑‡:Oew.Q›dืxJ๑†ต๑ดอา€v›มชอ4DpไkN@4ท1„ฺภชี––Œt\4ถศค๚zมะ•ฏฮฬฺฮ7ฌ[W^พn�r๗�ฑyำุ จ7r ๕œภM๏}๘๑ลฆ>�ฌปs‰ฦะ20A<,๐�g”!,ส(C]ˆ\as—G‹จ่�`�€Bhจล(™DQษั๗>๋๕ๆFม š‘ั ’/_๗ .Ÿj†-Cตeคx#R"SขR�)ั5Pƒjpฑฦด;ธฦYRZf™Œฺฐ์™�ณUฑ้�{๔F้Iโšœ. vบn่๓์ฎ˜ฟ๕t๘p๏W�๑อ��๕=ztห”ใษ+?ี'6 +ง=ผpึย ฏฤoYณ'๊ซปœˆxดดG๗๚ธธ1cRท่๖ท€*์‚n� SIจ่„RgTLLAฒฺ,v๋ลฌF_Vcช&V๓๕ฌฦf!b +R�ทj๎‚Kี๎VqฺองL)9๗ลนZ�„ุ3�DeKอoflูsOซD}�๚ฮฃeเ€N0ะ มห ›คเ:$U WC+‚ถE�ษj– ท“อ๊ื}ฃj–@BN)8ม$F0b4สึ๋อN�ๅิŒ”ac๓d+๛Fถ*�๖อฤ่ƒqมdฏE)Dก”aฦ“ัไ 4JC1๙วะ@4่_๔ ๆG๖�ฎ๑€†ำฒ{โOƒ๙„a †Šคล-$g]๖วคฦจบใทลƒ`~x๎รkส๋๋ปํ]�ว็E๘มu"ตฌงำ๖N›)B๑๏H\+ฆฒภTF&Bจอdฑ^๔i†ๅว4-ุๆฐc9ฆ‡-ฝ;Fixึฌ[ปVฒ5๓ฌฯพเYอ�Dฏ]บŒ^v�t็•hฤA‰ื`ฦ“3าฅฐltบ"]9ฎฃษIPŽŽS{นใxH…J+< ๊ถ.FSdธ ฃย%Kฎ,ูฃvฑ^ol๖5_ฦึjnV~ใช๕ฦU›Ssc ห7ช3Cึ~OŒFอุ๖เHไBป—๎BZ(JฦI(ฝ{ดิ`๒ึจšฑ+หzy่ฦMอ๏Žญ›;๛่ธ�P๎๚�‡g&ํก‡’’๎;lhŒ%l็ส=GbbาำgN\� ["ทฌzvฟ[รp.]Kห@…Q� I6PIตฅมpB6J(6๋ลF=[\oพ๘ฆˆ=)^ฌศชFAŠRS ฅYST/xQซW ฃัh๋hี6้Bด๋ิIื๖^‘ปฏ๎๐แคck,ํAJ“๎๛๋›-่ด–ญŠ๎์ฯa4NฒCt๗†1+2+uช€้„ษ``R@ ้๎(r9ีืlฝšjถไˆ‰–"ˆ%1"†คh�๙™#ะพช^‘็_”์�๎Ÿ=ณา—LฮWŽฌก=wzh„Bฒ7ฬ\p� +ๅกวƒ+ˆตยะ@ถ…ูฬ +ณ^oLmnีโuกลOk”pง;�4'โ๕ }z ๗๑ั๛ทฬ�2๙Oฏู7mkฟŒ„ิ ู‘๕บฏ๋ซ�2?็�ฝ๛ +}ไฃฯH^ ิ:จมต^lิ*€!สว†–๏๑ฺ็A 5J‘ฑ� c๙ฉcDข ™†D\๑ฝฉวYŸˆ/)่ฎ๘ŠW=8๑�+ฟ‰€>CUฟyd็ลไววก+๘Kิ X๋`7F‚แฒย‘ิtล็C�๘9 ทณิJg€๒ผˆSVdล‰ ฮQ๊เฉc +ŠrAh~เOfอื›�ฃŽmz)M๖:z^ส@2T™@๒”YdฎRBV(ฦษAn‡<น/‘ฤ–•xญ๏^�๒ฑื๗qU-๑hyใKtˆ–gใ ’*lPayี` @lŽพ!Zะ๗ซ๎j +jีRz๗ุ8�!’>.ฌx�๑ŠM?พ้ส๗7ฟบr๓&๙์ร๗š>๚จ้ฝw๒w๙฿๘�JDย1“„�@ฯำi`Fชw  l4 มF“‘2j`ŒJๆคLQd“อ`FN0็& +‘เ„I1›ŒEฏZM2$ฟฉ…ๆฌ๋YชSwGgูสNหVล�รNOŒ>hับยd ฆHˆD8Œtขกฌ“!�fŠ4วB,Šวฑ,^Š—c”ฎๆ �ƒeHrš’eจไ™†šว+y† ฆ‰ๆ<‡ะ9lฎa–i)^ม–+ฟ1,2%Cq$‰คก,าiLภ ฌ/๎หฒŒCŒs๑Vh,รซH)]EWฐ฿WC&ฃษjZ8�กŠฉ;Y๓๔๎“u�ึ ำ|หpNKูxปดlื}ฐ€”์`‚S�LลiP˜ฤdง$1ƒ“`ล)+3งฤ0มิI„1Lศ ุa”F‰d@’4šญื››SUฤๆหฮป3œ๒L�(*ย๒YX� +J0a!J:๎ฮz(ƒp.มK™ู@%”8i •ยไฅ ‰c]ไ�ค7ํษ2ไžสP’+O”&ส๓ศ:Gš#—’ๅฌT*•;M†ษAi*J3 $ซ1อ ่า็|0โ_๐$ปฏ ็“Zแœ5<๒๑t 6จ๑ pZ„)™ฐม,$U6ฐYVช5ภ่ดXrฌA`1Tศ'Uห‰ ี`”Aถ)ถ\หภ Q@j(XตJ?#ฃ5ื�ฤšด�ฃรัห&เฃึฅVฌจŠ-ิk‰ ์ฅๆชนถ‰ฦษ0I2–-(ฅ‹ '$L#“’ฯŒNz์ก'‹๎h0u GƒOขย’c�‡ฬ‘#ทOiค#}O’๙บž‡ะut˜เy๏ๆ”d‰: •ลฃ#โฤ™œ€ภ่4‘๘0eE68Eฮ1สQN0์?ยนŠ$ด�่ำๅMฮบœ๊�EY๏ฉsdอs\$ษhŽผ•ส’ŒdY2:Œ™ดปqoT&ฃษc@1!-ย‹Q}ฏ็‡›P=/~ลฃ8:ญๅŸ-๕่Už‡เ>=ฅหZ@‹iDรzใBl*CDธ$;ฬQค!�DจU5P!TGŽ์2"l`Œ๕๚ฐๆqรจใฬ; awŽ๗š่ห๒‰nำฤหบ|=KฤR5#CD๏เšยRค9EI1คSLูมูฮ์์ะ์ฐ์๐์Nููฎีd5]อVKซๅีสjรjใjSepฅณ2ค2ด2ฌ2ผฒSeDฅ+MFZขE +ฒ{+3�\๔œก๋‹๗ฆ�{oฦะ�Œ?�ม=3{๘,ruศภ๓�ณ–exอ7‹หพlY…ื\[(>้ดiYูƒZs{ธ–�๏ฎw�|}ุ�ณ๕ก๚/๊Cษ�๒œV b8@Hv0@$yC•:07wภ ืQ2�„$6†e‹๕bึๅf_––แR/‹Z"นE?’๎V�(อƒฝŠ| P�EึืำiพไสJ’ƒ๛_r}ย’๋’:C7=4ะa’<†0ซ#ยฤข�LuจCฏ^wิฝไ1Œฌsp(DYถCThc ๓ด—3ชึ�i?Z้ชe+›Sด|mS˜ศแ}P๗X�๛ ัิ้•]’](B๔ญไบ๗ว็็U๔ํปi๎๓?zU<๐เ‚โIT4<�ไ'฿V/ฉ\Tuํ“-•6�๐๔ๆะ๐อ;จฏีƒ[๘๘;” Bผ&๒Ÿฐ["E€$&oถำ„n๚NmŸ‰’ฯ๑5h•n๋ํ8ฬ๕๖Œ๔„›•p“#4ฒ(กuแP๓Z๘๋u๊KžNกaŽ@DA sฤุ(„E:๚XมD5$R}YZs๖KXh'�xค8�๔LBmˆ ฺI@Ÿ ุ4~R๑‚วoะ๗วฝ๓6yฝ›ๆํ�ฑoC�ฆvn��๔›๒*ท|rญjQๅ’๊o?yRŸ%ผ*zK-iณ„ณT*�ยw„‚อ68ฤ,Iaฆg gfqŽ5Tmะ็Z.u�QpๆŸWฮๆoKชฏวษ�a^>&Ÿๆ฿๒ฏ๙ฉ c7‰เ๔„ฺ�ณ!�ธPณ+<ฮ@lๅAม† +WpE ฉ่�เ +<ูๅฤ}qก ™K6›{ศ}zๅ็ฏQ‚X›ฎ๊Fp7ฮAv��*๕มwณM&ญ_ณ~sๅ†U๋๋ฏ�c๘žฑ3j๚?ตก๋ึขฦฏพjœ_•\3ฮฝ��นs|ศ?๑q_ง๐บคฎป(+ง<„2‘Œ”9~า:ถงh k‚ ม‚ชญPmุ`ณLฅ๔RมeHณ[}"’้)้บ˜฿!ีฉวJvš€ิT๙Uลำ;7๑แ่ะ-„๙�_aษ-็ž\ทnหžK}๒ท–ฝ๚šyh-%ปต9aธืLk$\ +คนL�ŒPด>n‡;บo&~ฐyฮฉ4t฿ฆqภภoฒ[า|Ÿ‘Pˆ@r„dด^๔]๔i~๎ƒšซกrอ�|>ฟว“ื๙ya“wrhOึDฤ (rvั0hƒห๋)ข$ฅ พซวXำE€๕�‚ฦ๙e ภปa�-1ก ฃ๕›ขGอ†๊o8|>วฯ๓ ญํ„ฮ๑๏ศ2ษ2ธผดNzืมK +Cค แำ๑iD�ยแntํฝv็I๖ส}•I�;‚[i:๔24 „ฉbฝจ7z: ี-ฬ>`žwํšd�แำJ‰j4 �ฮ%ฺ]ƒPH๒†…พƒซIภ‹ๆƒึjC•hSอะMJ ถเo>„฿�นถQ7ี=iทปไ_๐“(E<ธ{ฤะฺ๑งOๅ=Ÿ›ชะBดm‹?ืวห฿แo๑ท๙;�>/y๐0-ฅ[ภq^;j 1ช;™.ๆ‰gykชฝีฤt๏Pฑ“'๊OณNยEบAwษ๊k.7งฅ F�?‹ฯ๛๒YำญฆZ๑œ˜�๔dื  ๖ฦCPตรXnุP-E–Gํ้TS%ms<ฤ๊ŠตบHtค�o๕56๚š/๊IZ3z�ฌW3R~Fทzน}ฏณeหN�๕ู๏อ.xmฦžƒทn฿^พ๓‰G'6–�%๗Cฤ6’ศธืŸz๛ุ๋ฮงำปWm๚ํถ=+Š—u้๒JTิG/•‰ [ฑ-ๆHฌ ‚ ฬ๕๖2(21JB ๓PJr$ +Bี{uภejฐA"FขB' 1†ฆRต›�่2งD่บ๒จข7T๕IR๓ลf[†๘noŠ[Gอ.ไ Š!IHิ"ชV–Hme +�aไ‚1g?88ขlๆซgQอM$=�๒ฮ'Olฎ~ฟj/�ร Q้ณ“[6ฒฆO฿}๒žุr๕ทฎูจี—่hv " ห๋ ƒ`V�้ฎผ่ +u™กGPช”๎พQ˜ฐ฿๙EQ�ฉฟ’!ี˜t7}�ูฅ�2oD^1e฿่๛kงž:u์ต�ณโ?@�ห†@ีจX$ส๔็Fไ๒s�m~š7Eบั{@ฤษ=๔a๎‰‚>�˜Pจ6ชmPต๑ฯ‘ช)42Hม ,ฎ`–ฺฉ›\ถท^ะiึขง#อZดmC0ากภk‘๑=�ํชg๖~๛๕๏ึฎy’Eฏ|๙รฺต[�ภo๒๙ |บๅ“ฒMฟ�ˆ x฿…+ฮ฿๓ฺKŸฑŸซ9{0x่>ึŒฐี�<ฤ‡QูรจไaŒ<ฤจxˆyŒฤ „s€ศีู่``E–ด qK6šฌ๋;?Y—}อญ๖เŽ่�u8า&B2ั&BF„JจJ SbฆYREฑ"""qkEž›ฤเย&Tห�|>ฟ ๅฦ�๓,ฆ…’n% uผL๘i�สš@‚แ�xไมƒG">4ษ4‰r€กCDขรษ,Eถ๚tฎ›iฟส#ึGiธM=ฯ‡�เรฮืฒ„[ Zฮืgดฌ ฬ๐…w“˜มh F1šŒa“ษ(yฤˆึฃh=๚ˆึำaD{่—Fดพ_ั๊ฃYYŸิNŒ>b0N#ิHc2Iฆ ฦl’M{'แIฬไ4ลโ๛ˆ‡�วบ( )ึœŽ3I:อdฝ•LCwS๓8‡&แ<2ŽgJสc” †<ำd๓lฅะ\J–าRรRSฬdh›น1s=UY{a_ๅฉฯŽ=sŒ5�@ข}ำ†[ d™O๘ilขฅtHเ๖ฺฤ๎ 0๚๚“,แ.โdซ/ซY„EฑW˜”Ž(imC^ญใS๖๐)/ฃ>@ด=๎แZอแ„d๔†‘฿lี.suH•k[g‡+\rCxt หูYD๑‹อึซญs๘‹WSผ๏%C2Jฦ”d–,%หษJฒ!ู˜lส†l”Lู,[ส–ณ•lCถ1�4 +FกQx”q”i*LES๑TใTำ.ุ…vแ]d�ลvIปไ]ส.ร.ใ.ำ~ุ๖ใ�d?�ฯ๖K๛ๅ�ส~ร~ใ~ำ18†Žแcไ=ฦŽIวไcส1ร1ใ1ำ _bฦฟ™JงฒฉาTyช2ี �%B'ฃษจตVŠ‰Ž ๒G/1่ธแ€.่ัk๔จŒ^รึm*/฿ดนผ|๓ท7n|๛ํ๕๋๘jฯัฃ{๖9๏ไ๏๐ำ� ฅ จ'Jฉแห๙�[พm@ Uhƒำ๘:Iฒƒ ๙� ฅKgใCจวžlu!Oy็อ‘]*]๖๒ อจาโvYฉิY้สภ$…ฑ.QฒหHไ๋EgVณ3ี—ีl๕]พฺ ’_Kmิาโk7๕เฌ๚7/‘ชฏqช9์มZ&้าฉj…bฯ๔4ง ‰ุงj™2>ดเ7 ?-,)บ˜ +Nฯศ?;๓3ŽๅฃQปว=๐์่ท�zๅ(ภG’%๙“gŸGOำ…Sฦ็฿>ŽYR�กพ9‰ฌซz๚ˆๅ๋ฏ™+์O ษ”฿yb๛๖ท zํ ๚‰!Zm๋ต+ี๘ฯ6%™ธX7rAŠ^ูhJ–ุ3ิ* ั`ชn5fใY๖lห๛gYSหNœ+ฟ�’ก็ๆ’;—่Cญ๖ํ 2T’jGUเถH5๗Rm้!Z—าพทิช�ดT[P‡cฒq�๖m๋ืo�พ�ย๗--7ฟ๗ต|ฏ \ฦ�ฮ_ๆ๕�๏(ๅ๒|5zm@๋ัjพZ“k<-ีโื:oW,‹&„‘c”c”1…ภ!3(b‡฿(I4ู(AJ€�<๙wBR�b•ถD�?๖:3ลhpขโTB ฑ(žฤ*๑†(ƒ๔Pz,r h$โท‰ +ล 5f<ฒ Œ( +<ยonใ7^aM- +�แV‹๓}C‚n}nะAฌ ŒB/Dิœlƒ ี%FrˆA&๋EQ–๛[ฅ‹อ)ทสา=Z™‡,(“ฟ€FŸA=|oิา’แ๕CตŠO๔rVR‹ดูƒ่ๅ6t่ๅฤิA๋ๅ^`M-โ…9กGยใz้Um๎โ]ขฆฉ8คฆฆ†ฬ'๘�x{็�ง๋< ฯฅO‘`�� tท#-�ํศBืJั5๐ฤM� Šl=ๆgคd—e๒|2ZŽฒฮ฿ย๎5;vฌ๙ํŽ�Ÿลูพ;z๔ปA}ฒw6๐5�0™ฏฐ;ึ‡† wQzฝอo~.r +jฆฅฤ แ๋ต!  ญ ตAฉXโ:YตB๏ข/๋bsช.oูDวลฦ�๕NRฐSศEK‡UŽš๔pฐiฤ์ดQ›rG�nlz�PณcษไA‰๙…�=ำŒิา;๛…ฌม‘ฬุณ่�ถf€"o'a„%Yส.rHa’ฑJปษ*ค[ บod๘=C๗ЉัHไ๋X'‘ใqฌ�Kž€๓๑\นฏ!R,Š—ก\iš +%Qน…Aน‘SŽ�p๒pๅ$kบF฿บ•@฿บ^แใ‰UฒCจะหม+TGฌ–ไ„rาfRฐRษ6mึุ่EI›ฦ้ƒYฆ kฤP[๔"jš#็๑“่ฦ‹ฟ็_MšT_o'_V�ฎ8ya็J้๗W๔ธ8„์ฅตš+ฤk$ม™ &[/พฉฅ๗7S3Rดฝญ„_EoไO๐฿Doฐฆ– จœ—เDAcหKดk‚ˆ๗:‰ (2T‡lณข ฎ@—ฺ ป ลี๕7 �/:ต๎I 9ฤŸbด!zช$ดๅฌ90ชt�„ๅ๎@๓™ŒA9ตs็ิ๖˜‰๛ญ>sัไะ�YYฝCšOn๚ +ฟ|5ปwff๏พงtyZkb&z“ˆGซ‡๕wž<+  €"�y:$a™0Šd YฬYฒA๋C�^๕ซฅ�ž“ฃz�G๓ัผธ[$†"ผลwบe~ฦ?o๋P?1Š0๒‚๔'a่BE�ิœฺV?ฐ(Ÿhฉ๏2F fษซ�8?๙2ฺฝํnอ]งต�Uํu+}๏�#1}“๙๗ธQ{"ณo ์w• bhA…ํ—Y0s*ฑ,V้แ๐%ฯWฐRฅฬ`มQ™„eqS๋*%ศฑJ&ษ%ƒฅม๒ƒdห“๒ไ ส<ฒ‚,—๗์fo<‹—}ำrฟฮCท ` +๑ึ–g|›p๓s-๕6{๐Pšภฎ +#ฝ]ญ& fƒL1UศำL5?mD–*›b6ƒคD0„R“!4@า �cM*Qd�4W'lฮŒ€d๑โ(‹KD=™šฆzh฿Ž +2๘ล�@*เ�3ะ่ลh4�์ฤษg๙zTzvฦษ3ฯขRพ�ฌฦžR�ฉฑfj`ึ ˆิG}_ถ<าณ๕๓๖†ฤ”LPk—ต็ไ"!z‰�๎ุYƒ�Yt๘B๔<ยIh€2Xkก ีB>œDAš 'ล�'ส‡tฮ +}C3ยp(‚“p>A[เx6Bœ‚<ด +ะtM‚rศƒำฐ�`+ฌ…rธง �‡ฺ›ึ{ภ#บ*ศƒu �Q/๑p[qdA8ไA9ผC` x 6Šพba +์…kจี ๋8 +เg๐โ%H#UจB]t(FŸฃŸณG%*ญฎษKๅไฟ)C”ๅmCฐกซaฉแCฃ�ุร8อธยธำุ`��kczฤTozว�ล�ปk@ฏ€‚€ ฯYจeฎๅh 5pyเAk_๋ 5V�ฃพkณููžฑีู�ด}Tด7่ฆ=ี>ฮพ��ฉƒ:ๆ;^ัฝw†˜`ฐย61‘e + จ๖ฏˆŠาOผืฏ#ˆ‚�1>๕“็i‡c!๐w�ฑ€๛ˆFa�cdข,�q@P,Z๊?ถ@ก}'๔‡bXฅฐๆภl(„%]`&ฤCคB +ค@Dม (…(ศ9ฐรXณ`:AWˆ‚\X3! ข ฬ‡๙cฺh-ึ�š‹a,‚ฅ0 ๒! Œ0fม\˜ใกข`&ยtXณต;ฃ`บF? +ๆภˆ‚…P3`>ฬ™๙P E0]ปv/ฑAaร(†(†b˜ใต๕รํผ, า ็]ฯท>�๚์�ด ดณบDK�า —ภBศ„dัฏ๘๏_ +%‹กJ`ฬ„Yฺณ‹4้’`ฬ‚%0จตVi[Q�)สโš@P�5fม|(†eฏa�Iกใฯฎฌ#7ข๎โ๙งVc„ฤ�ฦทX�ยฃ�…ฬs�( +‹3BวณE0ข  +�%/Bฒัฝ"Zป ๊ด ตkณ�rอึV( �ํ๊ฌถีt ๋ึ$ฎ/bรฺ๓ �vฎฏP 3`‰_รโgถ_–™~ค[i.ัธธ�ฦงรLํพ"X่ง�JA�ญ๓ฎ[า,อkt Ž๎`%ัšๆฤณ๙ฺงฝfย˜๎—Oทม™PEม๋’6| +`ฬ๗�q—6�W�.๘_ห�v.VlวDœY‹ ๒กDใณ›|Mกฑ90J4~ฺq๘ๅuรL˜%“eš j>ฟฤŒะ๗�ตาoท๐ลm�–hvํ q,piืuป�.†BํฬฯษัตMฮd-๎Di”uะiฯ๑ฃzท๖]๊Vไtnu;ำ%ผ�ฺ๊%ZฆแQ๔oญะ๊ Zฬ\เ—Pทšฐ!Iฑฦอb ‰น0 fj๔๔{:ฺ๑|”lี\H0งM‹!S๓ฮq�งฆร (ึ"Cป:ฦขv~ Dพt…•-พ๋�V_Y๘ณ1 ใsB*แ�บฆDœฟ�ึt4๔H>�W๔)(๋๑B่พH๛l�Ž.–@ฉฦoํคป๚ตg&ฅm�‹ีๆย—[#šเ]ุ้ขถ3:งำV)…>;Z]k�ซ่x•ภ|ํฏv‰ฤณูู~+ิๅ ๓5i +�็uˆกB:“ลmk�‹ฯโ)Sว——… Ižƒ_็ไ๎๕๎ลๅ็xิQ\ ญ$$๙ๅจฎkI���Eท๕ฬโ6หl๕›{ณศ,ผทฏดL“*_{>๚g๒bt›�๗>!๎oอบัฌM๗แ๗ไ‹ž›Zyึ0ฟƒ&–B1ฬ๙ฤfมr g�zงรBX่ฯbย๛Eถi}ขฃ�už�c„ล5๑นุฯฃX็ื์E—๎็bธธZข�u7ยัฟZฏD฿ฅร�SŸ1v~[ฮn๗บV„๎{"/้๙ๅ^Šโ™™0ฆk๗สz^V๕ำ๚ใ�Eฤ๚eฉ๔JKGQไล‚6ค†ภ@mQ0ฦi๋Œ‚A0&@?ฃ]ห…ฑฃa Œ‚๑ ` ะ๔าOป"ฎGk�8r5Šฃเ–Nc ๔ำhO„(ถจTGj ƒ\ ดgBžถฦ@ซQc4ฺ#`4 ‡\mMฝฦ �a8<ดใมZ5ชฏ7FiŸโ�/:งใ`T‡U๏ๆJP�ฦูc ? ๑_ํ9ซั�‹๕iว#�๘ไ็ดŸ†‘ ,h๖‡`ธ๖—8๛Œั0 +ฦjx +ส��Žิdc�ฒ ิ8ะ5กsิFมh˜จ�1†ภ8 ฑา8�โ๏qš@ฌฉ๓!๐฿ถ๒XM�แ0\รVศ;V[a ๔ƒmt[mgฐFA๐ญฃ๑€&Ÿเ/W“PะืŠฯแmwŽ้ กำ~š�็โy!‰@d์ฯJาJํnํ�œuดฎ h ฝ ค†kw…ั0๚k”๔3บ=ๆjฒ๖๗cซำิํ^ท �^'กŸ‘šf๏‡�w่๔๎•B๗มปบ๚๙๗๏€Yป๖Eมs+?ยš…•�แ‚q—ฐ๑W+ +ยฦ„–tฮuัืhีใ~๛l๕ผ‘๗เ�๊Gญ๗�;ฑCงีบ๖�x +œt๕H2๒฿ขซวฎฐ\‹{ �ym๑O2wว๊ฑฝ*ํXvํk;Vzฌ�[tฯ}ํg๕๘ฌ็ฌ๖žงc ๗s™ซตK๎zO๕�Z}่ฑ[๏:Vฟ๙Zฎื‚‹�ช=ทU&ข๚ื+†ึฎEtƒ"ฟ��๏-ึึี%ำื๚)-ฝพ๗้ซ-�4-C��! +^F‚๒2ํXฬ’๔ŠaบvธWœ_qOWฌห๐๏๋ U–…ฟ8ปXหขขฃ!,๊ษ$?�Em�Y;&}บUtึ�ญOPห�I*0˜�sั฿้5†จ+ฤšฦ�ฦ|-Yร{ฬdG๑์rHาช๐…|OE)๖Kตฏ;…I� ๛�_๗k๓้ฑ0hqหแ~0รxxra๘—ฆ0 +T˜ c`Œ„‡เA ร`8L@˜!ฦมPm‚ๅD@_๐B,X +ฤมTp@8๔€x่=!‚!๎t† ศ7 ฺ ฬb�œ@ L‡nZ<ํY I —,˜“š�} �ณ�aผ9>9™๕๋„P9`ต๖�็เ@P๖�6 HีŽญฺ๏@ุYดใ€ƒ_f�<(VAf๐A&H‚Œ=ƒv— HึŽ%ํฆSํ<ัฮ`ํ ๒Nไ„sาฒ’๘8นอษญT๒ใ๒รJ๒�อ +๖='฿ง7oLd7+ศอี๔ฦ๕Xvc"นแฅืcษ}—ฬ�๋๙.™�/Nฎq๒m*นj'฿T‘ๆฏณfNš๋๏œ๗�ก_&_]ษg_U‘+๙ไŸœ�ใ๏แ์œ�=œ|ษษๅyไ';Bพ๘<”}q‹|J>ซ"Ÿr๒ 'ไ`s๒‘ƒ|XE>๘ซƒ}ภษ_7™ุ_ไ�•ไฝLาดษฤš2ษEN.ผkd8yืHฮs๒'็SูนNไํ`๒'oV‘ณๅv–“3œœ^I�เไuN^ใไิ๖ึศษINNp๒*'ว7™ุq;9f& 9ย8๙หัษ์/Gศ_VำฃG<์่drิKxศ+œฎ"๕•�ุหœิU๖cuทศK�ุ!N^ฬ'๓ษŸ-ไ€์็ไ๎m!โd'ด‘ZNž฿kaฯง’ฝ๒‡=*๛CฒG%ฟ.‘�~%y.‘�''ป9y–“š]กฌ&Ÿ์zฦสv…’gฌไi#ูษษŽํl'�ศถญIl'[“Hue?V]Eชž:ยช8y๊ษษ์ฉ#ไฉี๔ษว=์ษษไI/�ยษ๏8yโq{โy�C*ห=ฌฒูผษฤ6�ษ&ฉ(๗ฐŠ|R�˜สส=ไ1•lไd'๋9ytสๅdJ�ƒ“ตœ�VอaฟKึpฒz9Y๕ศJถŠ“GV’•.๒Nส,d'ห8YสIษ3+ $%๕ผา%fฒไ8]l#‹ฝt'sฒ“โcYqYPิ…-KŠบ๙œฬK%s9™“J +o‘ูGH'ณ8ษ็dๆ ›ษษ ฐฒ.2“iœLๅdส$›b!“๓ษCo'™ุƒv2ษD&r’g'8ฯษแก์T2Ž“ฑœŒแไ�•d4'ฃ์d$'#P"มษ๐#dX247„ ํIr๛�Xn20„ แdpœO aƒŽ!d@ะ“๔ฯQY้_ฝ^อ้ศrT’Sมk �ผึ/๔ซGวฝ๊อ63ฏ…x๋ัjฏf› ,�Lฒ๋‘ื›O๛rา%ฒ>ทH'ฝปLN2ิ–‘Ozu cฝ†‘žœ๔Hดณœค#�SยX๗a$-%Œฅq’ชๆฐTNบ%ฺYท0’F’ํ,9„$‚Yา’ุ5ˆ%ฺIb=หvตชฌk้*ุญข ๗yX'๗‚ู}3Y<']8‰ใ$6x‚s˜g ้Hb8‰ dัœธฃ™{%‰J$‘รˆKอa.N"8้ส:qVJย8 ๅ$„gps"มŽDœCv+s$ป••ู‰Mอa6NT”ศิb dV•Xu์-fHu์,Ff1‹Ž]€ูภŒ$ yQณ˜…m๕ค&NŒ†`fไฤL+‘9‘P"“8avBp&#ทF‰ gV† X ชG๙๋6ก„�พเš�ๆW�oห๙V endstream endobj -267 0 obj +276 0 obj <> stream xœ;มม endstream endobj -268 0 obj +277 0 obj <> stream xœmQ=kร0�๕+ฎƒ R�I้B uj๐โะฮŽtvฑ$$y๐ฟ/’ๅค”’ธw๏๔��ังSตxใ๊Š‹ีs @@ -963,7 +994,7 @@ g ๋ฬณ`l›1s4-ฬ&ณฟ’Uฏ๕ ฝIHŠ’‡7๑อ๊!‰ ฿ัุ%d่2hŒ$_{ลง -2ลั๊šกฉe‹d“ฆiบ…MQลึ+�ษวชkรพkุู6หๅ๋K`G�ื๙๑�ฒ�”.L'ธ๒„ฤ๛˜ตาพ*œฐŸiี>:?”ขสW endstream endobj -269 0 obj +278 0 obj <> stream xœcd`aa`dd”๐ษLJ-*ษฬ+-N-สLำ JM/อI,ษน��!ำอ#๗C–‡AŽ‹AพปB๒ฐห<ฏ�=EFB๚ืOVY†ฝ�ฒ Œ\‚ฒ ��๓(„>๑จ€จW<ช ฬŒŒl|�Ž)๙Iฉž)ฉy%™%•ฮ๙•E™้% @@ -973,128 +1004,123 @@ x b�๑พW}Ÿ–c�3�wฬ๗�ขฟํพOd��‚ฏ`ฺ.ฦ๓?L™ฟ}Ÿ ๚�โw๖3{VึN”�#๕[ฑฉชปzJไฉ฿J3'vญฌ›)๙G๛ท ่ฉ]คุ๘ผป– endstream endobj -270 0 obj -<> +279 0 obj +<> stream -xœฝ=ห’นqw~E‘;w–;ผ6ฝถ–ามญ#ห›ๅร’กqุแmKT;๚{E๗tก -๙บชw.’$™‰D"_๕๘ใŸ~:ผ�๘ร‡�ํค�ำแ?ฟ�ใแ�ป๏พ�ํ‡Wžฬค'==˜ษ$ฏดnJ1ฉC๐ำ็Ÿ?๋้๓_&=�ๅ๓แี๗'=}�๒๘ค'“ฆOห�ำ?�๛ืะZ�Aks๏์�w{๙้.?�ๅgธ�Œ—Ÿ้�๓ำ๙ฯใ๊๏‡๛ฟn็˜gXOซQ_.ฟ‰หสๆขถบลภšy์ๅ฿@_`<��ววy๕ปฏ�ํี๏~๘๐ธ&คA๔ณฦ(๋‹›’+ชY๒™ษ‘|ปIwh~ำl›šฑvEศCปโe>œYIX� H^�mZRฯฟทŽ๙ฯ�"ยGซ\ดVว)้ขlฮN\ฏ$ัญอดถHิf,ฉ�ำ:๒˜;๓Xดr!Ifด -ๆแ�ๆ๙๏ฑแ"'O้�มXฃl)e=฿rM� -Љmล\pฦ).ุ;� sXษu•yg๘๙f`�M ณยยY%๖Pา0งอ“;็wwมไ2ม]ภน๐›—eญี/นฮฌ9gH‘0—บ|_ˆX๙๗ด}�MาZ‡~aฯˆํโ -น0vฒXโ%’ขrQปฐU‰L๗3Žห_/๒๙๚๔ว›Šก5สkญs่›v` :ก—เ๕เฏ ๛œ^”‹)RgpŒ€,TI๖H๘‡Q� -เk{ ภmฯฏฤงล0วแŒฤ3�WC\ฏะฬa&ถŠโ@™'ฤลฦฌ๔N% <ู‹A;ฏ๒kžๆ`฿ˆแH Vจ์gPฆ� —”L”ฬ๙ฏn‡กญธ้Y8ั‰‰เ“2มiy @ฑx๔DZ`๊LŸ•R:ห๊�๕ฺw�์ฏYฝrX้5 "y‰ะ@ _IำhชJ8�€๕+2`�ม)่™๎ะช=�-ุ�ฺ}+ƒ4Zฏ‡ท!�8ผก”*yมzTยš™‘0p€ :สทˆ�ฌ๎‰’๎๑Yน˜��M์ด๑ัฬ]aฦL‹ฬธธถz](,๏xb%‰X6ซPยfE� >UAน uน ?�CะมN ^_pHCtNแiะฺ†o3t‡๐H๒‡ธัิŸคeHำr^j ŒฑpภPHc86nyB^ฃ!ถพ`]ีU็…บ๑‡z�๏ � X�� — |;ร>%P$ ตŠฺๆอฆึสฯƒxU�๒^ŸT4�›cv=ฎ1Iอ�ใU‚|Q.{๘ -V ‰=๐�ณ/#่;ภ8ฯ4’*„_:cภงฉcpe๊ท”Wu€ฟ-gฺ›�Žฤูvตm'ถ…๑ฤj"ศ+pฐก;ฏD<@‡ษว1ต BŽ*๊ธใมu-ว–Go\sฦH�ž!Wฝ„{2c$І ŠทฦoQฮdk\๓ัšU8โ6�?,!๙ /…Wƒ‹ชคb^8HiตJYk!F FŒRŒ2!L8m9บ�Žuwว3G4ธน9๏ฆpฦัด*1{ๆฌฝห ษ#7‚�4ใK[ปpู‹ทQภาA๚œK0G‘อm �<ำ …ถ๖�ฎ� œื•00�ฤ(8ำ�ท}๘ึเผํQb+=‚?!ๆุถ๖8aมอa๛›bžง„-ภd)ยฌU%�ธ๙๙ ๗ผฮ‡pV•Cpด]]‘์ภฑต็บป`Md5ญ�์h?ศ3B$;ศ{ว๒๐)ธืŠ?E:,ตš$œ’—ฺ�–ท�กอ0@จ๒™9ˆjฒ๋ๆ6Rco๔฿.ฏVคเIะY•M�a Œฤ<–+จกzeถ†<`O›ร„Rฯ0ะ๓ˆ}�a�ีดม ์๚฿|9�ืำOŸ๏฿?~�๋Ÿ�๘๘๛Ÿ�๚ฟ�wจ์KT!G3็เ|๘qาำ�uาสO�?๙้‡๓œŸ'=ฅจ’ณa๚ŸW?^ทZ‰J'cux‘ียI.๓/ฒXดสœ๙ผ5—ฃIฝี|าชcาคwญƒฒ&ฟ�zV+\ฬ�ึkŽ}โŸ21Uษฬ^™์๊7ผejАMzPโHƒัฆ -p๖สล\้Rีnจ-ง ‘—xสีถ!'ท#ทม0L‚�u`ฎฮข๓E%D!dOฦปัƒ d”‰S'}"งๅ8$1?ฬม๒vxdช1๕;˜ฏJส�,2aเ5ย‰ฉ”ƒหไปฎ�ณ�ม/โมOบQท๘เ�)+๛*‰๙฿ญร x&…๊์.51ชl‚‰›๊'จฬ6‹Yลไย ๑เ๗Aีฏ8e]ˆ๑ฬฉจ™•8hอฃl$;'mศ*nI{VW!P*ฮ’O?s#e ๐5น๖AL&9mx…1o“ก•6œา^ท ษY;๘W5U๕R}๛1n๘ILF9ฎ’�ฤ่”�fŸ!้๑zš๓gMrAฺU,Ih๙ำ?kc•ซ=Ge๓ณะฑ�F0—„แL(0c}j›฿0‘ใ็`�W ืPาAป<๋rไ‘๙�pง๐gtฏ5‰›ลkMร๙๏บ”ฤ๗ะ(อAJโห฿Pkภtdผ฿/b3ณ@ูรq'sูˆ6Kƒ๊ศหเตK&ฟ”จฝะRำญJZ๏๒oซ ส๛d’ง๚๙โo  น”fช(R`คไ�ผNฑ@:i๙L~k๏ฬ่?า��Oฯ8C;ž;ก >›ะ†แ๗Aส๓_ฉธ๎ฐงœอ๙vLฎำภ_ธๆ4c18^จ๒Pข�ภว๐x…!%้[ŸUา~{`cw‰# 4ุ๙^สHdShแถฒฯŠƒT: l1Z�ถ˜\ไฎํjd—๑๋M›INเฯ-xนพ›&LoEiท$้&‚†�Zฬธกฯ9ิ–๓เก๒œ•,Fกcu*mVE!!ผ฿{ไญฒๆำ! MทfฐฦZํ๑ ญผตN�•œlว‚ฃNํิๆ‚ฟm™qล˜๓o!ผฎ๓—วาŒb ์แN_“•7€�ฤ•้ƒำเ8|t@สีฆฝ\๔W๐๛*c‡…‹Xkถพๆ’๗.*\ษ&ฬW†‘Y^wฬ*ฝ";�ร;RE‹5^ๅ$5�๔ฮ -—ฌLNฮwหryœ ฏ}‹Vูบ”pn|5ใT? ?%ฌ้๑ึ~บ/ส›3L‚^็ดฬ฿ฃๆ#แSฯงv)ถ�‚กŽe$ั{–ม |Wำ™ตฝ๏sต@›๏ja;aX้qคw๎{0ณฬ๋Ttิ‘ฅ๒๐G…š‹B้‡L›D:๓U๏่i”—ข… MM๘๊nฝ็ต๘p��IzถZซœb��‘Vฑ�‰W>ไT?*=pฆ?ฅgPม ฤรfฝญปxS ึU๛4:ํน†ฐพาศrฏ7c{โฉตญ๔,ึ๋?ํถ ฺ&+7๑๒ไ™ J๊‰๊))lc๕ฌ�ย!%|๘ l๓rถ`Tuา๓ ฝ๎ด„T๓brT9kณ๓๋}๋Oxkงbฐ|฿gb ,ี้ ว2ยe^'งJั๒หํฒIWc๘ำŽ ํl‚ณ…ุ1A4mEW|Rj#yฏ๊พฬ™ฟ(*ั'„}ื+สZ ๎VDจ\ดZ˜)qLI฿H1j“ฌสูํiสม8„๎ข#฿:kเำฒ1qฐ?ฮซอ็"็ -–@3’2=ฐซC -ยิyก ฟ™้๙�้ซจTำmใžๅ‡ฯึ�ใ™Pม^K/ย๊n้x ๒ๅจ(6ช?)€ๆJ‹้ะใ๖[Z”(†๒ŠE -`›Uฮฉ6฿โ8๑ž‚ๆ ิ@~Pวฆไํยพ8mุฅqา๏ฑo’I�ฺบfฟรq๕„เ�š>ก%fถฅีPŽ�ฉ ”?mณ€โปžฦuีC•Bๆส๚–HDHR:}3 `oก!%RlƒŒ™X้�!งผMนชช๙ๆƒฮD!7a7ฐNm‹ป๏G’•ัœ:yeฌอ#งb0ห}ถBSgณ›�๓Vซ• -V0#์ภ>\—ด2.ฅ—cั-#k•ฮM2vณc8y|ฅm+OๆNฬ้ๆGf>’ ฐH˜;;i�ร<ฦeฯืNผ“ล็มฉKeN‚ำr8ฃฝฝ|k;mฮฟnL0”\ฐ๎(ฟฬ‘ˆKิ{9งLt.์์6ิล9;'พšd�O]p„ฺ�ิX๓ฉ2CสnฑjะSุ#ถฌ J;์‹ั™hฤณv`ต‹ุPง ��o�[ำฏษq–oเ+ย�}ฝm‡ด*WHงฮR JสYท'/น๖7ุะ*“’Vั.>H&@ฬ•@ต…ฃ7ใ9บาก'`!5Š2.d|Q�V$0F๙�โ�ๅ�ฟ#Dท-์Iโ‰~,๎WCม=๏‹Š��� uรภฦุm‹�7v๘่SQ%งwะูt๗�ป.�7ะนุ +xœอ=]นq๏๚-�ฺบ=yน��H”K|ฒ๘งท\N‚7›8๒�}0ณำ์f}‘ำ=ทศ‹Vา’ลbUฑXฌฏ~�แฯ?�ฟ��ร~7้ว?�t๘ฏ�tธ�๖�๏~๗แี�Lfา“žฬd’WZ7ฅ˜TŽ!๘้๓ฯŸ๕๔๙/“ž�๒๙๐๊ป“ž>~y|า“Iำวงe๎้ววŸ�ํ๋ตึ?jm๎�n/?�ๅงฟ� —Ÿ๑๒3~:�y\��p_โืํ๓ ๋i5๊หๅ7qYู3#’o7้อoZ‚-pS3ึฎyhWผฬ‡3+ ๋ฟษ๋ฟMK๊๙๗ึ1�๏yย[D๘h•‹ึ๊8%]”อูI‚๋•$บฃ™ึ‰ฺŒ%๕ZGs'`‹V.ฤ"ษŒVAย<��<�=6\ไไ)�?k”-ฅฬข็ปC.ฐฉ_A1ฑญ๘‘ ฮ8ล{งd+นฎ2๏ ?฿ ์ฏป tVXB8ห ฤย>Jๆดyr็�๎.˜\&ธ 8~๓ฒ, ต๚%ื™5็ )าๆR—๏ +�žถฏปIZ๋ภ/์๑ฑ]\!ฦNซCผคCRT.jถ*‘้�afยq๙๋E>_Ÿ�xS1ดFyญuฝcำ์/AB'๔ฒข�dŸำ‹ฒ`1E๊์ސ…*ษ �0ช_|mธํ๙•xโTขๆ8œ‘ธcๆ�jˆ๋๚‘9 ยฤVQ(๓„ธุ˜๕‘�ฉ„';๐b1 h็U~อำ์1� ฤ +•�เ สด?แ’’ ’’9�ีํ0T u7= 2:1|R&8ํ/(ฯ€žHหL้ณRJgY}ป^๛Ž›�5ซW+ฝT$/q:0ไ+iMU g๛ฐ~…CŒ;82ำZตงฟ%"�ป@ปoeF๋๕๐6ค‡—ใ/”R%/ุCJX33ฒ๐แbแภCGโ๑Ÿี=Qา=>+“฿ก{ ‰6>šน+ ม˜ฉq‘ืVข …ๅOฌ$หfJุฌจฟมง*(ด.๔g{z#ุ ิ๋ iˆฮ้1< Z�๐m†๎I�เะ7š‡เ;JsL๋W๑}€jฆ^ก~๛ ึ/๕•Šx๐Qฮvnม<œ�Pง?Ohnต/Œ\\Œลบา™fร,›ูฎ่Uึโ๒:}{%‰›o›ผM+!ร„a”ฏ9ฒค9ŒWก—ถชŽwHส’Vฮๆค/ึ๊'๑x&ฑดไ (ฐ�ไ[แ&ต�ˆ+~A๋0p\8บิำ�šGŠะ๐ ๏n–๕ล'i™าดœ—€Zc,0าN [žืhˆญ/XWuีycกn�กž๗;๗77่eวB฿Nภฐ…FIIhญขถyณฉต๒๓ ^ีถผภ'๗fภ˜]kLาc3๗x•A† _” ลลพ‚Cbผ๗์ห๚0ฮภณค +aภ—ฮ˜๐i๊\ G™๚-ๅUเoห™๖&ฟฃqGถ]m�‰ma<ฑš๒ +lhภฮ+ะ!B๒qL-จฃŠ:๎xp]หฑๅฤ฿ืœ1R gศU/แ�ฃฬ‰ข!จโญ๑›C”3ูZ'ื|ดfŽธ ๗KH>ศKแีเข*ฉ˜RZญRึZˆQ‚#ใ„LN[Žฎฟc��๑ฬ nnฮปฉœq๔วญJฬฦ�€9k๏2C๒ศเร?อธฦวึ.\๖โภm”ฐtะ…>็ฬQdsAฟฯtBกญ=ฟ+wC็u% Œภ?1 +ฮ๔6วmพ58oป@”ุลมJ ยOH„9ถญ=NXpsุ�ฆ˜็)a ๐YŠฐkUษ6n~~ร=ฏ๓!œU%ฦm—ม฿CW$;p,Bญภน๎.XYMซ7;ฺ๒Œษ๒ลฑ<| +๎ตโOQ‡K-dฃ& งไฅ6ฟๅ-h3 ช|fขš์บนิุ��ฦทหซ)xtV%G“w#1ๅŠjจ^™ญ!ุำๆ0กTว3 ๔ผb฿w˜w5mpป�ท_Ž�๙๔ำ็ใ๛๗�๖็?=�๑งฟ�๗_•}‰*ไhๆœ?Lz๚แรฟLZ๙้'?}ž๓๓คงUr6L�๕๊‡๋V+Q้dฌ/ฒZ8ษฅq�E‹V™!Ÿทๆr4ฉทšOZ•`Lš๔ฎ๕bPึไ—[ฯjฅƒ‹y�zอฑO�S&ฆ*™ู+“]�เ†ทLM2เ IJi0ฺTฮ^Yใฃ˜+�Aชฺ ีขๅ4!๒Oนฺ6ไไvไ6"†IpปฬีYBtพจ„(„์ษxื z0Œ2q๊ใd ๏Aได‡$ๆ'ƒ9ุ@ยL5ฆ~วณ๓UIy›E& ผF81•rp™|ืี{–?๘E<๘I7๊|;eๅo_%1�ปu˜ฯคP}€�ฅ&F•M0q`S�•ูf1ซ˜\ไ1>�>จ๚งฌ 1�€95ณ'ํฏy”-ƒ$โc็ค Yฅ ำ-iฯ๊j"Jลน@ฒเ้gnคฌqพ&แร>ˆษค ง ฏ0ๆm2ดา†ว๎ะW๐ณ[7d๖งด {ฬไTษVจ๙ฑ^ิ‚'ไ|�a�๐Ÿ๏”ื6ไ,ฅ–ใtH๔ ฿ๆภนใ@–�Sbภ฿มpไ— ฺoฯ%ณ6ATaฬJกII9g๑ท%pa8@ิ�^E~."้Q lวkณ›™„‰`^ง0ฌ ฤ๓๏ŠาA๏นดxูสคpบปไ�;,Uprฅ�ฺ2�$'[ฎ้ แI.J„8ซ$็ฐฐ™—กูAJ,็’�ˆภๆลyฬ฿wƒ,b๏G—[Lp๏ฒ�ใeฅGคc4ืโ*ฌ–TตลO๋SˆGฆ*wสา4�(j7ะ–˜:xเะลŠKโชdRI ๅ^keƒ�—jำnp๐ีeSถ0Š,฿#7žฉ~…แะžภW*€หj ธ�M’ฯฐ^แน•yุZฃr f€k=๛๗iiฉเ์๒wkฬ๐�฿zญb*7#QVเOไฺุ˜ฮึ2pฺ9วฎ+e“�mห '@,W|qš†”Ÿ“ส๎เhุีฤ\่{S'‰ซฃ๗�2\ƒŸV่ๅ ฅอน• ~Wจญ_q๎3Y�ศ$2\าb sฆŠ0๑K3@€อj:%4ฝcเ|ƒ ‡ภ:|Šฐดฅ!Kc]็wื่ ฎกUโ ญ+rภฏj/่ใเุ)(�–[ฌ๑ไ๔ + !ZpsŒ'บŠ‘�ฬtืำ้+๊eVqF2ชŒpฝ…A�ิ,ฌรพร^ฟHIค.YeCฺ5ใ/ฏt n.Oโ�K`เ/tฏฮ\pt œCv\  MI�@ —›cื๎๕Y�ฌCG8ห‹Wๅไ"๏ P7๚2oฦ7L˜๑ผ5้>ฝ3ถ>ี4่ฦ…‡TษrdงvšO๛์ ใiƒ[1นข•vฮ฿โp๕ม๚ฑt"bๆฎ:LNฦก5=จ๒น�pZ5>พชฐว�ฤbUqู๖‘y<็T)๖ยดwๆถ&šุc๗„ฑV…ขต๏#�SฤPญY �ฬ5.ฉMบ้Fr้<~MTศ��€๐ต[๕งtํ‰ฌฃT6N‡—" +‘๘œŠ.๘ดŸ(ี61Šz… )Yžศ–ฌŠ5๑—Cyžโ+Uื๖4ณ9฿.ƒษuXโ ื�’f,ว uCJ”๘ฏ0ค$}๋ณJฺol์.Qc€;฿K‰lสอ#�V๖YqJ„-F‹฿“‹�ตฝQ์2~� i3้ภ �9ฐ/ืwำ„้ญ่"ํ–$�Dะะ[‹7๔9‡ฺrQฆ ฝึฮ��-ผoj๎ .v}ย!ญ๛|๖s๑ใื)l(ำdฅ PฯhซB +ฮHม�kE\จ๋�)w:Wป\ไทฤ?ฮ- ๒ Mว$๋Utvฅi`ˆ๋ตH’ฯ?�€pj๔\็#๗Bฑ‚",I้ฒ๋หG!bT!๙9X฿j?น #hฒษ๏Šจ�>}!�X›vue_U�U0ํ Q๑ํƒ*%{s ‚c_]ัะ|gCเฑาฆส†ศ๚ใ†Pกฉvh'ฌ€ ๓ก#ธูแX˜x}ฦF  —ดcO์ทFŸ{จBœษ€€็๎:mน‘ป@ใฝฟS+%ZvJ—l�v�ผeี'๑ �ฯษEYg|๊2�‘ฅธlถ"Lbวˆฒบ€นฝคv„ฮภ˜^20‚ูF_ฉD:ทŸุs +) #๔€x>‰6•ฤ^Nฑ%5 €…>ฝ‹d.ฒฟฃปEถนW€kZศท[5ถลฤUใผ‘b๋ฑ(ฃMฬ{b๋0Mt{๙๔อำeI9ศฝส9$3ฐั_ฎตk!พ_ต2ษdE•ํว�†fิ:ฆ�๖ReอN�ุ�+ภ—จz-ณYrูฅ์ฆh(#g@๖๗5?เ.CZ�ฺVx�Šปฦธ endstream endobj -271 0 obj -<> +280 0 obj +<> stream -xœๅ]�“�6rื_1Vlห ๑ํ(ฮ๙d;พ+;U)๋-ฮƒค๒^%uทน์ํUr�}Šณ$H4MAŒ\•—i—C4๛ใ‡๎Fw๓๖ง?ฟฝ๕๊๖วืฟ๛ๆ$ฟ๚๊ท฿ผ~๖฿'u’'yzฉN„vาผืBkO๏�t๛^ž��ๅ$E0Zi๎$€ถ�ฮ�ถงฟผฟ๖�7'yz๓p{'OA˜ำ›ป๙�รว›?��g?K)–ฦO๕๔ฉ�อฟฟ๙�ณo฿<๛ืg฿�๘๚vIง*่๔^XญCศษTg2ทั1’ก�อ›�คW…bียFฅTwๆ(๗๔ ๆ�๙8�V,ณuV้‚h%ฝ�ƒ้ษ+S.ซ@DmŒ'™5pGy70๋�ใOR๘แSบKX๕w#ŸF%’O�’าž?2.�Šฆ๊�ณๅcX-tˆ=น็ˆeƒ0&ฺ~ชvฆ๊ใ*Iพ$ษiaฅ๓บ''ฑlึ้xDrKcKธฤจK,ฉ A๘ม๕d’*q[E-‚•ชyYm๊ห–0ฌbQz ]ทbZD7,ท{�$u›ท•่ -* -ฅด[…ถu”๐ -`„Šฺุฎœ/๑ -ฐาลVฮ?Gfฆถ—๘ฦ ]Wถ— & -ใฃํ๊xจมaต ะฎ๐0)ผ�เx•. -/CWฝƒเภแ๕ํHฃ]}�แภGbซ๗๔I}Qเผpง„–:�๓Œ5Qช่ะ?ƒo.ฺ๒>M?iLv˜yœ>๗ฏFOj�œ�ิั™ฝผหูฤ_ิต 4๗ไƒฅ9ีmท๔!ฏD]ยx็ฌษษ;X๛-๎4.+™e๏์]G{G9๊@๘ง …4!BWู*กคSฝU๖ใ'‡ฝฮยีA\ล˜Nภๅ{Œ–\จัO”ZqฑFg†๚?ลŒ๓ฃหํA-ผถฎ+ -iอ7อx0)ศยโŸ็:รf9 ็ˆ72 ฮห9โญL™vำ|f•ƒ๕Œ;*๋Pิ”๓…ๆเเ�Œ0š&<ํ`Dฒy?ปฏgํุฐ๖ยฉh๖๋๓ฤ๒ณฮฃ/$ฃ่x๑�a"„๘ศ\๔0n0$hฮ-ฺMยznศฮ/บฮณ[ฦ�iฆ`Šxาฑล"Yxส}�พม1$;noo—ฎ๗�ๆ�หฬVRฮ&0iอžฬˆ\^ณYs]+น\+[_วษm„–>ษ•ษ็‘X\^ฌฃ†Xอ๙อฐZOHYยฯuF8ซ ด.\ฯHYหนส‹ †ปฺชร‘ฃฐUู’ํตOpzภี฿8)@{้๒xIJ]นโYT�NSŠjT@ 7๒�}g!เฟ฿ๅส:%TศLะคฺ8Hฦ;ฒๅพl”เC0]Teฆช4�I8Sš|bozาค1*ัจ๕ฎJฯ’ทuL{H๖˜กฉZWnวF€R‹ bด๛y<กlโ@ฅ�ๆฅl๐zํั๑…“ู$ำ6ื_Tพ๛y.ยtฃŒฤ/ท…#Š„–f +7žWLŒyศ›๒๊ใร(ฦฎuž๎…—V…v™‘ )1d;KQ†lย 3FXๅM3{_p‡QŽrะขR[}„�”์รฎRF๊d“ู)Ž8ูๅbษถส ฑO“Vœฌ ))V€๎ๆๅ™Šฆ kRา้ั‘ฒพ+แ6แFฑ�#-”‘5ำ_+ฮแ‚5u-ไv†lm๖*แ‹ดปฬBอ™!ๅ”žษd๔_็ ส|c|ฃ\ซง฿ึไ‹cฒY~O;#ฒFกฏำ -•ฟ›EVจ ะ—’o@F๑ญ\w0ไ๔E:f%u๎งF6 -e#ิ๕Nส_ีฃแึ&76ฃ๛=๋$ะ,™ž๘šŠb“Zีะsh†ิ–?4ฎไ๖ภ„" O&€gซrnิฃ๑ฎ๗8&FH•0ˆRtผDยมสิ ภฌ,š—g๚Œ�8ฎร`šูŒI“jปาb[Hแ&ฟโู/ฏ�”BฎยอN1A 0ึwฌŸ^ๆ&โMฮP9สeF๊�้‡-'F^2e:ํไ•๘spฬ๐ฤ—@„มฟถ~?Aใ^\ญื.๚่…wเใ‘bุ๒y�า ร]?จษH=Xื�K’!ั0Wf็พsTo™ขiŠห]ซ -i+z๗ศ๔็sไ›ูๅ—>ฯ๏เžฤhTโX์ดษ?๗จ"ํิตฟง๛Oฯƒำบ่zฎพอsฎ˜^Xง�'๓ žมีvVdลมkจC�~บึ๐•8$” Hฉ์กiึ ๋ะšำุีุ8 Š้yบ;๗Akเ๚QH.๗ลV”ฤฐ“เj้ใ!ฟ๙)ญ�ษ -N๚TUซวžฃ– น๊oฌ๐›z"\เ -ผ›)H๑ *'9–B^†>หbฮ^W.8ฆ…๔@น\ 'ฯe^Vมตัj`‘๐ๆส4�Yฏๆฺฮบ9]o&a4� V˜Sเ(๋า~bV;*ฦo8P๛=ง่‰๏฿//ม™ ดถา^••ฐ�p›9ล๒ž›๙T3ศฤ/‚��&”7€n’Š ‘ญ|%r่ฬั�ยG๏่4K:‘CN #P๎,ฤ:R74OnR)วAm+ษภ‡I๐ ežAภฝ„ญกn`˜ใฒร๖#ทอ‚J™ย�žJฅ8A))™ิ˜ึฮ\%‡ฌหGธ~_kงฐWW=๋ฆˆ .;ัธM?ะโใ2-vฯI‚๋0ถV�K}!QIอab3 •$}พ9=‰a*ึŸN|šฉก6^ฤจ�~’WะRIหtpดญสฯŽรๅย=šฑQสtKŽ^I๎4ื๊ ดUฝี:pj�Lย„Rหƒ๏‡Jv�M"า๏%sM•ฉ15ฉ๊@๙l5บfV๎%)วU๊ 3pๆ&้ผ<`�ง†ๅฬ๛?ม๓ž๛?jํKแD^๐7GO(wš๐ 3เ" ]๎�ธไ‚ฬาโš‡ %อ�`Q”ฬ‰ษp( -NXM฿�”"ๆ -`ด™†‘™tj๑1ห+65บ›ฮU ๕(ข-ขโ`ได ฅSํaV� Lมฐ"ฆ-าTmโbGฉ(`รทž\า[Tแ1inImๅYฝ]ฑS์9a`อฏโไRฑc‹L”"�นๆIฑณ‰ฺiศ{V™Lฐ"†/œ บ…Ž5D$fฅ๓ƒ#%ฐEžูrZึ�ฌแๅ\&“Ÿ0nาeฮเ}ะ]8yิ'๗L‘q็ƒ�fj.5แ)MŠi7n4—L๋+!ช@" - ส๛v#ฉถ1sRเฆRw4WŸ‡ำWฤศ …vV้�6{ไรMเ๋k%‘—ำUFิ”ฆiPv๛N’€ฌล๕๙YPCœข1ง;ฺ -1ฉIK)† แŠีคฅJF‰แ๊เp�‹�2*Vk)tดp ทฌYธข)ใผ€5๔๕ุ‰IF‹เฉ•†w๕qdฒ๙ž�dฎZT`ฮ—]ฑจX/ƒศ>>:ปgQ�rฏ‡`Ck…ฑB_ํ%†ฟ,ดท™†zЇฃ‰ �w“ดฆฉŽ �ฏ$ 6๘ฯh๘UผGH<ๆSตFQ๑ึMฬ|X$ZWๆโ~bรœp่๚ศlฮปUC๓๎UๆM6“Iดิ/ข๑f‘p๏ป‘\4�S&ž;v<>๓ทšU๊์ฎOดืƒ2โ๛u•๗ฦฉพแ�9ี.‘‹^ปE5ณฯpW.p๖�%_Ÿ�ช<7b�J๛จg#yjํ[รJŸัษZ:›g^VœฆฌLuฝ–ŠY๏~ล]ด+ึJน‹1›lƒภbŒNY่|ุBด/œ฿v๒ัoY9๗ผำr๔)ฎe?kฎ0ั)พ๐C�–ๅq‹hฎ^„‹อม'นHsžีSฒแ -ัŽ=M๕ๅ–e†ดsซ2q‹ต)ว๙b]นแ9_ฌ]wะœc�…ชXถœš�ี _ๅ@ �๚ษัน=5ฃ๕zuัxิCตsie็jj๊,๊—Q�สใส|‹]ดฅš•1h็�…ษฆ™ด�k่œ$%zุ;m; E71G 0ฅปIY�S‰�๓9ฉu ฒฯฯ86p๏>ฯ) ฺฉ&kORHฉ#(๋โI -�t๚.`>mะsึถM8?฿0ห:ฆ}dฦั6›4—K=52‡�Z#›zขุsุ{w>gจโ๊ไ{๒ุ6็vkพ|ž7]ห‹ไ[W }ส๐ 8gฐ๕๐ไี -ˆ†�E)LWแ&vด๓b=iภq…-M้สฎ:ฅƒ_0�žc†g^ืิ—l�Š2โฎy+4…๘ฎาล‡cๅ<{„�ศkจS4…_ฎฐ2'ฆ6�r2ƒฺ๗ะ๕๏.๗่J^๘ำ*Šจ•๊›แขGyแO7ำฐVฯฺัด<ค๎&mลฟชำx‘+k[—7[ขcx‘.หV๎ไ<ขท”งwฎlhัข‘vv*ิๆ^Ÿ�ฃqร„Iม๔ลS”š/ฆผ็Y‹;ช&ฟศlไ(‹"4ๅŠ^งž๏฿-ฅž#}k†ps„ B†จLgŒๅ ทำห5ๅV™ฦ` š˜็ยn‚V‘52x~QP}ษ3ยถ‹ขบ�q4qณ9ฅม๏7Dฯ๑ข๖ฅ]"yิ‰งˆ็or)ำšœY-ศ‹x๐@]ฺฑYญษ‹อ"ฃํ*›ีŠ…ฺช€^�้คwฺh*›n?AWญ:�6†žgํqธ=4ฟWNo๚-ง \UฑFiUฯฮ่อ=@4”งืฮg”๖ƒf_฿“(^]แ…�@t‡งk7Wถ3;lฟQจุ�้%…I@4'Ÿฟซะ†๔AD๒œfnU็w,Ÿh;ž๓บ=5‡่<žO๒?ไdˆ‹ว8q€D๕/ง�jWrฑ^WฎŸPัœ<7!vๅ†ฏึ}6o %ƒˆ^ๅ9ณ�•ฑžX๎iP"ใเ{ร[t€hlž�ื7์๏Dง3๘แอœMณ™YT@4-C0"ู$Eiํี๒:M45k%…rฎ3ฦ=อZู3|5ศ›sO^‚ฌ+ด๖1๔}rW๏5<ศ1Hฐฦe`ˆžfmฌฐฎ3šฝษฺJแภ๔uจู?[B(ขฃY{+ข’ะเO.$ิE44๋ Et�4์ธ้`ฟฏฟ‘Wmเ ั�l”Z MืผฉOชขทyีzฆuศ.รdw4ใั=ถฑ�"[ขฟyŽl)~]#ด%:ž็ะv7_6 ัๆผŒm›ERŸ฿ล‰ศ3e[}ูมอํซLผA๕<งฬpW~8.ฃะฌM๎ัโ<ฯ ๎ห`ฦ"}0%!็Rฑพ�0L๚ฟ]Kv”อQ ฬsบข+/—ฏhท˜�๏7ขมyฒwๅI`b๖f.‘iโ์สขญynโ์๊ฑMลYcฃ,D๔\ฒึ—;ภๅHZWๆ2Ts๓44้GˆNq(F๕<‡กบล›ฮvร็๓ฉ�็4ล้/พ6ฏQrœs\Bฃซ๚z&ฃั�Yฬ…Žิฮ!B@4V/ย๚ฎ์Š\\�aLขุH'ภ0}h@Ot/z'…๕kiผZา{ฐ๊=ลs_ฒ้Q<ั2ณ.็iาตช5"#›F€ +.ฦั)ŠB๐“}�ฉ�แ๓�สŒP9~โaA�R๋กLf๘�� ฝย!Wžฏ�ใ๎ํ๛วWฏn฿�ํฯฟ��๐๖o�๕ืGF‡ิPๅ์อดญฟ�้$O?ฝ�—ก๒๒๔?'s๚๑�•?ไI)3L�๘์งหำ.ˆจดฟฦZC5ซQฎฑ–ี0<—นฦZ„fฯ‹yoR๚ฌบš๑RDซ”?ษฆ๕ผึซ๋ญgœ0Ruญ๕††!�]า}9Bบก�โ:๋)BTnืr๙^ท?ผฝ�รgฟ�฿” ๚(C๓๓B_ศ๔.ฟ)Mแ!จ›—)ร‹ท–M™^ฅ๋$kฏGX:€b—๏)฿’d"ฦฺ.ุ้ฌ0R2ฏง^?๕XžrCร็็ูพ‰d2‘vv ๐ฎลn�Ln O่1U”\|ณ'>ชวึI žปKๅศฑ˜•@~้ฮฯฃฟเไm]l๗๗นc๒ไˆœKE~ว‘Dไ9•wาv ฌฤŒg‡ู-”ถช(]@็�l&‡8Dˆืน„&|ึ2วงOหดฉ…!#+็้._ฟ�๋�?พ๙ๅ_}๗ํw฿I๙๕7_๏ธฦ๕„ข็jเ_ื่ Œฬญส6แหeพฬ�M็Gฉ*‚ใZไภP›ๅ^ฝ ‰CRฒเเr|ฃˆŠ"[\Jฑq-ะy6ต<-ฬ‘ฉ–"™ถY\สH'‰pฌม1 y†นFA~ป|โ๏ฟฆ]\sgoWญ<๋uOVQEI� kืฤ[žg*ล ŽYภข๒™ป'๓@†๐kย ๆ ๒\ิžฐบnJ)‹”๓"ฯ\ฌ[โ๏—�9Ÿใ‹E›*ฐธเd7'ฏ(*<ํม$๚.ฆ๚8'๒ฌ�ก~`ยšฟfฬฟ]}Š L6ฒ้G˜aPเยฒไka‚บๆI ำ$ฤYIX#�ž�WชงO้วฯ้�ใดผ0�]ย๒›าfฟ•r\KO�tg“_'5๚ฝขฟ7า~G�u\-{ฆ๊ส:��ฤ๒^‰3:็แฬž�๙๎“Lฉฏi9—�(a5,ท9cM”*:๔ฯเภ›‹vนOำA“fๆŸช<ชIŸ“[:z๎ —w9�๖ Fณ๗เ… 1v�แว'}`่+ัึƒ0�9k}+`ข›ึu%ณndœ�๋โ๐๎(๏\^)h!MˆะU<š๐K!%๊ฎท?y๊uฆ^จโ:&•เ.฿fดๆbŒžา4\”ั›eฃLqใ�่r›PA ฏญ๋‹FฺqM;,dฑ'รŸผย”ธdุโ9Oผ•-uถฮofหดตๆ2ซ ฌ�QA ๋!X<4”…ๆCโๆŒ›0››!ผ๎`Dฒ}oปฏK’อ�*/‚๑ัํึ้‰ๅ'รร๘$Eวหo:จ@็'™า-—=Œ› Ž๓‘v“ฐž 2ž๓‘ฎ๓์q…š)˜B t่๘ธ8ฃš�ยม1$Gnowฒ!น=พ—™ญคญbR›=™\rณYsซนd\+[‡วนm„–>ษ•ษ๏‘XaนYO qœWั ซ๕�”%ผ]g„ณ +B๋ย๕ • Œ[เbา˜ธทVไ“lซอ ;R…ภ“ด—.›–ว�๙ศ ๊wšRVSqคB†;๚;ฟBe •[ŸŠ"ˆbi\ท๋PฐIlจiฐD ƒะเ ฌ‹juำ�—dNงฉะ!ŒŒอšE๐|๔ู'9lเฏSท฿ฟฝ�รg?฿฿™โ ฬฐฎk„OฅKศหx"��‹‚r6ฯฌฟŸ +ƒ’xFLี๊F+cŒnชูk‚Š[L ๐฿๏rMอ +|ส{แศ‹$ใ9ขFy>ำCQfขJณd3ฅฬ'๎ฆว อ#X๏ช๔TjงะusV^ˆ–JนsมŸ fˆŒ�ฯใTชๅH๘›(๕7/ˆ`ƒืkŽ/œฌ&ฏ[b๚‹สw?ฯE˜n”‘๘ๅ0A$‡ข-iถฐrใัลฤ˜‡�ท)ฟ>• rfEจ{แฅUก]ๆ_dุBJ ูฮRิ†!›๐ฟŒVyำฬ�\๐ฦBๅ›Eคถ๚๛)ู‡�คŒิษ&ณS,q2ฒY™ฎฉ^ˆ�™ดโdMะHIฐ๊ฬp7/+uลำ~5)้žZfผ�#-บเ;† ึิต๕ีฝา*&sธข…/Š์ฒ*ื4Ÿๆื4ภฮู“๙ฦ๘FนZoฌ%๎_<ŽจL๑*�๛ฒjนŒะ—๒:๐jƒิ‚š๒z‡ยณ’8w‘ำ#…�ืั Nส_ีฃแึ&76ฃ๛=k^๓>cฆ'Wฃ�€žk€p0W80GFตฉTž EVjโ๔lีฮŠ4�๕GฤซP๛@ฎ้Ž๏!( ffeัผ>ำg์ฦq†Sิm‘@iาญq_Zl )ฃ[0 +฿~y๕ง์p…n^qš)•0�@ฯ๚้efr!฿๔์ ้ภnCNp~ฤP ™ขv +๒:�9<ๆxRฦ�๚�ปqต�พ๔๋ฃ�GŠaห็๙K7 {\�˜&#๕`]�,I†Dฯ4\™๛NQ}` +ง).w-2คญ่:ฺ#ณŸฯ‘wf—_๚<ฟCย{คQลcฑี&�ฃฒpดUื�ž๎?=ฮ๊ข๋นR7ฯ9cึ{แฃTGœห3ฝ0’รีfVdลภkP ิํฆk_qD(ARูC%าญA3ะšัุีุ; †izบ;๗AkเzRH.๗ลV”ฤฐ“เj้ใ!ว๙)ณ�ษ +N๚TU+วžฃ– นbp๋ฌˆ&์oว�$Hฎ�ป™‚ะเf์e‰ท‘ภbฮ^ื.2 คสeปœขdJ‹2Šฏซเฺh5ฐศys…š‘‹๏ฌ5็G้ช๊8Uoฅ`4๛ T˜3เจ™๘h/-+Z ใ4'%ทœ’/)xG็Wาi๒^yr็ ึ€gไ�๒�M*9”m&!y๘ไ"‰ž้ฅ•’ภ�คญ ฎ’Šua”สๅ $p�.ฎ”*ฬ�้ฉVŠ—ๆ2PWเ��5ยfฯp�Nื2TaฏฎไzึM^vชq›~ ลวe.Z์žืrlตš†บBฃ’ŽรฦV +*Y๚|“zยTซ?๙0$SCmผˆQ๙�ฏf`๚7šๅ>ศศaแb�ู(aบ%Cฏˆ5 VAX้\โhPœNทำฯEป[bB‘]เ6jRอา๏ฆsM—ฉI5ฉ๊Hm•แ๔;ฃๅเ๘J%Dห๔K๗เๆ55g๖(ฎ๗๔Pw_ +-๒ยฟ9’B ิS˜™้r�ว…dชW>Lเ(ษi� +‹โdNNžS้„ื>ฺฮ`80mฆaไรC&Zฌฬ๒Šอ๎ฆs L‰ฉD 0=PDDEŒ*Z€iFหม`:• fuะภ+bšั"aี&.vถŠ6„๋ษ%ฝEี9žฆ+ต•g๕ftลF2A iu�E_*v”‘๑J€Rก3bฒใŠฺiุ<นVใ‹‚ฮ�Bว*"ฦ๚1ย‘ุ j2QฺrZึ�ฌ๑ๅ\+“3nัejผ‘ัผบ '๚ไž ฯ“”Hื�j.!ํEu๔าcI�)ฮSฅrt|�๓[ศวL~b6O;/]-S๓ยsบ 5รฅ*‚ผ ~๖ฆqฆฬWฎO�9'uฎฃอุ(ด‹ก๏€"ฦK-Pน™†หว)bิ ”ป ZƒgbŠT:pธ–(<ห =&}ฉฌเ_oฮ;ƒฆ”ึB9ญCซภ๘, 1Q*ี5/ฬN–�ิ๓‘‰yQs|ะฎงจฅร”CEL‚š็ำ๕ณWb”๒Z8P*vี;„๓ม@o35—‹ว2รbฺ„™MฬvZ๘4]%DีJD!Ay฿n$ีvfN +�„๊ŽF๋#qบJ€˜ืCOžณJ๗ถุ!b”ำ<0งซ•รœๆ‰9}eค๋ƒณ�w’dฎฯทศ‚8‡Fฤhœ๎h+ฤฐ&-ฯํศM�ุ"ˆ(ตดBษ(1\Žฑ[F%ยj-…Ž๔–5KW@eŒ|่๋ฐรŒฑS# ๏.j3โ^มf{๖RนfNN1mซ๒ึDLโIeูบววPgฯเ,ง[Nlิฏญpม2๋‡h.1�eกนอ4ิณ;M\�ฟ›คU=ๅโ�+ ƒ๛3~o"fxฬjขZ1๎ศๅZWๆB~bรœk่๙ศDท�"ืะชกy%w +(๓d&›ฤ$Z๊xณHธ— i.๏*๎ฤ๑๘ฬ_rBซณ[>ั^สˆsุืU"�kง๚J„{๓TปD.z๗ีฬ>ฟ]นภุo—|}๎ซ +�Œ�+ํฃ โฉ}ดo7ช{F‡j้hlžzYqšฒ*aิ๕Z*fฝ๛wัฎ Xซใ.ฦlฑ ข1}แ�‚\฿นh;_8ฟํ4ไำ฿ฒj๎yงๅ่3\ส~ื\aขS|แ‡ถ-หใั\ฝ›%‚q‘,ๆ!*ฅdรข{ฎ—๊หญภ #h็V1dโkS‘๓ลzrƒjทž}ฑv�A“Žq{*`ูr`J๔W/|•1p๋'G+p{jF๋๕Jข๑จ‡j�าสฮีิ�Y”.ฃ’•ว•๙ปhKๅ*cะฮIŽM3)R*฿wฃ%บุm3 EK1GŠej�๖Rฒถก�็sF๋8 dŸŸqLเ^{ž4ฺฒฒLึžคRGPึล“๚้ฬ!\ภ$&r ก็|m“d~บaVLใลŠฃ๛k6(-H.็ิฦ๖๕ž’M9ฬ9์e;Ÿ3Dq•๑]นมฦ7›๑ๅsผhT^d�zŠ็S†K–s›มO=^ข€่เ]พ๔ิnRG3'ึณOุ2”ž<แ +QŽwฆ฿3ฌ r็w3๕dั…ป๐จ ๋ํšคB3‡๏*�z80ฮSE่m�ธV:…N๘e ++ณaj“.'จ}]�๎rwˆไ…๓,ฅP6บพ�3�ศ ๏น™†ตสw�z˜๙T๛I[๑ง๊)^$ฦฺึ]ฑZวๅฦฒ•;9Œ่ํไ้+šฑh˜ษตนื'๗h�ไ`R0}๑ๅแ‹™๎yŠโŽชฝ/า9ส"WMถขืฉ'๗wงFฉ็H฿ฺ„!�ะ`‚ะg๓้ŠฑD›๒Œฑํ4ไrM‰Tฆˆfๅ”3ุOะฒmว ฯฏ% +อ ์ขจnwM�ŽFi๐๛ ั[<บ ‘<ฺฤ#ร๓ท”9Lฮฌ‰Vใ9ย‹ีูœŠธบฒƒ๊nžร]ตƒ‰?จึ็9i�•\žกY9š�6ขีyD�—)–™Œ๔แ”ฤ1ีc}๙แน“f-ูQIG52ฯ Œฎผˆ\ฃ�bvฟ็ˆF็E฿“'Dง๓ภ(s!ฺ›็fฮพ์ะL3gWmช�8e1L1[_๎X._าบ2—ฃ šœงนI8Bt +‰C1ช๗9Dต7ํ†O๒S}ะiำ^|md+:ฝไ8นผFO๕%๚ฅ็ผF;�g1>PR;' ั`ฝˆ์ปฒ ธศ�ร:˜D;ฑ‘N€-`๚ะ€ž่^๔FŠhe๚M ƒภ4aๅญ>L#ษชkฤ๒D๑หwๅ๛ขๆ�Kฃ๗๋/qจอ๚ๆฆAีXœ"หž\ข๚Š็#๊F&q& ?โ๐ใK†Dท๐"~ํสnฒo_ณarขฏuฟvๅ7๘๗ณมฅยธŽ*ฅ.5g6Dฟk:๎ส#nP+žำMเ<ฝueDเขทfeIe�จทfn'็ธยV^ƒสๆmญ๒คคฐUโnง.Ÿ็_|4�#U:"อ–�& ๛U€&vศ๊cั=bC๖j๗ไก บึt ?นษพJGv์Uฅ๗�๗ำอห๑9/;-“พŽ—bู๑ป&rงœ8*Ž�ฬ$จ\๗Tหร฿อWเง(™1_ซeq็๛ญน่๊ด"๚)๘ช@uํ}s๐�—ู้8KJ2gfšhX_‹๔Bีzš๏…zbpคป็�๎ธฉต๋ฐ‚Œg๎ฝN{ฝทN็๎๒…gO๑ขะ|“”์^J๒ฃ๚šUฉQ—#๗๔"HX�>opฯท(5‚ฦใœท(ีJT†(�8�x…x}iE4HJ๖ำ1�zขL8๕šฅG�[-•-ฏ1พX5พ\ฅjิึญแqซymฐ—‘’SŽฌ4wžoเ๛ฬFฏธŒD-ธืขญซีไอL ‹†.แ&ขT ใo^j'ข#w๚7ๅ๎*์™พฉ๋k#W‘ปv“ฏAญQ*พbiP…n›Rฯ็ธา}พOฃc9ีฉ9eIg)๙‘�ช๘}”๋2เไT฿ขชwKวเฌcC…YwJXxๆuษีŸoาk7 นliยฅฌป� +ุ‚\qุP๚ซBฐปย ^7~+เ;ๆิโฑ\-Yงyพzs(Pิ‰W +ปผK~Ž !=ยู>ๆไศฝๆL ฤชแคŒ๐๋ew7:!DLd๎ฝ�C‘๔^5๛„ฎ [�ห‰ัHฝึ• !“ฝดA!]ฦปึห๐w๎(นฆ๋ก๚=๔พuL%ณโDๅ�&ƒp๕๛ปqMฉWจขดพ ขK|ฎR<๛)—ขp5สฅช๎Gqํ7ิ‚ฯซwฎc8บ๒Tัy์หฬคัQ€๒a‹nœyPj)ฆ‘ษPjb^”qQXงฺ‘ขข8่ญ)M‡วi˜yุจf๋L FT-เRYaฃำj7V|h„6sฎI9ก5Hื๛|^ป๎3 W+-`%ะ‚ฺ j%Tฏฃฦv1๕)+O<ข่rJ๋8‹.|Wฯุ์็ำl@้M]ข้:oๅ/gฎ3๕x๗ž‘`ฑ%๔@๕ฮ๗yฺ-�ๆ็œฉ—yGใฝ€ ใK฿šโย๓๐E&ยZ4_›^ 4�žE.n|H%lŒ{๛p�)ญ�R9#‚ŽOŠ๐ี“8ชสผ[ะ"๚แฅซDญ ้(‘‡C4ฃ‚ ฮW=จ�วๅใ็2์ภฆน]VึX&ห๐“TาiW๔kwว'(8 ซฏอrq๕;สำหO?ฎ|๗“ZๆำCŸ/�o–)•มkฌ!u๕ซY�q็1 ทไi๖@uuฎ็f๐.1;ฅ๗ˆึช8ืN8๐ยvCPฮa—KUCีšิบลลฉŠ๒ฌm๘�gL๖™u9O“ฎUญู4<Yq1mˆNQ‚Ÿ์๓ˆ๐ฎH�Ÿ฿VFŒส๑ฯ๒—Ze2ร็w่้uน๒|�๐๘Ÿwo฿?พzu๛ๆ๏๙๙๖๛ท�๓฿9๒V€ิiW�ใIž~|�ฏCqๆ้Nๆ๔ร๙;:ษa“Rสœ�๘์วหำ.ˆจดฟฦZCลซQฎฑ–ี0<—นฦZ„fฯ‹I™lพบ–๑RDซ”?ษฆๅฌAสซ-N8 ฬต”Q'ƒฒWZ0‚€ืu…^.฿์ํ๗o๏�๐ูฯ๗7ๅ‚>Yธƒฅษt+ฟILัจ›—)ใŠก~SๆUน:ลฺ๋&ฺ v9,งxxKฮ‡Rป`ฆฑยAh9ภฬ‹2žแ๓๓lร�*™ื:๏ิxอฉ!wค…c๒˜J<.พู ี#�$ฯ�ฅrXฬ7 ฟŒ†n็วร_p๒Œ*ถŠ๛ทนŸ๐ไœ+7~ว‘Dค•7ถv ฌ„pg�ี-”ถชจ#@ว๎l^GDL†ืน„&|๔1‡‹ O‰ป†ฤHŒฌœงป|��๑oo�๘ๆ็�}|๕�ท฿}'ๅื฿|uพใืˆž‹tx]ฃO12ื๊iW�-๓e.n:ฮIE +ื€Ce๒ฝsง–dภๅGุตฏธถaใZข๓์fy|—cS-g1ํณธพฮฺเšX:bฒ๑ tอข�v๙ฬฟ]�˜.oML6žต�๕สSQ๗dqcQ)ดฝๆuMฤๅแLqฮQL๏แุesŒ>๓,๗dศฐบ€dMXยœำหํร`ืญ)evrVไู„uc��๒?็ณuฑh@Eœถๆไe~ง=ฐD฿ลT็DžŸ?ิฯ0Xpuhืž")’MZzลัๅ๋(�้สาก…�M;AแL ป$„YI!#=ๅŸ„ˆโ)˜1็�ีัcด endstream endobj -272 0 obj -<> +281 0 obj +<> stream -xœฝ=�r\ท‘๏๚Š!ญุf(‚ธ_ผชdcYษfcง*eฝล๛`ชยญMลLVa*•ฟO™9 osฮH/คจƒKฃปั่๗ฟ๚๐�?พ~�๚��ฟ�๖ง๛o�ื_�๑�‹_|�อ›�ฟ3;ฝำป;ณ‹VนhญŽป”ŠJ6ฟ{�ำ�{ฝ{๓�N๏พ๓๛V~๗ฯ฿}ท๏๓ำNO’‹ปฟผ๘�ล^ผ�๎อ�เd.fUŒKŸb.ฏฃ๒ฦูO1WpvZ—�sEซฬDฐฐŸ,ุ—ๆ๒IซŒI;ฝi:็•‹N๛O5ŸIสณry฿�ํวงืฏ๏ฟ{๓�ov๚��Ÿ�๗ห?=�เ้Re�้Ÿึฯำฝ�๛N๏���้ลื๏vz๗๎ร�ฃ�ญย๎�ใฉ๗๔๋�O�๒ญ๕Z�รoภ๏x�=ตั?hgบ๖�W{�jฝบ6ฆ�ซฮo�็�ฟx๛ŽXบแ—๎’;nฦ+ฟš~\O?>›~ผ��‹ษโญjฬqซN„hXHฬ �‹ฺง›;‚าัeฟo๓๖ˆ�t์๚]�PICs ‰žzBี฿ธ฿ฬฺYฦ๙�ทN<>€ฯเ” %ฤต�๕์์อ๛_ฬ�hV5cล`ุ •7ูวน}fฌ;ศฺ`L<ึs‹?๖๛i&ปŒQ/`ิ•Nฎ`ับ&ด6๐=u[&มs<๔Arึถ2u๔•ชภีS๒ฑล}ฅ*ตข'†>sŸฎ๏ํV ๖ย)& ํฟ้ฉ1รcบฟทv!��ฏxŠFAvo$่๋้ว^๔ฝๅ็Oย~ุฬPภlถgOQ€ใ#ๆŒ›ละUืํนm|^@ฆฮWIฯถใxeAฑŽ9Nzšใe†�ฏคง›R%็ฬฌ‘R'ำฯ:d๔Dฯ๓ฝฮQEฯQศ�7๔œ|h=O%ถํบฮวq<8ฎƒ žE"FL*”Pึ2์›ฌฬn�!Ÿ•ทนไธภ๋จe?ึš๗—็;ฒ�sย*%ก’14ทKXษ<�q <3ปุล›;ฌ^cY3ธๅ้PE฿VGpœ[A ืX€;ฏผึ/3ค�eๅ—่ฌ็bฮH™ฅุu๓~ญzฏ��พc๐bJPฦุ’7๏ฎ•LวKvRฃO�1pv2��ลข|สบภ5อซค๖‹ปrฤ–Lุล*—}นyศ]ศ(๏‡�ช_39iEฝ$�ƒS!ฆ๕๋C๒� ผํSVึใ |๒“>1�wด9ิสข+~fhDแ&–�ิh5ณ๔ฝษŽุ…}ฟฦค%Œ>�VLsเฦFผkรฃt)“@ZโˆeฏฮQPštใ,�ฟX�๏@๏‡›ป\TI:ฆน้ฌ}UรaจGaก„๚o�ดพ˜ถs<&รํ‚ูŒษ3์(t!xn‹เgฮ%๕ˆใ ้๔๓žr �~7�๘z๚๑+~-ฆำฑ€ฎŒ 8T]ปhF iFใู&I‚า’qaซ#`ฦ$ฐฑtบ™,olฒอแqOชามต‡Gb‡ๅฝ)เT:IภŽvA๐€ฌ>ย!จ�€ฯ{?ภ :4Kf '๛-ค๐จฏuNซฑ<]”~ผิ˜ตุส–๕ฃ"d:ฮ -๑ƒtญ{83WขuC™r<*๘ฅภ–ไนnธgœธข“ร’ฯJปผgZต$>{u2ไโMขYzฆ’uญ#น_rร~�Qn9ธณฐ3-฿ฒบzเ่=๋)Fศ8๒มc|kูึo[rุA-ฯS{๛พ’?.u.v™AทX{)fณาฺkป.˜๒ธCี"๕pฤณยั:…vh๘”๗fณxี w3ยํ๒aYภY# 8cTHูฅฑด1ฆ7YY“œฉ^4sR‘ ŽูT 2ฝ+ฎ=L ?โ€%ˆฆC#F๚; ท ๏%˜rญnUปŠlดส‡`�๑—คp<าฌyu?/ „)๑dbะณ|.ˆต*4 (MฯYะนศฯฯƒC แฦ๒Eูส๖โซ�ฌฌํฮูDวF -�'‘�/ีt๋•�Y?…‡๘€'ฬJžฐP’ -ูไ �XณะIง0hฮ์yoWฬCQี,MคBƒ&C9b9d–7ย''AัŽN_^เH™dA'•mสซSHณ๊jŽ฿+ŠeirIsi๙+yRv6๐แฺv…ุQ8‚‡šศ�™v์E>*๙ทWฺP–ไ”๎�๙œ•q}สภ�ฒM~8˜}Qฺ:๏€]าฺ!ฮPธ|ึฯBส"คฬ nw5V|ฯรฟจ๖ฑรKšše)ง๗ 4hะ†r๊ะV฿˜t,Eฌ}สซ^&ร~ฆฏ*ึุ8ฐV��วr‡๓™ฒ1โ_-E˜›๑ฑ-„ู6# -@hI’$ฏt(๋ฯ'” ๔,z ธ„;cEถา/i7L฿9Y๔�–เoฮุCษ๘“vJี&ึ1ฮ/ฅ†NžiWBŒk/๘ฮy ั`R<ฬ[ฏ|๔&]<้yrPลhkY‚ๅคga 8�`tR!ูh–0โ์ทzฺฒึ…/ทfย:vฬมส?ฐ�ข ่Bด'๔Š_*y=ฺ#†ƒv0ƒ*คษLฆ‚๑œ€ฃ>NeL๐เๅํIฉGRœ3ส‡œ�Gแิ�sีƒ3าฝ -๊kE&กๆ•จฐญ|LqC.tW>ค(๏ฃ6ีBlN˜J ํD~ผ=w•้‡ใงQดจžทKVัAา}ษซฎคwฐ1ง—9�๋w @}ทไh D'๚.9๑80ํf(;œŒ�\-’็nm);ถโw/‡P{ๆฬปžคห’’ฎ๎JT>™-หฮ1ึ[7Aึ*๙lk๐คฦ„๗เ(}=<บ’;‚€จHต9ํOa1d&"ฬปไ:“N(j•P ำ1S•…D-+ธ๚N&G่ๅX\4SPฉ(Ay SVแ๙K฿ุ@0�†]U๏Oƒฒ8aA๚1\ป™ม'แ2 B5“ต(๎flเ“ฆ�์i`3ฏตoypœ$\ฒU>๙ธZ‹ƒท๑k™y€a�)'}v~ฎณ๊r… BNฮ๔0๛%ฉำwฃฎถ๐‹ร†—qQลฌณ�Ž๕แ+�gK ฤu“WKx๊nฉ้วีvbด{o�j฿ -)ฺ�#pLตจใ์ง—Xz—37ฮจRJ‰5ร ๘ฺˆ&๕ Xเ†›Ÿุ$%Xใ”ลฎ~›ๅปš๖ฤ–jทFkŠ_พo[^2๓ Žอ]๚%ŸaนฦฑฒLธ–Gfฝ/€M(h�MืlเxT,ฮH]cW+gHQ}…w~ศ–—`>ซผฎย๒9์B;=$ึํ)9ซvาHgคท$์–œnAG›์ˆYL FQ�Pอ[€Krw™R”M6ญO ุ๖rแแป=U๋uช—๎}€~ศ�kงส™๖X›๔ฺคศ<ญkJฬใ้ฏฐ’60ฃ_่J1=SlWFศ,@9‚ย(t”๓‹ึฟฤุžGๅ -I ึฑฎฦ๙2aูๆๅ.�› ใsJ |w dณฆyRV -ืqE„.ิ๑ษ�N’‰lrP6Eปฅ0~็'ไ�ธ�~f*ฉ=Fิv'�|ลฬ�œหfXr๔฿๑“ฬ`ผกช )๓แม†l1(ŸœMkใƒsฉx�ฺงืtต๖๖ิ—ิ„AUrฑฺ@;๔,ฃสz›�ก˜n๗ึ1*Z7ำŽธาC้œ} ขnศˆฆ†ฦ[ษDlํ”ัฎ ฯ-%๏6y/eฐuVัฅ‹PํภFฤอ€แๅ�ฒ-๔›ญโO@G์กp“Šƒ๙ศtฤ–ท›Bฟ%วํt|‹ˆyอใDยž‰Š†]uะธŸฺ,€6f!0๒,โr6#ฟฎ0z3pM'˜dƒ™d๓F>�W8�ณ๔.Ž F๙ำ๊ใฟนq3=ดV -(?ขE๔}ล+<@SNฅฤM็4ปฎ”ฯ๕n‰{9*ฌIธ4Oj5ธqXPw๋๕�ๆ๕๚Br*…’‹หึฐ‚˜ขGฃิ~:้ฅ๒.™Hz^๓ƒูฑ๋A‹+DQแ%ี ๋๘1น๋ธ#ด่ )@0ภภqวqท8ฦa(ท๊A€Mจึ\ข0๐๗€�สv'๗ภCว~G๊E�#๊ฆ๓hใe€T;ำXง|v›j]œ+ญฆ๗์ณ)ู๚ๅทฅa[&ร•{ซ‡’ตpDด฿ W๕ฉEv๘A%% ด}d,@ชูp๎8^eแJ2๒|Dผ–Uฌสษฦ<ยGœ.wฐ Xรญ–IชุR6q๏~ZฯO‹ํ~79าุดโbอฯJ˜ว:+๋’ฑูซ$kti�v'…า+I–m6#ก 8(คpcๆเ๒Ž”>ป,{=™E้ฐ-�ฐ�˜-R†ัE๙<=ส๓ฑjศjzh2IMผ0†ฅlสnจ๙ัUเiฎt์ฃ�ฐ�hŠ^ืาLkไศุFถŸณด&M"wิSBEr๎€H}[‰ไs๔V†๚ ‹–ห๓๏‰๋๋ฃ›พฺา TfŒต็\#œ{�,์ 5�๎n—"นดJPพ่”ืื@ั ๏ dnY ฒภWYl8“rํ-„ๅญถW1ฃ_�๏Q +xœล=�r\นq๏๚Š!ฅ�Mย�ฒVู๑jวษ*Uฉี[œ‡ฅสL9•ฅm™)—��ufๆ`€พฬ9#ๅ…upit7}Cใ๕o>=�๑แงOo�ผ�๐๗?�แ๕?��O�๗๔ซ_}๗��gู™�้�ูEซ\ดVว]JE%›‚฿}�๙๕Gฝ{๛ใN๏~|๛๏;ญ�๎o;ฟ{ฟ๏๓๓N๏ŠSE๛��>๛๑ู<{๗�ํ๋มษ\ฬช—พฤ\^Gๅณ_bฎเ์ด.�%ๆŠV™‰`a?Yฐ).อๅ“V%“vzำt>+J๘b๓iงL :}ก๙bŽJ[ทv}?�๙งว7o^ฟ๛ป๏wO“๊6›�ข9ฮ๒๑ฏ;ฝ๛๋ววg฿}ุ้�‡Oฏ๔ฮhvNฝง_~�ฯ—ฟืZ�^;s๘mใแท๖ว฿๛ฟ_L?เ—p�ฆ฿ฟm�ุว }7๗4�˜7�๕แ_Ÿฝ๛@ฌ฿เŸ�q็o\�ฟL?�์�ลฯoฑ40ๆ( 6ฃ฿ธ�๏‡�ฯว#2,๘nlVึg๋๚^3ัๆ~ก๏7ทาว฿.qในCง›;›_ถดj€ƒW +ยม๎Cu€%ปNภnpŒ8ฝ7€m•+r<”�๕?=�๗ห?<�H›ัEeBเ5K์0รb๘}ฤถี�ฎ=ถ่ฟฺใWŠ’ใน ภq‘ม#™N"†‹ส�”Wณ์�0Jon๚ฌผอ%วnG-๛ฑ>ั�ฟ<฿l"๔Hฌฒช๓Hsปt•ฬณ=วยณ]lma์#๓ รท<ญ่�สC Žs+pควR�yๅmด~€#ํ.+ฟ,Cg}Psฦส,มฦ›ทlU��๗ตฐš€WS‚2ฦ–ผ}ญd;Zย๊ฐ“ž}บ๎ึŽPฆ›ปX”OYธจyouาดัƒqWŽผยš ร Xๅฒ/— น=�ฐ๛_๕‹&€bMขi–$ผตส•RVฏษ๔o๐ึOYYฬ์ŠฉŒ่6}dบ๏hหจ•GW�ฬะžยM,�ฉัmf |“ฑ๛~๗ŒqKุ ธญจๆภŒPx7‡ F้R&™ดฤหžฃฌ4้ฦY๘ฑ�฿�๗7wนจ’tLsำYชž‡รP‚;“ฐŒŸึำvŽวdธ]ฐ #y†….ฤ!ฯm<๐ฬนณ�คžrc!อ�Š๕ณ๖๏ฆ฿M?~รฏลtzะ˜ฑฉ€ชฃkอh"อh<�IP๊ฌผv~ซG`F$0ดtบ™ฬolฒษแqO๔้]เฏะrแฐผ_C�K'ุ‘ŽฃUH@C8"ต็(P๑ผG้ฝโ|‡ฦsษฌแdฤ%€๕ีช๎มi5–ว‹าณ[๙ฯฒU„Lว"~ฎuหทๆ*Bดd(RŽ'ฟxภฒ€<ี ๗i�ภต’ฃ#ฏผŽ›Tหv}OดjIธ}๖๊dศล›D๓๔L&#๊ZGzฟเ†�ฎ# �spk;:`kZพ%ม๋yˆ1B€ภ‘๏ &ใ[ห๖~�’รjyžฺ�๗lm‹ฝ?.u.v€Cทุ{)fณา�kป.˜๓ธCU#๕pฤดฦั๚Lcฏ†ฯAyoถK‚W v7ฑ#�0Ÿd\d\ž|zตาtื›ฌฌIฮTWš9)IPษl,*ะ H™�G$ิH$Ž]B€h24rค๏ฐ‚›pa‚่ผ„ฃJา{‹lดส‡`�2ํ—„p<ะ!ญš'ขๅม”z6ฑ็ŠYพคZ•P”‡ฆ็,็\ไื็ม!Pƒ๐c๙ขl e๛N|ี๕€๑ ู9[ุ่Hป$ฒปฅZndF 4E�Gไ qŸ�ธม-P3ŒNRGฃูi[ฦ))NG&Dด�6— S)แL@NoK„ƒi�8ฑข๛�#G้ฌrVEV๋พ_ ฅ๒FซtVWxUz�๑ฎkฮ}70…๚(ส“‘<วO@EBๆ์,ศ๐„ฮึ Msb>�H่ฎL๊รˆ๙},Œ‡้zณ๖‘k�(จ๗Cตฺ๑Jฤ@‘hท.ฑU๙-Fุ฿ฮ)ํ“๕ห[lั•:_x๔#"#�;eโt\m�ใ2O6บ[Eุๅ 3ํฌZOWฺนึ^฿Ž๛ +œจ�›ฌข/n๕�‹็D�ฏOศ‹สg็ˆ7ˆkีP#ึว#9แe๓๛ฑฉDFaบžเ–EKqLYด"Zห™ก!ํ“กNŒ$่fฐ-ดยปฬ#šศUO๒0จำ#ƒ +๋1€๛ฏucรGใG?/UไoศiI&hฏbฐยนKถๆ *็ŠฐNZฌฉ—?‰ฮd.ื๖A๔!6œยŽภจxD`อ0C�๒ qฬTภ�๏}๒ฃQb2R(RVJz(€˜ุ �ฉท�ฮต5บta€นศฆ‡ƒ†ด$ฅs์๛ฎ�ภ�6๔0j,หKLตœห#J)[ฬญbˆn๕�ท็ฬฦมIฃ^ซคตัภŠๅlศ"6t6ข�๐ ธิaŠา8๘8@oค4ฤ,ง/กปTวC‡o—ฆกญJd1~ม,tา)LcZƒ3{žฤ�3ยPh`5Kูะ ษPtŽX™่๐ษIPดฃ„ำ—8R6™OQลP๒j“d1/ ฎๆ๘ฝขX–&—4'–ฟ’'e_ณmWˆ�„#xจน์0วiว�่ฃ€{uกg ŽA/��๓!ชœ๓๚c์nู(?ฬพLwcฝvIk‡@:C hเZ? )‹2ƒบ�ี€๑k�Eต^า„ะ,KyอธกAƒ6”WG€ถบฦคc)bํS^๕2๖3xcฑศต"ะุ่๖—หฮgสฦˆตLanฦฤถผf�T™@$^’$�ช\Lฮ�+*ณž๖:Aq wฦŠ”ค_าn˜พ5. rฒ่78.ม฿œฑ‡๒&ํ”ชTญ!2^(-Rnจ7VY›b\{ำ�kpฮk่‰“ขaฎ8eหไ3ฟxฺณqQiช๏ฒœ๗,ฌ‡Œžถบึa` cท�‚ฒพฤ^nอ†u� ฃ•€`ฟE7ะ‡ho่•ฐZ๒šตQ ?ํfE#Hร™ฬ +ใูว~œฮ*ฤไ.ภั�ณS=จ87Uทิัvฝ=WK8#๕+7LณQ.ฅ๒ฑ� +พk(Iเ‰"5ฮ์“ไโg$ะ›๕น('Šฆคlv�(ŸE +ะ}ซฺg„u8พ๊ไŸp�แ˜‰%�ฬฅ)Sผฤี�ƒZ๊ๆฮซโKถ๕6Md?Q{fีBk‘nฯZe๚แุ G”-ขใํ’atะคt_ซ+๏รlฬ!ฦeP๗*ศส๏ฮ ว"ํ>Dƒ)4C๙�t†จGนฤ5หžw ’ฎุ0ภ—œe) ฒธFbQ4๋ฦe3ฮ$•�ล œv๋๋ โXAห8ฑ,ภZPษฺr  ™sนฮดkฆm1+0fิ3LวLU:…žบฑกŒŠะ๖g{�Pน’_ฤ=ฐค„๙Lัฃ>�EL'…‡"}ฉม๐[vฝท บP‹$ืรตฑHaไมHฮ�่ข๓/ฒ๓๛[ดlƒQNว๘,[o”qฺdๆ’|ญ�2o?a”];ี�ฐษฌ`H;ตV%_‚จฉ�๖YผFs7Sx`cฮL…,ฃณๆTฝn}vฑณ€รiร +ก +DmจฺaจฯRO#แท�ฐ�•Y(๓ืkP8Jฬย[†ˆ +@fƒซไ ถฮใ+„ฤl๗gฑูร๔0€>ะ™-ˆ)ึ๏ฌSฮธธล๘C๙ล„จ›–ค—อ‡’ +Wฑ‘ฬ:2iVฦ>รcQrศู2�ื(>ฏ.„]ีถZ’ยถu฿tวN๗Œ๛ึvJฅ„ฅฅ่!ŽY7 (fuฎDพ\ค€Hษฉa“S1Gฟšฏsทํ๖…*|`Sโjีก๎เถฅOฌdZ4วhI +_ฎ4tซ:f€�uำw๋NR“ขPตeKสy€‘+ฃžv› ถm)ส๏ท๓๒62_˜UqM™fถ…]ท์h$z‰wHV}EPยv?อฯW ตกO/‹-pณTๆฦ†ขb.ย๛ +gJCงrศลเ๒”�šเฆD�Pjต฿ˆ]ๆ็ฐ ห๔ฐ!‘๔%57˜๒lqŠ`ฎพPl๘‹P๕ม$ืฦg๑ฅ๐Iไฦ1่Nƒๆ�ะส ำฌƒpฑˆ+็๊€0"G_03ยญสK ้ฒซ๕AลโEtAb�๎ˆัฦ&4QฅR>ภy…‘ญั�7๎�๖�7`ˆƒฐfl สดDbชo ฐ5๏˜3†ฃณEQ Wsว2ส}*๓ 8Cฬžใๅฉว๘ฦศ่”pG$-/Ÿ +'ฐm๑ทึฃผั๘r(ณžLDˆ� …่@9Ieญ3*–X.๑ถฺญd(ฑว6gsHfHู�;๖ศ๛ฝงซ<ˆD)๋•ฮั–‹ r1OZ€ ;“ŒฯJ๋เ6ฃฯu>‚๎V•๔–U๒dุฬใ�ั5hN“gษ Tา’‚�฿psโ์r6\%KPBt๒^pg%ั ฃาฮฆ๕๎ฌ'๘l,แ‚ช{ +ไ„W� ิ๎ล7lตuN,คr๗ฯฐ1EšŽณ?œ^A้_ฮ�Li—ฅ”X๓ส€ใhRb>น๙‘;@Rn€ษVm์๊ํsXˆ2้ึ(cM๑ห`หK–#csทmษ'Pฎ…qฌ,ฎ„ๅ‘™ๆ `j wำ�8E3R๗ถุีสIXT_แฒๅ�%˜ไฏ+o|ปะ๎‰u{JฮJค…4าู) {(ƒN*ฺdGไศb*60*๘‡Jฺ\’ใหฤฌŒ๖i}=๒mพKะc#�˜ฉVน๗i๚!วฏU!{ฌ +z ญSdจึ5%fˆ๑ [ุI˜A/tฅ˜žฉt+ #ไ ๔?a:ไ๙M๋ibฌะฃreœซHW3}™ฮฐh๒r๎นƒ๑9ฅLพ;Pฒiำผ็Kt{ฐ"B +hŒ�kษ’ฑl‚WFgปแฺ์ฬKK]~?3%ฬŽพ#jป“!>ซbๆว~ฮy3,9๚๏๘Qd0�Pน„l๘PaC6็•ำมŠฏXKd› ต�ึv8�ปfณตท•^ +P~mTษลj?ํPvšŸฎ|ูไ5lปท†Qต8ร็†๕รP:g฿‚(ุ1ขฉกq„wN2U$�)ฃ]@ž[บฒeุ+[™จŒญณŠ.]„j6ข/'ด^N:�Bฟู*�t$�bžTฌฬgฆ#ถผ�.9nงใ;Dฬkื &๖D”—บ๎ภ�ิๆดั €‘7 Rูu…3.ด\ำ &ู`&ูผQฃOทGŽ�$#V+งณเ5ฟ•9ฝqV +จอ>ขE๔}ล+…>@SNฅฤM็œปฎ†ฮ๕n‰k9*ฌIธ4Oj5ธNqXPีVf5dvQ +�์L\งpQE๋ฝ฿ฮ[๔1๑พ�๙�Kuli6 �04hd<Œศ๖๊ป฿ž๛๋  วชฆรีกjd]ภG้ยPึC|™๑ย๕‰(~ฯจก]DหFOฯhX6ฬ]ซ0$งR(นim /ˆ™๛p4J฿้ง“ž ๏แ’Y€$่5?˜ปุณธB ^าํัฐ‚“ษŽ;B“� ขัpๆ8\[ัj๒lƒ=6•’ a€m8ีํ`0ฑvZ! �์Uถ9ฅ-ฬบŸึ๓ำf~ัJงฑiลล�3?+๑ถU สธ‹์K‚):ำณFiป#มŽhฃ68๓]/‹`cF฿ฐ†ฃลฮ.Iฌ sˆตuป�‹ฆj?�๊๐Š”mฒrฆุดบ�z,ฌFS;Xสb๔z*ณ”Žž๋๙ESเHฎL?แนlิp4ฏ๏Hฉž56คj_—z|yMN>„zุ‚:.{p`คฃญฦ๕9๊)ว�ฮ‚eม ุSูืง-�๔co5/‘›}™Jพ�E๘๑ภ4ว<(โ˜�t;tะธ78ม=ิY`{* endstream endobj -273 0 obj -<> +282 0 obj +<> stream -xœฝ=k7r฿�+FkYัz%Š๏วฯ๒K๑Yg; ขoq>œŒ(@€\t๛�๔ฬtซXUdwป๒6ลbฑXoพ๚๗ฟ�๕๘ีWฏ~๙�ง๚ีฯ=�๗๓�:��๕w?|�ู�ฬA๔แฅ9Dซ\ดVวCJV9๋ใแ๗ฟฝ๚]~�วA�๑๛๑ณ๏�๔แ�วW๔มh๏>\{Oฟ��ํ?ž�ฆต�ํ�๔S[s�ํ�๙ทŽ—฿แ๔๛๙�พ{๛ู›wŸ��go~๙�U ฆi 3Z+kƒีพž้€งuบ้ญ2F‡O{u๙`ง฿ฯ.`;ฎ๕oZปบCตฤ๙�/ฟ ;ฦร๔ใz?�ฟด๙2ณ๗—�ำๅฉอ<›s็'�ถ๓‡ห๖ๆZ๚:_-๐ฒ`mx0mฌฐ{้pVe๊็ฮ ">��žฐฃ๓Žนเ:๗xฌ�&๎ฤŒ†ศขŽL‰Y ฤรyk^ “จg(lจณP ตH`\i๎ฃต<ฐ“ -Y9›๕v6p�qูจWเsสš`�โฮ�hยแOœั@p ฑOM฿นM ู#\�๙๗$…›co—sฝ๐ 9๔#๘๋0i<€ต๗นd3ภB77„Pอ�ซพ‘<ๆศ๐ ว๕๎lg!ก -13ึ๑Œฺ้๋ฟไae8๛yŸ.�Y๖เ$๖เฝrฮฟ•=8ดง3ฐLc�ญIQy“ญA˜ฐ‰–๐�ื˜CC™ศฯR฿ uw0�v9.sืˆ๐มฏั0n๐9ศrxฆ?pำ|ผ—้wx ฎQศœVa๚4่t>ชlr4hYyAP‘a๕๚ณ…_�ธ๐?๓๐…พœ”6:ธ�gไฤU๎D#ฮถp t52Zณรp_ ’ล็“่jาlจ]`็฿�ย+^|•็เฎ็…�ณ(๑5ง•sม์P~ฃจoฆ\T‰e^ล๛f ˜aaF ๘v๔Rt,„b๔ˆฤิกfxฌHmM„mIอถX”Nฦl‹|าO ๚้๚ƒ"ท@ุคœึ&�€6j๙ข๏H’1–ร˜๛ํDฃtิ5žF็O่œRป฿—A ุ@M๖Xw�Csุq$š™†<%”†ผ *ปP๖R#ิะ/ธต3฿&”๘๋vีว๙,ฺ…]�ฎ&Rษ๑“าusนpดŠ?‘โKป๏�ŠฤๅMTฮๅฐวฦE"�Eฤฑ•–pูฝJ�&—0ะๅ -4 -ิ็2๕{พ<พ๓@[‚=�ำ+€T{ธOณBห2พcm~kป> -�๋ศOุฐ/Nใย�ึฐ+ {ณาGใจฯข#Bฮ {†•@h† !�œฒณ๐[๛ะป^`๓o X๓ฉZ์้46[�(ย3ัBฆญr~ฒ˜od"ฒซๆ…m@†ฅง ดKกค †ถฮดื4ร"lwhฤ฿มีX๗ Rz4Pภ#žก=ˆ"ฏ�ฃัzŠ.ฟฐหุˆ#กVศิดฑ�๒I…Œฦ=Vฬฮศั๋๕ุ‡ ๙„Y”g่Kๆณ @โ๕Jwim—๔ฮะ&„๎คzVžƒHFด˜ณr~‡๒žฐูV,ฺf•Mะล7ƒ�Wmใฬญอ™A‰้๚า๎ูPmดภm›ปษ -mQไNhศช ฐๅฯ]ธDำี๓วbjญa6GU\ศกOL]cุeํFา#Z{—-I้ �~jทn€)c#๑dว\ห‰b!x m๙์ๅ�p่Ÿวศ๕ุ„�vcŒภ+zx„ž�!mษ(“Wฮ—พHZ๗ัสๅโ๕?๖ฦท๐ฃ>6@m|B+dซ@™=๛"9šˆ0ซ.งงm>rm๊lื1!dรีง JํlKภภึ\๕SH9Tx - ^fไˆ{J๑ฎS๖j=ทฝŒFq�F†๕:Yลฉ๖‚็BIโBQ+์vwNๅฦ๘$ๅฉ•๕ฉุะ5ฦโ–Kt”‚0ฆฬ`#�๏Px—_อ‘Q๋ˆYzืQล9y‚ �ั+gส$๐t BนNทf_พ�ใ‰Nโ1ญกฺ–ข’)ปH๖กฟ๗?L่PkPvฺO๖�xผ|ƒฐๅŠย™Z“ฏsZู’฿zแU�œ"Dฆiรzูฒ๛^l|˜็r 1KึnŠ๚#ฯ5†i๒t๓฿TGิใˆค!|„�บ‘ ยJม่ฃr!๎๗wํ�—…dๅ]0๑�ผ(ž’(ะ9๚ Ž -ˆ@wำd๔*็†X}ำ‚๙?Šดทik๚šปnภy -๛rg^�aห$๙J๑ธาฦ) g‘AจีL{5ผ,i@ๅตขiะYๅBูeMAB ˆ•สุ์ึ�ม฿W-w•I�)ำoUTเECด๘W.Iฺ๙AVB=q็5ฒ˜nuยญ!ถ/wฒ่hม›ส6 วq๖ฐIํ|สW†%‘ไหT๓žๆ–bฅ]� -๘�T‘่ฝt่MV.บํล•แ�ฉ> b˜๑‘ฃ‹‘ร^sRย๏น\@๘|ข้ž -X #yWกdขึ7Hผบ้,–�gบฝ์+ษ๔ซ€qศŠn&Uฬฅ+{ฮxAQ๐pฦ4ฃ`17ภภ†c!โต,?hฌ๒:ฤ2€ึžwdaภ“แ{๒xLฦงำทท�‡ŠฤฉoF๘๘o๓Yขพอlฟ}ล}(�ว}๘š๛๐š๛๐๎ร]eDdพJ‹บ๋mอ]ีY งึ๔ใSA๋|“c:b~ฒDขีJ'็�nš�’สHœQuŽˆG‡g>�์ช$อ™œR yจUŠฺฤ�/4บึ0ไsRฮู4Cืq:ณ+แิฮmๆ฿Rญ"ุฌฌC�Hยม N%ํ%dฏBt{.1.ตศ#H๐vพd๋žwฃแฐ—„๐.ภั„kวต™ŒŽษเก{๋Tไ’*EวˆUV�้๓๗?ฐC-ฑว๘ำทยบ�H“‹r>šฐ{�ืะa+LYญ•ณึนํ๘ฟุX๓ทฃ’‚rฉ„=ซ๏�แ0ZE;4ซผึI๊g็%\ &จ˜cสท8๋ิ้ฝ>�ฺถ๘Lณ๖ขฒฑจlMด๛r-Nกำ7;yจƒ™๘ใo๙O†๙๔ณฐzยw2ลwŸnฐร q๎๔๓ฑไํทฃ Kp๘/๎๓LQU฿��‰ฃ˜^)n3Zแฉp,V]‹# /y4Bšิาด'3คŸtA ๚7 คหGq„Aซ๐ณส๛’q•ˆฏล.„ฐ�$ฑ:v`l5BำŽm›ŒXC gฅ6ƒs˜aึ™c ฝ0๑+]ๅฮ‚G์Q)Hแ๓คฐ#xผ_ล€œซrษฆh�‹๑ซG็๔6ั*ฯ&Dq?D’�แฌ@+o^บƒสมว‹p4ูณx€k-ฬQ�iฑeS›Ž'ธบˆP2ิธ๕ู๕ำ?ร9�t�!-ฯ,dถ�Yาลมร‹Sผ็น9�{6ZๅQ -๖่ืŒŽ4ฐภร -qจ<’สฆ๘‚๏ฺ 4ฒณ ฮ2 �~Vีjปู…ลดสšwYอ N/มกšฃฌฟlzELศP฿ฬŠๆณ8†ˆBŠR�ช�a)๒Nk่k CR•, &5'E”;Y9QƒฎmๅษU์ฎ“ำะ(ให…้;x˜๙ˆ`)อห9;pœ2R๙Ÿ)฿mยฦqา๛ะ‰ลjะAวภเ#ณฮ๐MO~ƒ—-6-�L?๔๒ใล`ี!฿šV|๐*ฆh}�ŒuŒฺฒFOุ๛CQษ9‹ณอำใJo๔Mท—”ž4ฒฤ…>r`}‘xžอ*คt3มo!&.`นข�Eด[!ไ/ มซๆ@M+เNMุq๏ิ0G�]OgCจ24TW4่ฌR๒!m๖o๏Qฅล/zพ์ะฺr˜๊%ํ:6Sฏqฦ‚JขฤQะงIฐ•โT9ญaฏ‡q~ฺNศไM๖ฎนB˜อzˆd0ช!d๐Bๆฝ`z�ศ/บฃ’๕ฒh๑xMMฦVๆC]Pึ*b์ �„ ฿ำสˆD6„vป“ีถ�๑clำซŒpB๊ข‚ตy„ ษบัK๘/ภั%‚๕*> ๏น๎’฿ๅ‹W)e7ขร{"<"ซเrฮซI8๓ดS:”ไGภ๎ ฒN *ๅ`,gฃฺฌ‰Bล}ลฒฎฬT4Y้yฮ+c‚IŽฎDศD]Q*้a4ๆ่/แp่Y่jLฃฉธwๆe”>`m—ๆgQmWF< 1RtศฏME“ สอ๒…๘b"๎กY#=8ผLE๒๐“p“ฏด-nเ\�ข`คtpฏŒwษ๏g 2^ฑฟ2$@-jๅ&ซ’‹�u-b7)8•ถ+%๛อeเm…5 ๑C\ๅš:r‘*ช๎-“๒Sfฎู€‰�)๓ก–ษeC๕Œywf�Q'ไศฃe“#ๆฺเ๒9y๖pV\†u9—W&Hฐ!9b�–Aฺย•๋ปูK‡�ฆฯฺ๓ t๛]ซœ> -Œh้๘OฌŠ a๋๑G~J่l0*”’QD\KภŒณฃŽsรc5‡Š’ บก0ช ผภp�e$๕ฬฏ๏Gฝัโp@ฑฝ)‰ถ๓…8Tvผใ ’'ฆ–-1n๐ต€ฦ(Czฯ๊i…ขิ{w ๏K๊ -!*จ๐k*หMGQ\ๆฮ-1๓™ค‡D\ัช”ธ+™v†œ–mFถmP]ฌงุืKผื—cSPญ๊Nฦฃอ™ž๎Ch*ถ8*,Uƒ๊…4ฟŠิ๑งชŠ‚ั@!0"๖อˆ=4^IฤํFร‘ั4ไ‰ภท็ฒ6|ฺแฬสr,Gf$`ฒส:„GซSฮสศŸฏbo—tฺฅt8—ข*ฅ์Rj8˜ะ>r๊8ฌคำฦŽ๒๛YpT ใ17E `ณ๙W4๔ "++ฉฤ5ž@t<$ž�Fu‹งNS*ฦ๒๙๏li๔ก -h บ๛ผ I™รf๛<๒๗-I(แฒ�š|"J ่คRpษ €92ๅvุtyฌeฌACฮE<า๔ค๘์@hB"bฉสT"z?€แ'K็๚}'ภCH˜ฎƒ‹Ÿfw˜sd=ˆkาj"ฃร{ue๙ด�ธ–6ˆ–8– -&Cc“` -ณCฎ -คRา™| จeฤ†I/`ฤE๖�ša ็ร๖จีซศŸฉฒป๓NYญw˜�Z๛ะˆa๖!J Ÿi7IS -#64’|โปb9Žฎ‰jนคGเL”ฑ:p83Bไวdไ!พห �?๒JZ7ฦ�Šˆฆ3 �g+�:ekั$ ืJ„ฎแ@tโMVด1๙›฿๖‘[{E‘ ”ฅำo‹ฒฺmท๚5‘�GฦํŒา>่„ห.VLtY3†h™ยณ€—๐7š€„ƒOrW~ๆ๗Œ(:ไฌสฦ่4ฐg�๐Idืฦ่นๅ�ย:„ต1DZWNT�ฅ†…ทL<ณเœ*!�†n… ž™B-ๆGึเf(œงฯNx1(5N/+ }ุ<>ฆๅ๛ีG‡hIๆจึ>พสฎ@ ขuาe๕Ž๒=ใ๗`kPษYู0�ืpTยงy1j Y น84SO—ใ PwขŸU๒พธ‘‡จ`�ธ5<$ƒ‰๎V˜~‹๘ู์ุๆขสZU�”4�iผ๊5@'Œƒ/- ๗„’ํข -ึค�ธ‡‰^(hฐฯ~ถ๖Vิ๊KN[ecธษแแ �กัฝ yฎ’9๙v•6Oำmฯา7‹๕™lตBถf(ฏ•ศ ม=q[SQeŒก�กื๋ML*์QฤŽ0a๐0QPืFYฃท›฿ษื*:คธฤ)c=*žฒืจXhJ๑yB ฏiPอ�๘๒n1dCl/+]๔\ฝ๓๚KสN๚Qj'l iKI‡Bีศาส•�๎-"1Do’7จ5ฎฌV9ธ่?ษฎ -oJโŸฉ‘)ก์FY�ศ๘้ไ‡ˆ๒V™oไ„ำ>zeb(v?_ฐไูhเ๘zํžNsๆeAMวย{G;ถk์.` ,�‘ปแœต`Ž\P<�่‰j์โ‰ชdาถ๑ฑ”jดจญ;ฃฌอบ์pqษ2ง@ซJ๔QŽ5์ธ๑@�๘าั๗SOฟ˜ไ‰6งŸ�r�็‰”ฮ�ื?’ccu”๔์>ย;+hl,จ3BvSeิภ’_กิ^†ZHึ~rOY…b‘†ก\(l๐ผ๗จ^6กรeš^m”3ZTฌMRึ™==ƒ–Wืdภฌจฐตฏ๖c๏ฺsBซ‘—ๆยYB`จ๖R™fnมPญ๔ึx†จ .w่9๓k$60ฤQ0ฒยwญ -ำ๎HwI yOฟ�yI|ษ�!ฃํH‘)Iy›Cู^เหบช`<|นๆ��KญฌืSa8ฟฟ`an*Ih{-v1TตcUษ๋ฝT5ว ฉ“fž๏ัeุ–ฝd(ฃ[ลฺ๊ขL(ฉ เ|H‘ะส๊โฝ5—e<ฟMR\;๐ตผI�w|ฯKJOฎจH•สBฃิnpยˆ๒x~ฅC‚]+ฮ——Iฦ�Ta€อ๕ึŽ�ฑฏกv†ั’Mf*ํ�n๐อt„ม™vกฏOฉdMJK%|IŠยm้’เ‘สW '>�๘šlค„๘Šทโฒแ|ไ[ย๋ๆภ5|X=ฎ/K6๘ฏ้ึ่~”{~โžฐ›1ุ|d[42์a#I ภ‰จ–-jˆฬhl&qV*˜etN},สปฐ�ฆ๓๙จA>&eขศ=L!ด6‰บR๎�็Zœ๓eฃ8ืฦ๓ษ™ \ˆ ๕z@*ะ‘AB#?รฯ{xTa้ต๖`ฆo™ฟS์๔ฎท3�%M –ัOj๕u|M๏ไ๒Lเ9Bฆ+๐DญFตC�ษ7TˆบยฦXšัRตP‚๒ฎ์ฐฉ๕^๗™BxJH๚Zaฒ^Qำ€ฟวแ8tlXี๋ฮMะ-uฤž2ฃฝf�>˜(…3bycˆ_ี’ธึ&์nจ,:�($ฤ๒AลŒ(†c๙ฅป %ศ] ฬ‡*R�:]5VH ลวขสDั-ๅิo”๗v‡e aW>ฅ‹๊;’Tฏฤ“ฌ๐šiOะ‘กgšl�ง˜ํดต�=�T่ะ„ด�ผ@ˆัญำnRๆขอ:�`Œ๖_,Gภก�ด นฤžDุN๎1hฃกำฐ฿‡ -ซญhƒ็ฦื5Sc~ีž X์FธE1n`เ/†Ž|—8l -์FnSiืฦํ—8ใO‘�‡ฦ&ๅ}ิ�Exำ๓�หh”qN ”BMšpPQˆคไ8`ง`šHึเำ‘ฉ†8b&Aslaืp/–�ฺYสณ๕tำ๚ฃ�D az+O™P™ŽๆุŽ„Z42ล)์jฃอ๒Žz?โFย๗ฮJ F8�Džb†|ก lฆ_Uกซud\rๅ$ฃ|ิ{ž�ฎนd๐Jg‘ฎู”�cํP|„fโ`c–\hฯlp‚ค “.ฮฎ`–ซŠ“]ูผ๙‘+จ‡;l[[ธgSƒQฝไ–?nุ)๚๕ึeฃ๊๒zR๊sƒณอฬ.€ศwb�ูำท\เŸo”XFTีH๋)‡"—ม"ž�›ฝz� +xœฝ=kฏทu฿�+ึWŠข๋+Q|“ใ8VlGu�,Š๊[ำ‘Q(‹Vั�G1ป;ณž��้ืŸพูฯmห}6“๗!„S๏eŒpn็…v๏›9lศฐim]h�‹฿OฃZ+อบฮดฌใผVฑว็๗พ> &a่kหeฐว06" P‹ร�K<ๆ;บ5๒๘)ฑƒไ^ƒC�๙:šภฃH๘Sg\#’Pฺ}"}ก:pF\�้๗ภ’ยอฑ7 ŽฟEj[oYศก?‚ฟ“ฦX{ŸK’Lน4DJิrๆ•๕๗šยœ>เธ�=Pe2๑๑ฏ ึ๑Œ6XFย—a8๛iŸฎ�E๖P4๖0Ÿ�ฎๆX†[ะ€EOwฆd]๕!ย^Dภ[฿" ๅฒ!H„hพ^UF๛ w•!X|j0n&LBs่๖:�J o1ต… ้๛šล0Oูค\ne1๗Rฬ”งe๏ํ)bำp€oFฏฤ ‚ภจE‘ฐ€:ด�•น�ภ‚‰ถ/ิใm1ถ8?ฐ/๚Q?ฎ่‡ห? +ิบโ}1มZWn@ญ|ˆ-˜เ ญGCธ�ั^ ฃฎษT*›๚ศ�๗ePvงะ“fฌ๙’œw�‰ๆBร…จ9+บdjHำ^z„*๚น~แ�Œ9ลก๙ธว“yq�จฌ&าีTgR™j�ค„M.‰X๑'V€ก/ฏ8iŒพz“Š�eŽไ),k6๏ฬM‰พ„‚๑€.X R >็ฉ฿ษ-เ๙%~ฺใฯ2ฐจAต‡�z‘๓=ถ๖7ฺ๕ฃยภๅ �’T.�o ฟาฐทh}<Ž€�LTอrZุ็`˜Q!„็ุ๒'œกE�ฺž+ 5�ฏ:ฌ†HŽtˆัVถŠศLD3‘ๅ\M*๑jถyะk�yศไDrJฦ†’ฆฒ"ม๑ึzM ยw‡F�/ศB‹๔ˆbๅGU<โ ฺƒ*2ษฺ?ญง้ส ;j%ธ”ว+-Ÿีษx�c�์„�ฝ^๛O˜CE�๓-ฐYzป๒]จํ’฿žม„ะิฮ*3อˆ–S4ฉ”๋…wŒอถแะพš๊’"!์ฟข?—ถdeฆ๋ ธfCญ�ท%W“WฺปศาPT`ห_บpฉึ ฎ็๗ฤDอaพf3…TSŸ˜บๆฐ๓ฺฆFP‹—ŸŠฑษ†�ิฌn�)ภธคลฏ7@็6ยีฑž(‚ึ–/^พt€C�<.@~hวf�ฐ›`�@ะร# E”ษQ-ชY.Z“ชณ้zาbUkBข]แว�x +?๊sลฦรธ'`๑Qc๏]๔์Kไh"ฦฒฺ-โๆ#ืฆมvย6�|:๑Š Dg[ใถๆขžBสแยSD d�ศ2ฃD$ุSŠw}˜ฒ7[้ฅํ4Šว๋ศPฃ� ซ8อ^ศ\H‹ฬ>›Tใี๗ฝนšเq*eใc™|ฺ๊bqKโ%‡คŒฉ3l–ฟqาjƒBŒ�[ฌี1ณ๔nฃ†qส๔ภธr4มMณผำฃ]เ:�˜yลv‹%„วS+ตŸ&S�ด‡`ฦ๛ท�#LJษมฦูv›o‚•%8vูม๕zU๐@ญฝ!XใS*q๗ษ…ท,9Lt i#บลรฑ๛ r๒ +ณ@|Rด˜ข�Hป ฤ$อžl๙๛€ึˆz,‚พ��:@ฅญบTS ๓&ีบ฿q�ตxŸRM ษณ-บtQ($Q8 ;v๔A 8ƒnาd๔—†ุ|ห‚๙?จดwีึ๔•"q+ย€฿๖•ฮผพส–iข3•ใq๏$S@ฯ*ฆ"ƒัจ…๖8`x]าˆถซYำTMš\ฺกํb„ษ'ใ| ซ�เ๏›–‰ป๊$�T่ท)"๐๛މ!Z]+ �™๘ABB;s—5Š˜nsฎฏาื;Y๕ฑเƒอ%๐ใ‚{ุคu‰(�d…+€ำšC๒EชeO“pK‰.R‰.|LˆljHG>๔U;๔5š4ฅ=ฤ–@๎าž5ภ๘Q"‹‘ณ�2Rฦใน�?๘xข้”„+?d\ฅM™ผb@Nนบ<�ฒอฝผซ`ูฤซ”€qศ~๎f=,” wูย โ฿แ8‚hAมji` € .&B Dj&tะymสำZ{~‘•�ฮ&๏ูื1›Ž฿~”>4$ฮ}sสท$[ฮ๗mA �๖•๔a’>้รืา‡ืา‡Ÿคw๙P๘ช-๊ฎท5w=TW…žจี'บ`’ต๕&วtฤ๒˜่Co-!†�4�—‹ธ jอ�mC O|๘ูEGZr8ต%p!‡ึ”l]�งก‘š…b-&_F`่บLvฅœฺฅอ๒ซตQัIํษWใcบเFฒ qช*/ษš2ฅv�bRV)HเโT�Zx@ŽƒรฦฑGำ๎*ะนูๆXย"บ๗NC0ี™iฒ9cz!��Kqจ5์๚FY8pu2!f—๖SภRŒTž๒ึš0ƒุฑg3‚h�Ž\ฎB2ažmฯ๚;f๗ศx#œ5ูMซฏv–�ล‰'ƒK&ื\๊MNใA™#<ฆXnฑว w๎๕๓ฑ�ํGณ–เ๐ฟปฏฐ.ฬกlO๒(ฆXฮU�ŒVAxชŒMืใˆa"jžฒ)ำด'7คŸtF �ทHฆ๋‘GกŒaซ๑๓&ฦฉโB _ซ}a—$ฒq`luJำŽ› ZC งง?ƒKคc•ึ™c วฐศ+�ไึ‚G S8Hแหคฐ#~ผ_ศ€ซq“้&i฿ ๓kG—b๔ฎขU™Mจrฟ๗ฆZฟรiVฮ”ื{™“ฉ)ๆ’๋pZ<ภฅๆ(A์ดฺดนMว\�L4jL}w� ล€G?žHห YLxžuuศ๐โDoT)ŒlEูHhGIhุณ฿2V8าภBฆ๚@)ฆบ)Ž��Rk�๗“ฦึะึ™ฌ,†๊lq.๔eณปม้e89 +ภ ,&˜qิ!„ญq1๕dV4šศ1BI TNถšj๓ŽขI0yฏกำ1 ‰Uaผˆฬ\ ฏfก&mั5ณ|~‘ผaa8ฬ๘Šq"4ฮrNฐจ๕�4ะท€ผัฤ{สก'๖�(๙์vtำY1Nzต ทกฤ,ƒถำZ๎2IM�ฬ�ุ๕ŸƒUˆ5ถฤMฮ9๘ืฑz๘"Z=ใศ“)>คx‹“N1๔dค์ึutฉ�‹$ั$ุ–งhชRน•เทดŒ‰�อ๑99ฎnY%dI^"ต�87™mŠK์™๕2‘1ฅ8}4u*%฿น‚ˆฯžวpKwx)กŽดหW™โaPฺj๊† ศ‹†€˜Ÿ$ะษX–ฬ™ญ'H๘อล‰&กŠ๔๒oJzI›'ciศ��eg”'ชผW3œ}M64ojแŠี›์๓;Ž๗้Œนuฑgฟช+๗!ฬ>ฦ ๗ูrสป/!ฟ28“ฦC0ึ•+LืเmฉK’ผRศ฿*:|ŒV่“ฑตคtrป]ศG‰๊ju2>Y๗ฃาๆ’k~ ฒ›CชR mm[mA6๓@ืQด%๏ว๖€rถชnฒ!งwUžG‘f9ฐ…‰,๕ณ‹=อ'v'\๔๏ำ‚๏ุญ�•�V๗๊๑๏�'ัSXcๆ_ึ๛๘IN*ถํrษๆฉัจิvฬo ;-ฑj๒€&yJi}š|kX‹ ถ่K๘ผ๖-‡‘ใฅีภŽn2ึ�=ฮ%~ศc\ƒZๆ'gj๒“pปa>9ใgq`!๒$~iณถO๖ผลh•ๅPญรล<;๖ฃ9ฬ}5![ไ ,$์R#!ม…Im™’™ขq๗พศl์ิl๙�ล2์๘๎‹Š OsเWภž-7ห๑อฑต „qญตžPง—ศา™แjตžง†๚1ยฦXFFบ;พฯฟB['าn<&,ญฮ<ี†[p(|P€]}น6@{bฏjแbั&c}�aทว˜Epทฦพลฦ�ี~„๏"&๗พ_4�&ฦ ํศ^,;.ร‘tภ๕า:Dr๑U\[แ-G๑r์<ึHf…ฮ�ˆ!.ิdผwถ\mˆณึ�_ n”ทBจTIš฿ ™ฌ๛0EV…hrLำูlุ$]goยแะ(Zxธ€ฏฏ[9—N๔]7คฟSเ]ฆ9 hฝqฤo+หฦ2๋9ฎ�สฐn +UึŠvจ +รฤ#ืj›dqn™ฌูTžะฌ;l–•UАZ5W`(ฮxฏ7ฃzเi M6ฉ!7��บ€Fล…ธย‘F“ˆ~ศ็€C/BOหVK�๚‰wชr ํยkง}<ภ‚ญไ›dJVฦผ๓8RH8އ” ศ๒แ92“ศ@ึศŽ�™rxƒ|0วไ4๐Laเ\�ขพฅƒdฃq1”ธŸ5่xลh‡Q…l-5คbผฏ;ฬfญ\ˆ=,l๊_‰&LSWื2†3‹hƒ’‡ธศ5m&"U๔`—NสO…น~Fผ ็ุ(หฤ์; oืฒษ.SรcZP™8ฤ\{ซ*‘�’฿ๅ–6}ัN` �๏Rถ๐๘Q9�Zlˆม๘เฎท!เxฟ6ฟ%9“ฆฉข7Jภ‚฿ฅM\รc‘รื์ิา G2mเ†฿RB@าwฝ๐x}๔‡3„�MI”ฮวฅภaTv @�ฆ–k๒ีเ€ฤ@ยg…ำ*‚poุƒพ/น+„)*ฏy่ฉ->ๅข0wn‰‘$ฮช•โ ~2>ค]ฅษxฟศq๙ะfไiƒๆb=&ณž_4�bฬw ส7�ูHลฅ๔Aไ๛0šŠ๏ฦาษอ`ฃz!ฯฏ2ŸC๙ ฆอ`!™{"ๅทอ/Fำฐ'฿žฺ๋๐  รน…V…‘plฮ&๋ญญApRF�r9ปฃW•ำฎ…แ—Œuฦ6 mฃค๗]ๅm‡�ั้Xš"„ํ!ื7tG"#+ซร�#:š/g`ฃ@jโœ!%ะy,Ÿ�.พv6Tู\&มษŽ˜็�”ๆR๓J†Žyy๚ึขจ€าyC๛�Dรณœ-ฆคP�˜cนฯsญ_ฮฯ}OสหT กdŽb�%=96;ค01!]ำ\่1ว8€ฎaf!ีๅภ๏xธz|ึ$›B�4ป#œ ๊A\ณFญศ<�ซ ว'ย๚วญดมด|์š้ศุ์‚˜ยฮRวSBNxC#ณ[ญŒู0ํ๑?Œธ,~�R๛๔|ธ>�๗ขสง jฌด:รžฒuฤ๚๔aXL(HBฮ“�4 R‘ใ‹�Kq|f‘—ะž„3qฆn่พ‘ŒYS‡ไ.Gx� จ้�sใ!ด3 ๛g +'�:ฏั I�n9“]ร�4มo 1~ห�>rioจ�;i‘>ฃ฿7ฤXมงwrฦฦd .๛ฟฺ0ัaช] +ฯWฤ฿xRz(ษ`ญv8{W�3๊ฆ๑ม›๊ๆ`�žu๏``  ๋น…๏ \RkqุwใrAฏœaซิธ์Fี!3ฅtบU6xa +ญ ˜gฎ—(\ฆฯN<3xAŒ'^Q>b๚ศu"๘–๏6ฆ%Ÿ7 ึง”๓์œอ6้S01fฏฆ๑‹C†ฺSj5>อ� @8ชแ๓ยIej`ฬow„šoฝ#5ฤjJŒSy^ถอ�ษมYFOลไไrธถD\mqn+`1:q๕f +ฅ|2Dฃฝ@8%%“ƒ2พผT�3สvศ&yWn€˜œ†‚�ํg[๏'mI�๛ฝ�๘œnsH@ญwˆ๛๑ชU๒ฎ);หช๙ถ'W้›ีอถฺ g ิŠืJำwHOฯFŠฅŽ1–/{ฝ�4aฅสž1๕้ๅฒ ๚YRฅ๖0อ5ชฏ/:0ž$ฬdSษธ VXฯ\ฑใ} Mฉ]žnซฺํ!ต๖gำR–:(ฦ๖จ +h0>๚‡ั R)MูะุŒ่}21อO4ํNบั ำa2�MS฿.๖์‚LRๅJh Fเrฏˆ\ไgnาว1๛ +๏@ฉTuf—าฺAจ-ฤ{ฒ้H๋ใ{ด~ฝ‘~8�M/š่ยงงUํ{ๅJแุ”ฯuฝ…ฏh†�9SN{tžญัจn2�Zg4Q�Tฎƒ‹ฎ๕bz’์ุธmสณT/๘Zจn๖h6Y๎•ฬ๎pŸ~๐ฐˆVฒV์Qc�Vมท*5u DƒัQ6ิ-†+WฯFoc/๕ฯ๑ ภศWlP`ŸB๖ฮj–=7ณฝบ>้ž p fฆRฎ-ฆ–โใฬcfžyธt~ ต- H//!„ŠŒข]0ฐแ@์ xO#žNิ…}CŽo"ฏY5Ÿใ.ป`YขอOฟ_ษ˜ าปิDูRd$ฃ ท–‚ขฅ๎๏ๅ„ะPc%ฐๅ7—็ _/Žm�~โ){๎ต†'[L๖ล๏็8qะฉ่4–Xƒ‰9\]‹๓W€าศ๗G 6&G�›bS*  qพj์dseE.Mˆ[กง}ย +Uก‘ฎy;ร9j!ws )ีฐ{‡จ ‘œ๊!rฬ3ฏ�ššBŽŸd_•คฃQ๏๋7‘ฆ�จใ๊ฝtq>�้๒JQาพi 3��หi๒๛๑๘B$QขŒใ[ถ{N$%Z>œฉ5 W์7้่n1ม€€ิ�้"„sถ:๒Hษฌฃ'ฑ‰‹งๅัิm“RHUำ�]žLฬe—ฟKœ™—T�์R ธN.Žu6ไ[Iรf�-ฯใฑZ๙}S^C…-ไ‡™Qา+FNAYœ!P@}ฏฺั‹0Fzฒ-ข2ึ’“แษ๖ž++qi2ลฉเN�ุ ^สค๑ญถd”1”žnE +ณPต๔”L,๖zๅQ&๕kยรฉh๘sB๘a2%ฅ\Hคฆ2Eใฎ z๐ง+™3P''“vัd2"ฐH@AWถวนฎฅฑ•๚hธžฦ6|'/จะO…vJฌ๕–?^๗Tข8FjBMqŸพํU�’ะลฺŠ๎„qL�G0ฤถ:ง%บ่L,qW้^bZFต๎โyส“๋—3ฬิ hŸ้hฅ็Xภ&๑คผ_wI๋Q�eešต“l็�Pถ๓ฮไโ๛Gทžอป๐ูๆw๗/ญ™k;–ไAญ‹ K{Tuล๚Kฝณ—Žีzฐ80ฌฉฯ�0ห์xฮรพวฐผ่e:ฯผยe'ใาTฆœ้ืึx;ล่�yฯo“AJพ–,�฿ษ=ฯ๙o XุๆสสกQศ+‘๘Yฤๆ8C๛ึภƒฯาZqm‰qp…ไzo  pumยว๎ุƒWฃRgฦyฏฑ“ูฐZโ๕&ส๋j'nุ…<ฝnŠwฅธ‘ "�–ๅ~฿ฦ8ฝZ9๑๑ŸฏลมFส}hŽqฬ7$r~[ย๋ๆ 5|ุ<ฎฌ�ท๔ ซ็ฏ�‡œส<~ุ้่uถV5ฐ๙Qlั<นdฆอ$5'ขZQูHL•t4ถeฎ—s^+—9“Kฝ�x๔dิW•‹q9fท๕Edฺ•๓ดแ&8/ \ฎฐ&Ipจ.5™Oฯšx{ศ H โ3\๑R�JF^[็.h๚ฃ๐wŽ›�๕vFบฃิ +๊Qk‡A]›Eำฝ’Yk —บ'ํftษQฝ0„ซฑ&Aิ•5ฦrRื2าหdru;Šg๖ž›�ฆT์ฅkป า@พลแ8|ไdำ+๑$&;aO…ั^ L*ฤนcDฺbWญ|คฎ•ฅ๚ช�dฃ+ว� ‚<Nd—แ6” ‹s5ิ$๘้:tห %Gj๋Ž™{-—%'“kฺc�˜ฃ‰ฅœ=ณ฿ฒœ`%~Xt่ึึถ�ฮ4ศใบผ:ˆ5๊5v9ฬA]๊cํๆ•tœg์ฉมd_mูฟ‹ŸO๚ฦTˆ~ ษุอศDh$๑ยvŠ`Aอ*€��"ฆb ž›ธ˜9„ง6ํ JSpXLDมŸ`เำต=„#_>ฮh€ย:L<ถฤ�KH๗+ถ‡ๆ�ฃz3 endstream endobj -274 0 obj -<> +283 0 obj +<> stream -xœญXKo1พ็WธR* Žk{ƒJ}x๔€ศrh#ยฉ+h๓�…ฒฑ๕ุ3qR.๋f;ž็7฿ุ;๛�็พ;?Ÿ�^}บfโโโ๒๚j๔—I&˜`Sษฌโฺ*%,sNqmฌdหวูRฐๅ3์yู.Lฐลำl%˜�ฐลjท{ณ,œ� !๎„nถซฒี๖๏Nยwk/bถซิ�UธษT -ลญฒFYฏGศ~ํ‚6�ึoฤึฌlE7�๎•Q”ว�VฯืiVยZRlx�}D“‰Qล�ฎ1ช�tา๊bzดŠๅYQม๛พฺPK�OXK ๒‘S q v• eชๅฉW“:ค@HํpSŒŠ‚R„IpCฤ"ํม`๘g์พ,€Y�๖ไ€า 7๙น๘<บYŒพnnฏfCn‘ท˜–k37๖xr!บฑๅfn“ฝค„ิงะค0™สฟห8,Wf#–๖m1ถ�ด.’]ฺ‘ถภฑ‘่้ƒๅ›ว์e•wjศหม"}Yณโ๙ ูๆ๑ฅฤ)ัพท+uœ>กž“iEš๒4CV""Z'hƒึ:�f-ฌ+Šx้ฝํ๓แ0ฉCฉื˜ิ›A— D?๚7 -งEั@ำpmตhŽฅ๗›ว[ะ\ญใฦฬ[g่ๆJลุ๘cมžŠP๎0%;สๅX[๏๏ Tฅ&4�ๅiŒ์Zธง„้ฬเyิ~วŽ๊dˆฐ# ม1ฃ‰ฮ=ศjษรกvCพGำU8]`ฒฎ`ฒืงฌXษู๑ยฉ^ONฃ๕n‡6JO;ฃไก)๒ะ‚kk>B˜HiS@ ฆๅญ›[G๓G"u} q7Y�าlข7j�’ตผ!NN*m˜@Kฑœธ[&wหn1ๆลๅ($5d�รต-qง15เIž–P%เฌ[จA6˜A้}B7ยํKข�ง•ขฏk0๔.k`+ลqUน‰0,Ž5 ฉ ษ๚่8Š&\UU๕pE๛วRt&-ืบ}ษ•่ช6\ -!Cฬ\ก,>‹น�Œ:฿<0ฃ=Y™Rึ�zท'š๖�๘๔ชะ๚h ‡าqY•L็รษพ๏8ั[4ภ๒ข!]tdฉi™สB€,)‹5ญ ~ํข๚หอพ�wฟฯ~u“ฌั#นm[ำT4šฺ๛ํ|‚ิฤฬlsWœโึ8QใJอะฤะช’6F.ฝฐเ๖`( ‘ฯ)ถŠ๋F๓‹อ�ฦG�Uw๓O๒v๐KX*žย[ˆ ๗๏€vœภNN๋q’๓— -rำ +xœญZKo7พ๛WฌS;‰’Šโ›ปEฃถS Eาช[�ClT=Eh�k-)ฮp†ปZ๙ฒ [รyqๆ›แpW�๛y๛๎�๊ำอOท|��๚๖ๆ์ฟF5ฒ‘อR5^ ใต–พ A ใผjพฌd๓๐ต‘อื‡ํู๕บ‘อ๚qต‘’ย5๋อau�Z๙๓๕”๒NJต7ผใ฿~๘=,–^ eLgใ;ผ Kb๔�ญ=ไฆ ถhจKษ๐>#฿AE ้Qj๙ำ+=z[๔ทใeธ…nกผhBVqnบL_GLy 8F9a๑ื๚็ณ๋ณ฿ฯ>|บYๅ1ฃŠ˜1}8�Nˆีดยฒ!๓bpก.RaฑTฝ Bˆส+ธ๋บง—wCคŠNิ%ว��๑�ฐ*FXŒ(“”ปๅ�ข ฟXe„sV?G.™ภ็Œษcท’Tั๚๑ไBySฬฤึˆกf"’˜$ŠNŠ”ำv<M ป\+Œ๋œ?มแ–FคdŸฯึ‰ฮwฮิ0ษภuS๘ณเ…\ฎžg‚,rฏจ‚“ +าH~ฑL–4yZuม,ฝœฆ|Ž�2 $ฐพ๊่ฝ"w—�ƒหส’qnx9ฟรƒพ;Ž`~ฦLจbพษlŒ +g0/๛‡่ซสA.บ~Yดษผ'กM�ธNœ_p๑’ึ1ม 5%ถ†%ึ +ใด'4B3R"๎ปbื—ส‹ฮ{็๖๖9๎‡ฒ9ดตk–Ÿ--‹5%0œ-†ซ-้ฑ>กf‰†3ึฑๆ?๑{U1ฦฒฎ�=‡ณๆกM] ์tcฌ8 R-x�„;ฮG�Vด๖–[~ี?n๚ว›ัP�0ก_ฌx�?~Dฆ๐้Fีua\ aŒฦ๛š6ข”ึศNถ“๚ปไ๗ฒน@Œ๑žก4)Y๎‘(ฦ{‘฿ยฮฒผb�Ÿีซ2aฮy�\ฝi`ฮ“#DP๔ธว`}[,M�ฃS์าใ}�ฐภี[$ูมcM”<์2ฤ‹�s6�>6RพAVCgGM!ฦ๏Rp=�%๒ีnŒ วญ1?Gๅ่2๖žอs_หsๅ… RฮOt�:9-ค•Šภh๘ vSj‰`พใš฿‘–6TypิQ�Gก1FยีhEั?ต?๒ณ~KvโQ’N6`he-*ส�ิ=B�|‰ถhH ˜vุ„ปๆขไs?ล•9gชอkBqฆešี ”฿Wธ(•QR9้ฑ1‘z™ฤํ�u@žา7„žH-L0n�ษ„7diฅ่\ื†œ๐ž๛นาา"ยcŠOน๑Gม;2ฉู‹ผ`xฮศ)fกธJณQฯฦŸ +๘D�b j\ึA,ฆvš›ฝGถ�ฐTxใ%ิ(-ลeูH"฿ ‰z๔8Œะo/่|๒fฯฯ…1ๆษ*็มž-‰�88๛ฏ‚%mK|� +ย)ท=คษ0^ษg”๐ฮh_๕ขrJ\$8€K1ง"ฤL0„Zวeรญศz๐หว๚,๋ฎ้้jฉnk‡3™Cำฮd•ำ์M€ัY5%ฑฆ<๚ณๆอBHึํ‡ใ1[N›าวลืuผใ๋฿ฆนสi�ะ4o3hศˆ;ศร@Wƒ`…iฅssqเ{โ๘พlƒp=ๆนjถ#ฒ&/>ล‰ปช@LฒณN(“Mฦฉ[U–ฏuxีุ‹ZCฤqฉอ‘ริ=ฯ†!Aฬ๔‚„žฃคRา0บฤฝหป(ึ]Dรัฆ. ƒร้:ฮ™ฯrDฤใ0=2ธLW;ฆlเ6n�kŸŒx/…iญ4sัร%P["qญhC็‡^s9 š ผๅๅ‡ส๕ƒ�ฮ๊ –ืฟ|เf,‡Hฌ(V~y ‚�9็N฿ยฑั๓่บnˆฏ t<ฎถq,ิ!QW`A~ัA๔c้ฏ–�ั<ฌz`ฤฆq`DKkH7ษ7i'#Ÿค3มธข +ูณํ ห šO(ฑ|ีพ%๑ึŸ๚� ภvBIฉขอ๕oิ -_‘H7œP|๖ภ�‘ณz…4,๏›ขcจk่๑๕‚f…ฎฮวๆHI[ึ@z@ล ฃ‰ญฎำL�bยŒ’ัทxย:nโ1—Ÿสฎ>~��๓๚๏ํข�Hฮ)แ�ึู๑Dำฃื ๘"งV5หYด๐.ศ ชL)š\ดย+Xๆ์Ž7� +ผๅต;*o๔ษ_ฮๅmมh™�š6มŽรื๘ล๑ภTบQ>}‹”Š๖jนพN�ษe! endstream endobj -275 0 obj +284 0 obj <> stream xœuฑJรPFOŒตUชvฌDœD@ค`]\ฺ @@ -1103,7 +1129,7 @@ F ฬตา8+ค/<ฐŠภโaญRkpยเุด๓AพmWำQ”Ih�ใŒ œ%–มl�ฝE5VW~ช�džต�X€์)๔ฯด�:ืบ๖๔Žb‘ˆk#&ผ_ยค 3๗0ฑ๗ ุI์ endstream endobj -276 0 obj +285 0 obj <> stream xœ}ฟKqฦ?ืU–X 94%MQKS†N๘#ิฆ๓�Q v�๗BšหกฉhˆFk ขูฦ๚‚ ! @@ -1111,20 +1137,20 @@ x ๔’0l+ฯฝ฿ฃศy7ฝฎำ;ฏืซษฅบ;QŽ?V.๘_๎tFภเ3LหEฦKถ)y ๐๋z”80eลIP๖คŸk๑‰ไT‹/%[ัp” ๅ:8ีม…�ถผ+%ฟ๗dŠฑะŒ"ย�Gฆท™ `d_ฟ{ูนูึ–gzž็m\‡ะ8rœฯSวiœ๚ตญ๖�fๆ๋ ดฝิ1\ํรศC�๓U`จ ีSท๔ฆฅ]ู จŸร@†oมฝ๖ ใโ_ฑ endstream endobj -277 0 obj -<> +286 0 obj +<> endobj -278 0 obj +287 0 obj <> stream -Typst 0.15.1en2026-08-02T00:27:40-03:002026-08-02T00:27:40-03:005application/pdfod6Ce8g5ofbkk30tkgkhhg==od6Ce8g5ofbkk30tkgkhhg==proof1.7 +Typst 0.15.1en2026-08-11T18:27:20-03:002026-08-11T18:27:20-03:005application/pdfJCSPa/4Mr2ZKVhRZ6582Sg==JCSPa/4Mr2ZKVhRZ6582Sg==proof1.7 endstream endobj -279 0 obj -<>/ViewerPreferences<>/Outlines 10 0 R>> +288 0 obj +<>/ViewerPreferences<>/Outlines 10 0 R>> endobj xref -0 280 +0 289 0000000000 65535 f 0000000016 00000 n 0000000101 00000 n @@ -1138,275 +1164,284 @@ xref 0000000840 00000 n 0000000906 00000 n 0000001109 00000 n -0000001771 00000 n -0000004169 00000 n -0000004955 00000 n -0000005909 00000 n -0000006007 00000 n -0000006078 00000 n -0000006139 00000 n -0000006206 00000 n -0000006288 00000 n -0000006361 00000 n -0000006435 00000 n -0000006517 00000 n -0000006589 00000 n -0000006673 00000 n -0000006745 00000 n -0000006863 00000 n -0000006933 00000 n -0000007003 00000 n -0000007148 00000 n -0000007216 00000 n -0000007288 00000 n -0000007406 00000 n -0000007537 00000 n -0000007605 00000 n -0000007733 00000 n -0000007805 00000 n -0000007875 00000 n -0000007945 00000 n -0000008055 00000 n -0000008123 00000 n -0000008195 00000 n -0000008265 00000 n -0000008335 00000 n -0000008405 00000 n -0000008475 00000 n -0000008545 00000 n -0000008615 00000 n -0000008685 00000 n -0000008839 00000 n -0000008911 00000 n -0000008983 00000 n -0000009083 00000 n -0000009155 00000 n -0000009225 00000 n -0000009295 00000 n -0000009365 00000 n -0000009435 00000 n -0000009505 00000 n -0000009575 00000 n -0000009645 00000 n -0000009715 00000 n -0000009785 00000 n -0000009956 00000 n -0000010026 00000 n -0000010104 00000 n -0000010224 00000 n -0000010291 00000 n -0000010406 00000 n +0000001820 00000 n +0000004250 00000 n +0000005044 00000 n +0000006086 00000 n +0000006240 00000 n +0000006311 00000 n +0000006372 00000 n +0000006439 00000 n +0000006521 00000 n +0000006594 00000 n +0000006668 00000 n +0000006750 00000 n +0000006822 00000 n +0000006906 00000 n +0000006978 00000 n +0000007096 00000 n +0000007166 00000 n +0000007236 00000 n +0000007381 00000 n +0000007449 00000 n +0000007521 00000 n +0000007639 00000 n +0000007770 00000 n +0000007838 00000 n +0000007966 00000 n +0000008038 00000 n +0000008108 00000 n +0000008178 00000 n +0000008288 00000 n +0000008356 00000 n +0000008428 00000 n +0000008498 00000 n +0000008568 00000 n +0000008638 00000 n +0000008708 00000 n +0000008778 00000 n +0000008848 00000 n +0000008918 00000 n +0000009072 00000 n +0000009144 00000 n +0000009216 00000 n +0000009316 00000 n +0000009388 00000 n +0000009458 00000 n +0000009528 00000 n +0000009598 00000 n +0000009668 00000 n +0000009738 00000 n +0000009808 00000 n +0000009878 00000 n +0000009948 00000 n +0000010018 00000 n +0000010088 00000 n +0000010158 00000 n +0000010228 00000 n +0000010298 00000 n 0000010515 00000 n -0000010633 00000 n -0000010703 00000 n -0000010775 00000 n -0000010845 00000 n -0000010915 00000 n -0000011029 00000 n -0000011117 00000 n -0000011185 00000 n -0000011253 00000 n -0000011339 00000 n -0000011425 00000 n -0000011505 00000 n -0000011591 00000 n -0000011679 00000 n -0000011764 00000 n -0000011857 00000 n -0000011954 00000 n -0000012009 00000 n -0000012078 00000 n -0000012171 00000 n -0000012336 00000 n -0000012421 00000 n -0000012562 00000 n -0000012671 00000 n -0000012812 00000 n -0000012905 00000 n -0000013006 00000 n -0000013061 00000 n -0000013234 00000 n -0000013416 00000 n -0000013542 00000 n -0000013796 00000 n -0000013869 00000 n -0000013942 00000 n -0000014044 00000 n -0000014124 00000 n -0000014197 00000 n -0000014274 00000 n -0000014376 00000 n -0000014451 00000 n -0000014572 00000 n -0000014647 00000 n -0000014768 00000 n -0000014882 00000 n -0000014962 00000 n -0000015090 00000 n -0000015218 00000 n -0000015354 00000 n -0000015434 00000 n -0000015562 00000 n -0000015690 00000 n -0000015818 00000 n -0000015898 00000 n -0000016026 00000 n -0000016154 00000 n -0000016282 00000 n -0000016362 00000 n -0000016490 00000 n -0000016618 00000 n -0000016750 00000 n -0000016830 00000 n -0000016903 00000 n -0000017024 00000 n -0000017097 00000 n -0000017218 00000 n -0000017348 00000 n -0000017428 00000 n -0000017554 00000 n -0000017680 00000 n -0000017806 00000 n -0000017886 00000 n -0000018057 00000 n -0000018168 00000 n -0000018240 00000 n -0000018312 00000 n -0000018386 00000 n -0000018458 00000 n -0000018530 00000 n -0000018602 00000 n -0000018674 00000 n -0000018746 00000 n -0000018920 00000 n -0000018992 00000 n -0000019084 00000 n -0000019156 00000 n -0000019235 00000 n -0000019307 00000 n -0000019379 00000 n -0000019451 00000 n -0000019523 00000 n -0000019598 00000 n -0000019670 00000 n -0000019742 00000 n -0000019897 00000 n -0000019998 00000 n -0000020072 00000 n -0000020144 00000 n -0000020216 00000 n -0000020327 00000 n -0000020437 00000 n -0000020512 00000 n -0000020595 00000 n -0000020669 00000 n -0000020741 00000 n -0000020813 00000 n -0000020885 00000 n -0000020957 00000 n -0000021102 00000 n -0000021175 00000 n -0000021246 00000 n -0000021317 00000 n -0000021388 00000 n -0000021460 00000 n -0000021532 00000 n -0000021604 00000 n -0000021774 00000 n -0000021848 00000 n -0000021920 00000 n -0000021992 00000 n -0000022064 00000 n -0000022136 00000 n -0000022208 00000 n -0000022280 00000 n -0000022352 00000 n -0000022424 00000 n -0000022496 00000 n -0000022687 00000 n -0000022761 00000 n -0000022833 00000 n -0000022905 00000 n -0000022977 00000 n -0000023052 00000 n -0000023124 00000 n -0000023259 00000 n -0000023333 00000 n -0000023405 00000 n -0000023508 00000 n -0000023582 00000 n -0000023654 00000 n -0000023726 00000 n -0000023798 00000 n -0000023870 00000 n -0000023942 00000 n -0000024014 00000 n -0000024089 00000 n -0000024161 00000 n -0000024233 00000 n -0000024435 00000 n -0000024510 00000 n -0000024583 00000 n -0000024656 00000 n -0000024727 00000 n -0000024800 00000 n -0000025200 00000 n -0000025563 00000 n -0000025600 00000 n -0000025637 00000 n -0000025690 00000 n -0000025743 00000 n -0000025795 00000 n -0000025845 00000 n -0000025897 00000 n -0000025950 00000 n -0000026003 00000 n -0000026056 00000 n -0000026179 00000 n -0000026313 00000 n -0000026447 00000 n -0000026570 00000 n -0000026693 00000 n -0000026842 00000 n -0000027409 00000 n -0000027617 00000 n -0000027769 00000 n -0000028644 00000 n -0000028855 00000 n -0000028995 00000 n -0000029211 00000 n -0000029450 00000 n -0000029610 00000 n -0000029816 00000 n -0000030029 00000 n -0000030157 00000 n -0000030285 00000 n -0000030413 00000 n -0000030541 00000 n -0000030669 00000 n -0000030752 00000 n -0000031389 00000 n -0000035839 00000 n -0000035920 00000 n -0000036713 00000 n -0000048023 00000 n -0000048103 00000 n -0000048878 00000 n -0000061414 00000 n -0000061491 00000 n -0000061922 00000 n -0000062394 00000 n -0000067750 00000 n -0000074317 00000 n -0000079777 00000 n -0000087012 00000 n -0000088036 00000 n -0000088379 00000 n -0000088786 00000 n -0000088899 00000 n -0000089972 00000 n +0000010584 00000 n +0000010660 00000 n +0000010783 00000 n +0000010850 00000 n +0000010965 00000 n +0000011074 00000 n +0000011192 00000 n +0000011262 00000 n +0000011334 00000 n +0000011404 00000 n +0000011474 00000 n +0000011588 00000 n +0000011676 00000 n +0000011744 00000 n +0000011812 00000 n +0000011898 00000 n +0000011984 00000 n +0000012064 00000 n +0000012150 00000 n +0000012241 00000 n +0000012326 00000 n +0000012419 00000 n +0000012516 00000 n +0000012571 00000 n +0000012640 00000 n +0000012733 00000 n +0000012898 00000 n +0000012983 00000 n +0000013124 00000 n +0000013233 00000 n +0000013374 00000 n +0000013468 00000 n +0000013570 00000 n +0000013626 00000 n +0000013800 00000 n +0000013982 00000 n +0000014108 00000 n +0000014366 00000 n +0000014439 00000 n +0000014512 00000 n +0000014614 00000 n +0000014694 00000 n +0000014767 00000 n +0000014844 00000 n +0000014946 00000 n +0000015021 00000 n +0000015142 00000 n +0000015217 00000 n +0000015338 00000 n +0000015452 00000 n +0000015532 00000 n +0000015660 00000 n +0000015788 00000 n +0000015924 00000 n +0000016004 00000 n +0000016132 00000 n +0000016260 00000 n +0000016388 00000 n +0000016468 00000 n +0000016596 00000 n +0000016724 00000 n +0000016852 00000 n +0000016932 00000 n +0000017058 00000 n +0000017184 00000 n +0000017312 00000 n +0000017392 00000 n +0000017465 00000 n +0000017586 00000 n +0000017659 00000 n +0000017780 00000 n +0000017910 00000 n +0000017990 00000 n +0000018116 00000 n +0000018243 00000 n +0000018370 00000 n +0000018450 00000 n +0000018621 00000 n +0000018733 00000 n +0000018805 00000 n +0000018877 00000 n +0000018951 00000 n +0000019023 00000 n +0000019095 00000 n +0000019167 00000 n +0000019239 00000 n +0000019311 00000 n +0000019486 00000 n +0000019558 00000 n +0000019650 00000 n +0000019722 00000 n +0000019801 00000 n +0000019873 00000 n +0000019945 00000 n +0000020017 00000 n +0000020089 00000 n +0000020161 00000 n +0000020233 00000 n +0000020305 00000 n +0000020460 00000 n +0000020561 00000 n +0000020635 00000 n +0000020707 00000 n +0000020779 00000 n +0000020890 00000 n +0000021000 00000 n +0000021075 00000 n +0000021158 00000 n +0000021232 00000 n +0000021304 00000 n +0000021376 00000 n +0000021448 00000 n +0000021519 00000 n +0000021753 00000 n +0000021826 00000 n +0000021897 00000 n +0000021969 00000 n +0000022041 00000 n +0000022113 00000 n +0000022185 00000 n +0000022257 00000 n +0000022429 00000 n +0000022503 00000 n +0000022575 00000 n +0000022647 00000 n +0000022719 00000 n +0000022791 00000 n +0000022863 00000 n +0000022935 00000 n +0000023007 00000 n +0000023079 00000 n +0000023151 00000 n +0000023223 00000 n +0000023298 00000 n +0000023370 00000 n +0000023442 00000 n +0000023514 00000 n +0000023763 00000 n +0000023837 00000 n +0000023912 00000 n +0000023984 00000 n +0000024056 00000 n +0000024128 00000 n +0000024200 00000 n +0000024338 00000 n +0000024412 00000 n +0000024484 00000 n +0000024587 00000 n +0000024661 00000 n +0000024733 00000 n +0000024805 00000 n +0000024877 00000 n +0000024950 00000 n +0000025023 00000 n +0000025096 00000 n +0000025173 00000 n +0000025246 00000 n +0000025319 00000 n +0000025535 00000 n +0000025610 00000 n +0000025683 00000 n +0000025754 00000 n +0000025826 00000 n +0000025900 00000 n +0000026466 00000 n +0000026829 00000 n +0000026866 00000 n +0000026903 00000 n +0000026956 00000 n +0000027009 00000 n +0000027061 00000 n +0000027114 00000 n +0000027166 00000 n +0000027219 00000 n +0000027272 00000 n +0000027325 00000 n +0000027448 00000 n +0000027582 00000 n +0000027716 00000 n +0000027839 00000 n +0000027962 00000 n +0000028111 00000 n +0000028678 00000 n +0000028886 00000 n +0000029038 00000 n +0000029913 00000 n +0000030124 00000 n +0000030264 00000 n +0000030480 00000 n +0000030719 00000 n +0000030879 00000 n +0000031085 00000 n +0000031298 00000 n +0000031426 00000 n +0000031554 00000 n +0000031682 00000 n +0000031810 00000 n +0000031938 00000 n +0000032021 00000 n +0000032658 00000 n +0000037108 00000 n +0000037188 00000 n +0000037976 00000 n +0000049040 00000 n +0000049121 00000 n +0000049901 00000 n +0000062507 00000 n +0000062584 00000 n +0000063015 00000 n +0000063487 00000 n +0000069039 00000 n +0000075653 00000 n +0000081181 00000 n +0000088562 00000 n +0000090324 00000 n +0000090667 00000 n +0000091074 00000 n +0000091187 00000 n +0000092260 00000 n trailer -<> +<> startxref -90159 +92447 %%EOF \ No newline at end of file diff --git a/docs/design.typ b/docs/design.typ index 38fa6fdb..2492329d 100644 --- a/docs/design.typ +++ b/docs/design.typ @@ -69,8 +69,11 @@ graphics when available.) *Effect* (out, queued): `spawn{pane, cwd}`, `write{pane, bytes}`, `resize_pty{pane, cols, rows}`, `open_link{url}`, `read_file{path}`, -`new_file{pane, serial}`, `set_clipboard`, `bell`, `quit`. The core never -performs IO; it asks. This is what makes the browser build honest instead of a +`new_file{pane, serial}`, `set_clipboard`, `read_clipboard`, `bell`, `quit`. +The core never performs IO; it asks โ€” and `read_clipboard` is the one ask with +an answer coming back, an ordinary `paste` event, or nothing at all when the +shell cannot read the clipboard (most terminals refuse the OSC 52 read). This +is what makes the browser build honest instead of a fork: a wasm shell simply answers `spawn` differently (or not at all) โ€” the core does not know. @@ -231,8 +234,11 @@ click-and-type; terminals get splice runs (shift right, never overwrite; absolute-row anchored), files get real edits. tty: raw pty forwarding (Ctrl-key toggle, default Ctrl-b, `--tty-toggle`), mouse still usable, promptClickMove on entry, prompts visible (hidden in the other modes via -OSC 133). `p` pastes the yank register; yank -mirrors out via OSC 52. +OSC 133). `y` fills the yank register and `p` pastes it; neither touches the +system clipboard, which is helix's five words โ€” `SPC y/Y/p/P/R`, out via +`set_clipboard` and back via `read_clipboard` โ€” and nothing else, so a delete +cannot clobber what the desktop was holding. A paste from an outer terminal +arrives bracketed, as one `paste` event. *Tag.* Live prefix (mode indicator, cwd or path) + editable tail with the full modal editor; defaults `New Del` / `Save New Del`; an image tag is @@ -263,8 +269,9 @@ the tag bar, the gutter and the move box; the selection colors stay fixed because they encode which button you pressed. `NextColor` browses the ring one step at a time โ€” at 228 it is no longer how you REACH one โ€” `Theme ` jumps to one and `ThemeSel` (`SPC t t`) lists them all into an -output buffer whose rows are those very commands โ€” so n/N EXECUTE each row -instead of looking it and stepping the list wears the themes. Colors toggles +output buffer whose rows are those very commands โ€” execute a row (Tab, middle +click) and the theme goes on; n/N select such a row WHOLE, since a command +line holds no place to pick out of it. Colors toggles all recolor passes; Debug stats overlay; Dump writes state ZON. *Web (replay viewer parity).* Embedded dump; focus, border/move drags, wheel, diff --git a/docs/helix-keys.md b/docs/helix-keys.md index e43bc6b4..214a1280 100644 --- a/docs/helix-keys.md +++ b/docs/helix-keys.md @@ -29,8 +29,8 @@ layer: gap offsets + ranges over the flat text). Differential harness: collapse) โ€” the checked-in helix goldens are the ground truth, verified case-by-case by `zig build hxdiff`. Motion-created ranges live in `pane.vsel` marked IMPLICIT (`vsel.explicit = false`); `v` extend mode, - `x`/`X`, terminal `n`/`N` (lookStep) and file `n`/`N` (searchStep) set - EXPLICIT ones. `d`/`c`/`y`/`~`/โ€ฆ act on the active selection either + `x`/`X` and `n`/`N` (the look-ring walk, `lookWalk`) set EXPLICIT ones. + `d`/`c`/`y`/`~`/โ€ฆ act on the active selection either way โ€” that is the point of the model. The pardes-specific chords (normal-mode Enter look / Tab execute) act on EXPLICIT selections only and fall back to the word under the @@ -55,7 +55,10 @@ Parity column (phase 5): **helix-verified** = matched field-by-field (text/mode/cursor/anchor) against the helix goldens by `zig build hxdiff`; **pardes-specific** = key helix leaves unbound (or a deliberate pardes binding) โ€” cannot mismatch a golden; **waived** = corpus-covered divergence -with a reason in `test/hxcases/waivers.jsonl`. +with a reason in `test/hxcases/waivers.jsonl`; **out of corpus** = helix's +own key and meaning, but the work leaves the core as an EFFECT the headless +differential has no shell to perform โ€” the clipboard commands, and nothing +else. | Key | Behavior (pardes today) | Notes / quirks vs helix | Parity | | --- | --- | --- | --- | @@ -80,9 +83,9 @@ with a reason in `test/hxcases/waivers.jsonl`. | `x` / `x` | select current line / extend one (n) line(s) down, char-range through the newline, cursor ON the `\n` | col-0 vim-ism removed (phase 5); matches `extend_line_below`, mode stays normal | helix-verified | | `d` | delete selection (implicit or explicit); bare cursor = the 1-wide selection | always yanks (`Alt-d` noyank in B); terminals: drops typed runs only | helix-verified | | `c` | change (delete + insert mode); linewise selections open a fresh indented line | same shape as `d` | helix-verified | -| `y` | yank selection; bare cursor yanks the 1-wide selection (char under cursor) | line-yank vim-ism removed (phase 5); yank keeps selection AND cursor (helix). Also emits `set_clipboard` (OSC 52 out) | helix-verified | +| `y` | yank selection; bare cursor yanks the 1-wide selection (char under cursor) | line-yank vim-ism removed (phase 5); yank keeps selection AND cursor (helix). Writes the DEFAULT REGISTER and nothing else โ€” the system clipboard is `SPC y`, which is helix's own split and so moves this row TOWARDS helix, not away: a `d` of one character can no longer clobber what the desktop was holding | helix-verified | | `u` / `U` | undo / redo | restores the pre-edit selection (helix); snapshot granularity, no `Alt-u`/`Alt-U` history walking (skipped) | helix-verified | -| `p` (normal) | paste the core's yank register after the selection | helix default-register semantics; yank still mirrors OUT via OSC 52 (`set_clipboard`) but `p` never reads the system clipboard back โ€” most terminals refuse the OSC 52 read, which left `p` a silent no-op | helix-verified | +| `p` (normal) | paste the core's yank register after the selection | helix default-register semantics, and only the register โ€” nothing on this path reads or writes the system clipboard. `SPC p` is the word that does, and on a tty its read is OSC 52, which most terminals refuse: an honest no-op there rather than a paste of the wrong text | helix-verified | | `Esc` (body normal) | clear a pending modal prefix / exit select mode, keeping the selection, then run `Last`: hop to the pane you were in before this one, whichever kind it was, exactly like `SPC j j` โ€” so held down it alternates between two panes, two files as readily as a file and its shell | Pardes-specific focus binding layered on helix's cleanup. A leader path, tag, topbar or search owns Esc while it is active; raw tty forwards it | pardes-specific (cleanup helix-verified) | | `Esc` (insert) | back to normal mode, cursor right after the insertion (no vim left-step) | | helix-verified | | `Enter` (normal) | acme **look** chord: EXPLICIT selection, else file-ish word under cursor | pardes-specific, keep (helix normal-mode Enter unbound). Covers helix `gf`. Implicit motion residue falls back to the cursor word | pardes-specific | @@ -92,9 +95,11 @@ with a reason in `test/hxcases/waivers.jsonl`. | `Ctrl-w` + `h/j/k/l`/arrows | directional pane focus prefix โ€” normal/tty modes only | pardes' own window handling (helix window mode skipped, section C). Runs the SAME `Left`/`Down`/`Up`/`Right` builtins `SPC w h/j/k/l` runs; kept alongside the leader because a pane in raw **tty** mode never sees `SPC` (the shell owns it), so this is the only keyboard way out of one. Insert mode owns `Ctrl-w` = delete-word-back, so a tag being TYPED into swallows it; from a tag in normal mode (`:`) it moves focus to the neighbour's BODY, while the bare letters `h/j/k/l` there move to its TAGLINE (next row) | pardes-specific | | `Alt-n` | new terminal below (any mode) | shadows helix `Alt-n` TS sibling-select โ€” skipped anyway (tree-sitter) | pardes-specific | | `Alt-c` | move active terminal to a fresh column (any mode) | helix `Alt-c` is change-noyank; the pardes window op wins (do-not-touch contract). `Alt-d` + `i` covers the behavior | waived (`alt-c-window-op`) | -| `Space` (normal, body) | the pardes LEADER: a key path from here runs a BUILTIN with no arguments โ€” the same builtins the topbar and the tags hold. `SPC k` Kill, `SPC d` Del, `SPC f s` Save, `SPC f n` New (an empty temporary file focused in the calling pane's column), `SPC f f` Find (fd over the pane's directory, results into `+Search`), `SPC f g` Grep (grep -R over the CONTENTS of every pane's directory, the ones another pane already covers dropped, rows relative to the asking pane's own directory, results into `+Search`; like Find it takes an ARGUMENT โ€” `Grep foo` executed, or a selection chorded onto the word, searches that and skips the input), `SPC h t` Tutor, `SPC c n`/`SPC c d` Newcol/Delcol, `SPC t d/c/n/r` Debug/Colors/NextColor/Crt, `SPC t t` ThemeSel (the whole theme ring as `Theme ` rows in an output buffer โ€” the one list whose rows are COMMANDS, so n/N execute each row instead of looking it and stepping is a live preview), `SPC t p/l/a` Petscii/Palette/Ascii (an image pane's renderer toggles โ€” the words its tag used to spell out, so the bar stays a bar), `SPC s d`/`SPC s r` Dump/Restore, `SPC w h/j/k/l` Left/Down/Up/Right (directional pane focus โ€” the `Ctrl-w` prefix's four moves as builtins), `SPC j o`/`SPC j i`/`SPC j j`/`SPC j l` Back/Forward/Last/Jumplist (the jump stack: walk it back, walk it forward, hop to the pane before this one โ€” what body-normal Esc runs โ€” and read the stack as a clickable buffer). `?` at ANY depth opens the Help builtin listing what the prefix can still reach (`SPC ?` = all, `SPC h ?` = the docs group), into a `+Help` output buffer. The pending path shows at the right edge of the active pane's tag; Esc โ€” or any unmapped key โ€” abandons it | helix spends Space on pickers/LSP (section C); pardes has neither, and acme's builtins are what a leader is for. Enum-derived: the paths, the Help lines and the execute dispatch all fold out of one `Builtin` enum at comptime. Normal mode on a BODY only โ€” tags are always insert, tty keys belong to the program | pardes-specific | -| `/` then `n`/`N` (any pane) | pardes' own plain-substring search into a `+Search` output buffer, n/N walk the result rows and look them (EXPLICIT selections) | KEEP, do not touch; not in the corpus (helix `/` is regex search) | pardes-specific | -| `n`/`N` (terminal panes, no search armed) | lookable-token motion over scrollback (EXPLICIT selections) | KEEP, do not touch | pardes-specific | +| `Space` (normal, body) | the pardes LEADER: a key path from here runs a BUILTIN with no arguments โ€” the same builtins the topbar and the tags hold. `SPC k` Kill, `SPC d` Del, `SPC f s` Save, `SPC f n` New (an empty temporary file focused in the calling pane's column), `SPC f f` Find (fd over the pane's directory, results into `+Search`), `SPC f g` Grep (grep -R over the CONTENTS of every pane's directory, the ones another pane already covers dropped, rows relative to the asking pane's own directory, results into `+Search`; like Find it takes an ARGUMENT โ€” `Grep foo` executed, or a selection chorded onto the word, searches that and skips the input), `SPC h t` Tutor, `SPC c n`/`SPC c d` Newcol/Delcol, `SPC y/Y/p/P/R` the five clipboard words (next row), `SPC t d/c/n/r` Debug/Colors/NextColor/Crt, `SPC t t` ThemeSel (the whole theme ring as `Theme ` rows in an output buffer โ€” rows that are COMMANDS rather than places, so a theme is previewed by EXECUTING one, Tab or a middle click; `n`/`N` do not run them, they step past to the next look-able text on the ring), `SPC t p/l/a` Petscii/Palette/Ascii (an image pane's renderer toggles โ€” the words its tag used to spell out, so the bar stays a bar), `SPC s d`/`SPC s r` Dump/Restore, `SPC w h/j/k/l` Left/Down/Up/Right (directional pane focus โ€” the `Ctrl-w` prefix's four moves as builtins), `SPC j o`/`SPC j i`/`SPC j j`/`SPC j l` Back/Forward/Last/Jumplist (the jump stack: walk it back, walk it forward, hop to the pane before this one โ€” what body-normal Esc runs โ€” and read the stack as a clickable buffer). `?` at ANY depth opens the Help builtin listing what the prefix can still reach (`SPC ?` = all, `SPC h ?` = the docs group), into a `+Help` output buffer. The pending path shows at the right edge of the active pane's tag; Esc โ€” or any unmapped key โ€” abandons it | helix spends Space on pickers/LSP (section C); pardes has neither, and acme's builtins are what a leader is for. Enum-derived: the paths, the Help lines and the execute dispatch all fold out of one `Builtin` enum at comptime. Normal mode on a BODY only โ€” tags are always insert, tty keys belong to the program | pardes-specific | +| `SPC y` `SPC Y` `SPC p` `SPC P` `SPC R` | helix's clipboard menu on helix's own letters: yank the selection to the system clipboard (`ClipYank`) or the PRIMARY selection alone (`ClipYankMain`), paste the system clipboard after (`ClipPaste`) / before (`ClipPasteBefore`) the selection, replace the selection with it (`ClipReplace`) | the ONLY five words in pardes that touch the desktop's clipboard โ€” `y`/`d`/`c`/`p`/`P`/`R` and the acme cut/paste chords are the internal register alone. Builtins rather than bare chords because a leader path names a builtin: they land in Help's index and are executable words like every other verb. One divergence: pardes keeps a single register VALUE where helix keeps one per range, so `SPC y` at N cursors joins them with newlines (`Pardes.setYank`, the divergence `msel-yank-paste` already waives). On a tty the write is OSC 52 out and the READ is OSC 52 back, which many terminals refuse or gate โ€” so `SPC y` works there and `SPC p` can be a no-op | out of corpus | +| a paste from the OUTER terminal | one `Event.paste`, spliced in at the cursor | the tty shell enables bracketed paste and coalesces `paste_start`..`paste_end` into a single event; before that the bytes arrived as individual key presses and normal mode RAN them, which is how a pasted `d` deleted a line. The bytes deliberately never enter the yank register โ€” clipboard and default register are separate stores in both directions | pardes-specific | +| `/` (any pane) | pardes' own plain-substring search into a `+Search` output buffer: the tag takes the pattern, Enter fills the buffer, and its rows are ordinary look targets | KEEP, do not touch; not in the corpus (helix `/` is regex search). The stepping half is the next row | pardes-specific | +| `n` / `N` (any pane) | MOTION, not a jump: move the SELECTION to the next / previous look-able text and open NOTHING. Enter โ€” the look chord โ€” on what it leaves selected is what opens it | KEEP, do not touch; not in the corpus (helix's `n`/`N` walk regex search hits). The text stepped is the largest whitespace-delimited run `look.resolve` can act on (`look.lookableSpan`, wrapper punctuation peeled off both ends), and the walk is a RING across PANES: every pane that has performed a Look, most recent first (`Pardes.look_src`), then the output buffers that have not, newest first, and only when both are empty the active pane. Exhausting a pane enters the next at its first (forward) / last (backward) span and the end wraps to the start, so `N` is the exact inverse of `n`. What it lands on becomes an EXPLICIT `vsel` with the cursor on its FIRST column, in the pane the walk focuses. ONE motion in every pane kind and every buffer kind โ€” a PDF steps the `+Search` buffer its own search filled, `n` to select the row and Enter to jump. The single thing a buffer may change is the GRAIN of what a step selects, and it changes it with one flag rather than a branch: `output_pane.Traits.commands` makes a step take the WHOLE LINE, because a command list (`ThemeSel`/`FontSel`) holds words to run and there is no path inside `Theme gruvbox` to pick out. Tab on what `n` selected wears the theme, which is the same middle click on the row is. `]d`/`[d` are helix's diagnostic motions, a different binding, and they do still jump to each diagnostic (`docs/lsp.md`) | pardes-specific | | insert: printable text | file: real edit; terminal: typed run splice | | helix-verified (file) | | insert: `Enter` | newline; keeps the current full indent levels and adds one 4-space logical tab when the text before the cursor ends in `(`, `[`, `{`, or `)` (including `})`) | plain lines match `insert_newline`; delimiter heuristic is pardes-specific | helix-verified (plain) / pardes-specific (delimiter) | | insert: `Backspace` (+ `Shift-Backspace`) | delete prev char, joins lines at col 0 | matches `delete_char_backward`; `Ctrl-h` alias in B | helix-verified | @@ -139,7 +144,7 @@ Phase 2 state added to `Pane`: `count` (accumulator, capped 0xffff), | Key | Behavior | Notes | Status | | --- | --- | --- | --- | | `r` | replace selection/char with ``, newlines kept | terminals: replaces the typed-run byte under the cursor if any, else no-op (`runByteAt`) | helix-verified (phase 5) | -| `R` | replace selection (or cursor char) with the yank register; pasted text becomes the selection, head on its last char | uses the INTERNAL yank (`p.yank`), no clipboard round trip; empty register = no-op; terminals: no-op | helix-verified (phase 5) | +| `R` | replace selection (or cursor char) with the yank register; pasted text becomes the selection, head on its last char | uses the INTERNAL yank (`p.yank`), no clipboard round trip โ€” `SPC R` is the system-clipboard twin; empty register = no-op; terminals: no-op | helix-verified (phase 5) | | `~` | switch case of selection/char, selection kept | terminals: run byte only | helix-verified (phase 5) | | `` ` `` | selection to lowercase | terminals: run byte only | helix-verified (phase 5) | | ``Alt-` `` | selection to uppercase | terminals: run byte only | helix-verified (phase 5) | @@ -276,8 +281,8 @@ text. | Key(s) | Helix behavior | Reason | | --- | --- | --- | -| `?`, `*`, `Alt-*` | rsearch / selection-as-pattern | search โ€” pardes has its own `/` n N (plain substring into an output buffer, kept as-is); helix regex search machinery not wanted | -| `Space` mode, all rows (`f F e . b j g G k s S d D r a h ' w c C Alt-c p P y Y R / ?`) | pickers, LSP actions, clipboard menu, global search, palette | helix's space mode is pickers + LSP + a clipboard menu, none of which exist here โ€” but the KEY is taken: pardes' own leader runs the acme builtins (section A). Clipboard: yank mirrors out via OSC 52, `p` pastes the register | +| `?`, `*`, `Alt-*` | rsearch / selection-as-pattern | search โ€” pardes has its own `/` (plain substring into an output buffer, kept as-is) and an `n`/`N` that SELECTS the next look-able text instead of walking match hits; helix regex search machinery not wanted | +| `Space` mode, all rows but the clipboard menu (`f F e . b j g G k s S d D r a h ' w c C Alt-c / ?`) | pickers, LSP actions, global search, palette | helix's space mode is pickers + LSP, neither of which exists here โ€” but the KEY is taken: pardes' own leader runs the acme builtins (section A). The clipboard menu is the half that DOES exist now: `y Y p P R`, helix's letters on helix's leader, in section A | | Popup `Ctrl-u`/`Ctrl-d`, Completion menu, Signature help tables | LSP popups | LSP | | Picker table (all rows), Prompt table (all rows) | picker / prompt internals | pickers โ€” pardes' tag line is its own one-line editor | | `gn` `gp` `ga` `gm` | next/prev/alternate buffer | buffer nav โ€” pardes panes aren't a buffer list | @@ -288,7 +293,7 @@ text. | `]f [f ]t [t ]a [a ]c [c ]e [e ]T [T ]x [x` | TS unimpaired jumps | tree-sitter | | `]g [g ]G [G` | git change jumps | needs VCS diff state | | `gd gD gy gr gi`, `=`, `]d [d ]D [D`, insert `Ctrl-x` | definition/refs/format/diagnostics/completion | LSP | -| `"` ``, insert `Ctrl-r` | register select / insert | registers โ€” single yank register only | +| `"` ``, insert `Ctrl-r` | register select / insert | registers โ€” one yank register and no way to name a second; the system clipboard is not spelled as a register here either, it is the five `SPC` commands in A | | `Q` / `q` | record / replay macro | macros โ€” needs replayable input log | | `Ctrl-i` `Ctrl-o` `Ctrl-s` (normal) | jumplist forward/back/save | jumplist | | `Alt-u` / `Alt-U` | undo-history earlier/later | history timeline โ€” linear snapshot u/U covers pardes | @@ -304,7 +309,7 @@ text. | `Z` (sticky view mode) | persistent view mode | marginal; `z` one-shots suffice | | `zm` (view) | align middle horizontally | marginal even with hscroll | | `.` | repeat last insert | **deferred by decision**: needs recording the insert session's keystrokes and a replay path โ€” a new subsystem; undo is whole-buffer snapshots with no edit log to piggyback on. Revisit after phases 2โ€“5 if the log exists by then for another reason | -| Select/extend mode section (prose) | `v` turns all motions into extenders, `n`/`N` keep selections | implemented for motions (phase 5: `pane.select` + the fixed anchor, differential-verified โ€” see the `v` row in A); helix's search-`n`/`N` extension doesn't apply (pardes `n`/`N` are its own search/look ops) | +| Select/extend mode section (prose) | `v` turns all motions into extenders, `n`/`N` keep selections | implemented for motions (phase 5: `pane.select` + the fixed anchor, differential-verified โ€” see the `v` row in A); helix's search-`n`/`N` extension doesn't apply (pardes' `n`/`N` is the look-ring motion, which REPLACES the selection with the span it lands on) | ## Differential testing (phase 5) diff --git a/docs/lsp.md b/docs/lsp.md index 097386e6..bce9b2cc 100644 --- a/docs/lsp.md +++ b/docs/lsp.md @@ -61,17 +61,20 @@ sub/file.zig:LINE:COL-ENDCOL text 1-based line and column. The second form carries the answer's RANGE where the protocol gave one on a single line (a token, a symbol's name), and a look on it SELECTS that span rather than parking at its first cell โ€” so -`gd` lands on the whole name and `gr` steps references with each one -highlighted. This is the format `look.zig` already resolves, `runSearch` -already produces and `n`/`N` already step โ€” so: +`gd` lands on the whole name, and a `gr` reference stepped to with `n`/`N` and +opened with Enter arrives with the reference itself selected. This is the +format `look.zig` already resolves, `runSearch` already produces and `n`/`N` +already walk โ€” so: - **one row from a goto** โ†’ jump straight there (`lookAt`) -- **several rows** โ†’ an output buffer, which `n`/`N` walk +- **several rows** โ†’ an output buffer, which `n`/`N` walk: a step SELECTS a row + and Enter opens it which means helix's multi-result picker required **no picker code at all**. The `+Search` buffer *is* the picker. Non-location answers (`hover`, `code_action`, -`format`) open `+Hover`/`+Lsp` instead and do not arm the stepper โ€” `n` over a -documentation blurb would step to nowhere. +`format`) open `+Hover`/`+Lsp` instead, which are prose and not places โ€” `n`/`N` +find nothing look-able in a documentation blurb and walk straight past it to the +next pane on the ring. Rename is deliberately the one exception to rows as presentation. The backend emits `@edit START END` records through `lsp.edit()`, using half-open byte @@ -98,7 +101,7 @@ chain says neither, and stops being true the moment the row is read anywhere but beside its own buffer. `test/snapshots/lsprelpath.snap` pins both directions end to end โ€” the enum one level up (absolute row) and one level down (`inner/tint.zig`, a stripped path that still has a separator in it), each with the `n` step that -opens it, plus a right click. +selects it and the Enter that opens it, plus a right click. This is the rule `look.grep` already follows for its own rows (`look.zig`, the `shown` computation), written a second time; the two are now the same function diff --git a/docs/macos.md b/docs/macos.md index 7f695000..ff19ff93 100644 --- a/docs/macos.md +++ b/docs/macos.md @@ -61,10 +61,12 @@ removing; it is the encoding being right. The one real difference is IO. The browser has no ptys, so `src/web.zig` forwards every effect out to JavaScript as a numbered code plus a byte payload, and JavaScript performs it. macOS has `forkpty`, `read` and `write` right there, -so effects never cross the boundary at all: `pardes_tick` drains the core's -effect queue and performs each one in Zig, the way `drainEffects` in -`src/tty/tty.zig` does. That is why the runtime struct is two callbacks and not -twelve. +so almost no effect crosses the boundary at all: `pardes_tick` drains the +core's effect queue and performs each one in Zig, the way `drainEffects` in +`src/tty/tty.zig` does. That is why the runtime struct is three callbacks and +not twelve โ€” and why two of the three are the clipboard: the pasteboard is +AppKit's, in both directions, and is the one piece of IO the Zig side cannot +reach for itself. ## The seam @@ -100,13 +102,20 @@ is made of and what opens a path from argv or the Dock (`Look `). it. `pardes_resize` also carries one cell in *physical* pixels, which only the native PDF placement path reads โ€” pass the backing-store size, not points. -**Runtime callbacks.** `pardes_runtime_s` is a `userdata` and two functions, +**Runtime callbacks.** `pardes_runtime_s` is a `userdata` and three functions, copied by value during init so the struct need not outlive the call. `wakeup` -means "your state moved, please pump me"; `set_clipboard` fires inside a tick -when the yank register changes, with the text borrowed for the duration of the -call. There is no `open_url` callback because the core already opens links -itself through `/usr/bin/open` (`src/look.zig`), and no file callbacks because -it owns the filesystem side too. +means "your state moved, please pump me". `set_clipboard` hands over text to put +on the pasteboard, borrowed for the duration of the call; it fires inside a tick +for the five `SPC` clipboard words and for the tag's own `y` chord, and for +nothing else โ€” an ordinary `y` or `d` writes the core's register and never +reaches here, which is what stopped deleting a character from clobbering the +desktop's clipboard. `read_clipboard` is that direction reversed: "give me the +pasteboard", with no payload either way, because the host answers by calling +`pardes_paste` โ€” and NSPasteboard being synchronous, that usually happens inside +the callback itself, before it returns. Both are main thread, inside +`pardes_tick`. There is no `open_url` callback because the core already opens +links itself through `/usr/bin/open` (`src/look.zig`), and no file callbacks +because it owns the filesystem side too. **Lifecycle.** `pardes_init` returns 0 or an opaque nonzero code, `pardes_deinit` tears down, `pardes_tick` drains pty output plus the effect @@ -195,11 +204,14 @@ already-Exec is the only case with nothing to do. The view also needs system's business and never arrives โ€” and the user needs "Force Click and haptic feedback" on in System Settings, which nothing in this process can read. -Twisting two fingers is a dial, and a dial over a list of search hits is `n`. -`pardes_rotate` takes raw degrees and libpardes quantizes them, one search step -per 10ยฐ, keeping the remainder โ€” the same accumulate-and-spend shape as -`pardes_scroll`, in Zig for the same reason: it is then unit-tested on a machine -with no trackpad. AppKit reports counterclockwise as positive and the forward +Twisting two fingers is a dial, and a dial over a list of look-able places is +`n`. A notch moves the SELECTION one place along and opens nothing; Enter opens +the one the dial stopped at, which is what makes the dial worth spinning at all +โ€” a stepper that opened every place it passed could not be. `pardes_rotate` +takes raw degrees and libpardes quantizes them, one step per 10ยฐ, keeping the +remainder โ€” the same accumulate-and-spend shape as `pardes_scroll`, in Zig for +the same reason: it is then unit-tested on a machine with no trackpad. AppKit +reports counterclockwise as positive and the forward step is clockwise, so the sign inverts here and nowhere else. The banked remainder is deliberate hysteresis; a gesture beginning passes 0 to clear it, so the first degree of a new twist cannot inherit a nearly-complete notch from the @@ -244,10 +256,11 @@ asserting the machine's timer jitter. Both halves are goldens. `rotate.snap` turns the dial at 4ยฐ per 100 ms (40ยฐ/s, under the floor) and asserts the screen is byte-identical across the release, then at 12ยฐ per 5 ms and asserts it is not. The list it walks is twenty-four -hits rather than three for a reason worth keeping: `n` at the last match has -nowhere to go, so on a short list the hardest possible flick and no flick at -all produce the same screen โ€” a golden that would have passed before momentum -existed. +places rather than three for a reason worth keeping, and `n`/`N` becoming a +RING only sharpened it: a short ring comes round, so a hard flick can stop +exactly where a single notch would have and the two screens agree โ€” a golden +that passes before momentum exists. Twenty-four is longer than the cap can +travel (about eleven), so the fling has nowhere to hide. ## A drop is a click plus Look @@ -306,8 +319,11 @@ the *word under the pointer* and most words resolve to nothing: and the screen does not move. The pulse still fires โ€” the gesture worked. - **Exec** (three fingers) on a builtin name runs it. On ordinary prose it types that word at a shell, which needs a terminal pane to type into. -- **`n`/`N`** (twist) steps a results buffer. With no `/pattern`, Grep or Find - behind it there is nothing to step. +- **`n`/`N`** (twist) moves the SELECTION to the next look-able place and opens + nothing; Enter opens what it landed on. It walks a ring across panes โ€” the + ones a Look came from first, then the output buffers none has โ€” so a twist + with no results buffer anywhere still steps the pane in front of you. A screen + with no filename on it is what has nothing to step. `PARDES_LOG=1` prints every decoded gesture to stderr โ€” the fingers counted, the stream it came in on, the button it resolved to, the pressure stage, the @@ -319,12 +335,13 @@ because guessing at that from a screenshot cost an afternoon. Every Exec and every Look taps the trackpad. The core arms a one-slot pulse in the ONE dispatcher โ€” `lookAt` and `execute`, the two functions a middle click, a -right click, Enter, Tab, a tag chord, `n`/`N` stepping and the `Look`/`Exec` -builtins all funnel into โ€” and the host takes it once per pump with -`pardes_take_haptic`. Exec gets `.generic`, the definite tap of something done; -Look gets `.alignment`, the lighter detent AppKit uses when a dragged guide -snaps. A pulse, not a queue: five Execs inside one keystroke are one thing the -hand did. +right click, Enter, Tab, a tag chord and the `Look`/`Exec` builtins all funnel +into โ€” and the host takes it once per pump with `pardes_take_haptic`. Exec gets +`.generic`, the definite tap of something done; Look gets `.alignment`, the +lighter detent AppKit uses when a dragged guide snaps. A pulse, not a queue: +five Execs inside one keystroke are one thing the hand did. A twist taps nothing +now that `n`/`N` only move the selection, and that is the honest report: the +detent belongs to the Enter that opens, and that is where it fires. Three details are load-bearing. `execute` arms only at `exec_depth == 0`, because `Exec ls` re-enters as `ls` and one Tab is one gesture however many @@ -672,7 +689,7 @@ zig build unit-test -Dplatform=macos That covers the ABI's Zig side, the effect drain, and the two quantizers the trackpad depends on โ€” `takeScrollTicks` and `takeRotationNotches` are pure -functions precisely so that "how many search steps is a 180ยฐ twist" is answerable +functions precisely so that "how many notches is a 180ยฐ twist" is answerable on a machine with no trackpad in it. The header is kept honest with ghostty's trick. `build.zig` runs `translate-C` diff --git a/src/builtins.zig b/src/builtins.zig index f207ed9f..39a147fa 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -107,7 +107,7 @@ pub const OutputTraits = struct { name: []const u8, steps: bool = false, jumps: bool = false, - executes: bool = false, + commands: bool = false, }; /// The enum: field name = struct name, value = index into `all()`. Everything @@ -297,12 +297,13 @@ pub const Shell = struct { }; /// ...and the list of what Theme takes, as a buffer you walk. Its rows are -/// `Theme ` COMMANDS rather than locations, so n/N execute them instead -/// of looking them (output_pane.Traits.executes) and stepping the list wears -/// each theme in turn โ€” the picker is the list, and there is nothing to -/// confirm because arriving already applied it. +/// `Theme ` COMMANDS rather than locations, which is one flag on the +/// buffer (output_pane.Traits.commands) and changes what a step SELECTS: the +/// whole line, since there is no path inside it to pick out. Tab on what n +/// selected wears that theme โ€” the same middle click on the row is โ€” so +/// walking the list with n/Tab is trying them on, and stopping is choosing. pub const ThemeSel = struct { - pub const output: OutputTraits = .{ .name = config.themes_buffer, .steps = true, .executes = true }; + pub const output: OutputTraits = .{ .name = config.themes_buffer, .steps = true, .commands = true }; pub fn run(c: Ctx) void { output_pane.openThemes(c.p, c.id) catch |err| c.p.reportError(c.id, "themes", err); } @@ -368,7 +369,7 @@ pub const Font = struct { /// unreadable one โ€” and this picker EXECUTES what it steps onto, so listing /// them would mean the list wearing one on the way past. See fonts.monospaced. pub const FontSel = struct { - pub const output: OutputTraits = .{ .name = config.fonts_buffer, .steps = true, .executes = true }; + pub const output: OutputTraits = .{ .name = config.fonts_buffer, .steps = true, .commands = true }; pub const enabled = pardes.font_picker; pub fn run(c: Ctx) void { if (comptime enabled) apply(c) else unreachable; @@ -455,6 +456,61 @@ pub const Ascii = struct { } }; +// ---- the system clipboard ---- + +// helix's `` clipboard menu, and the ONLY five words in pardes that +// touch the desktop's clipboard. Everything else โ€” `y`, `d`, `c`, `p`, `P`, +// `R`, the acme cut/paste chords โ€” lives entirely in the internal register, +// which is helix's arrangement and, less abstractly, the reason deleting a +// character no longer throws away whatever you had copied from a browser. +// +// They are builtins rather than bare chords because the leader table is the +// remapping surface and a leader path names a builtin: spelling them here +// puts them in Help's index, makes them executable words like every other +// verb, and costs no second mechanism. Their paths ARE helix's letters, on +// the same leader helix uses โ€” see config.leader_path. +// +// The two directions are not symmetric, and cannot be. Writing is a fire-off: +// the core owns the bytes and the shell copies them out. READING has to leave +// the core and come back โ€” SDL and NSPasteboard answer inside the same drain, +// a browser answers a promise later, and a terminal answers over OSC 52 or, +// far more often, refuses outright. So a paste is a REQUEST (the +// read_clipboard effect) that may simply never be answered, and a `SPC p` +// that does nothing in a locked-down terminal is the honest outcome rather +// than a bug to paper over with the internal register. + +pub const ClipYank = struct { + pub fn run(c: Ctx) void { + c.p.clipYank(c.pane, false); + } +}; + +/// helix `Y`: the PRIMARY selection alone, where `SPC y` joins every +/// cursor's. One cursor makes them the same word. +pub const ClipYankMain = struct { + pub fn run(c: Ctx) void { + c.p.clipYank(c.pane, true); + } +}; + +pub const ClipPaste = struct { + pub fn run(c: Ctx) void { + c.p.clipRequest(c.id, .after); + } +}; + +pub const ClipPasteBefore = struct { + pub fn run(c: Ctx) void { + c.p.clipRequest(c.id, .before); + } +}; + +pub const ClipReplace = struct { + pub fn run(c: Ctx) void { + c.p.clipRequest(c.id, .replace); + } +}; + // ---- panes and columns ---- pub const Save = struct { diff --git a/src/config.zig b/src/config.zig index 189d6a0e..d6d6813d 100644 --- a/src/config.zig +++ b/src/config.zig @@ -109,6 +109,20 @@ pub const leader_path = paths: { .Lspwhy = "lw", .Del = "d", .Kill = "k", + // THE CLIPBOARD MENU, on helix's own five letters and nowhere else. + // These are the only paths in the table that keep their helix spelling + // unprefixed, and they can: `y` `Y` `p` `P` `R` were free at the top + // level, and moving them into a group would have made the one thing + // here that IS helix's leader stop looking like it. + // + // Bare `y`/`p`/`P`/`R` remain the DEFAULT register โ€” that split is the + // whole design (see builtins.zig's clipboard section), and it is why + // an ordinary delete no longer reaches past the editor. + .ClipYank = "y", + .ClipYankMain = "Y", + .ClipPaste = "p", + .ClipPasteBefore = "P", + .ClipReplace = "R", // the `f` file group (spacemacs): Save left vim's `w` to join Find and // New here, which frees `w` for the window group (SPC w h/j/k/l). .Save = "fs", @@ -282,6 +296,27 @@ pub const tty_toggle_default: u21 = 'b'; /// means what Escape always means. pub const tty_toggle_alt: []const Chord = &.{.{ .cp = Key.escape, .shift = true }}; +/// What LEAVING raw tty mode hides on the shell's prompt rows. +/// +/// A prompt is CHROME. `user@host ~/src $` is redrawn on every keystroke, says +/// nothing a second time, and is never what you want to select, look at or +/// edit โ€” so blanking it is most of what turns a scrollback into a readable +/// document, and pardes has always done it (OSC 133 is how it knows). +/// +/// What it USED to take with it was the command you had typed at that prompt, +/// because the two share a grid row and the row was the unit. That command is +/// content: the one thing on the row worth keeping, and the thing you reach +/// for `b` to get at in the first place. OSC 133 marks the two separately โ€” +/// per CELL, not just per row โ€” so `.prompt` blanks the prompt's own cells and +/// leaves the input sitting in the COLUMNS it really occupies. Those columns +/// are not cosmetic: clicking the command in normal mode and pressing the +/// toggle carries the click into the shell's own cursor (promptClickMove), +/// which counts them. +/// +/// `.prompt_and_input` is the older behaviour, kept for anyone who wants a +/// terminal to read as output and nothing else. +pub const tty_blank: enum { prompt, prompt_and_input } = .prompt; + // ---- the tag line and the topbar ---- // The topbar is a HAND-PICKED subset in a fixed order, not a derivation: row 0 @@ -801,14 +836,17 @@ pub const select_regex: []const Chord = &.{.{ .cp = 's' }}; pub const split_regex: []const Chord = &.{.{ .cp = 'S' }}; // ---- edits ---- +// +// Every one of these reads or writes the DEFAULT register and only that. +// The system clipboard is five separate words on `SPC y Y p P R`, which is +// helix's split and the reason `d` cannot silently eat what you copied out of +// a browser. See leader_path above and builtins.zig's clipboard section. pub const delete: []const Chord = &.{.{ .cp = 'd' }}; pub const delete_noyank: []const Chord = &.{.{ .cp = 'd', .alt = true }}; pub const change: []const Chord = &.{.{ .cp = 'c' }}; pub const yank: []const Chord = &.{.{ .cp = 'y' }}; pub const replace_with_yank: []const Chord = &.{.{ .cp = 'R' }}; -/// helix: the DEFAULT register, not the system clipboard โ€” most terminals -/// refuse the OSC 52 read, so a round trip would never come back pub const paste_after: []const Chord = &.{.{ .cp = 'p' }}; pub const paste_before: []const Chord = &.{.{ .cp = 'P' }}; pub const switch_case: []const Chord = &.{.{ .cp = '~' }}; diff --git a/src/gui/gui.zig b/src/gui/gui.zig index 7e34a928..82866a30 100644 --- a/src/gui/gui.zig +++ b/src/gui/gui.zig @@ -2473,10 +2473,19 @@ fn dispatch(g: *Gui, core: *pardes.Pardes, sev: *const c.SDL_Event) void { while (tptr[tlen] != 0) : (tlen += 1) {} if (tlen == 0) return; const text: []const u8 = tptr[0..tlen]; - const cplen = std.unicode.utf8ByteSequenceLength(text[0]) catch return; - if (cplen > text.len) return; - const cp = std.unicode.utf8Decode(text[0..cplen]) catch return; - core.update(.{ .key = .{ .cp = cp, .text = text[0..cplen], .ctrl = g.live_ctrl, .alt = g.live_alt } }); + // ONE event is not one codepoint. An IME commit arrives whole โ€” + // the entire phrase the candidate window was holding โ€” and so does + // anything composed (dead keys, `Ctrl-Shift-u`, a compose-key + // sequence that resolves to more than one scalar). Decoding only + // text[0] dropped the rest on the floor, silently. Validate the + // whole string first so a truncated or malformed sequence costs + // nothing rather than half a phrase already forwarded. + const view = std.unicode.Utf8View.init(text) catch return; + var it = view.iterator(); + var at: usize = 0; + while (it.nextCodepoint()) |cp| : (at = it.i) { + core.update(.{ .key = .{ .cp = cp, .text = text[at..it.i], .ctrl = g.live_ctrl, .alt = g.live_alt } }); + } }, c.SDL_EVENT_MOUSE_BUTTON_DOWN, c.SDL_EVENT_MOUSE_BUTTON_UP => { const b = sev.button; @@ -2959,6 +2968,19 @@ fn drainEffects( defer gpa.free(z); _ = c.SDL_SetClipboardText(z.ptr); }, + .read_clipboard => { + if (g == null) continue; + // SDL answers synchronously, so the paste the core is waiting on + // lands inside this same drain โ€” nothing to remember, no reply + // path to plumb. SDL3 hands over an OWNED copy that is ours to + // SDL_free, and reports "no text" as an EMPTY string rather than + // null, so the length check is what actually rejects a miss. + const raw = c.SDL_GetClipboardText() orelse continue; + defer c.SDL_free(raw); + const text = std.mem.span(raw); + if (text.len == 0) continue; + core.update(.{ .paste = text }); + }, .lsp => |e| if (threads_ok) spawnLsp(core, queue, e), .pipe => |e| if (threads_ok) spawnPipe(core, io, gpa, queue, pipe_tasks, e), .watch => |w| { @@ -3010,6 +3032,15 @@ fn drainEffectsWeb(core: *pardes.Pardes, gpa: std.mem.Allocator, g: *Gui) void { defer gpa.free(z); _ = c.SDL_SetClipboardText(z.ptr); }, + .read_clipboard => { + // emscripten fills SDL's clipboard only from a real paste gesture, + // so an empty answer here is the ordinary case and not a failure. + const raw = c.SDL_GetClipboardText() orelse continue; + defer c.SDL_free(raw); + const text = std.mem.span(raw); + if (text.len == 0) continue; + core.update(.{ .paste = text }); + }, // look on a URL โ†’ a new tab .open_link => |url| openLinkWeb(gpa, url.slice()), // nothing to spawn/write/resize/save/dump into, and no filesystem to diff --git a/src/look.zig b/src/look.zig index 7169cf8b..36390ec2 100644 --- a/src/look.zig +++ b/src/look.zig @@ -225,6 +225,82 @@ test ".pdf Look paths are ordinary files when MuPDF is disabled" { } } +/// Where a look-able word actually SITS inside a run of non-whitespace. +pub const Span = struct { start: usize, end: usize }; + +/// The punctuation a path wears in prose and never owns. Two sets, because +/// the two ends are not alike: a directory may legally END in `/`, and the +/// `:` that closes `grep -n`'s `main.zig:100:` is junk on the right and +/// meaningful nowhere on the left. +const lead_trim = "([{<\"'`*"; +const trail_trim = ")]}>\"'`*,;:.!?"; + +/// The largest look-able span inside one whitespace-delimited `word`, or null +/// when nothing in it resolves. This is the whole heuristic behind n/N: split +/// on whitespace, and take the biggest piece of each run that Look can act on. +/// +/// TWO resolve attempts at most, which is what keeps a motion across a +/// screenful of prose from being a hundred realpaths: the run with every +/// wrapper character peeled off BOTH ends at once, then โ€” only if that found +/// nothing โ€” the run exactly as written. +/// +/// PEELED FIRST, which is the ordering that matters. `resolve` is lenient +/// about a tail it cannot parse (`main.zig:12:3,` yields the FILE and drops +/// the position, by design), so asking it about the raw run first would +/// happily answer yes and swallow the comma along with the `:3`. Peeling +/// first hands it `main.zig:12:3` and the look lands on the column. The raw +/// run stays as the fallback for the file genuinely named `foo,` or `..`, +/// where the peel eats something real. +/// +/// Deliberately NOT a search for the longest resolving substring: that costs +/// a syscall per prefix to find a path hiding inside a word nobody typed as +/// one. A run needing a cleverer peel is still one Enter away with the cursor +/// parked on it. +/// +/// Direction-free on purpose: n and N ask this the same question about the +/// same run and get the same span back, which is what lets the two motions be +/// exact inverses of each other. +pub fn lookableSpan(word: []const u8, cwd: []const u8, realbuf: *[4096]u8) ?Span { + if (word.len == 0) return null; + var lo: usize = 0; + var hi: usize = word.len; + while (lo < hi and std.mem.indexOfScalar(u8, lead_trim, word[lo]) != null) lo += 1; + while (hi > lo and std.mem.indexOfScalar(u8, trail_trim, word[hi - 1]) != null) hi -= 1; + if (lo < hi and resolve(word[lo..hi], cwd, realbuf) != .none) return .{ .start = lo, .end = hi }; + // nothing came off, so the peeled attempt WAS the raw one + if (lo == 0 and hi == word.len) return null; + if (resolve(word, cwd, realbuf) == .none) return null; + return .{ .start = 0, .end = word.len }; +} + +test "lookableSpan peels prose punctuation off a path, largest first" { + if (!platform_has_fs) return; + var realbuf: [4096]u8 = undefined; + // the bare run resolves whole, wrappers and all left alone + try std.testing.expectEqualDeep( + @as(?Span, .{ .start = 0, .end = "src/look.zig".len }), + lookableSpan("src/look.zig", ".", &realbuf), + ); + // ...and a wrapped one gives back the span INSIDE the wrappers + try std.testing.expectEqualDeep( + @as(?Span, .{ .start = 1, .end = 1 + "src/look.zig".len }), + lookableSpan("(src/look.zig),", ".", &realbuf), + ); + // the `:LINE:COL` tail is part of the span: it is what a look READS + try std.testing.expectEqualDeep( + @as(?Span, .{ .start = 0, .end = "src/look.zig:12:3".len }), + lookableSpan("src/look.zig:12:3,", ".", &realbuf), + ); + // grep -n's trailing delimiter comes off, the line number stays + try std.testing.expectEqualDeep( + @as(?Span, .{ .start = 0, .end = "src/look.zig:12".len }), + lookableSpan("src/look.zig:12:", ".", &realbuf), + ); + try std.testing.expectEqual(@as(?Span, null), lookableSpan("nothing-here", ".", &realbuf)); + try std.testing.expectEqual(@as(?Span, null), lookableSpan("", ".", &realbuf)); + try std.testing.expectEqual(@as(?Span, null), lookableSpan("((()))", ".", &realbuf)); +} + /// Resolve a looked-at word against the pane's directory. `realbuf` must /// outlive the returned Target (native paths point into it; web paths are /// process-lifetime slices in the embedded source archive). diff --git a/src/macos.zig b/src/macos.zig index ef68d7e7..dce136f4 100644 --- a/src/macos.zig +++ b/src/macos.zig @@ -122,14 +122,15 @@ pub const Image = extern struct { rgba: [*]const u8, }; -/// Sync with: pardes_runtime_s. Two callbacks, because everything else the +/// Sync with: pardes_runtime_s. Three callbacks, because everything else the /// core asks for it already does itself โ€” it owns the ptys, and look.openLink -/// hands URLs to /usr/bin/open. Both are optional at the ABI level: a host that +/// hands URLs to /usr/bin/open. All optional at the ABI level: a host that /// passes null simply does without, rather than trapping inside the library. pub const Runtime = extern struct { userdata: ?*anyopaque = null, wakeup: ?*const fn (?*anyopaque) callconv(.c) void = null, set_clipboard: ?*const fn (?*anyopaque, [*]const u8, usize) callconv(.c) void = null, + read_clipboard: ?*const fn (?*anyopaque) callconv(.c) void = null, }; const color_default: u32 = 0x01000000; @@ -1127,6 +1128,16 @@ fn drainEffects(st: *State, threads_ok: bool) bool { const y = core.yank orelse continue; cb(st.runtime.userdata, y.ptr, y.len); }, + // The host answers with pardes_paste, which the AppDelegate calls + // straight back inside this call: NSPasteboard reads are + // synchronous, so the paste event lands here, mid-drain. That is + // safe and deliberate โ€” pardes_paste only feeds core.update, and + // whatever that queues is picked up by this same loop rather than + // waiting a tick. A host with a null callback simply never pastes. + .read_clipboard => { + const cb = st.runtime.read_clipboard orelse continue; + cb(st.runtime.userdata); + }, // An empty answer, immediately: the honest reply from a shell with // no worker, and the only safe one. Tab after a `.` DIVERTS to the // backend instead of indenting and indents late, when the answer diff --git a/src/macos/Sources/AppDelegate.swift b/src/macos/Sources/AppDelegate.swift index cda35ff0..077367a4 100644 --- a/src/macos/Sources/AppDelegate.swift +++ b/src/macos/Sources/AppDelegate.swift @@ -162,6 +162,15 @@ final class AppDelegate: NSObject, NSApplicationDelegate, PardesViewDelegate { let pasteboard = NSPasteboard.general pasteboard.clearContents() _ = pasteboard.setString(yank, forType: .string) + }, + read_clipboard: { _ in + // Also the main thread, also inside pardes_tick โ€” but this one + // answers immediately: NSPasteboard reads are synchronous, so + // the paste lands back in the core before this call returns. + // No pump, deliberately: the tick that emitted the effect is + // still draining and picks up whatever the paste queued. + guard let text = NSPasteboard.general.string(forType: .string) else { return } + AppDelegate.paste(text) }) // The real grid, never a placeholder: the core holds each shell's @@ -590,12 +599,19 @@ final class AppDelegate: NSObject, NSApplicationDelegate, PardesViewDelegate { func pardesViewRequestsPaste(_ view: PardesView) { guard let text = NSPasteboard.general.string(forType: .string) else { return } - // Swift lends a temporary NUL-terminated UTF-8 buffer for the duration - // of the call, which is exactly as long as the core borrows it. - pardes_paste(text, text.utf8.count) + AppDelegate.paste(text) pump() } + // Swift lends a temporary NUL-terminated UTF-8 buffer for the duration of + // the call, which is exactly as long as the core borrows it. Static, and + // pumping is the caller's business: the read_clipboard callback is a C + // function pointer that can capture nothing and is already inside a tick, + // where the gesture path is not. + private static func paste(_ text: String) { + pardes_paste(text, text.utf8.count) + } + // ponytail: one window, no tabs โ€” the core has no multi-window notion, so // the last window closing really is the end of the process. func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { diff --git a/src/macos/pardes.h b/src/macos/pardes.h index 1591130e..9a64501a 100644 --- a/src/macos/pardes.h +++ b/src/macos/pardes.h @@ -129,7 +129,7 @@ typedef enum { // ---------------------------------------------------------------- runtime -// What the host lends the core. Two callbacks, because everything else the +// What the host lends the core. Three callbacks, because everything else the // core wants done it already does itself: it owns the ptys, and it opens URLs // through /usr/bin/open. Copied by value during pardes_init, so the struct // need only outlive that call. @@ -145,6 +145,11 @@ typedef struct { // The yank register changed. `text` is borrowed for the duration of the // call only. Main thread, inside pardes_tick. void (*set_clipboard)(void *userdata, const char *text, size_t len); + + // Ask the host for the system clipboard. The host answers by calling + // pardes_paste, which may be synchronous inside this call. Main thread, + // inside pardes_tick. + void (*read_clipboard)(void *userdata); } pardes_runtime_s; // ---------------------------------------------------------------- lifecycle diff --git a/src/output_pane.zig b/src/output_pane.zig index 8ff98845..37ec6033 100644 --- a/src/output_pane.zig +++ b/src/output_pane.zig @@ -83,19 +83,27 @@ pub const Traits = struct { /// look path resolves, so the buffer IS helix's picker. Prose (a hover /// blurb, a formatting diff) has nowhere to step to. steps: bool = false, - /// ...and what a step DOES with the row it lands on. Off, the row is a - /// LOCATION and its leading word is LOOKED. On, the row is a COMMAND LINE - /// and the whole of it is EXECUTED โ€” so walking the list runs each row in - /// turn, which is what makes a picker over things that take effect - /// immediately (ThemeSel) a plain list of the words you would have typed. - /// Both go through the ordinary builtin (config.look_cmd / exec_cmd), so a - /// row does exactly what the matching mouse button on it would. + /// ...and WHAT THE ROWS ARE. Off, each is a LOCATION with a look-able + /// `path:LINE:COL` word inside it. On, each is a COMMAND LINE โ€” the whole + /// row, exactly as you would have typed it (ThemeSel's `Theme gruvbox`) โ€” + /// with no path in it to pick out. + /// + /// TWO readers, one fact, which is why the column is named for the fact: + /// n/N (lookWalk) select the look-able span inside a location row, and + /// THE WHOLE LINE of a command row, since the line is + /// the unit there. Either way they only select; Enter + /// looks what they left, Tab runs it. + /// searchStep Looks a location row's leading word and Execs a + /// command row whole โ€” still how `]d`/`[d` and acme's + /// button-3 arrive somewhere in one gesture. + /// Both go through the ordinary builtins (config.look_cmd / exec_cmd), so + /// a row does exactly what the matching mouse button on it would. /// /// Nothing about this is output-pane specific, which is why it is a column - /// here and not a branch in searchStep: `file_row` answers it too, so a + /// here and not a branch in either reader: `file_row` answers it too, so a /// file pane whose lines happen to be commands is one word away from /// behaving the same. - executes: bool = false, + commands: bool = false, /// an answer of exactly ONE row jumps straight there instead of opening /// this buffer at all โ€” helix: the gotos jump on a single location and /// show a picker on several, a symbol list is always a picker. @@ -129,7 +137,7 @@ pub fn traits(o: Origin) Traits { .name = meta.name, .steps = meta.steps, .jumps = meta.jumps, - .executes = meta.executes, + .commands = meta.commands, }; }, .query => |k| switch (k) { @@ -358,10 +366,10 @@ pub fn openJumps(p: *Pardes, id: usize) !void { /// The ThemeSel builtin: the theme ring written out as one `Theme ` row /// per theme โ€” the ordinary builtin with its argument, exactly the line you -/// would type โ€” into a buffer whose `executes` trait makes n/N RUN each row -/// rather than look it. So walking the list is trying the themes on, and -/// stopping on one is choosing it; there is no picker mode, no preview state -/// and nothing to commit or cancel, because every step already did the thing. +/// would type โ€” into a buffer whose `commands` trait says the rows are words +/// and not places. n/N therefore select each row WHOLE and Tab runs it, so +/// walking the list is trying the themes on and stopping on one is choosing +/// it: no picker mode, no preview state, nothing to commit or cancel. /// /// The command's own name comes from the builtin rather than a literal: the /// word is derived from the struct in exactly one place (builtins.word), and a diff --git a/src/pardes.zig b/src/pardes.zig index f95b4e69..ae6c4cbc 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -373,8 +373,17 @@ test "MuPDF pane renders, navigates, searches, and round-trips its page" { const results_id = pane.search_pane orelse return error.MissingPdfSearchResults; const results = p.panes[results_id].?.file.?.content; try std.testing.expect(std.mem.indexOf(u8, results, "design.pdf:") != null); + // n SELECTS the first result row and opens nothing: the walk's only list + // here is the unlooked +Search buffer, so focus lands THERE. Enter is what + // jumps, and the document query survives both. p.update(.{ .key = .{ .cp = 'n' } }); - try std.testing.expect(pane.search_row != null); + try std.testing.expectEqual(results_id, p.active); + const results_pane = p.panes[results_id].?; + try std.testing.expect(results_pane.vsel.active and results_pane.vsel.explicit); + try std.testing.expectEqual(@as(i32, 0), results_pane.cur_row); + try std.testing.expectEqual(@as(i32, 0), results_pane.cur_col); + p.update(.{ .key = .{ .cp = Key.enter } }); + try std.testing.expectEqual(@as(usize, 0), p.active); try std.testing.expectEqualStrings("Pardes", pane.pdf.?.search_query); // Search state is owned and untruncated, and changing pages invalidates @@ -1255,7 +1264,7 @@ test "PDF builtins and leader paths follow the MuPDF feature gate" { const traits = output_pane.traits(.{ .cmd = maybe_sections.? }); try std.testing.expectEqualStrings(config.pdf_sections_buffer, traits.name); try std.testing.expect(traits.steps); - try std.testing.expect(!traits.executes); + try std.testing.expect(!traits.commands); const help_row = for (builtin_rows) |row| { if (row.cmd == maybe_sections.?) break row; } else return error.MissingPdfSectionsHelpRow; @@ -1431,11 +1440,17 @@ test "PdfSections output, Look, and n/N share exact cached outline destinations" try std.testing.expectEqual(outline_ptr, pdf_pane.pdf.?.outline.?.entries.ptr); try std.testing.expectEqual(output_revision, p.panes[output_id].?.file.?.revision); - // n and N execute the generated row through ordinary Look. The root and - // child intentionally resolve to the same exact XYZ destination. + // n SELECTS the generated row and Enter runs it through ordinary Look, so + // the pair is one step of what used to be one keypress. The look is made + // FROM the sections buffer, which is what keeps that buffer at the head of + // the walk: the next n resumes there even though the jump left focus on + // the PDF. The root and child intentionally resolve to the same exact XYZ + // destination. p.active = 0; p.update(.{ .key = .{ .cp = 'n' } }); - try std.testing.expectEqual(@as(?usize, 0), pdf_pane.search_row); + try std.testing.expectEqual(output_id, p.active); + try std.testing.expectEqual(@as(i32, 0), output.cur_row); + p.update(.{ .key = .{ .cp = Key.enter } }); try std.testing.expectEqual(@as(usize, 1), pdf_pane.pdf.?.page); const child_destination = pdf_pane.pdf.?.outline.?.entries[1].destination.internal; const expected_y = @as(f64, @floatFromInt(pdf_pane.pdf.?.page_starts[1])) + @@ -1443,12 +1458,17 @@ test "PdfSections output, Look, and n/N share exact cached outline destinations" @as(f64, @floatFromInt(pdf_pane.pdf.?.page_heights[1])); try std.testing.expectApproxEqAbs(expected_y, pdf_pane.pdf.?.document_scroll_y, 0.001); p.update(.{ .key = .{ .cp = 'n' } }); - try std.testing.expectEqual(@as(?usize, 1), pdf_pane.search_row); + try std.testing.expectEqual(@as(i32, 1), output.cur_row); + p.update(.{ .key = .{ .cp = Key.enter } }); try std.testing.expectApproxEqAbs(expected_y, pdf_pane.pdf.?.document_scroll_y, 0.001); p.update(.{ .key = .{ .cp = 'n' } }); + p.update(.{ .key = .{ .cp = Key.enter } }); try std.testing.expectEqual(@as(usize, 2), pdf_pane.pdf.?.page); + // ...and N is the exact inverse of n: the row it walks back onto is the + // one n came from, and looking it lands on the same destination again. p.update(.{ .key = .{ .cp = 'N' } }); - try std.testing.expectEqual(@as(?usize, 1), pdf_pane.search_row); + try std.testing.expectEqual(@as(i32, 1), output.cur_row); + p.update(.{ .key = .{ .cp = Key.enter } }); try std.testing.expectEqual(@as(usize, 1), pdf_pane.pdf.?.page); try std.testing.expectApproxEqAbs(expected_y, pdf_pane.pdf.?.document_scroll_y, 0.001); @@ -1474,18 +1494,25 @@ test "PdfSections output, Look, and n/N share exact cached outline destinations" try std.testing.expect(pdf_pane.pdf.?.outline_reveal_pending == null); try p.setPdfSearchQuery(&pdf_pane.pdf.?, ""); - // Step forward onto the external row: it uses the existing open_link - // effect and searchStep restores focus to the owning PDF. - p.active = 0; + // Step forward onto the external row: two n's reach it, Enter takes the + // existing open_link effect, and a URL look moves focus nowhere โ€” so the + // walk is still standing in the buffer, ready for the next n. + // + // Asked FROM the sections buffer rather than from the PDF, because the two + // direct lookAt calls just above put the shell at the head of the ring and + // this is a test about the rows, not about the ordering. + p.active = output_id; p.update(.{ .key = .{ .cp = 'n' } }); p.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(@as(i32, 3), output.cur_row); + p.update(.{ .key = .{ .cp = Key.enter } }); var opened = false; while (p.nextEffect()) |effect| switch (effect) { .open_link => |uri| opened = std.mem.eql(u8, uri.slice(), "https://example.com/manual"), else => {}, }; try std.testing.expect(opened); - try std.testing.expectEqual(@as(usize, 0), p.active); + try std.testing.expectEqual(output_id, p.active); // Missing/hostile coordinates clamp to page space. x affects only a // layout with horizontal overflow and still does not touch raster state. @@ -3099,6 +3126,12 @@ pub const Event = union(enum) { /// with no filesystem (the browser) or no watcher simply never sends one โ€” /// nothing in the core waits for it. file_changed: struct { pane: u8, bytes: []const u8 }, + /// Text from the SYSTEM clipboard, borrowed for this call. Two ways in, + /// one handler (applyPaste): SOLICITED, the answer to a `read_clipboard` + /// the core emitted for `SPC p` / `SPC P` / `SPC R`, which decides where + /// it lands; and UNSOLICITED โ€” an outer terminal's bracketed paste, a + /// Cmd-V, the browser's paste event โ€” which means `SPC p`, paste after. + /// Neither touches the default register: that is `y`'s alone (helix). paste: []const u8, /// One builtin command line, handed to the shell by a pardes launched /// INSIDE this one (see nested.zig) โ€” `Look /abs/path` and nothing else @@ -3134,8 +3167,15 @@ pub const Effect = union(enum) { /// path dump.outPath resolves (acme-style: another instance loads it /// with -l, or the Restore builtin loads it into this one) write_dump, - /// the yank register changed; the shell reads it off the core (OSC 52 out) + /// mirror the yank register OUT to the system clipboard; the shell reads + /// it off the core (OSC 52 out, SDL_SetClipboardText, NSPasteboard). + /// Emitted ONLY by the explicit clipboard commands โ€” see setClipboard. set_clipboard, + /// ...and the other direction: ask the shell to READ the system clipboard. + /// The answer comes back as an ordinary `Event.paste`, which the core + /// routes to whichever of `SPC p` / `SPC P` / `SPC R` asked for it + /// (Pardes.clip_pending). No payload: the bytes travel in the event. + read_clipboard, /// answer a language query OFF the event loop and post the rows back as an /// `lsp_resp` Event. The shell reads the file's path and content off the /// core (like save_file) and must SNAPSHOT them before the worker starts โ€” @@ -3219,6 +3259,15 @@ pub const CharSel = struct { explicit: bool = false, }; +/// One position in the n/N walk: a look-able span on one row of one pane, +/// inclusive of both columns. Also what the walk REMEMBERS having stood on +/// (Pane.look_at) โ€” see lookStand for why the cursor alone cannot say. +pub const LookSpot = struct { + row: i32, + col0: i32, + col1: i32, +}; + /// ponytail: at most this many cursors at once. helix's `Selection.ranges` is /// an unbounded Vec; a fixed array keeps a Pane trivially copyable (the undo /// snapshots memcpy it) and costs nothing at one cursor. The ceiling only @@ -3718,6 +3767,11 @@ pub const Pane = struct { prompt: Prompt = .none, search_pane: ?usize = null, search_row: ?usize = null, + /// Where n/N last stood in this pane, or null when the walk has not been + /// here. Distinct from `search_row`, which points into the RESULTS BUFFER + /// a search armed on this pane; this one is a place in the pane's own + /// text, and n/N step it in every kind of pane. + look_at: ?LookSpot = null, /// The selection an `s`/`S` input was armed on, as gap offsets over the /// motion surface. Every keystroke re-derives the preview FROM here rather /// than from the previous preview โ€” which is what helix's regex_prompt @@ -4346,6 +4400,19 @@ pub const Pardes = struct { jumps: [MAX_JUMPS]Loc = undefined, njumps: usize = 0, jcur: usize = 0, + /// THE PANES THAT HAVE LOOKED, oldest first, at most one entry each โ€” the + /// spine n/N walks (lookWalkPanes). Serials rather than slots, for the + /// same reason the jumplist stores them: a freed slot is reused, and an + /// entry naming a dead pane must not resolve to the newcomer sitting in + /// its place. + /// + /// Not the jumplist, though it looks like one. `jumps` records where FOCUS + /// has been, and a look moves focus to what it OPENED; this records where + /// the look was made FROM, which is the pane holding the list you are + /// working through. The two answer different questions and would only + /// coincide by accident. + look_src: [MAX_PANES]u32 = undefined, + n_look_src: usize = 0, /// hands out Pane.serial; monotonic, never reused next_serial: u32 = 0, theme_idx: usize = 0, @@ -4468,9 +4535,14 @@ pub const Pardes = struct { effects_head: usize = 0, effects_len: usize = 0, - /// modal yank register (gpa-owned); a yank also mirrors out to the system - /// clipboard via the set_clipboard effect. + /// helix's DEFAULT register (gpa-owned): what `y`/`d`/`c` write and + /// `p`/`P`/`R` read. Never the system clipboard โ€” `SPC y`/`SPC p` are the + /// two commands that cross that line. yank: ?[]u8 = null, + /// a `SPC p`/`SPC P`/`SPC R` waiting on the shell's clipboard read, or + /// null. At most one: a second request replaces the first, and any + /// keystroke abandons it (update). + clip_pending: ?ClipRequest = null, /// the last serialized dump (gpa-owned), read by the write_dump effect dump_out: ?[]u8 = null, /// where the shell wrote the last dump (shell reports back after @@ -4709,6 +4781,37 @@ pub const Pardes = struct { } else null; } + /// The slot holding the pane with this serial, if it is still open. + pub fn paneBySerial(p: *Pardes, serial: u32) ?usize { + return for (p.panes, 0..) |slot, i| { + if (slot) |pane| if (pane.serial == serial) break i; + } else null; + } + + /// `id` just performed a look: put it on top of the walk's spine. + /// + /// MOVE to the top rather than push, so a pane you keep looking out of + /// stays one entry instead of filling the list with itself โ€” the walk's + /// order is "which panes, most recent first", not "how many times". + /// Dropping the oldest when full can only ever discard a DEAD pane's + /// serial: MAX_PANES entries with no duplicates already names every slot + /// there is. + fn noteLookSource(p: *Pardes, id: usize) void { + const pane = p.panes[id] orelse return; + var w: usize = 0; + for (p.look_src[0..p.n_look_src]) |s| { + if (s == pane.serial) continue; + p.look_src[w] = s; + w += 1; + } + if (w == p.look_src.len) { + std.mem.copyForwards(u32, p.look_src[0 .. w - 1], p.look_src[1..w]); + w -= 1; + } + p.look_src[w] = pane.serial; + p.n_look_src = w + 1; + } + /// chunk arbitrary-length bytes into fixed-size write effects (order kept) pub fn emitWrite(p: *Pardes, id: usize, bytes: []const u8) void { var off: usize = 0; @@ -4830,8 +4933,18 @@ pub const Pardes = struct { // fight one โ€” at worst it clears something the prompt was already // hiding. switch (ev) { - .key, .mouse => for (p.panes) |slot| { - if (slot) |pane| pane.msg_len = 0; + .key, .mouse => { + for (p.panes) |slot| { + if (slot) |pane| pane.msg_len = 0; + } + // ...and the same reasoning bounds a clipboard read in flight. + // A terminal that gates or refuses the OSC 52 request never + // answers at all, so the request cannot be allowed to sit and + // then fire minutes later into whatever pane is focused by + // then: it lives exactly until your next keystroke, and a + // shell that answers within one round trip (every one but a + // refusing tty) is unaffected. + p.clip_pending = null; }, else => {}, } @@ -4896,11 +5009,7 @@ pub const Pardes = struct { } } }, - .paste => |bytes| { - // a shell-level paste (bracketed/SDL): load the register, paste - p.setYank(bytes); - if (p.panes[p.active]) |pane| p.normalPaste(pane, false); - }, + .paste => |bytes| p.applyPaste(bytes), .command => |line| _ = p.executeBuiltinLine(p.active, line), .pinch => |scale| p.ov_pinch_scale = scale, .touch_scroll => |delta| p.ov_touch_scroll_delta = delta, @@ -4910,6 +5019,11 @@ pub const Pardes = struct { p.sync(); } + /// THE DEFAULT REGISTER, and nothing else. helix: an ordinary `y`/`d`/`c` + /// writes here and the system clipboard never hears about it โ€” which is + /// also the bug this spelling fixes, because a mirror on every write made + /// deleting one character clobber whatever the desktop was holding. + /// `SPC y` is the command that crosses over (setClipboard below). fn setYank(p: *Pardes, text: []const u8) void { // Inside a multi-selection replay the register collects EVERY range's // text, in document order โ€” the passes run last-range-first, so each @@ -4929,6 +5043,84 @@ pub const Pardes = struct { } if (p.yank) |y| p.gpa.free(y); p.yank = p.gpa.dupe(u8, text) catch null; + } + + /// ...and the register PLUS the system clipboard, which is the whole + /// difference between `y` and `SPC y`. + /// + /// One mirror per KEYSTROKE rather than per cursor: a multi-selection + /// replay runs last-range-first and `multi_first` marks its first pass, so + /// emitting there queues exactly one effect โ€” and the shell reads + /// `core.yank` when it DRAINS, by which time every later pass has folded + /// its range in. That asymmetry used to be a silent hole: the old mirror + /// sat past the join's early return, so a multi-cursor yank reached the + /// clipboard on one cursor and not on two. + fn setClipboard(p: *Pardes, text: []const u8) void { + p.setYank(text); + if (!p.multi_on or p.multi_first) p.emit(.{ .set_clipboard = {} }); + } + + /// Where a `SPC p` / `SPC P` / `SPC R` goes once the shell answers. + pub const ClipRequest = struct { + pane: usize, + /// the pane's identity, not its slot: the answer can arrive whole + /// keystrokes later (a tty's OSC 52 round trip) and a freed slot is + /// reused by an unrelated pane. + serial: u32, + mode: enum { after, before, replace }, + }; + + /// `SPC p` / `SPC P` / `SPC R`: ask the shell for the system clipboard and + /// remember what to do with it. The request is deliberately fire-and-hope + /// โ€” a terminal that refuses the OSC 52 read simply never answers, and the + /// next keystroke drops the request (see update) rather than letting a + /// paste land minutes late in whatever pane is focused by then. + pub fn clipRequest(p: *Pardes, id: usize, mode: @FieldType(ClipRequest, "mode")) void { + const pane = p.panes[id] orelse return; + p.clip_pending = .{ .pane = id, .serial = pane.serial, .mode = mode }; + p.emit(.read_clipboard); + } + + /// The shell answered with system-clipboard text โ€” or the desktop pasted + /// into us unasked. Either way the bytes are pasted WITHOUT going through + /// the register: helix's clipboard commands and the default register are + /// separate stores, and a paste that quietly overwrote your `y` would be + /// the same clobbering bug in the other direction. + fn applyPaste(p: *Pardes, bytes: []const u8) void { + const req = p.clip_pending; + p.clip_pending = null; + if (bytes.len == 0) return; + const id = if (req) |r| r.pane else p.active; + const pane = p.panes[id] orelse return; + if (req) |r| if (pane.serial != r.serial) return; + p.active = id; + switch (if (req) |r| r.mode else .after) { + .after => p.pasteText(pane, bytes, false), + .before => p.pasteText(pane, bytes, true), + .replace => p.replaceWithText(pane, bytes), + } + } + + /// `SPC y` / `SPC Y`: the selection to the system clipboard. `main_only` + /// is helix's capital โ€” every cursor's text joined, versus the primary + /// selection's alone. A PDF has no editable buffer to replay over, so its + /// own selection answers directly. + pub fn clipYank(p: *Pardes, pane: *Pane, main_only: bool) void { + if (comptime pdf_enabled) if (pane.pdf) |pv| { + if (pv.selection_text.len > 0) p.setClipboard(pv.selection_text); + return; + }; + // the ordinary `y` path, so what reaches the clipboard is exactly what + // the key would have put in the register โ€” including the multi-cursor + // join, which is replaySels' business and not a second implementation + if (pane.nsel > 0 and !main_only) { + p.replaySels(pane, .{ .normal = .{ .edit = .{ .kind = .yank, .count = 1 } } }); + } else { + const others = pane.nsel; + pane.nsel = 0; + p.normalYank(pane); + pane.nsel = others; + } p.emit(.{ .set_clipboard = {} }); } @@ -5238,8 +5430,16 @@ pub const Pardes = struct { } // y โ€” yank what the chord would run: the selection, else the word under // the cursor. The path is selectable, so this is how you copy it out. + // + // The ONE register write that still mirrors to the system clipboard + // without `SPC` in front of it, and it is not an exception so much as + // the only spelling available: a tag is always in insert mode, the + // leader is body-normal only, so `SPC y` cannot be pressed here โ€” and + // "copy this path somewhere else" is the entire reason the chord + // exists. A path that only reached the internal register would be a + // key that does nothing you can observe. if (hit(key, config.tag_yank)) { - if (p.tagChordText(pane)) |txt| p.setYank(txt); + if (p.tagChordText(pane)) |txt| p.setClipboard(txt); return; } // insert entry (one line, so I/A are the tail's ends). The prefix is @@ -5831,7 +6031,19 @@ pub const Pardes = struct { const goff: i32 = @intCast(screen.pages.scrollbar().offset); const vp_row: i32 = pane.gridRow(pane.cur_row) - goff; if (vp_row >= 0) { - if (screen.pages.pin(.{ .viewport = .{ .x = @intCast(@max(0, pane.cur_col)), .y = @intCast(vp_row) } })) |click_pin| { + // ...and its COLUMN back through the hidden prompt. Outside + // tty the prompt row shows the typed command left-hugged at + // column 0 (term_pane.promptRow), so a cursor three cells into + // what you can see is three cells past the prompt's END on the + // real grid โ€” and it is the real grid this pin addresses. + var grid_col: i32 = @max(0, pane.cur_col); + if (screen.pages.pin(.{ .viewport = .{ .x = 0, .y = @intCast(vp_row) } })) |row_pin| { + if (row_pin.rowAndCell().row.semantic_prompt != .none) switch (term_pane.promptCut(row_pin)) { + .cut => |cols| grid_col += @intCast(cols), + .keep, .blank => {}, + }; + } + if (screen.pages.pin(.{ .viewport = .{ .x = @intCast(grid_col), .y = @intCast(vp_row) } })) |click_pin| { const cursor_pin = screen.cursor.page_pin.*; var pit = cursor_pin.promptIterator(.left_up, null); if (pit.next()) |prompt_pin| { @@ -7343,11 +7555,9 @@ pub const Pardes = struct { }, .pipe_selection => return p.startPipe(pane), .search => return p.startSearch(pane, config.search_marker), - .search_step => |direction| { - const delta: i32 = if (direction == .forward) 1 else -1; - if (p.searchStep(p.active, delta)) return; - if (pane.isTerminal()) return p.lookStep(pane, pl, delta); - }, + .search_step => |direction| return p.lookWalk( + if (direction == .forward) @as(i32, 1) else -1, + ), } } @@ -7731,13 +7941,18 @@ pub const Pardes = struct { try output_pane.fillResults(p, id, dir, from, pat, content, anchor); } - /// n/N: step to the next/previous row of this pane's results buffer and - /// ACT on it โ€” which of the two acme verbs that is comes from the buffer's - /// own traits, so this is one motion over "a list of things you can run", - /// not two kinds of stepping. A location list (every search, the jumplist, - /// every language answer) Looks the leading `path:LINE:COL` word; a command - /// list (ThemeSel) Execs the whole row. False = no live search: a - /// terminal's n/N falls back to lookStep, anything else stays put. + /// Step to the next/previous row of this pane's results buffer and ACT on + /// it โ€” which of the two acme verbs that is comes from the buffer's own + /// traits. A location list (every search, every language answer) Looks the + /// leading `path:LINE:COL` word; a command list (ThemeSel, FontSel) Execs + /// the whole row. False = no live results to step. + /// + /// n/N used to BE this, and are not any more (lookWalk): stepping a list + /// of places now selects and stops, because a step that also opened meant + /// you could not walk past a hit without landing on it. What still comes + /// through here is what is not n/N at all: `]d`/`[d`, whose whole job is + /// to GO to the next diagnostic, and acme's button-3, where clicking a + /// word that names nothing searches for it and goes to the first hit. fn searchStep(p: *Pardes, id: usize, delta: i32) bool { const pane = p.panes[id] orelse return false; const rid = pane.search_pane orelse return false; @@ -7772,7 +7987,7 @@ pub const Pardes = struct { // clicked row can never drift apart. A command row goes whole (its // argument is the tail after the name); a location row is cut to the // leading file-ish word, since the rest of it is the matched text. - if (tr.executes) { + if (tr.commands) { p.runBuiltin(config.exec_cmd, rid, "", std.mem.trim(u8, ln, " \t\r")); } else { var hi: usize = 0; @@ -7964,59 +8179,260 @@ pub const Pardes = struct { p.reportError(w.pane, "language response", err); } - /// n/N on a terminal pane: a MOTION over lookable tokens. Select the - /// next/prev whitespace-separated token that look.resolve can turn into a - /// file/dir (several per line: an ls row hops big.txt -> plain.txt), park - /// the cursor at its start, open NOTHING โ€” Enter's normal-mode handler - /// looks the selection. Wraps around when nothing lies in the direction - /// (fresh out of tty mode the cursor sits below the output, so the first - /// n lands on the first token). Deliberately only THIS pane's directory, - /// where the look itself walks every pane's: the motion resolves every - /// token it steps over, so the other directories would cost tokens ร— - /// panes realpaths on a single keystroke โ€” and a token the motion skips - /// is still openable by looking it, which is all n/N is a shortcut for. - fn lookStep(p: *Pardes, pane: *Pane, pl: PaneLines, delta: i32) void { - _ = p; // a pure motion now: Enter's normal-mode handler does the look - pane.pinCursor(); // fresh out of tty mode the cursor still tracks the shell + // ---- n/N: the walk over look-able text ---- + + /// How many rows ONE PRESS may scan, across every pane it visits. A + /// shell's motion surface is its whole scrollback and every whitespace run + /// on it costs a realpath, so the walk is bounded. + /// + /// Running out STOPS the walk where it stands rather than treating the + /// pane as exhausted and moving on, and that distinction is load-bearing: + /// giving up in the middle of a pane and hopping to the next one would + /// make the two directions disagree about where a pane ENDS, and n/N have + /// to be exact inverses. Not moving is the one failure that always is. + /// A pane whose next look-able text is eight thousand rows away is a pane + /// to scroll, not to step. + const max_look_rows = 8192; + + /// Where a step STARTS inside a pane. `col` null enters the pane at the + /// row's edge โ€” every span on it is ahead of you โ€” which is what a hop + /// from a neighbouring pane does. `strict` says the column is a position + /// the walk itself established, so the span sitting ON it is the one you + /// are already at and the step must go past it. + const LookFrom = struct { row: i32, col: ?i32, strict: bool = false }; + + /// Entering a pane from a neighbour: the first row going forward, the last + /// going back. Spelled once because it is exactly what makes the two + /// directions inverses across a pane boundary. + fn lookEdge(delta: i32) LookFrom { + return .{ .row = if (delta > 0) 0 else std.math.maxInt(i32), .col = null }; + } + + /// Where the walk currently stands in `pane`. + /// + /// `Pane.look_at` and not the cursor alone, because the cursor cannot + /// answer the question. A cursor parked on the first look-able span may + /// mean the walk put it there โ€” so the next step is the SECOND span โ€” or + /// that the pane simply opened that way, which is every fresh +Search, and + /// there the next step must be the FIRST. `search_row` answered the same + /// question the same way for the same reason. When the recorded stand no + /// longer matches the cursor you have moved it yourself since, and the + /// cursor wins: the walk continues from where you are looking. + fn lookStand(pane: *Pane) LookFrom { + if (pane.look_at) |s| if (s.row == pane.cur_row and s.col0 == pane.cur_col) + return .{ .row = s.row, .col = s.col0, .strict = true }; + return .{ .row = pane.cur_row, .col = pane.cur_col }; + } + + /// The panes n/N walk, in the order it walks them: every pane that has + /// performed a LOOK, most recent first, then the OUTPUT buffers none has, + /// newest first โ€” and, only when that comes to nothing at all, the pane + /// you are in. + /// + /// The look history is the spine because looking is what marks a pane as + /// the one you are reading things OUT of โ€” the +Search you are stepping, + /// the diagnostics list, the shell whose `ls` rows you keep opening. The + /// unlooked output buffers come after it so a fresh `/`, which has looked + /// at nothing yet, still has somewhere for the first `n` to go: its own + /// results. FILO among them, so two searches step the newer list first. + /// + /// The ACTIVE pane is the fallback and NOT a member, which is the + /// difference between n continuing a list and n wandering off it. Look a + /// row out of a +Search and focus lands in the file that opened; the next + /// n has to go back to the +Search, not start walking the paths that + /// happen to be in the source you just opened. Only when nothing has + /// looked and no buffer has answered โ€” a shell one minute into a session, + /// which is where n/N started life โ€” is the pane in front of you the list. + fn lookWalkPanes(p: *Pardes, out: *[MAX_PANES]usize) []const usize { + var n: usize = 0; + var i = p.n_look_src; + while (i > 0) { + i -= 1; + const id = p.paneBySerial(p.look_src[i]) orelse continue; + out[n] = id; + n += 1; + } + const looked = n; + for (p.panes, 0..) |slot, id| { + const pane = slot orelse continue; + const f = pane.file orelse continue; + if (f.output == null) continue; + for (out[0..looked]) |k| { + if (k == id) break; + } else { + // insertion by serial descending โ€” at most MAX_PANES + // comparisons, which is not a sort worth naming + var at = n; + while (at > looked and p.panes[out[at - 1]].?.serial < pane.serial) : (at -= 1) + out[at] = out[at - 1]; + out[at] = id; + n += 1; + } + } + if (n == 0) { + if (p.panes[p.active] == null) return out[0..0]; + out[0] = p.active; + n = 1; + } + return out[0..n]; + } + + /// The next STEPPABLE span in `pane` from `from`, in `delta`'s direction, + /// or null when the pane has none left that way. `budget` is the caller's + /// remaining row allowance and is spent here; a null return with a budget + /// of zero means GAVE UP, not exhausted (see max_look_rows). + /// + /// One flag decides what a span IS. In an ordinary pane it is the largest + /// look-able run on the row (look.lookableSpan) and a row may hold several + /// โ€” an `ls` line hops big.txt -> plain.txt -> sub. In a buffer whose rows + /// are COMMANDS (output_pane.Traits.commands: ThemeSel, FontSel) it is the + /// WHOLE LINE, because `Theme gruvbox` has no path inside it to pick out + /// and the line is the unit you would run. Same motion, same selection, + /// same Enter/Tab afterwards; only the grain differs. + /// + /// Symmetric by construction either way, and that is the whole point: both + /// directions ask the same question about the same rows, and both compare + /// against `col0` โ€” the column the walk parks the cursor on. So a step + /// forward off a span and a step back onto it are the same two positions + /// read in the two orders. + fn lookSpanIn(p: *Pardes, pane: *Pane, from: LookFrom, delta: i32, budget: *usize) ?LookSpot { + const pl = p.paneCursorLines(pane) catch return null; const nrows: i32 = @intCast(pl.lines.len); - if (nrows == 0) return; + if (nrows == 0) return null; + const whole_row = if (pane.file) |*f| output_pane.fileTraits(f.output).commands else false; + const dir = paneDir(pane); var realbuf: [4096]u8 = undefined; - var k: i32 = 0; - while (k < nrows) : (k += 1) { - const r = @mod(pane.cur_row + delta * k, nrows); + const start = std.math.clamp(from.row, 0, nrows - 1); + var r = start; + while (r >= 0 and r < nrows) : (r += delta) { + if (budget.* == 0) return null; + budget.* -= 1; const ln = pl.lines[@intCast(r)]; - var hit_t0: usize = 0; - var hit_t1: usize = 0; + var best: ?LookSpot = null; var i: usize = 0; while (i < ln.len) { while (i < ln.len and (ln[i] == ' ' or ln[i] == '\t')) i += 1; const t0 = i; - while (i < ln.len and ln[i] != ' ' and ln[i] != '\t') i += 1; - if (i == t0) break; - // on the cursor's own row (no wrap yet) only tokens strictly - // past the cursor count, in the motion's direction - if (k == 0) { - if (delta > 0 and @as(i32, @intCast(t0)) <= pane.cur_col) continue; - if (delta < 0 and @as(i32, @intCast(t0)) >= pane.cur_col) continue; + var spot: LookSpot = undefined; + if (whole_row) { + // one span per row, from its first non-blank cell to its + // last: the trailing trim keeps a padded row selecting the + // command and not the padding + const end = std.mem.trimEnd(u8, ln, " \t\r").len; + if (end <= t0) break; + i = end; + spot = .{ .row = r, .col0 = @intCast(t0), .col1 = @intCast(end - 1) }; + } else { + while (i < ln.len and ln[i] != ' ' and ln[i] != '\t') i += 1; + if (i == t0) break; + const sp = look.lookableSpan(ln[t0..i], dir, &realbuf) orelse continue; + spot = .{ + .row = r, + .col0 = @intCast(t0 + sp.start), + .col1 = @intCast(t0 + sp.end - 1), + }; } - if (look.resolve(ln[t0..i], pane.cwdSlice(), &realbuf) == .none) continue; - hit_t0 = t0; - hit_t1 = i; - if (delta > 0) break; // first token forward; keep the last one backward + // AFTER the span, never before it, and against `col0` rather + // than the whitespace run's start. Those are different columns + // the moment a wrapper is peeled: `(mise.toml)` is a run + // starting at 0 and a span starting at 1, and a backward step + // filtered on the run would find the span it is standing on + // still ahead of it and never leave the row. Only the start row + // is filtered at all, so the resolves this costs are one row's. + if (r == start) if (from.col) |c| { + if (delta > 0 and (if (from.strict) spot.col0 <= c else spot.col0 < c)) continue; + if (delta < 0 and (if (from.strict) spot.col0 >= c else spot.col0 > c)) continue; + }; + best = spot; + if (delta > 0) break; // first one forward; keep the last one back } - if (hit_t1 == 0) continue; - // anchor the selection at the token's end, cursor at its START; - // EXPLICIT: Enter's look chord acts on it - pane.vsel = .{ .active = true, .row = r, .col = @intCast(hit_t1 - 1), .explicit = true }; - pane.msel.active = false; - pane.nsel = 0; - pane.cur_row = r; - pane.cur_col = @intCast(hit_t0); - pane.cur_pinned = true; - pane.ensureCursorVisible(); - return; + if (best) |b| return b; } - // nothing lookable anywhere: stay put + return null; + } + + /// n/N: move the SELECTION to the next/previous look-able text and open + /// NOTHING. Enter looks what this leaves selected, and that separation is + /// the change: a step is a motion you can take twenty of and then decide, + /// where it used to be twenty panes. + /// + /// The sequence stepped is the concatenation, in lookWalkPanes' order, of + /// each pane's look-able spans in document order, AND IT IS A RING. `n` is + /// the next position on that ring and `N` the previous one, computed the + /// same way from the same state โ€” so x presses one way and x back land + /// exactly where you started, across pane boundaries included: a pane + /// entered forward is entered at its FIRST span, and leaving it backward + /// from that span drops into the previous pane's LAST. + /// + /// A ring rather than a list with two ends, for two reasons that turn out + /// to be one. A shell's cursor sits at the PROMPT, below everything it has + /// printed, so a walk that could not come round would have nowhere to go + /// on the very first press โ€” which is the case n/N was written for. And a + /// ring is still exactly reversible, so nothing is given up for it: acme's + /// search has always been one, and this is that. + /// + /// (One press is not symmetric, and cannot be: from a cursor the walk has + /// never stood on, the first step ACQUIRES a position rather than moving + /// one โ€” see lookStand. Every press after that is exact.) + /// + /// No walk state outside the panes themselves, which is what makes this + /// robust where the old stepper was not: nothing to go stale when a search + /// refills, a pane closes, or you move the cursor and step on from there. + /// + /// ONE MOTION, EVERYWHERE. Not a pane kind, not a buffer kind, not a mode: + /// n/N are this walk in all of them, which is the other half of making + /// them trustworthy. A PDF used to step its results buffer and jump; it + /// steps the same ring now, which IS that buffer, and Enter does the + /// jumping. The single thing any buffer gets to change is the GRAIN of + /// what a step selects, and it changes it with one flag rather than a + /// branch here: `Traits.commands` makes a row select WHOLE, because a + /// ThemeSel line is a word to run and not a place to go (lookSpanIn). + /// + /// `]d`/`[d` are not n/N. They are helix's diagnostic motions, their job + /// is to ARRIVE at the next diagnostic, and they still reach searchStep. + fn lookWalk(p: *Pardes, delta: i32) void { + var buf: [MAX_PANES]usize = undefined; + const order = p.lookWalkPanes(&buf); + if (order.len == 0) return; + // Start where you ARE when that is somewhere the walk goes; otherwise + // at its head, which after a look is the pane you looked FROM โ€” the + // look focused what it OPENED, and that is not a walk pane. + const at: usize = for (order, 0..) |id, i| { + if (id == p.active) break i; + } else 0; + var from = lookStand(p.panes[order[at]] orelse return); + // ...then every OTHER pane once, in the direction of travel, entered + // at its edge โ€” and `k == order.len` brings the starting pane round a + // second time, from ITS edge, which is the wrap. That bound is also + // what makes a screen with nothing look-able on it terminate. + var budget: usize = max_look_rows; + var k: usize = 0; + while (k <= order.len) : (k += 1) { + // `+ 2 * len` only so the backward subtraction stays unsigned + const idx = (if (delta > 0) at + k else at + 2 * order.len - k) % order.len; + const pane = p.panes[order[idx]] orelse continue; + if (p.lookSpanIn(pane, from, delta, &budget)) |spot| + return p.landLookSpot(order[idx], pane, spot); + if (budget == 0) return; // gave up mid-pane: stay put, stay reversible + from = lookEdge(delta); + } + } + + /// Select `spot` and focus its pane. The selection is EXPLICIT so Enter's + /// look chord acts on it, with the anchor on the span's last cell and the + /// cursor on its FIRST โ€” the same shape the old terminal stepper left, and + /// the reason `col0` is the position the walk compares against. + fn landLookSpot(p: *Pardes, id: usize, pane: *Pane, spot: LookSpot) void { + pane.pinCursor(); // fresh out of tty mode the cursor still tracks the shell + pane.vsel = .{ .active = true, .row = spot.row, .col = spot.col1, .explicit = true }; + pane.msel.active = false; + pane.nsel = 0; + pane.cur_row = spot.row; + pane.cur_col = spot.col0; + pane.cur_pinned = true; + pane.look_at = spot; + p.active = id; + pane.ensureCursorVisible(); } const EditText = struct { text: []u8, row0: i32 }; @@ -8601,13 +9017,20 @@ pub const Pardes = struct { } } - /// helix p/P: a yank ending in '\n' pastes as whole lines below/above - /// the SELECTION's line span; anything else splices inline at the - /// selection's outer edge. The paste (repeated times) becomes - /// the implicit selection, cursor on its last char (linewise: ON the - /// last pasted line's newline). + /// helix p/P: the DEFAULT register, after/before the selection. fn normalPaste(p: *Pardes, pane: *Pane, before: bool) void { - const y0 = p.yank orelse return; + p.pasteText(pane, p.yank orelse return, before); + } + + /// ...and the paste itself, over text from wherever: the register above, + /// or the system clipboard `SPC p` asked the shell for, which deliberately + /// never passes through the register on its way here. + /// + /// Text ending in '\n' pastes as whole lines below/above the SELECTION's + /// line span; anything else splices inline at the selection's outer edge. + /// The paste (repeated times) becomes the implicit selection, + /// cursor on its last char (linewise: ON the last pasted line's newline). + fn pasteText(p: *Pardes, pane: *Pane, y0: []const u8, before: bool) void { if (y0.len == 0) return; p.pushUndo(pane); pane.select = false; @@ -8830,11 +9253,15 @@ pub const Pardes = struct { p.setEditText(pane, new); } - /// `R`: replace the selection (or the cursor char) with the yank register; - /// the pasted text becomes the selection, head on its last char (which - /// for a trailing-newline yank is the '\n' cell of the last full line) + /// `R`: replace the selection (or the cursor char) with the DEFAULT + /// register. `SPC R` is the same verb over the system clipboard. fn normalReplaceYank(p: *Pardes, pane: *Pane) void { - const y = p.yank orelse return; + p.replaceWithText(pane, p.yank orelse return); + } + + /// The pasted text becomes the selection, head on its last char (which for + /// a trailing-newline `y` is the '\n' cell of the last full line). + fn replaceWithText(p: *Pardes, pane: *Pane, y: []const u8) void { if (y.len == 0) return; pane.select = false; const eb = p.editTextEol(pane, selRows(pane)) orelse return; @@ -11566,9 +11993,13 @@ pub const Pardes = struct { if (pane.tag_edit) pane.mode = .normal; }, .search => p.startSearch(pane, config.search_marker), - .search_step => |direction| { - _ = p.searchStep(p.active, if (direction == .forward) 1 else -1); - }, + // A PDF is not a special case: it steps the same ring every other + // pane does, which in practice is the +Search or +PdfSections + // buffer its own search filled. n selects the row, Enter jumps to + // the page. + .search_step => |direction| return p.lookWalk( + if (direction == .forward) @as(i32, 1) else -1, + ), else => {}, } } @@ -11760,6 +12191,10 @@ pub const Pardes = struct { pub fn lookAt(p: *Pardes, id: usize, txt: []const u8) void { const pane = p.panes[id] orelse return; p.noteHaptic(.look); + // ...and this pane is now the head of the n/N walk. Recorded HERE, at + // the one dispatcher every look reaches, so a right click, an Enter, a + // stepped result row and the word `Look` all count alike. + p.noteLookSource(id); const trimmed = std.mem.trim(u8, txt, " \t\r\n"); // `` @`ls -la` `` names a COMMAND, not a path: run it, and land in the // pane that answers โ€” looking at a thing means being SHOWN it, and a @@ -12184,10 +12619,9 @@ pub const Pardes = struct { var row: i32 = 0; var skip: i32 = 0; while (lines.next()) |raw| : (row += 1) { - const is_prompt = if (pane.mode != .tty) - if (prompts.next()) |pin| pin.rowAndCell().row.semantic_prompt != .none else false - else - false; + // stepped for EVERY line, before the skip below, or the + // row iterator falls out of step with the dump's lines + const prompt_pin = if (pane.mode != .tty) prompts.next() else null; if (skip > 0) { skip -= 1; continue; @@ -12202,7 +12636,15 @@ pub const Pardes = struct { skip = o.rows - 1; continue; }; - const shown = if (is_prompt) "" else raw; + // same rule the motion surface and the body use, so a dump + // reloads showing exactly what the pane showed + const shown = if (prompt_pin) |pin| + if (pin.rowAndCell().row.semantic_prompt != .none) + term_pane.promptRow(pin, raw) + else + raw + else + raw; @memcpy(stream_buf[stream_len..][0..shown.len], shown); stream_len += shown.len; } @@ -13814,3 +14256,360 @@ test "hopping between two panes does not grow the jump stack" { try std.testing.expect(p.active != before); try std.testing.expectEqual(depth, p.njumps); } + +/// A results buffer with rows we control: three look-able locations and one +/// row with nothing look-able on it at all. Returns its slot. `pat` is the +/// recorded pattern and is what keeps two of these APART โ€” fillResults refills +/// a buffer whose origin, argument and directory all match. +fn walkFixture(p: *Pardes, id: usize, cwd: []const u8, pat: []const u8) !usize { + const rows = try std.fmt.allocPrint(p.gpa, + \\build.zig:1:1 first + \\(mise.toml) and build.zig.zon:3:2-9 two on one row + \\nothing look-able on this row at all + \\uucode_config.zig:7:1 last + \\ + , .{}); + try output_pane.fillResults(p, id, cwd, .search, pat, rows, null); + return p.panes[id].?.search_pane orelse error.MissingResults; +} + +test "n/N select look-able text and open nothing" { + if (platform == .web) return; + const gpa = std.testing.allocator; + var cwdbuf: [4096]u8 = undefined; + const cwd = std.mem.span(@as([*:0]u8, @ptrCast(std.c.getcwd(&cwdbuf, cwdbuf.len) orelse return))); + var pathbuf: [4096]u8 = undefined; + const boot = try std.fmt.bufPrint(&pathbuf, "{s}/mise.toml", .{cwd}); + + const p = try Pardes.init(gpa, .{ .cols = 100, .rows = 40, .file = boot }); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 100, .rows = 40 } }); + const rid = try walkFixture(p, p.active, cwd, "one"); + const rp = p.panes[rid].?; + const panes_before = p.freeSlot(); + + // Nothing has looked yet, so the walk's list is the one unvisited output + // buffer. The first n lands on row 0's leading token, FOCUSES that buffer, + // and opens nothing whatsoever. + p.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(rid, p.active); + try std.testing.expectEqual(panes_before, p.freeSlot()); + try std.testing.expectEqual(@as(i32, 0), rp.cur_row); + try std.testing.expectEqual(@as(i32, 0), rp.cur_col); + // EXPLICIT, anchored on the span's last cell: what Enter's look acts on + try std.testing.expect(rp.vsel.active and rp.vsel.explicit); + try std.testing.expectEqualStrings("build.zig:1:1", p.currentSelText(rp) orelse ""); + + // Row 1 holds TWO: a parenthesised path, whose wrappers are peeled off the + // selection, and a `path:LINE:COL-END` whose position tail is kept. + p.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(@as(i32, 1), rp.cur_row); + try std.testing.expectEqualStrings("mise.toml", p.currentSelText(rp) orelse ""); + p.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(@as(i32, 1), rp.cur_row); + try std.testing.expectEqualStrings("build.zig.zon:3:2-9", p.currentSelText(rp) orelse ""); + + // Row 2 has nothing to step to and is skipped entirely. + p.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(@as(i32, 3), rp.cur_row); + try std.testing.expectEqualStrings("uucode_config.zig:7:1", p.currentSelText(rp) orelse ""); + + // Past the last span the ring comes round to the first. + p.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(@as(i32, 0), rp.cur_row); + + // ...and Enter on a selection is what finally opens something. + p.update(.{ .key = .{ .cp = Key.enter } }); + try std.testing.expect(p.freeSlot() != panes_before); + try std.testing.expect(std.mem.endsWith(u8, p.panes[p.active].?.file.?.path, "/build.zig")); +} + +test "N is the exact inverse of n, across panes and the ring's seam" { + if (platform == .web) return; + const gpa = std.testing.allocator; + var cwdbuf: [4096]u8 = undefined; + const cwd = std.mem.span(@as([*:0]u8, @ptrCast(std.c.getcwd(&cwdbuf, cwdbuf.len) orelse return))); + var pathbuf: [4096]u8 = undefined; + const boot = try std.fmt.bufPrint(&pathbuf, "{s}/mise.toml", .{cwd}); + + const p = try Pardes.init(gpa, .{ .cols = 100, .rows = 40, .file = boot }); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 100, .rows = 40 } }); + + // TWO buffers, so the walk has a pane boundary to cross and a seam to wrap + // over โ€” the two places a hand-rolled inverse gets it wrong. + const first = try walkFixture(p, p.active, cwd, "one"); + p.update(.{ .key = .{ .cp = 'n', .alt = true } }); // a shell to hang the second off + p.sync(); + const second = try walkFixture(p, p.active, cwd, "two"); + try std.testing.expect(first != second); + + const Mark = struct { pane: usize, row: i32, col: i32 }; + const here = struct { + fn at(pp: *Pardes) Mark { + const pane = pp.panes[pp.active].?; + return .{ .pane = pp.active, .row = pane.cur_row, .col = pane.cur_col }; + } + }.at; + + // The FIRST press only acquires a position โ€” before it the cursor is + // wherever the shell left it, which is not a place on the ring โ€” so the + // symmetry claim starts one step in. Everything after that is exact. + p.update(.{ .key = .{ .cp = 'n' } }); + const base = here(p); + + // Twelve more forward is further than either buffer holds, so the trail + // crosses both pane boundaries and wraps over the seam; record every + // position it passes through. + var trail: [12]Mark = undefined; + for (&trail) |*m| { + p.update(.{ .key = .{ .cp = 'n' } }); + m.* = here(p); + } + // ...and twelve back must retrace it exactly, position by position, ending + // on the one the count started from. + var i = trail.len; + while (i > 0) { + i -= 1; + p.update(.{ .key = .{ .cp = 'N' } }); + const want = if (i == 0) base else trail[i - 1]; + try std.testing.expectEqual(want.pane, p.active); + try std.testing.expectEqual(want.row, p.panes[p.active].?.cur_row); + try std.testing.expectEqual(want.col, p.panes[p.active].?.cur_col); + } + + // The walk visited both buffers rather than circling inside one. + var saw_first = false; + var saw_second = false; + for (trail) |m| { + if (m.pane == first) saw_first = true; + if (m.pane == second) saw_second = true; + } + try std.testing.expect(saw_first and saw_second); +} + +test "n/N select a command row whole, and a look puts its pane at the head" { + if (platform == .web) return; + const gpa = std.testing.allocator; + var cwdbuf: [4096]u8 = undefined; + const cwd = std.mem.span(@as([*:0]u8, @ptrCast(std.c.getcwd(&cwdbuf, cwdbuf.len) orelse return))); + var pathbuf: [4096]u8 = undefined; + const boot = try std.fmt.bufPrint(&pathbuf, "{s}/mise.toml", .{cwd}); + + const p = try Pardes.init(gpa, .{ .cols = 100, .rows = 40, .file = boot }); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 100, .rows = 40 } }); + + // A COMMAND list: its rows are words to run, so a step takes the whole + // line โ€” there is no path inside `Theme acme` to pick out. + p.runBuiltin(.ThemeSel, p.active, "", null); + const tid = p.panes[p.active].?.search_pane orelse return error.MissingThemeList; + const tp = p.panes[tid].?; + try std.testing.expect(output_pane.fileTraits(tp.file.?.output).commands); + p.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(tid, p.active); + const row0 = std.mem.trimEnd(u8, modal.lineSlice(tp.file.?.content, 0), " \t\r"); + try std.testing.expectEqualStrings(row0, p.currentSelText(tp) orelse ""); + // ...and Tab RUNS what n selected, which is how a theme is worn now. + const theme_before = p.theme_idx; + p.update(.{ .key = .{ .cp = 'n' } }); + p.update(.{ .key = .{ .cp = Key.tab } }); + try std.testing.expect(p.theme_idx != theme_before); + + // A LOOK is what puts a pane at the head of the walk. Look from the boot + // pane and the next n steps THERE, not in the theme list, even though the + // look moved focus into whatever it opened. + p.runBuiltin(.Look, 0, "", "build.zig"); + p.sync(); + try std.testing.expect(p.active != 0); + p.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(@as(usize, 0), p.active); +} + +/// Drain the queue and say whether the shell was asked to do `want`. +fn drainedEffect(p: *Pardes, want: std.meta.Tag(Effect)) bool { + var seen = false; + while (p.nextEffect()) |effect| { + if (std.meta.activeTag(effect) == want) seen = true; + } + return seen; +} + +test "only the SPC clipboard commands cross to the system clipboard" { + if (platform == .web) return; + const gpa = std.testing.allocator; + const p = try Pardes.init(gpa, .{ .cols = 80, .rows = 24, .file = "mise.toml" }); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 80, .rows = 24 } }); + const pane = p.panes[0].?; + + // An ordinary yank fills the DEFAULT REGISTER and asks the shell for + // nothing. This is the whole helix split, and the bug it closes: before + // it, every y/d/c mirrored out, so deleting one character threw away + // whatever the desktop was holding. + _ = drainedEffect(p, .set_clipboard); + p.update(.{ .key = .{ .cp = 'y' } }); + try std.testing.expect(p.yank != null and p.yank.?.len > 0); + try std.testing.expect(!drainedEffect(p, .set_clipboard)); + p.update(.{ .key = .{ .cp = 'd' } }); + try std.testing.expect(!drainedEffect(p, .set_clipboard)); + + // `SPC y` is the one that does, and it puts the SAME text there that `y` + // put in the register โ€” it is the ordinary yank path plus the mirror. + p.update(.{ .key = .{ .cp = ' ' } }); + p.update(.{ .key = .{ .cp = 'y' } }); + const yanked = p.yank orelse return error.MissingYank; + try std.testing.expect(drainedEffect(p, .set_clipboard)); + + // `SPC p` cannot read the clipboard itself: it ASKS, and the answer comes + // back as an ordinary paste event whenever (or never โ€” a terminal may + // refuse the OSC 52 read, which is a no-op and not a hang). + const before = pane.file.?.content.len; + p.update(.{ .key = .{ .cp = ' ' } }); + p.update(.{ .key = .{ .cp = 'p' } }); + try std.testing.expect(p.clip_pending != null); + try std.testing.expect(drainedEffect(p, .read_clipboard)); + try std.testing.expectEqual(before, pane.file.?.content.len); // nothing yet + p.update(.{ .paste = "PASTED" }); + try std.testing.expect(p.clip_pending == null); + try std.testing.expect(std.mem.indexOf(u8, pane.file.?.content, "PASTED") != null); + // ...and it did NOT land in the register on its way past, nor echo back + // out to the clipboard it came from. + try std.testing.expectEqualStrings(yanked, p.yank orelse ""); + try std.testing.expect(!drainedEffect(p, .set_clipboard)); + + // An UNSOLICITED paste โ€” the outer terminal's bracketed paste, a Cmd-V โ€” + // is the same event with no request behind it, and means paste after. + p.update(.{ .paste = "UNASKED" }); + try std.testing.expect(std.mem.indexOf(u8, pane.file.?.content, "UNASKED") != null); + try std.testing.expectEqualStrings(yanked, p.yank orelse ""); + + // A request the shell never answers dies at the next keystroke rather + // than firing late into whatever pane is focused by then. + p.update(.{ .key = .{ .cp = ' ' } }); + p.update(.{ .key = .{ .cp = 'P' } }); + try std.testing.expect(p.clip_pending != null); + p.update(.{ .key = .{ .cp = 'l' } }); + try std.testing.expect(p.clip_pending == null); +} + +test "leaving tty hides the prompt and keeps the command typed at it" { + if (platform == .web) return; + const gpa = std.testing.allocator; + const p = try Pardes.init(gpa, .{ .cols = 80, .rows = 24, .file = "mise.toml" }); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 80, .rows = 24 } }); + p.update(.{ .key = .{ .cp = 'n', .alt = true } }); // a shell under the doc + const shell = p.active; + const sp = p.panes[shell].?; + try std.testing.expect(sp.isTerminal()); + + // Exactly what an OSC 133 shell draws: prompt, then the marker that says + // the rest of this row is the user's, then what they typed. One grid row. + p.update(.{ .output = .{ + .pane = @intCast(shell), + .bytes = "\x1b]133;A\x1b\\user@box ~/src $ \x1b]133;B\x1b\\grep -rn TODO src/", + } }); + p.sync(); + + const rowOf = struct { + fn at(pp: *Pardes, pane: *Pane, needle: []const u8) ?[]const u8 { + const rows = term_pane.shellRows(pp, pane) catch return null; + for (rows) |r| if (std.mem.indexOf(u8, r, needle) != null) return r; + return null; + } + }.at; + const bodyRowOf = struct { + fn at(pp: *Pardes, pane: *Pane, needle: []const u8) ?[]const u8 { + const body = term_pane.bodyText(pp.scratch.allocator(), pane) catch return null; + var it = std.mem.splitScalar(u8, body, '\n'); + while (it.next()) |r| if (std.mem.indexOf(u8, r, needle) != null) return r; + return null; + } + }.at; + + // The BODY is what you look at, and it follows the mode: in tty the pane + // is the program's own screen, so the prompt is there. + sp.mode = .tty; + try std.testing.expectEqualStrings( + "user@box ~/src $ grep -rn TODO src/", + bodyRowOf(p, sp, "grep") orelse return error.MissingPromptRow, + ); + + // Out of tty the prompt goes and the command stays โ€” LEFT-HUGGED, so it + // lines up with the output below instead of sitting in a bay of blanks + // where the prompt used to be. + sp.mode = .normal; + try std.testing.expectEqualStrings( + "grep -rn TODO src/", + bodyRowOf(p, sp, "grep") orelse return error.MissingPromptRow, + ); + + // The MOTION SURFACE cuts either way, and deliberately: it is what the + // cursor moves over, and in tty mode nothing moves over it โ€” the keys all + // belong to the program. + p.shell_rows.stale = true; + try std.testing.expectEqualStrings( + "grep -rn TODO src/", + rowOf(p, sp, "grep") orelse return error.MissingPromptRow, + ); + + // ...and a prompt with nothing typed at it yet is all chrome, so the whole + // row goes, which is what it has always done. + p.update(.{ .output = .{ + .pane = @intCast(shell), + .bytes = "\r\n\x1b]133;A\x1b\\user@box ~/src $ \x1b]133;B\x1b\\", + } }); + p.sync(); + p.shell_rows.stale = true; + try std.testing.expect(rowOf(p, sp, "user@box") == null); +} + +test "entering tty walks the shell cursor to the column clicked past the prompt" { + if (platform == .web) return; + const gpa = std.testing.allocator; + const p = try Pardes.init(gpa, .{ .cols = 80, .rows = 24, .file = "mise.toml" }); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 80, .rows = 24 } }); + p.update(.{ .key = .{ .cp = 'n', .alt = true } }); + const shell = p.active; + const sp = p.panes[shell].?; + p.update(.{ .output = .{ + .pane = @intCast(shell), + .bytes = "\x1b]133;A;cl=line\x1b\\prompt> \x1b]133;B\x1b\\0123456789", + } }); + p.sync(); + sp.mode = .normal; + p.shell_rows.stale = true; + + // The command shows LEFT-HUGGED, so its column 3 is the '3'... + const rows = try term_pane.shellRows(p, sp); + var row: i32 = 0; + const at = for (rows, 0..) |r, i| { + if (std.mem.indexOf(u8, r, "0123456789") != null) break i; + } else return error.MissingInputRow; + row = @intCast(at); + try std.testing.expectEqualStrings("0123456789", rows[at]); + + // ...but the shell's own cursor lives on the real grid, eight cells + // further right, behind the prompt this pane is not showing. + sp.cur_row = row; + sp.cur_col = 3; + sp.cur_pinned = true; + while (p.nextEffect()) |_| {} + p.enterTty(shell); + + // The walk is arrow keys the shell understands. Seven lefts: readline's + // cursor sits past the '9' and the click was on the '3'. + var lefts: usize = 0; + var rights: usize = 0; + while (p.nextEffect()) |effect| switch (effect) { + .write => |wr| { + if (std.mem.eql(u8, wr.bytes.slice(), "\x1b[D")) lefts += 1; + if (std.mem.eql(u8, wr.bytes.slice(), "\x1b[C")) rights += 1; + }, + else => {}, + }; + try std.testing.expectEqual(@as(usize, 0), rights); + try std.testing.expectEqual(@as(usize, 7), lefts); +} diff --git a/src/term_pane.zig b/src/term_pane.zig index 9f13832f..1243dfa1 100644 --- a/src/term_pane.zig +++ b/src/term_pane.zig @@ -18,6 +18,7 @@ const Pane = pardes.Pane; const EditSnap = pardes.EditSnap; const Ovl = pardes.Ovl; const modal = @import("modal.zig"); +const config = @import("config.zig"); /// The memo behind `shellRows`. ONE entry for the editor, because the motion /// surface is built for the pane the cursor is in and a second pane asking @@ -78,6 +79,65 @@ const Rows = struct { rows: [][]const u8, }; +/// What LEAVING raw tty mode does to one prompt row, decided from its cells +/// alone. See config.tty_blank for why any of this happens. +pub const PromptCut = union(enum) { + /// show the row exactly as ghostty dumped it + keep, + /// show nothing at all + blank, + /// drop this many leading COLUMNS โ€” the prompt โ€” and keep the rest, which + /// is what was typed at it + cut: usize, +}; + +/// The prompt and the command typed at it share a grid row, and OSC 133 marks +/// them apart CELL by cell (`Cell.semantic_content` is output / input / +/// prompt). The row flag every caller tests first is only ghostty's "some cell +/// in here is a prompt cell" index; taking the row on that flag alone is what +/// used to throw the command away with the prompt. +pub fn promptCut(pin: ghostty_vt.Pin) PromptCut { + if (config.tty_blank == .prompt_and_input) return .blank; + const cells = pin.cells(.all); + var cols: usize = 0; + while (cols < cells.len and cells[cols].semantic_content == .prompt) cols += 1; + // Flagged, but with no prompt cells at the FRONT: a right-side prompt, or + // a repaint that has moved on. Nothing here is the prompt, so hide nothing. + if (cols == 0) return .keep; + // ...and all prompt, nothing typed yet: the row is chrome end to end. + if (cols >= cells.len) return .blank; + return .{ .cut = cols }; +} + +/// That decision applied to `raw`, the line ghostty dumped for `pin`'s row. +/// Always a slice OF `raw` โ€” dropping the prompt is a left-hug, so the command +/// starts at column 0 with no run of blanks in front of it where the prompt +/// used to be, and there is nothing to allocate or copy anywhere. +/// +/// Walking the dump rather than rebuilding the row out of cells keeps ghostty +/// the single authority on how a cell spells itself โ€” wide glyphs, combining +/// marks and all. One non-spacer cell is one dumped grapheme, and that is what +/// makes the cell walk and the byte walk stay in step. +pub fn promptRow(pin: ghostty_vt.Pin, raw: []const u8) []const u8 { + const cols = switch (promptCut(pin)) { + .keep => return raw, + .blank => return "", + .cut => |n| n, + }; + const cells = pin.cells(.all); + var at: usize = 0; + var col: usize = 0; + while (col < cols and at < raw.len) { + const cell = &cells[col]; + var cps: usize = 1; + if (pin.grapheme(cell)) |extra| cps += extra.len; + for (0..cps) |_| at = modal.nextGrapheme(raw, at); + // the tail cell of a wide glyph spells nothing of its own + col += if (cell.wide == .wide) @as(usize, 2) else 1; + } + return std.mem.trimEnd(u8, raw[at..], " \t"); +} + /// A terminal's shell rows as the surface sees them: the WHOLE /// history+active grid, prompt rows blanked (OSC 133), absolute grid rows /// from 0. The raw material the motion surface is composed from โ€” the @@ -130,8 +190,10 @@ fn buildRows(alloc: std.mem.Allocator, p: *Pardes, pane: *Pane) !Rows { var n: usize = 0; var it = std.mem.splitScalar(u8, full, '\n'); while (it.next()) |raw| { - const is_prompt = if (pit.next()) |pin| pin.rowAndCell().row.semantic_prompt != .none else false; - const shown = if (is_prompt) "" else raw; + const shown = if (pit.next()) |pin| + if (pin.rowAndCell().row.semantic_prompt != .none) promptRow(pin, raw) else raw + else + raw; if (n > 0) { text[at] = '\n'; at += 1; @@ -159,11 +221,13 @@ pub fn bodyText(arena: std.mem.Allocator, pane: *Pane) ![]const u8 { var lines = std.mem.splitScalar(u8, raw, '\n'); var n: usize = 0; while (lines.next()) |ln| { - const is_prompt = if (pane.mode != .tty) - if (prompts.next()) |pin| pin.rowAndCell().row.semantic_prompt != .none else false + vp[n] = if (pane.mode != .tty) + if (prompts.next()) |pin| + if (pin.rowAndCell().row.semantic_prompt != .none) promptRow(pin, ln) else ln + else + ln else - false; - vp[n] = if (is_prompt) "" else ln; + ln; n += 1; } std.debug.assert(n == vp.len); diff --git a/src/tty/tty.zig b/src/tty/tty.zig index e8e3c1bd..eadc3a9d 100644 --- a/src/tty/tty.zig +++ b/src/tty/tty.zig @@ -37,6 +37,13 @@ pub const Command = struct { winsize: vaxis.Winsize, mouse: vaxis.Mouse, paste: []const u8, + /// The bracketed-paste brackets. vaxis posts them ONLY because this + /// union declares fields with these exact names โ€” its Loop gates every + /// event on `@hasField` โ€” and the pasted bytes themselves arrive + /// BETWEEN them as ordinary key presses, which the loop accumulates + /// into one `.paste` above instead of running as commands. + paste_start, + paste_end, /// a language query finished on a worker; rows are lsp-domain-owned lsp_done: struct { id: u32, rows: []u8 }, /// a selection-filter worker finished; every stdout is gpa-owned @@ -403,6 +410,15 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { // gtk-enable-primary-paste=false โ€” no mode we request can surface middle // clicks there (see test/snapshots/ghostty-mid.snap). try vx.setMouseMode(tty.writer(), true); + // Bracketed paste. Without it a paste into pardes-in-a-terminal is just a + // flood of key presses: plausible-looking in insert mode, and in normal + // mode every pasted character runs as a command. With it the terminal + // wraps the bytes in \x1b[200~ / \x1b[201~ and the loop coalesces them. + // No defer to switch it back off, for the same reason the mouse modes + // above have none: setBracketedPaste records state.bracketed_paste, and + // vaxis's resetState โ€” reached from the `defer vx.deinit` above, while the + // tty is still open โ€” sends the disable off that flag. + try vx.setBracketedPaste(tty.writer(), true); pardes.image.start(io, allocs.image); if (comptime pardes.pdf_enabled) pardes.pdf.start(allocs.pdf); @@ -569,6 +585,16 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { var check_files = false; var pending: ?@TypeOf(Command.value) = .tick; + // Where a bracketed paste is assembled. It has to outlive one drain pass: + // the burst arrives over as many passes as the terminal takes to write it, + // and the markers are the only thing that says where it ends. + var paste_buf: std.Io.Writer.Allocating = .init(gpa); + defer paste_buf.deinit(); + var in_paste = false; + // 4 MiB ceiling, past which the tail is dropped rather than grown into. A + // paste that large is a mis-click on a file, not an edit, and the core + // would have to hold the whole of it as one undo entry. + const max_paste_bytes: usize = 4 << 20; while (!core.quit) { var event = if (pending) |ev| blk: { pending = null; @@ -610,7 +636,31 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { } core.update(.{ .eof = .{ .pane = @intCast(e.id) } }); }, - .key_press => |key| core.update(.{ .key = .{ + .key_press => |key| if (in_paste) { + // Between the markers a key is DATA, never a command. Same + // two inputs as the dispatch below, so a pasted character + // is exactly the character the core would have been given. + const text = key.text orelse ""; + const cp = mapKey(effCp(key)); + const bytes: []const u8 = if (text.len > 0) + text + else if (cp == pardes.Key.tab) + "\t" + else if (cp == pardes.Key.enter or (key.mods.ctrl and cp == 'j')) + // vaxis gives control bytes no text at all: a line + // break inside a paste reaches the ground parser as a + // bare CR (-> Key.enter) or, from a terminal that does + // not translate them, a bare LF โ€” which that parser + // reports as ctrl+j. Nothing in here is a real + // keypress, so both of them are just a newline. + "\n" + else + // arrows, F-keys, a stray escape: noise a paste has no + // business carrying, dropped rather than smuggled in. + ""; + const room = max_paste_bytes -| paste_buf.written().len; + paste_buf.writer.writeAll(bytes[0..@min(bytes.len, room)]) catch {}; + } else core.update(.{ .key = .{ .cp = mapKey(effCp(key)), .text = key.text orelse "", .ctrl = key.mods.ctrl, @@ -653,6 +703,18 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { core.update(.{ .paste = bytes }); gpa.free(@constCast(bytes)); }, + .paste_start => { + in_paste = true; + paste_buf.clearRetainingCapacity(); + }, + .paste_end => { + in_paste = false; + // ONE event for the whole paste โ€” the core borrows the + // bytes for the call, exactly like the OSC 52 arm above. + const pasted = paste_buf.written(); + if (pasted.len > 0) core.update(.{ .paste = pasted }); + paste_buf.clearRetainingCapacity(); + }, .command => |line| { core.update(.{ .command = line }); gpa.free(line); @@ -683,7 +745,12 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { }, } batch += 1; - if (stop or output or native_pdf_page_changed or batch >= 64) break; + // A paste in flight keeps draining WITHOUT rendering: a hundred + // thousand pasted characters are one edit, not a hundred thousand + // render-worthy events. That cannot spin โ€” the drain still ends + // the moment the queue runs dry (tryEvent below) โ€” so a terminal + // which sends paste_start and never paste_end costs one frame. + if (stop or output or native_pdf_page_changed or (!in_paste and batch >= 64)) break; event = (try loop.tryEvent()) orelse break; } tz_event.end(); @@ -983,6 +1050,20 @@ fn drainEffects( // mirror the core's yank register out via OSC 52 if (core.yank) |y| vx.copyToSystemClipboard(tty.writer(), y, gpa) catch {}; }, + .read_clipboard => { + // ...and the other direction, OSC 52 read. The answer arrives on + // vaxis's reader thread as an ordinary `.paste` event and reaches + // the core through the same path an outer bracketed paste does โ€” + // this request is the only wiring it needs. "The answer arrives" + // is the optimistic reading: a clipboard READ is an exfiltration + // primitive and terminals treat it as one (ghostty prompts by + // default, xterm ships it off, a multiplexer or ssh link may eat + // it), and a refusal looks exactly like silence. So the core's + // pending request is dropped by the next keystroke rather than + // pasting minutes late, and `SPC p` in a locked-down terminal + // honestly does nothing. + vx.requestSystemClipboard(tty.writer()) catch {}; + }, .lsp => |q| { if (!threads_ok) continue; // pre-loop drain: nothing to answer to yet const pane = core.panes[q.pane] orelse continue; diff --git a/src/tutor.txt b/src/tutor.txt index 1d51a4ac..fe80c9e3 100644 --- a/src/tutor.txt +++ b/src/tutor.txt @@ -164,16 +164,25 @@ edit, select and look in. It is not a document, though, and never takes a column of its own: it opens BELOW the pane that asked for it, in that pane's column, be that a file or a shell โ€” and a file you then open from - its rows goes where files go, not under the list. `n`/`N` step the rows - and look each one, so the view follows along. Right-clicking a word that names no file in ANY open - pane's directory searches for it โ€” acme's button 3 โ€” except in tty mode, - where the click belongs to the program on the other end. On a shell with no - search armed, n/N instead step the lookable tokens in its output. + its rows goes where files go, not under the list. `n`/`N` walk those + rows, and walking is ALL they do: a press moves the SELECTION to the + next look-able thing and opens nothing, so you can step past nine hits + to reach the tenth without opening the nine. Enter โ€” the look chord โ€” + opens the one you stopped on. The walk is a RING over PANES and not + over one buffer: the panes you have looked out of come first, most + recent first, then the output buffers you have not, newest first, and + only when there is neither does it step the pane in front of you โ€” so + n/N work on a shell that never had a search armed, and off the end + they come round to the start. `N` is `n` backwards exactly: ten + forward and ten back is where you began. + Right-clicking a word that names no file in ANY open pane's + directory searches for it โ€” acme's button 3 โ€” except in tty mode, + where the click belongs to the program on the other end. A hit in a file reads `path:LINE:COL-ENDCOL`, the ordinary look target carrying the SPAN that matched. A hit in a shell or an output buffer has no file to name, so it reads `@pN:LINE:COL-ENDCOL` โ€” pane N, then the place in - it. Looking either one goes there and SELECTS the span, which is why n/N - land ON a hit rather than beside it. + it. Looking either one goes there and SELECTS the span, which is why an + Enter on a row n/N stepped to lands ON the hit rather than beside it. The range is part of the PATH syntax and not part of search: type one anywhere text lives and a look on it selects. `main.zig:412-418` is whole lines, `main.zig:412:9-21` is columns on one line, `main.zig:412:9-418:1` @@ -182,8 +191,9 @@ FIND: the "Find" builtin (SPC f f) arms the same tag input, but Enter walks the pane's DIRECTORY instead of its text โ€” `fd`, in-core โ€” and writes one matching PATH per row into the same "+Search" buffer. Rows are look - targets like any other, so n/N step them and each found file opens; the - match is on the name, plain and case-insensitive, ".git" is skipped. + targets like any other, so n/N select them one at a time and Enter + opens the one you meant; the match is on the name, plain and + case-insensitive, ".git" is skipped. LAYOUT: columns split the screen; windows stack within a column. Panes abut with no wasted gap โ€” a pane's own trailing edge (its last column, or @@ -519,6 +529,10 @@ SPC k Kill (quit) SPC d Del (close this pane) SPC f s/f f/f n Save / Find / New SPC h t Tutor (this file) SPC c n / c d Newcol / Delcol + SPC y / SPC Y the selection to the SYSTEM clipboard (every + cursor's text joined, or the main cursor's alone) + SPC p / SPC P paste the system clipboard after / before the + selection; SPC R replaces the selection with it SPC t d/c/n/r Debug / Colors / NextColor / Crt toggles SPC t p/l/a Petscii / Palette / Ascii: an image pane's renderer โ€” glyph art instead of pixels, the C64 @@ -530,6 +544,14 @@ SPC j j Last: the pane you were in before this one โ€” what body-normal ESC runs, so it alternates + Those five are helix's own clipboard letters, and the only words that + reach the desktop's clipboard at all: ordinary y d c p P R and the + 1-2 / 1-3 chords all stay in pardes' own register, so deleting a + character can never throw away what you copied from a browser. In a + terminal the copy goes out as OSC 52 and the paste asks for it back + the same way โ€” plenty of terminals refuse that read, so there SPC y + works and SPC p may honestly do nothing. + `?` works at ANY depth: SPC ? lists everything, SPC h ? lists only what the "h" group holds. Help writes into a "+Help" OUTPUT BUFFER, the same kind of pane "/" search results land in โ€” so it opens below @@ -565,9 +587,11 @@ k off the TOPMOST tagline = the top bar, j back down) zt zz zb Ctrl-d/u Ctrl-f Ctrl-w hjkl Alt-n/c Esc = last document <-> last terminal (body normal) + n/N = select the next/prev look-able text, across panes + (a ring); Enter opens what you landed on SPC = the leader: a key path runs a builtin (SPC ? lists them; SPC k Kill, SPC d Del, SPC f s Save, SPC f f Find, - SPC f n New, + SPC f n New, SPC y/Y/p/P/R the system clipboard, SPC w hjkl focus, SPC j j the pane before this one) vs Helix: no multi-cursor; selection is LINE-first (x), plus v chars. diff --git a/src/web.zig b/src/web.zig index e17e147e..637fa56f 100644 --- a/src/web.zig +++ b/src/web.zig @@ -438,6 +438,10 @@ export fn pardes_effect_next() u32 { if (s.core.yank) |bytes| putEffect(s, bytes); break :blk 7; }, + // 13, and no payload either way: the browser cannot hand the clipboard + // over synchronously, so the answer arrives later as an ordinary + // pardes_paste โ€” or never, if the permission prompt says no. + .read_clipboard => 13, .lsp => |e| blk: { effect_aux0 = e.id; effect_aux1 = e.pane; diff --git a/src/web/app.mjs b/src/web/app.mjs index 3d32a16b..d7a4b6f6 100644 --- a/src/web/app.mjs +++ b/src/web/app.mjs @@ -329,6 +329,11 @@ export class PardesRuntime { download(data, "pardes-dump.zon", "text/plain;charset=utf-8"); } else if (kind === 7) { navigator.clipboard?.writeText(decoder.decode(data)).catch(() => {}); + } else if (kind === 13) { + // Async and permission-gated, unlike every other effect here: a refused + // or unsupported read is simply a paste that never happens, which is + // what the core already tolerates from an empty clipboard. + navigator.clipboard?.readText().then((text) => this.wasm.pardes_paste(this.writeInput(text))).catch(() => {}); } else if (kind === 10) { this.running = false; } else { diff --git a/test/macos_e2e.swift b/test/macos_e2e.swift index 42bc8229..16992271 100644 --- a/test/macos_e2e.swift +++ b/test/macos_e2e.swift @@ -47,7 +47,7 @@ private struct ScriptError: Error { let message: String } -/// What the two C callbacks reach through `userdata`. A class, because a C +/// What the three C callbacks reach through `userdata`. A class, because a C /// function pointer cannot capture: a pointer the runtime struct carries is the /// only way back into Swift state. private final class Host { @@ -177,6 +177,18 @@ private final class Driver: PardesViewDelegate { yank = String(decoding: bytes, as: UTF8.self) } host.clipboard = yank + }, + read_clipboard: { ud in + // Main thread, inside pardes_tick, and answered on the spot: + // the core asked for the clipboard and pardes_paste hands it + // back before this returns. `host.clipboard`, never + // NSPasteboard, for the same reason as set_clipboard above. + // No pump โ€” the tick that emitted this effect is still + // draining and will pick up whatever the paste queued. + guard let ud else { return } + let host = Unmanaged.fromOpaque(ud).takeUnretainedValue() + let text = host.clipboard ?? "" + text.withCString { pardes_paste($0, text.utf8.count) } }) let rc = pardes_init(&runtime, got.cols, got.rows) diff --git a/test/snapshots/argv.golden b/test/snapshots/argv.golden index 1109132c..6cf79be0 100644 --- a/test/snapshots/argv.golden +++ b/test/snapshots/argv.golden @@ -94,7 +94,7 @@ == snap dirarg grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/argv/cwd/sub New Del -| +| ls | inside.txt | | diff --git a/test/snapshots/boot.golden b/test/snapshots/boot.golden index d347b7eb..d0e9ba09 100644 --- a/test/snapshots/boot.golden +++ b/test/snapshots/boot.golden @@ -1,7 +1,7 @@ == snap boot grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/boot/cwd New Del -| +| ls | hello.txt | | diff --git a/test/snapshots/builtins.golden b/test/snapshots/builtins.golden index a54b8281..61d7bec1 100644 --- a/test/snapshots/builtins.golden +++ b/test/snapshots/builtins.golden @@ -96,30 +96,30 @@ | 2 SPC and its keys, a chord, a button, the | 3 topbar - or the name, executed anywhere. | 4 -| 5 SPC ? Help topbar -| 6 SPC c d Delcol -| 7 SPC c n Newcol topbar -| 8 SPC d Del -| 9 SPC f c Config -| 10 SPC f f Find topbar -| 11 SPC f g Grep topbar -| 12 SPC f n New topbar -| 13 SPC f s Save -| 14 SPC h t Tutor topbar -| 15 SPC j i Forward C-i -| 16 SPC j j Last -| 17 SPC j l Jumplist -| 18 SPC j o Back C-o -| 19 SPC k Kill topbar -| 20 SPC l D WsDiagnostics -| 21 SPC l S WsSymbols -| 22 SPC l a CodeAction -| 23 SPC l d Diagnostics -| 24 SPC l h SelectRefs -| 25 SPC l i Lspinfo -| 26 SPC l k Hover -| 27 SPC l r Rename -| 28 SPC l s Symbols +| 5 SPC ? Help topbar +| 6 SPC P ClipPasteBefore +| 7 SPC R ClipReplace +| 8 SPC Y ClipYankMain +| 9 SPC c d Delcol +| 10 SPC c n Newcol topbar +| 11 SPC d Del +| 12 SPC f c Config +| 13 SPC f f Find topbar +| 14 SPC f g Grep topbar +| 15 SPC f n New topbar +| 16 SPC f s Save +| 17 SPC h t Tutor topbar +| 18 SPC j i Forward C-i +| 19 SPC j j Last +| 20 SPC j l Jumplist +| 21 SPC j o Back C-o +| 22 SPC k Kill topbar +| 23 SPC l D WsDiagnostics +| 24 SPC l S WsSymbols +| 25 SPC l a CodeAction +| 26 SPC l d Diagnostics +| 27 SPC l h SelectRefs +| 28 SPC l i Lspinfo == snap index-tail grid=120x60 cursor=7,58 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del @@ -153,34 +153,34 @@ | | | /tmp/pardes-snap/builtins/cwd/+Help New Del -| 26 SPC l k Hover -| 27 SPC l r Rename -| 28 SPC l s Symbols -| 29 SPC l w Lspwhy -| 30 SPC s d Dump topbar -| 31 SPC s r Restore -| 32 SPC t a Ascii -| 33 SPC t b Tagbottom -| 34 SPC t c Colors -| 35 SPC t d Debug topbar -| 36 SPC t i PdfTint -| 37 SPC t l Palette -| 38 SPC t n NextColor topbar -| 39 SPC t p Petscii -| 40 SPC t r Crt -| 41 SPC t s PdfSections -| 42 SPC t t ThemeSel -| 43 SPC t w Wrap -| 44 SPC t z PdfFit -| 45 SPC w h Left C-w h, C-w left -| 46 SPC w j Down C-w j, C-w down -| 47 SPC w k Up C-w k, C-w up -| 48 SPC w l Right C-w l, C-w right -| 49 Look enter, right-click -| 50 Exec tab, middle-click -| 51 Theme -| 52 Shell -| 53 +| 31 SPC l s Symbols +| 32 SPC l w Lspwhy +| 33 SPC p ClipPaste +| 34 SPC s d Dump topbar +| 35 SPC s r Restore +| 36 SPC t a Ascii +| 37 SPC t b Tagbottom +| 38 SPC t c Colors +| 39 SPC t d Debug topbar +| 40 SPC t i PdfTint +| 41 SPC t l Palette +| 42 SPC t n NextColor topbar +| 43 SPC t p Petscii +| 44 SPC t r Crt +| 45 SPC t s PdfSections +| 46 SPC t t ThemeSel +| 47 SPC t w Wrap +| 48 SPC t z PdfFit +| 49 SPC w h Left C-w h, C-w left +| 50 SPC w j Down C-w j, C-w down +| 51 SPC w k Up C-w k, C-w up +| 52 SPC w l Right C-w l, C-w right +| 53 SPC y ClipYank +| 54 Look enter, right-click +| 55 Exec tab, middle-click +| 56 Theme +| 57 Shell +| 58 == snap not-a-picker grid=120x60 cursor=7,58 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del @@ -214,34 +214,34 @@ | | | /tmp/pardes-snap/builtins/cwd/+Help New Del -| 26 SPC l k Hover -| 27 SPC l r Rename -| 28 SPC l s Symbols -| 29 SPC l w Lspwhy -| 30 SPC s d Dump topbar -| 31 SPC s r Restore -| 32 SPC t a Ascii -| 33 SPC t b Tagbottom -| 34 SPC t c Colors -| 35 SPC t d Debug topbar -| 36 SPC t i PdfTint -| 37 SPC t l Palette -| 38 SPC t n NextColor topbar -| 39 SPC t p Petscii -| 40 SPC t r Crt -| 41 SPC t s PdfSections -| 42 SPC t t ThemeSel -| 43 SPC t w Wrap -| 44 SPC t z PdfFit -| 45 SPC w h Left C-w h, C-w left -| 46 SPC w j Down C-w j, C-w down -| 47 SPC w k Up C-w k, C-w up -| 48 SPC w l Right C-w l, C-w right -| 49 Look enter, right-click -| 50 Exec tab, middle-click -| 51 Theme -| 52 Shell -| 53 +| 31 SPC l s Symbols +| 32 SPC l w Lspwhy +| 33 SPC p ClipPaste +| 34 SPC s d Dump topbar +| 35 SPC s r Restore +| 36 SPC t a Ascii +| 37 SPC t b Tagbottom +| 38 SPC t c Colors +| 39 SPC t d Debug topbar +| 40 SPC t i PdfTint +| 41 SPC t l Palette +| 42 SPC t n NextColor topbar +| 43 SPC t p Petscii +| 44 SPC t r Crt +| 45 SPC t s PdfSections +| 46 SPC t t ThemeSel +| 47 SPC t w Wrap +| 48 SPC t z PdfFit +| 49 SPC w h Left C-w h, C-w left +| 50 SPC w j Down C-w j, C-w down +| 51 SPC w k Up C-w k, C-w up +| 52 SPC w l Right C-w l, C-w right +| 53 SPC y ClipYank +| 54 Look enter, right-click +| 55 Exec tab, middle-click +| 56 Theme +| 57 Shell +| 58 == snap window-group grid=120x60 cursor=7,32 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del @@ -277,10 +277,10 @@ | /tmp/pardes-snap/builtins/cwd/+Help New Del | 1 pardes builtins under SPC w | 2 -| 3 SPC w h Left C-w h, C-w left -| 4 SPC w j Down C-w j, C-w down -| 5 SPC w k Up C-w k, C-w up -| 6 SPC w l Right C-w l, C-w right +| 3 SPC w h Left C-w h, C-w left +| 4 SPC w j Down C-w j, C-w down +| 5 SPC w k Up C-w k, C-w up +| 6 SPC w l Right C-w l, C-w right | 7 | | @@ -340,27 +340,27 @@ | 2 SPC and its keys, a chord, a button, the | 3 topbar - or the name, executed anywhere. | 4 -| 5 SPC ? Help topbar -| 6 SPC c d Delcol -| 7 SPC c n Newcol topbar -| 8 SPC d Del -| 9 SPC f c Config -| 10 SPC f f Find topbar -| 11 SPC f g Grep topbar -| 12 SPC f n New topbar -| 13 SPC f s Save -| 14 SPC h t Tutor topbar -| 15 SPC j i Forward C-i -| 16 SPC j j Last -| 17 SPC j l Jumplist -| 18 SPC j o Back C-o -| 19 SPC k Kill topbar -| 20 SPC l D WsDiagnostics -| 21 SPC l S WsSymbols -| 22 SPC l a CodeAction -| 23 SPC l d Diagnostics -| 24 SPC l h SelectRefs -| 25 SPC l i Lspinfo -| 26 SPC l k Hover -| 27 SPC l r Rename -| 28 SPC l s Symbols +| 5 SPC ? Help topbar +| 6 SPC P ClipPasteBefore +| 7 SPC R ClipReplace +| 8 SPC Y ClipYankMain +| 9 SPC c d Delcol +| 10 SPC c n Newcol topbar +| 11 SPC d Del +| 12 SPC f c Config +| 13 SPC f f Find topbar +| 14 SPC f g Grep topbar +| 15 SPC f n New topbar +| 16 SPC f s Save +| 17 SPC h t Tutor topbar +| 18 SPC j i Forward C-i +| 19 SPC j j Last +| 20 SPC j l Jumplist +| 21 SPC j o Back C-o +| 22 SPC k Kill topbar +| 23 SPC l D WsDiagnostics +| 24 SPC l S WsSymbols +| 25 SPC l a CodeAction +| 26 SPC l d Diagnostics +| 27 SPC l h SelectRefs +| 28 SPC l i Lspinfo diff --git a/test/snapshots/builtins.snap b/test/snapshots/builtins.snap index f6b5723b..3b8fb684 100644 --- a/test/snapshots/builtins.snap +++ b/test/snapshots/builtins.snap @@ -30,10 +30,12 @@ snap index key g e stable 700 15000 snap index-tail -# n/N here must NOT run the rows. ThemeSel's buffer executes what it steps -# onto, and that is safe because wearing a theme is free; this list holds Kill, -# Del and Delcol, so stepping it would end the session. Three presses, and the -# panes and the listing are all where they were. +# n/N here run NOTHING, and no longer could: they are a MOTION, and the only +# thing they do is move the selection onto look-able text. A row here is a key +# path and a NAME โ€” this list holds Kill, Del and Delcol โ€” and a name is not a +# path, so the ring finds nothing to stop on in this buffer or in the file +# above it. Three presses, and the panes and the listing are all where they +# were. Picking a command is executing its row, two snaps down. key n key n key n @@ -48,17 +50,20 @@ wait 10000 Right stable 700 15000 snap window-group # back to the whole index, and a NAME in it is live text like anywhere else: -# middle-click `Tutor` and the tutor opens. That is the picking a stepping -# picker would have done, minus running the rows you passed. +# middle-click `Tutor` and the tutor opens. That is how a list of commands is +# picked from โ€” you run the row you want and the ones you passed stay unrun, +# which is the whole reason n/N were never allowed to be the picker. # # The one place in this suite a builtin cannot be added for free: the click is # a SCREEN coordinate, so every row inserted above `SPC h t` in the listing -# moves Tutor down one and this number with it. +# moves Tutor down one and this number with it. The five clipboard builtins +# put three there โ€” SPC P, SPC R and SPC Y, uppercase sorting ahead of the +# lowercase `SPC h` โ€” which is why this reads 49 and not 46. key space ? wait 10000 SPC c n stable 700 15000 -press middle 20 46 -release middle 20 46 +press middle 20 49 +release middle 20 49 wait 10000 PARDES TUTOR stable 700 15000 snap tutor-from-index diff --git a/test/snapshots/chordcut.golden b/test/snapshots/chordcut.golden index ebe3769a..16d007e2 100644 --- a/test/snapshots/chordcut.golden +++ b/test/snapshots/chordcut.golden @@ -1,7 +1,7 @@ == snap opened grid=90x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4 @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/chordcut/cw -| +| ls | f.txt g.txt | | @@ -32,7 +32,7 @@ == snap cut grid=90x30 cursor=7,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 2 f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4 @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/chordcut/cw -| +| ls | f.txt g.txt | | @@ -63,7 +63,7 @@ == snap copied grid=90x30 cursor=10,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 2 f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4 @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/chordcut/cw -| +| ls | f.txt g.txt | | @@ -94,7 +94,7 @@ == snap pointpaste grid=90x30 cursor=16,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 2 f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4line @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/chordcut/cw -| +| ls | f.txt g.txt | | @@ -125,7 +125,7 @@ == snap replaced grid=90x30 cursor=11,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 2 f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4line @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/chordcut/cw -| +| ls | f.txt g.txt | | @@ -156,7 +156,7 @@ == snap cancelexec grid=90x30 cursor=25,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4line @@ -171,7 +171,7 @@ | | | /tmp/pardes-snap/chordcut/cw -| +| ls | f.txt g.txt | | @@ -187,7 +187,7 @@ == snap execafter grid=90x30 cursor=25,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4line @@ -202,7 +202,7 @@ | | | /tmp/pardes-snap/chordcut/cw -| +| ls | f.txt g.txt | | @@ -218,7 +218,7 @@ == snap cancellook grid=90x30 cursor=25,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4line @@ -233,7 +233,7 @@ | | | /tmp/pardes-snap/chordcut/cw -| +| ls | f.txt g.txt | | @@ -249,7 +249,7 @@ == snap lookafter grid=90x30 cursor=7,17 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls ls | 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt | 3 line 3 | 4 line 4line @@ -264,7 +264,7 @@ | | | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls | 2 line 2 f.txt g.txt | 3 | @@ -342,7 +342,7 @@ == snap ttyprobe grid=90x30 cursor=44,13 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw$ /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 $ ls +| 1 line 1 $ ls ls | 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt | 3 line 3 $ | 4 line 4line $ @@ -357,7 +357,7 @@ | | | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls | 2 line 2 f.txt g.txt | 3 | @@ -373,7 +373,7 @@ == snap ttyprompt grid=90x30 cursor=38,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/chordcut/cw$ /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 $ ls +| 1 line 1 $ ls ls | 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt | 3 line 3 $ | 4 line 4line $ @@ -388,7 +388,7 @@ | $ | $ line | /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw -| 1 line 1 +| 1 line 1 ls | 2 line 2 f.txt g.txt | 3 | diff --git a/test/snapshots/cmdword.golden b/test/snapshots/cmdword.golden index f5d6f003..940ce6fb 100644 --- a/test/snapshots/cmdword.golden +++ b/test/snapshots/cmdword.golden @@ -48,7 +48,7 @@ | | /tmp/pardes-snap/cmdword/cwd New Del | echo ZZ''E -| +| echo ZZ''E | ZZE | | @@ -79,9 +79,9 @@ | | /tmp/pardes-snap/cmdword/cwd New Del | echo ZZ''E -| +| echo ZZ''E | ZZE -| +| echo ZZ''L | ZZL | | @@ -110,9 +110,9 @@ | | /tmp/pardes-snap/cmdword/cwd New Del | echo ZZ''E -| +| echo ZZ''E | ZZE -| +| echo ZZ''L | ZZL | | @@ -141,11 +141,11 @@ | | /tmp/pardes-snap/cmdword/cwd New Del | echo ZZ''E -| +| echo ZZ''E | ZZE -| +| echo ZZ''L | ZZL -| +| ls | cmds.txt p.txt zzmark.txt | | @@ -172,11 +172,11 @@ | | /tmp/pardes-snap/cmdword/cwd New Del Exec | echo ZZ''E -| +| echo ZZ''E | ZZE -| +| echo ZZ''L | ZZL -| +| ls | cmds.txt p.txt zzmark.txt | | @@ -203,13 +203,13 @@ | | /tmp/pardes-snap/cmdword/cwd New Del Exec @`echo ZZ''T` | echo ZZ''E -| +| echo ZZ''E | ZZE -| +| echo ZZ''L | ZZL -| +| ls | cmds.txt p.txt zzmark.txt -| +| echo ZZ''T | ZZT | | diff --git a/test/snapshots/cornerdrag.golden b/test/snapshots/cornerdrag.golden index ae933701..a1aa5d03 100644 --- a/test/snapshots/cornerdrag.golden +++ b/test/snapshots/cornerdrag.golden @@ -1,7 +1,7 @@ == snap hover-corner grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cornerdrag/cwd New Del โ•Ž /tmp/pardes-snap/cornerdrag/cwd New Del -| โ•Ž +| ls โ•Ž ls | w.txt โ•Ž w.txt | โ•Ž | โ•Ž @@ -16,7 +16,7 @@ | โ•Ž |โ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œ | /tmp/pardes-snap/cornerdrag/cwd New Del โ•Ž -| โ•Ž +| ls โ•Ž | w.txt โ•Ž | โ•Ž | โ•Ž @@ -32,7 +32,7 @@ == snap edge-drag grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cornerdragโ•Žcwd New Del /tmp/pardes-snap/cornerdrag/cwd New Del -| โ•Ž +| ls โ•Ž ls | w.txt โ•Ž w.txt | โ•Ž | โ•Ž @@ -47,7 +47,7 @@ | โ•Ž | โ•Ž | /tmp/pardes-snap/cornerdragโ•Žcwd New Del -| โ•Ž +| ls โ•Ž | w.txt โ•Ž | โ•Ž | โ•Ž @@ -63,7 +63,7 @@ == snap edge-done grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cornerdrag/ /tmp/pardes-snap/cornerdrag/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/cornerdrag/ -| +| ls | w.txt | | @@ -94,7 +94,7 @@ == snap corner-drag grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cornerdrag/ /tmp/pardes-snap/cornerdragโ•Žcwd New Del -| โ•Ž +| ls ls โ•Ž | w.txt w.txt โ•Ž | โ•Ž | โ•Ž @@ -109,7 +109,7 @@ | โ•Ž | โ•Ž | /tmp/pardes-snap/cornerdrag/ โ•Ž -| โ•Ž +| ls โ•Ž | w.txt โ•Ž | โ•Ž | โ•Ž @@ -125,14 +125,14 @@ == snap corner-done grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cornerdrag/cwd New Del /tmp/pardes-snap/cornerdrag/cwd New De -| +| ls ls | w.txt w.txt | | | | | /tmp/pardes-snap/cornerdrag/cwd New Del -| +| ls | w.txt | | @@ -156,14 +156,14 @@ == snap clamp-x grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cornerdrag/cwd New Del /tmp/pardes-snap/cornerdrag/โ•Žwd New De -| โ•Ž +| ls ls โ•Ž | w.txt w.txt โ•Ž | โ•Ž | โ•Ž | โ•Ž | โ•Ž | /tmp/pardes-snap/cornerdrag/cwd New Del โ•Ž -| โ•Ž +| ls โ•Ž | w.txt โ•Ž | โ•Ž | โ•Ž @@ -187,14 +187,14 @@ == snap clamp-y grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cornerdrag/cwd New Del โ•Ž /tmp/pardes-snap/cornerdrag/cwd New De -| โ•Ž +| ls โ•Ž ls | w.txt โ•Ž w.txt | โ•Ž | โ•Ž | โ•Ž | โ•Ž | /tmp/pardes-snap/cornerdrag/cwd New Del โ•Ž -| โ•Ž +| ls โ•Ž | w.txt โ•Ž | โ•Ž | โ•Ž @@ -218,7 +218,7 @@ == snap clamp-done grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cornerdrag/cwd New Del /tmp/pardes-snap/cornerdrag/cwd New De -| +| ls ls | w.txt w.txt | | diff --git a/test/snapshots/cursorline.golden b/test/snapshots/cursorline.golden index 3a0f5cd9..ce416b91 100644 --- a/test/snapshots/cursorline.golden +++ b/test/snapshots/cursorline.golden @@ -1,7 +1,7 @@ == snap top grid=150x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cursorline/cwd/cur.txt Save New /tmp/pardes-snap/cursorline/cwd New Del /tmp/pardes-snap/cursorline/cwd New Del -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 cur.txt cur.txt | 3 line 3 | 4 line 4 @@ -16,7 +16,7 @@ | 13 line 13 | 14 line 14 | 15 line 15 /tmp/pardes-snap/cursorline/cwd New Del -| 16 line 16 +| 16 line 16 ls | 17 line 17 cur.txt | 18 line 18 | 19 line 19 @@ -63,7 +63,7 @@ == snap down3 grid=150x30 cursor=7,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/cursorline/cwd/cur.txt Save New /tmp/pardes-snap/cursorline/cwd New Del /tmp/pardes-snap/cursorline/cwd New Del -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 cur.txt cur.txt | 3 line 3 | 4 line 4 @@ -78,7 +78,7 @@ | 13 line 13 | 14 line 14 | 15 line 15 /tmp/pardes-snap/cursorline/cwd New Del -| 16 line 16 +| 16 line 16 ls | 17 line 17 cur.txt | 18 line 18 | 19 line 19 diff --git a/test/snapshots/doccol.golden b/test/snapshots/doccol.golden index c6d5468a..a18a3546 100644 --- a/test/snapshots/doccol.golden +++ b/test/snapshots/doccol.golden @@ -1,7 +1,7 @@ == snap boot grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del -| 1 AAA +| 1 AAA ls | a.txt b.txt c.txt | | @@ -32,7 +32,7 @@ == snap two-docs grid=100x30 cursor=7,17 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del -| 1 AAA +| 1 AAA ls | a.txt b.txt c.txt | | @@ -63,7 +63,7 @@ == snap moved grid=100x30 cursor=57,20 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del -| 1 AAA +| 1 AAA ls | a.txt b.txt c.txt | | @@ -94,7 +94,7 @@ == snap worked grid=100x30 cursor=59,21 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del -| 1 AAA +| 1 AAA ls | a.txt b.txt c.txt | | @@ -125,7 +125,7 @@ == snap third grid=100x30 cursor=57,26 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del -| 1 AAA +| 1 AAA ls | a.txt b.txt c.txt | | diff --git a/test/snapshots/dump.golden b/test/snapshots/dump.golden index 2b81e2f2..1cda1a95 100644 --- a/test/snapshots/dump.golden +++ b/test/snapshots/dump.golden @@ -11,14 +11,14 @@ .{ .kind = .terminal, .tag = "/tmp/pardes-snap/dump/cwd New Del", - .body = "\nd.txt\n\n\n\n typed-marker\n\n\n\n\n\n\n\n", + .body = "ls\nd.txt\n\n\n\n typed-marker\n\n\n\n\n\n\n\n", .scroll = 0, .cols = 48, .rows = 14, .vweight = 1, .terminal = .{ .cwd = "/tmp/pardes-snap/dump/cwd", - .stream = "\nd.txt\n", + .stream = "ls\nd.txt\n", .stream_b64 = .cursor = .{ .col = 2, .row = 2 }, }, @@ -28,14 +28,14 @@ .{ .kind = .terminal, .tag = "/tmp/pardes-snap/dump/cwd New Del", - .body = "\nd.txt\n\n\n\n\n\n\n\n\n\n\n", + .body = "ls\nd.txt\n\n\n\n\n\n\n\n\n\n\n", .scroll = 0, .cols = 48, .rows = 13, .vweight = 1, .terminal = .{ .cwd = "/tmp/pardes-snap/dump/cwd", - .stream = "\nd.txt\n", + .stream = "ls\nd.txt\n", .stream_b64 = .cursor = .{ .col = 2, .row = 2 }, }, @@ -45,14 +45,14 @@ .{ .kind = .terminal, .tag = "/tmp/pardes-snap/dump/cwd New Del", - .body = "\nd.txt\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", + .body = "ls\nd.txt\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", .scroll = 0, .cols = 48, .rows = 28, .vweight = 1, .terminal = .{ .cwd = "/tmp/pardes-snap/dump/cwd", - .stream = "\nd.txt\n", + .stream = "ls\nd.txt\n", .stream_b64 = .cursor = .{ .col = 2, .row = 2 }, }, diff --git a/test/snapshots/edit.golden b/test/snapshots/edit.golden index 58fda8f9..ed7a2a41 100644 --- a/test/snapshots/edit.golden +++ b/test/snapshots/edit.golden @@ -1,7 +1,7 @@ == snap inserted grid=100x30 cursor=16,9 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/edit/cwd New Del /tmp/pardes-snap/edit/cwd New Del -| +| ls ls | e.txt e.txt | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/edit/cwd New Del -| +| ls | e.txt | | diff --git a/test/snapshots/exec-bigdrag.golden b/test/snapshots/exec-bigdrag.golden index da0e2467..3cfe6ef9 100644 --- a/test/snapshots/exec-bigdrag.golden +++ b/test/snapshots/exec-bigdrag.golden @@ -1,61 +1,61 @@ == snap alive grid=200x60 cursor=119,37 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/exec-bigdrag/cwd New Del /tmp/pardes-snap/exec-bigdrag/cwd New Del -| bash: line: command not found -| big.txt +| ls bash: line: command not found +| big.txt 4line 2705line 2706line 2707line 2708line 2709line 2710line 2711line 2712line 2713line 2714lin | bash: 4line: command not found -| +| 15line 2716line 2717line 2718line 2719line 2720line 2721line 2722line 2723line 2724line 2725li | bash: 15line: command not found -| +| 726line 2727line 2728line 2729line 2730line 2731line 2732line 2733line 2734line 2735line 2736l | bash: 726line: command not found -| +| 2737line 2738line 2739line 2740line 2741line 2742line 2743line 2744line 2745line 2746line 2747 | bash: 2737line: command not found -| +| 2748line 2749line 2750line 2751line 2752line 2753line 2754line 2755line 2756line 2757line 275 | bash: 2748line: command not found -| +| e 2759line 2760line 2761line 2762line 2763line 2764line 2765line 2766line 2767line 2768line 27 | bash: e: command not found -| +| ne 2770line 2771line 2772line 2773line 2774line 2775line 2776line 2777line 2778line 2779line 2 | bash: ne: command not found -| +| ine 2781line 2782line 2783line 2784line 2785line 2786line 2787line 2788line 2789line 2790line | bash: ine: command not found -| +| line 2792line 2793line 2794line 2795line 2796line 2797line 2798line 2799line 2800line 2801line | bash: line: command not found -| +| 2line 2803line 2804line 2805line 2806line 2807line 2808line 2809line 2810line 2811line 2812lin | bash: 2line: command not found -| +| 13line 2814line 2815line 2816line 2817line 2818line 2819line 2820line 2821line 2822line 2823li | bash: 13line: command not found -| +| 824line 2825line 2826line 2827line 2828line 2829line 2830line 2831line 2832line 2833line 2834l | bash: 824line: command not found -| +| 2835line 2836line 2837line 2838line 2839line 2840line 2841line 2842line 2843line 2844line 2845 | bash: 2835line: command not found -| +| 2846line 2847line 2848line 2849line 2850line 2851line 2852line 2853line 2854line 2855line 285 | bash: 2846line: command not found -| /tmp/pardes-snap/exec-bigdrag/cwd New Del -| bash: e: command not found -| big.txt +| /tmp/pardes-snap/exec-bigdrag/cwd New Del e 2857line 2858line 2859line 2860line 2861line 2862line 2863line 2864line 2865line 2866line 28 +| ls bash: e: command not found +| big.txt ne 2868line 2869line 2870line 2871line 2872line 2873line 2874line 2875line 2876line 2877line 2 | bash: ne: command not found -| +| ine 2879line 2880line 2881line 2882line 2883line 2884line 2885line 2886line 2887line 2888line | bash: ine: command not found -| echo alive-o''k +| liecho alive-o''kne 2890line 2891line 2892line 2893line 2894line 2895line 2896line 2897line 2898li | bash: line: command not found -| +| 0line 2901line 2902line 2903line 2904line 2905line 2906line 2907line 2908line 2909line 2910lin | bash: 0line: command not found -| +| 11line 2912line 2913line 2914line 2915line 2916line 2917line 2918line 2919line 2920line 2921li | bash: 11line: command not found -| +| 922line 2923line 2924line 2925line 2926line 2927line 2928line 2929line 2930line 2931line 2932l | bash: 922line: command not found -| +| 2933line 2934line 2935line 2936line 2937line 2938line 2939line 2940line 2941line 2942line 2943 | bash: 2933line: command not found -| +| 2944line 2945line 2946line 2947line 2948line 2949line 2950line 2951line 2952line 2953line 295 | bash: 2944line: command not found -| +| e 2955line 2956line 2957line 2958line 2959line 2960line 2961line 2962line 2963line 2964line 29 | bash: e: command not found -| +| ne 2966line 2967line 2968line 2969line 2970line 2971line 2972line 2973line 2974line 2975line 2 | bash: ne: command not found -| +| ine 2977line 2978line 2979line 2980line 2981line 2982line 2983line 2984line 2985line 2986line | bash: ine: command not found -| +| line 2988line 2989line 2990line 2991line 2992line 2993line 2994line 2995line 2996line 2997line | bash: line: command not found -| +| echo alive-o''k | alive-ok | diff --git a/test/snapshots/exec.golden b/test/snapshots/exec.golden index c3c53696..abc60aec 100644 --- a/test/snapshots/exec.golden +++ b/test/snapshots/exec.golden @@ -1,7 +1,7 @@ == snap exec grid=100x30 cursor=16,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/exec/cwd New Del /tmp/pardes-snap/exec/cwd New Del -| +| ls ls | e.txt e.txt | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/exec/cwd New Del -| +| ls | e.txt | | @@ -32,7 +32,7 @@ == snap kept grid=100x30 cursor=6,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/exec/cwd New Del /tmp/pardes-snap/exec/cwd New Del -| ZZARG +| ZZARG ls | ./c.sh e.txt | | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/exec/cwd New Del -| +| ls | e.txt | | @@ -63,7 +63,7 @@ == snap chord grid=100x30 cursor=6,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/exec/cwd New Del /tmp/pardes-snap/exec/cwd New Del -| ZZARG +| ZZARG ls | ./c.sh e.txt | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/exec/cwd New Del -| +| ls | e.txt | | @@ -94,7 +94,7 @@ == snap deleted grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/exec/cwd New Del /tmp/pardes-snap/exec/cwd New Del -| +| ls ls | e.txt e.txt | | diff --git a/test/snapshots/fileedit.golden b/test/snapshots/fileedit.golden index ae0a60fe..72e6b713 100644 --- a/test/snapshots/fileedit.golden +++ b/test/snapshots/fileedit.golden @@ -1,7 +1,7 @@ == snap edited grid=150x30 cursor=17,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fileedit/cwd/f.txt Save New Del /tmp/pardes-snap/fileedit/cwd New Del /tmp/pardes-snap/fileedit/cwd New Del -| 1 liEDIT''MEne 1 +| 1 liEDIT''MEne 1 ls ls | 2 line 2 f.txt f.txt | 3 line 3 | 4 line 4 @@ -16,7 +16,7 @@ | 13 line 13 | 14 line 14 | 15 line 15 /tmp/pardes-snap/fileedit/cwd New Del -| 16 line 16 +| 16 line 16 ls | 17 line 17 f.txt | 18 line 18 | 19 line 19 @@ -32,7 +32,7 @@ == snap deleted grid=150x30 cursor=7,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fileedit/cwd/f.txt Save New Del /tmp/pardes-snap/fileedit/cwd New Del /tmp/pardes-snap/fileedit/cwd New Del -| 1 liEDIT''MEne 1 +| 1 liEDIT''MEne 1 ls ls | 2 line 3 f.txt f.txt | 3 line 4 | 4 line 5 @@ -47,7 +47,7 @@ | 13 line 14 | 14 line 15 | 15 line 16 /tmp/pardes-snap/fileedit/cwd New Del -| 16 line 17 +| 16 line 17 ls | 17 line 18 f.txt | 18 line 19 | 19 line 20 @@ -63,7 +63,7 @@ == snap undone grid=150x30 cursor=13,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fileedit/cwd/f.txt Save New Del /tmp/pardes-snap/fileedit/cwd New Del /tmp/pardes-snap/fileedit/cwd New Del -| 1 liEDIT''MEne 1 +| 1 liEDIT''MEne 1 ls ls | 2 line 2 f.txt f.txt | 3 line 3 | 4 line 4 @@ -78,7 +78,7 @@ | 13 line 13 | 14 line 14 | 15 line 15 /tmp/pardes-snap/fileedit/cwd New Del -| 16 line 16 +| 16 line 16 ls | 17 line 17 f.txt | 18 line 18 | 19 line 19 diff --git a/test/snapshots/filewatch.golden b/test/snapshots/filewatch.golden index 3224dd27..f81d5709 100644 --- a/test/snapshots/filewatch.golden +++ b/test/snapshots/filewatch.golden @@ -1,7 +1,7 @@ == snap edited grid=150x30 cursor=15,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/filewatch/cwd/w.txt Save New De /tmp/pardes-snap/filewatch/cwd New Del /tmp/pardes-snap/filewatch/cwd New Del -| 1 liMYEDITne 1 +| 1 liMYEDITne 1 ls ls | 2 line 2 sub w.txt sub w.txt | 3 /tmp/pardes-snap/filewatch/cwd/sub/s.txt | 4 line 4 @@ -16,7 +16,7 @@ | 13 | | /tmp/pardes-snap/filewatch/cwd/sub/s.txt Save Ne /tmp/pardes-snap/filewatch/cwd New Del -| 1 line 1 +| 1 line 1 ls | 2 line 2 sub w.txt | 3 line 3 | 4 line 4 @@ -32,7 +32,7 @@ == snap reloaded grid=150x30 cursor=15,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/filewatch/cwd/w.txt Save New De /tmp/pardes-snap/filewatch/cwd New Del /tmp/pardes-snap/filewatch/cwd New Del -| 1 EXTERNAL +| 1 EXTERNAL ls ls | 2 sub w.txt sub w.txt | | @@ -47,7 +47,7 @@ | | --:--:-- reloaded /tmp/pardes-snap/filewatch/cw | /tmp/pardes-snap/filewatch/cwd/sub/s.txt Save Ne /tmp/pardes-snap/filewatch/cwd New Del -| 1 line 1 +| 1 line 1 ls | 2 line 2 sub w.txt | 3 line 3 | 4 line 4 @@ -63,7 +63,7 @@ == snap reloaded_sub grid=150x30 cursor=15,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/filewatch/cwd/w.txt Save New De /tmp/pardes-snap/filewatch/cwd New Del /tmp/pardes-snap/filewatch/cwd New Del -| 1 EXTERNAL +| 1 EXTERNAL ls ls | 2 sub w.txt sub w.txt | | @@ -78,7 +78,7 @@ | | --:--:-- reloaded /tmp/pardes-snap/filewatch/cw | /tmp/pardes-snap/filewatch/cwd/sub/s.txt Save Ne /tmp/pardes-snap/filewatch/cwd New Del -| 1 RENAMED +| 1 RENAMED ls | 2 sub w.txt | | @@ -94,7 +94,7 @@ == snap undone grid=150x30 cursor=15,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/filewatch/cwd/w.txt Save New De /tmp/pardes-snap/filewatch/cwd New Del /tmp/pardes-snap/filewatch/cwd New Del -| 1 liMYEDITne 1 +| 1 liMYEDITne 1 ls ls | 2 line 2 sub w.txt sub w.txt | 3 /tmp/pardes-snap/filewatch/cwd/sub/s.txt | 4 line 4 @@ -109,7 +109,7 @@ | 13 | | /tmp/pardes-snap/filewatch/cwd/sub/s.txt Save Ne /tmp/pardes-snap/filewatch/cwd New Del -| 1 RENAMED +| 1 RENAMED ls | 2 sub w.txt | | diff --git a/test/snapshots/find.golden b/test/snapshots/find.golden index 0a33df22..30f9a2ab 100644 --- a/test/snapshots/find.golden +++ b/test/snapshots/find.golden @@ -162,7 +162,7 @@ | 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt -== snap first grid=120x40 cursor=7,2 +== snap first grid=120x40 cursor=7,20 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/find/cwd/here.txt Save New Del | 1 Find @@ -205,8 +205,8 @@ | 3 zqmark-alpha.txt == style first |0: 0-56 #949494,#121212, 57-119 d,#121212, -|1: 0-1 #ffffff,#626262, 2-99 #949494,#121212, 100-119 d,#121212, -|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-10 #bdbdbd,#080808, 11-119 d,#080808, +|1: 0-1 #ffffff,#262626, 2-99 #949494,#121212, 100-119 d,#121212, +|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-119 d,#080808, |3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, |4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, |5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, @@ -223,8 +223,8 @@ |16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, |17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, |18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, -|19: 0-1 #ffffff,#262626, 2-99 #949494,#121212, 100-119 d,#121212, -|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-119 d,#080808, +|19: 0-1 #ffffff,#626262, 2-99 #949494,#121212, 100-119 d,#121212, +|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-15 #bdbdbd,#080808, 16-119 d,#080808, |21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, |22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, |23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, @@ -241,10 +241,10 @@ |34: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, |35: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808, |36: 0-1 #ffffff,#262626, 2-99 #949494,#121212, 100-119 d,#121212, -|37: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 #080808,#80a0ff, +|37: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-25 #bdbdbd,#080808, 26-119 d,#080808, |38: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-31 #bdbdbd,#080808, 32-119 d,#080808, |39: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-119 d,#080808, -== snap second grid=120x40 cursor=7,2 +== snap second grid=120x40 cursor=7,29 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/find/cwd/here.txt Save New Del | 1 Find @@ -255,8 +255,6 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del -| 1 gamma body | | | @@ -264,10 +262,10 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del -| 1 beta body | | +| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del +| 1 beta body | | | @@ -275,6 +273,8 @@ | | | +| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del +| 1 gamma body | | | @@ -285,19 +285,15 @@ | 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt -== snap third grid=120x40 cursor=7,2 +== snap third grid=120x40 cursor=7,33 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/find/cwd/here.txt Save New Del | 1 Find | | | -| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del -| 1 alpha body | | -| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del -| 1 gamma body | | | @@ -305,12 +301,12 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del -| 1 beta body | | | | +| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del +| 1 beta body | | | @@ -318,27 +314,27 @@ | | | +| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del +| 1 gamma body | | +| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del +| 1 alpha body | | | /tmp/pardes-snap/find/cwd/+Search New Del -| 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt -== snap back grid=120x40 cursor=7,2 +| 4 +== snap back grid=120x40 cursor=7,29 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/find/cwd/here.txt Save New Del | 1 Find | | | -| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del -| 1 alpha body | | -| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del -| 1 gamma body | | | @@ -346,12 +342,12 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del -| 1 beta body | | | | +| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del +| 1 beta body | | | @@ -359,27 +355,26 @@ | | | +| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del +| 1 gamma body | | +| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del +| 1 alpha body | | | /tmp/pardes-snap/find/cwd/+Search New Del | 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt -== snap word grid=120x40 cursor=9,5 +== snap word grid=120x40 cursor=7,29 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/find/cwd/here.txt Save New Del | 1 Find | | -| Find / -| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del -| 1 alpha body | | -| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del -| 1 gamma body | | | @@ -387,12 +382,13 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del -| 1 beta body | | | | +| Find / +| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del +| 1 beta body | | | @@ -400,27 +396,27 @@ | | | +| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del +| 1 gamma body | | +| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del +| 1 alpha body | | | /tmp/pardes-snap/find/cwd/+Search New Del | 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt -== snap cancel grid=120x40 cursor=7,2 +== snap cancel grid=120x40 cursor=7,38 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/find/cwd/here.txt Save New Del | 1 Find | | | -| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del -| 1 alpha body | | -| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del -| 1 gamma body | | | @@ -428,12 +424,12 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del -| 1 beta body -| | | | +| Find / +| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del +| 1 beta body | | | @@ -441,27 +437,25 @@ | | | +| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del +| 1 gamma body | | +| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del +| 1 alpha body | | | /tmp/pardes-snap/find/cwd/+Search New Del | 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt -== snap nomatch grid=120x40 cursor=7,2 +== snap nomatch grid=120x40 cursor=7,38 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill -| /tmp/pardes-snap/find/cwd/here.txt Save New Del +| /tmp/pardes-snap/find/cwd/here.txt Save New Del Find / | 1 Find | -| /tmp/pardes-snap/find/cwd/+Search New Del -| 1 -| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del -| 1 alpha body | | -| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del -| 1 gamma body | | | @@ -469,12 +463,14 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del -| 1 beta body | | | | +| /tmp/pardes-snap/find/cwd/+Search New Del +| 1 +| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del +| 1 beta body | | | @@ -482,27 +478,25 @@ | | | +| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del +| 1 gamma body | | +| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del +| 1 alpha body | | | /tmp/pardes-snap/find/cwd/+Search New Del -| 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt +| 4 == snap refit grid=120x40 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill -| /tmp/pardes-snap/find/cwd/here.txt Save New Del +| /tmp/pardes-snap/find/cwd/here.txt Save New Del Find / | 1 Find | -| /tmp/pardes-snap/find/cwd/+Search New Del -| 1 -| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del -| 1 alpha body | | -| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del -| 1 gamma body | | | @@ -510,12 +504,14 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del -| 1 beta body | | | | +| /tmp/pardes-snap/find/cwd/+Search New Del +| 1 +| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del +| 1 beta body | | | @@ -523,27 +519,23 @@ | | | +| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del +| 1 gamma body | | +| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del +| 1 alpha body | | | /tmp/pardes-snap/find/cwd/+Search New Del -| 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt -== snap topbar grid=120x40 cursor=12,7 +| 4 +== snap topbar grid=120x40 cursor=12,33 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill -| /tmp/pardes-snap/find/cwd/here.txt Save New Del +| /tmp/pardes-snap/find/cwd/here.txt Save New Del Find / | 1 Find | -| /tmp/pardes-snap/find/cwd/+Search New Del -| 1 -| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del -| 1 alpha body -| /tmp/pardes-snap/find/cwd/+Search New Del -| 1 zqmark-alpha.txt -| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del -| 1 gamma body | | | @@ -551,14 +543,16 @@ | | | -| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del -| 1 beta body | | | | | | +| /tmp/pardes-snap/find/cwd/+Search New Del +| 1 +| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del +| 1 beta body | | | @@ -566,9 +560,15 @@ | | | +| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del +| 1 gamma body | | +| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del +| 1 alpha body +| /tmp/pardes-snap/find/cwd/+Search New Del +| 1 zqmark-alpha.txt | /tmp/pardes-snap/find/cwd/+Search New Del -| 1 sub/ZQMARK-beta.txt | 2 sub/nest/zqmark-gamma.txt | 3 zqmark-alpha.txt +| 4 diff --git a/test/snapshots/find.snap b/test/snapshots/find.snap index 1fd36aa6..8f288525 100644 --- a/test/snapshots/find.snap +++ b/test/snapshots/find.snap @@ -1,11 +1,13 @@ # The Find builtin (SPC f f) = `fd`, in-core: it arms the SAME tag input `/` # does, but Enter walks the pane's DIRECTORY instead of its text and writes one # matching path per row into a "+Search" OUTPUT BUFFER. Every row is therefore -# an ordinary look target, which is the whole point: n/N step the rows and look -# them with no code of their own, opening each found file, and focus returns to -# the pane that owns the search so the next n keeps stepping. The walk skips -# .git, matches the NAME case-insensitively, and sorts (readdir order is not -# stable). `SPC f s` is Save, which moved out of `w` to make this group. +# an ordinary look target, which is the whole point: n/N SELECT the next/prev +# one with no code of their own, and the look chord โ€” Enter, the same one that +# opens a path anywhere else โ€” is what OPENS it. Focus then follows the file +# that opened, but the look was made FROM the results buffer, so the next n +# resumes stepping that same list. The walk skips .git, matches the NAME +# case-insensitively, and sorts (readdir order is not stable). `SPC f s` is +# Save, which moved out of `w` to make this group. dirmk sub dirmk sub/nest dirmk .git @@ -35,25 +37,30 @@ key enter wait 10000 zqmark-alpha.txt stable 700 15000 snap results -# n looks row 1 โ€” a path, so the file OPENS โ€” and focus comes back here. The -# look comes FROM the results buffer, but that is an output pane and not a +# n SELECTS row 1 and Enter looks it โ€” a path, so the file OPENS. The look +# comes FROM the results buffer, but that is an output pane and not a # document, so the file joins the docs above it (below here.txt) instead of # stacking under the list: the +Search stays at the foot of the column. key n +key enter wait 10000 beta body stable 700 15000 snap first snapstyle first key n +key enter wait 10000 gamma body stable 700 15000 snap second key n +key enter wait 10000 alpha body stable 700 15000 snap third -# N walks back up: the file is already open, so the look just focuses it +# N walks back up one row; Enter looks it, and the file is already open, so +# the look just focuses it key N +key enter stable 700 15000 snap back # executing the WORD Find (middle-click in a body) arms the same input โ€” the @@ -66,23 +73,39 @@ key esc settle 100 stable 400 5000 snap cancel -# a no-match walk opens an empty list; n then has nowhere to go. The list is -# exactly as tall as its results โ€” one blank row plus its tag โ€” and it stacks -# above the earlier one, whose height is untouched. +# every search is asked from a PANE, and both a look and now a step leave you +# somewhere else โ€” so click back into here.txt first. That is not bookkeeping: +# a search never refills the buffer it was asked FROM (fillResults skips it), +# so `owned by here.txt` is the whole premise of the two steps below. +press left 8 3 +release left 8 3 +stable 400 5000 +# a no-match walk opens an empty list of its own. It is exactly as tall as its +# results โ€” one blank row plus its tag โ€” and it stacks above the earlier one, +# whose height is untouched. key space key f key f text zzqq key enter stable 700 10000 +# n does not stop on the empty list, because the walk is a RING across panes +# rather than one buffer's rows: with nothing look-able here it carries on +# into the list that DOES have some โ€” the zqm one โ€” and resumes it one row +# past where the N above left it. Nothing opens; only the selection moved. key n stable 400 5000 snap nomatch # ... and asking for `zqm` AGAIN re-arms the list it ALREADY filled instead of -# stacking an identical twin under the empty one โ€” even though n/N were armed -# on the zzqq list, so the reuse is by what a buffer HOLDS (this search, this -# pattern, this directory), not by which one the pane happens to point at. The -# frame is therefore the `results` frame unchanged, down to the byte. +# stacking an identical twin under the empty one โ€” even though the step above +# left the cursor sitting in the zqm list, so the reuse is by what a buffer +# HOLDS (this search, this pattern, this directory), not by which one anything +# happens to point at. Asked from here.txt again (the click, as above), and +# the LIST it rewrites is therefore the `nomatch` frame unchanged, down to the +# byte โ€” only the cursor comes back with it. +press left 8 3 +release left 8 3 +stable 400 5000 key space key f key f @@ -94,10 +117,12 @@ snap refit # Find is a TOPBAR word too (row 1, its own column, next to Grep): the same # builtin the leader path runs, reached with the mouse. Chorded โ€” a selection # held when it runs IS the argument โ€” so dragging over `alpha` and clicking -# Find walks for that name with nothing typed and no input armed. -press left 8 8 -drag left 13 8 -release left 13 8 +# Find walks for that name with nothing typed and no input armed. Row 34 is +# `alpha body`: the three found files stack in the order the looks above +# OPENED them, which is beta, gamma, alpha down the column. +press left 8 34 +drag left 13 34 +release left 13 34 stable 400 5000 press middle 12 1 release middle 12 1 diff --git a/test/snapshots/fsearch.golden b/test/snapshots/fsearch.golden index f0c89e1b..bbe7df83 100644 --- a/test/snapshots/fsearch.golden +++ b/test/snapshots/fsearch.golden @@ -1,7 +1,7 @@ == snap opened grid=180x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -32,7 +32,7 @@ == snap typing grid=180x30 cursor=8,29 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -63,7 +63,7 @@ == snap results grid=180x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -94,7 +94,7 @@ == snap first grid=180x30 cursor=10,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -150,13 +150,13 @@ |24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808, 120-120 d,#444444, 121-121 d,#080808, 122-179 #bdbdbd,#080808, |25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808, 120-120 d,#444444, 121-121 d,#080808, 122-179 #bdbdbd,#080808, |26: 0-1 #ffffff,#262626, 2-48 #949494,#121212, 49-59 d,#121212, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808, 120-120 d,#444444, 121-121 d,#080808, 122-179 #bdbdbd,#080808, -|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 #080808,#80a0ff, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808, 120-120 d,#444444, 121-121 d,#080808, 122-179 #bdbdbd,#080808, +|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808, 120-120 d,#444444, 121-121 d,#080808, 122-179 #bdbdbd,#080808, |28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808, 120-120 d,#444444, 121-121 d,#080808, 122-179 #bdbdbd,#080808, |29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-25 #bdbdbd,#080808, 26-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808, 120-120 d,#444444, 121-121 d,#080808, 122-179 #bdbdbd,#080808, == snap second grid=180x30 cursor=10,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -171,7 +171,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -187,7 +187,7 @@ == snap third grid=180x30 cursor=10,11 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -202,7 +202,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -212,13 +212,13 @@ | | | /tmp/pardes-snap/fsearch/cwd/+Search New Del -| 1 g.txt:2:1-4 MARK a | 2 g.txt:6:1-4 MARK b | 3 g.txt:10:1-4 MARK c +| 4 == snap back grid=180x30 cursor=10,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -233,7 +233,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -249,7 +249,7 @@ == snap cancel grid=180x30 cursor=10,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -264,7 +264,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -277,10 +277,10 @@ | 1 g.txt:2:1-4 MARK a | 2 g.txt:6:1-4 MARK b | 3 g.txt:10:1-4 MARK c -== snap nomatch grid=180x30 cursor=10,7 +== snap nomatch grid=180x30 cursor=7,28 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/fsearch/cwd/g.txt Save New Del /tmp/pardes-snap/fsearch/cwd New Del /tmp/pardes-snap/fsearch/cwd New Del -| 1 l1 +| 1 l1 ls ls | 2 MARK a g.txt g.txt | 3 l3 | 4 l4 @@ -295,7 +295,7 @@ | | | /tmp/pardes-snap/fsearch/cwd New Del -| +| ls | g.txt | | @@ -305,6 +305,6 @@ | /tmp/pardes-snap/fsearch/cwd/+Search New Del | 1 | /tmp/pardes-snap/fsearch/cwd/+Search New Del -| 1 g.txt:2:1-4 MARK a | 2 g.txt:6:1-4 MARK b | 3 g.txt:10:1-4 MARK c +| 4 diff --git a/test/snapshots/fsearch.snap b/test/snapshots/fsearch.snap index af1363dd..b9b7ddf4 100644 --- a/test/snapshots/fsearch.snap +++ b/test/snapshots/fsearch.snap @@ -1,11 +1,11 @@ # `/` file search: the pattern types into the tag (persistent, no popup); # Enter searches the buffer in-core and writes `path:LINE:COL-ENDCOL text` into # a +Search OUTPUT BUFFER (a file pane with no file behind it โ€” no Save in its -# tag); n/N select the next/prev row there and look it, so the file pane -# scrolls to the hit AND SELECTS IT โ€” the row names the match's whole span, not -# just where it starts. Esc abandons the input; a no-match search opens an EMPTY buffer -# (every search gets its own, stacked under the pane) and leaves n with -# nowhere to go. +# tag); n/N SELECT the next/prev row there and open nothing, and Enter โ€” the +# look chord โ€” is what scrolls the file pane to the hit AND SELECTS IT: the row +# names the match's whole span, not just where it starts. Esc abandons the +# input; a no-match search opens an EMPTY buffer (every search gets its own, +# stacked under the pane) with nothing in it for n to stop on. file g.txt l1\nMARK a\nl3\nl4\nl5\nMARK b\nl7\nl8\nl9\nMARK c\nl11\nl12 start 30 180 -n 3 wait 8000 g.txt @@ -34,21 +34,25 @@ key enter wait 10000 g.txt:2:1-4 MARK stable 700 10000 snap results -# n selects result 1 in the results buffer, scrolls the file to line 2 and -# selects the four cells the pattern matched there โ€” the styles below are what -# prove the second half of that +# n selects result 1 and Enter looks it: the file scrolls to line 2 and the +# four cells the pattern matched there come up selected โ€” the styles below are +# what prove the second half of that key n +key enter stable 700 15000 snap first snapstyle first key n +key enter stable 700 15000 snap second key n +key enter stable 700 15000 snap third -# N walks back up to result 2 (line 6) +# N walks back up to result 2 (line 6), Enter looks it key N +key enter stable 700 15000 snap back # Esc abandons the input: the tag tail is restored @@ -58,7 +62,8 @@ key esc settle 100 stable 400 5000 snap cancel -# a no-match search: n has nowhere to go (nothing changes, no crash) +# a no-match search: nothing in the empty list for n to stop on, so the ring +# carries it back into the list that has rows and it resumes there key / text zzqq key enter diff --git a/test/snapshots/ghostty-mid.golden b/test/snapshots/ghostty-mid.golden index d951915c..39da0f5b 100644 --- a/test/snapshots/ghostty-mid.golden +++ b/test/snapshots/ghostty-mid.golden @@ -1,9 +1,9 @@ == snap ghostty-mid grid=100x30 cursor=4,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ghostty-mid/cwd New Del /tmp/pardes-snap/ghostty-mid/cwd New Del -| ZZPAD +| ZZPAD ls | ./g.sh g.txt -| +| ./g.sh | GHOSTOK | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/ghostty-mid/cwd New Del -| +| ls | g.txt | | diff --git a/test/snapshots/grep.golden b/test/snapshots/grep.golden index a8252249..846ab703 100644 --- a/test/snapshots/grep.golden +++ b/test/snapshots/grep.golden @@ -1,7 +1,7 @@ == snap opened grid=180x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/grep/cwd/a.txt Save New Del /tmp/pardes-snap/grep/cwd New Del /tmp/pardes-snap/grep/cwd New Del -| 1 hello TARGET one +| 1 hello TARGET one ls ls | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/grep/cwd New Del -| +| ls | a.txt noise.txt sub | | @@ -32,7 +32,7 @@ == snap typing grid=180x30 cursor=15,29 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/grep/cwd/a.txt Save New Del /tmp/pardes-snap/grep/cwd New Del /tmp/pardes-snap/grep/cwd New Del -| 1 hello TARGET one +| 1 hello TARGET one ls ls | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/grep/cwd New Del -| +| ls | a.txt noise.txt sub | | @@ -63,7 +63,7 @@ == snap results grid=180x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/grep/cwd/a.txt Save New Del /tmp/pardes-snap/grep/cwd New Del /tmp/pardes-snap/grep/cwd New Del -| 1 hello TARGET one +| 1 hello TARGET one ls ls | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/grep/cwd New Del -| +| ls | a.txt noise.txt sub | | @@ -94,7 +94,7 @@ == snap first grid=180x30 cursor=18,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/grep/cwd/a.txt Save New Del /tmp/pardes-snap/grep/cwd New Del /tmp/pardes-snap/grep/cwd New Del -| 1 hello TARGET one +| 1 hello TARGET one ls ls | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/grep/cwd New Del -| +| ls | a.txt noise.txt sub | | @@ -122,10 +122,10 @@ | 1 a.txt:1:7-12 hello TARGET one | 2 a.txt:3:6-11 last TARGET line | 3 sub/b.txt:2:1-6 TARGET inside sub -== snap opened-hit grid=180x30 cursor=17,4 +== snap opened-hit grid=180x30 cursor=12,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/grep/cwd/a.txt Save New Del /tmp/pardes-snap/grep/cwd New Del /tmp/pardes-snap/grep/cwd New Del -| 1 hello TARGET one +| 1 hello TARGET one ls ls | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line | @@ -140,7 +140,7 @@ | /tmp/pardes-snap/grep/cwd/sub/b.txt Save New Del | 1 deep | 2 TARGET inside sub /tmp/pardes-snap/grep/cwd New Del -| +| ls | a.txt noise.txt sub | | @@ -150,13 +150,13 @@ | | | /tmp/pardes-snap/grep/cwd/+Search New Del -| 1 a.txt:1:7-12 hello TARGET one | 2 a.txt:3:6-11 last TARGET line | 3 sub/b.txt:2:1-6 TARGET inside sub -== snap nomatch grid=180x30 cursor=17,4 +| 4 +== snap nomatch grid=180x30 cursor=37,28 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/grep/cwd/a.txt Save New Del /tmp/pardes-snap/grep/cwd New Del /tmp/pardes-snap/grep/cwd New Del -| 1 hello TARGET one +| 1 hello TARGET one ls ls | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line | @@ -166,28 +166,28 @@ | | | -| /tmp/pardes-snap/grep/cwd/+Search New Del -| 1 +| +| | /tmp/pardes-snap/grep/cwd/sub/b.txt Save New Del | 1 deep | 2 TARGET inside sub /tmp/pardes-snap/grep/cwd New Del -| +| ls | a.txt noise.txt sub | | | | | -| -| +| /tmp/pardes-snap/grep/cwd/sub/+Search New Del +| 1 | /tmp/pardes-snap/grep/cwd/+Search New Del -| 1 a.txt:1:7-12 hello TARGET one | 2 a.txt:3:6-11 last TARGET line | 3 sub/b.txt:2:1-6 TARGET inside sub +| 4 == snap chordsel grid=180x30 cursor=19,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/grep/cwd/a.txt Save New Del /tmp/pardes-snap/grep/cwd New Del /tmp/pardes-snap/grep/cwd New Del -| 1 hello TARGET one +| 1 hello TARGET one ls ls | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line | @@ -197,28 +197,28 @@ | | | -| /tmp/pardes-snap/grep/cwd/+Search New Del -| 1 +| +| | /tmp/pardes-snap/grep/cwd/sub/b.txt Save New Del | 1 deep | 2 TARGET inside sub /tmp/pardes-snap/grep/cwd New Del -| +| ls | a.txt noise.txt sub | | | | | -| -| +| /tmp/pardes-snap/grep/cwd/sub/+Search New Del +| 1 | /tmp/pardes-snap/grep/cwd/+Search New Del -| 1 a.txt:1:7-12 hello TARGET one | 2 a.txt:3:6-11 last TARGET line | 3 sub/b.txt:2:1-6 TARGET inside sub +| 4 == snap chord grid=180x30 cursor=19,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/grep/cwd/a.txt Save New Del /tmp/pardes-snap/grep/cwd New Del /tmp/pardes-snap/grep/cwd New Del -| 1 hello TARGET one +| 1 hello TARGET one ls ls | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line | @@ -228,21 +228,21 @@ | | | -| /tmp/pardes-snap/grep/cwd/+Search New Del -| 1 +| +| | /tmp/pardes-snap/grep/cwd/sub/b.txt Save New Del | 1 deep | 2 TARGET inside sub /tmp/pardes-snap/grep/cwd New Del -| +| ls | a.txt noise.txt sub | | | | | -| -| +| /tmp/pardes-snap/grep/cwd/sub/+Search New Del +| 1 | /tmp/pardes-snap/grep/cwd/+Search New Del -| 1 a.txt:1:7-12 hello TARGET one | 2 a.txt:3:6-11 last TARGET line | 3 sub/b.txt:2:1-6 TARGET inside sub +| 4 diff --git a/test/snapshots/grep.snap b/test/snapshots/grep.snap index 817f613f..1d3efc9e 100644 --- a/test/snapshots/grep.snap +++ b/test/snapshots/grep.snap @@ -6,8 +6,9 @@ # looking it SELECTS the hit โ€” with the path RELATIVE to the directory # of the pane that asked โ€” the same directory its results buffer is named in, # so the short name resolves; only a hit from outside that tree stays absolute. -# n/N walk the rows like any other result list, and a row pointing into a file -# nothing has open yet opens it. +# n/N SELECT the next/prev row like any other result list and open nothing; +# Enter looks what they leave selected, and a row pointing into a file nothing +# has open yet opens it. dirmk sub file a.txt hello TARGET one\nnothing here\nlast TARGET line file sub/b.txt deep\nTARGET inside sub @@ -44,25 +45,32 @@ key enter wait 10000 sub/b.txt:2:1 stable 700 15000 snap results -# n looks the first row: absolute path, line 1, columns 7..12 (`TARGET`), and -# those six cells come up selected +# n selects the first row and Enter looks it: absolute path, line 1, columns +# 7..12 (`TARGET`), and those six cells come up selected key n +key enter stable 700 15000 snap first -# ...and stepping on into sub/b.txt opens the file nothing had open +# ...and stepping on into sub/b.txt, then looking it, opens the file nothing +# had open key n +key enter stable 700 15000 key n +key enter wait 10000 TARGET inside sub stable 700 15000 snap opened-hit -# a pattern nothing holds: an empty list of its own, n has nowhere to go. -# Armed from the LEADER, not the topbar word: the n above left the hit -# SELECTED in a.txt (a ranged result row is one a look selects), and a topbar -# execute chords whatever is selected into its argument โ€” so a middle-click -# here would run `Grep TARGET` and never ask for a pattern at all. The leader -# path runs the builtin with no argument, which is what this step is about; the -# chord itself is the last two snaps below. +# a pattern nothing holds: an empty list of its own, with nothing in it for n +# to stop on โ€” so the ring carries that step back into the TARGET list. The +# look above is why both of those read the way they do: it left the cursor in +# sub/b.txt, so the empty list is named in sub/ rather than cwd/, and it left +# the hit SELECTED there (a ranged result row is one a look selects). +# Armed from the LEADER, not the topbar word, because of that selection: a +# topbar execute chords whatever is selected into its argument, so a +# middle-click here would run `Grep TARGET` and never ask for a pattern at +# all. The leader path runs the builtin with no argument, which is what this +# step is about; the chord itself is the last two snaps below. key space key f key g diff --git a/test/snapshots/hscroll.golden b/test/snapshots/hscroll.golden index 959dac81..3aad04d8 100644 --- a/test/snapshots/hscroll.golden +++ b/test/snapshots/hscroll.golden @@ -1,7 +1,7 @@ == snap opened grid=90x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd -| 1 short1 END_A_MARKER_WAY +| 1 short1 END_A_MARKER_WAY ls ls | wide.txt wide.txt | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/hscroll/cwd -| +| ls | wide.txt | | @@ -32,7 +32,7 @@ == snap wheeled grid=90x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd -| 1 ND_A_MARKER_WAY_OUT_RIG +| 1 ND_A_MARKER_WAY_OUT_RIG ls ls | wide.txt wide.txt | | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/hscroll/cwd -| +| ls | wide.txt | | @@ -63,7 +63,7 @@ == snap clamped grid=90x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd -| 1 short1 END_A_MARKER_WAY +| 1 short1 END_A_MARKER_WAY ls ls | wide.txt wide.txt | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/hscroll/cwd -| +| ls | wide.txt | | @@ -94,7 +94,7 @@ == snap dollar grid=90x30 cursor=26,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd -| 1 padpadpadpadpad_TAIL +| 1 padpadpadpadpad_TAIL ls ls | wide.txt wide.txt | | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/hscroll/cwd -| +| ls | wide.txt | | @@ -125,7 +125,7 @@ == snap zero grid=90x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd /tmp/pardes-snap/hscroll/cwd -| 1 short1 END_A_MARKER_WAY +| 1 short1 END_A_MARKER_WAY ls ls | wide.txt wide.txt | | @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/hscroll/cwd -| +| ls | wide.txt | | diff --git a/test/snapshots/images.golden b/test/snapshots/images.golden index 4d54e9bf..e02ec8d6 100644 --- a/test/snapshots/images.golden +++ b/test/snapshots/images.golden @@ -1,7 +1,7 @@ == snap img-open grid=150x30 cursor=11,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | img /tmp/pardes-snap/images/cwd/pic.ppm New Del /tmp/pardes-snap/images/cwd New Del /tmp/pardes-snap/images/cwd New Del -| +| ls ls | pic.ppm pic.ppm | 4*๐Ÿฌน~F~N๐Ÿฌฐ|G๐Ÿฌโ–šY~KF๐Ÿฌดs>T&zZ/๐ŸฌปiTY=`S~โ•ณbkZR37v๐Ÿฌฆ๐Ÿฌตd4QHZ8Xโ–›โ–Ÿ @@ -16,7 +16,7 @@ | ๐Ÿฌ†fโ”‚Q_V๐Ÿฌ—wGx๐Ÿฌฑ=5โ–›5*&V๐ŸฌŸ๐Ÿฌ„ZrXGz2๐Ÿฌ๐Ÿฌปโ–ˆ | !๐ŸฌทW๐Ÿฌ(๐Ÿฌญ]7x_>โ–—er๐Ÿฌฏ~โ–šdi๐Ÿฌฌ4jY:๐Ÿฌโ–Ÿ | gU~๐Ÿฌง3โ–™bjr\C#kKMpffAjps๐Ÿฌ๐Ÿฌป /tmp/pardes-snap/images/cwd New Del -| *๐ŸฌฏG"๐Ÿฌฃโ–Ÿd๐Ÿฌฎโ–€zJ๐ŸฌชEHVโ–Ÿโ•ณ9}yโ–›โ–„ +| *๐ŸฌฏG"๐Ÿฌฃโ–Ÿd๐Ÿฌฎโ–€zJ๐ŸฌชEHVโ–Ÿโ•ณ9}yโ–›โ–„ ls | ``))~RyJ๐ŸฌดjA~w=hLpX๐Ÿฌ๐Ÿฌปโ–ˆ pic.ppm | 4xโ–€J"TG7=y-QZ๐Ÿฌ™โ•ฒ~โ–›๐Ÿฌป | ๐Ÿฌฏ/+โ•ณf9ZG๐Ÿฌ•+{QN_๐Ÿฌ๐Ÿฌน @@ -94,7 +94,7 @@ == snap no-ascii grid=150x30 cursor=11,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | img /tmp/pardes-snap/images/cwd/pic.ppm New Del /tmp/pardes-snap/images/cwd New Del /tmp/pardes-snap/images/cwd New Del -| +| ls ls | pic.ppm pic.ppm | โ•ณโ•ฑโ•ฑ๐Ÿฌป๐Ÿฌซ๐Ÿฌด๐Ÿฌธโ”‚๐Ÿฌœ๐Ÿฌด๐Ÿฌฌโ–ˆโ–—โ•ฒโ”‚โ–ˆ๐Ÿฌทโ–ˆ๐Ÿฌด๐Ÿฌ™๐Ÿฌ‹โ”€๐Ÿฌฌ๐Ÿฌ‹โ•ณ๐Ÿฌบ๐Ÿฌฒโ”‚โ–ˆ๐Ÿฌซโ–œโ–žโ”‚๐Ÿฌช๐Ÿฌ๐Ÿฌด๐Ÿฌ๐Ÿฌธโ•ฒ๐Ÿฌฃโ–ˆโ–ˆ๐Ÿฌ›๐Ÿฌธ๐Ÿฌ›๐Ÿฌธโ”‚๐Ÿฌป | ๐Ÿฌ๐Ÿฌบโ”ผโ”€โ–œ๐Ÿฌฑ๐Ÿฌฌ๐Ÿฌป๐Ÿฌธ๐Ÿฌ”โ•ฒโ–ˆ๐Ÿฌปโ•ฑโ–ˆโ–ˆ๐Ÿฌโ•ฒโ–™๐Ÿฌป๐Ÿฌนโ–™โ–€๐Ÿฌบโ•ฒโ”ผ๐Ÿฌบโ•ณ๐Ÿฌทโ–œโ”€๐Ÿฌ™โ–ˆโ”‚โ”‚๐Ÿฌด๐ŸฌŽ๐Ÿฌนโ•ฒโ–ˆ๐Ÿฌบโ–œ๐Ÿฌดโ”€โ–™๐Ÿฌปโ•ฒ @@ -109,7 +109,7 @@ | ๐ŸฌŽโ•ฑโ”‚โ”€โ–ˆโ–ˆ๐Ÿฌณโ–€๐Ÿฌช๐Ÿฌบ๐ŸฌŽโ”‚โ–œโ–ˆ๐Ÿฌด๐Ÿฌธ๐Ÿฌป๐Ÿฌ†๐Ÿฌœโ–Ÿโ–ˆ๐Ÿฌป๐Ÿฌฌโ–€๐Ÿฌบโ•ฑโ–œ๐Ÿฌต | โ”‚โ–Ÿโ–๐Ÿฌปโ–ˆ๐Ÿฌฌ๐Ÿฌฅ๐Ÿฌฌ๐Ÿฌ•โ–ˆ๐Ÿฌป๐Ÿฌดโ”ผ๐Ÿฌ‘๐Ÿฌ๐Ÿฌฌโ–žโ•ฑโ–Ÿ๐Ÿฌฌโ•ฑ๐Ÿฌโ–œ๐Ÿฌฃโ–ˆโ•ณโ–ˆ | ๐Ÿฌฐโ–ˆโ”‚๐Ÿฌง๐Ÿฌฐโ–›โ•ฑ๐Ÿฌฌโ•ฒโ”€๐Ÿฌฌโ–ˆโ”ผ๐Ÿฌฉโ–ˆ๐Ÿฌฌโ–œโ”€๐Ÿฌดโ”‚๐Ÿฌ๐Ÿฌฒโ”€๐Ÿฌต /tmp/pardes-snap/images/cwd New Del -| ๐Ÿฌด๐Ÿฌท๐Ÿฌฐ๐Ÿฌ๐Ÿฌธโ–˜โ•ฑ๐Ÿฌโ–„โ”‚โ•ฒโ–žโ–ˆโ•ณโ•ฑโ–Ÿโ•ฑ๐Ÿฌ๐Ÿฌ›๐Ÿฌฌ๐Ÿฌถ๐Ÿฌปโ–ˆ +| ๐Ÿฌด๐Ÿฌท๐Ÿฌฐ๐Ÿฌ๐Ÿฌธโ–˜โ•ฑ๐Ÿฌโ–„โ”‚โ•ฒโ–žโ–ˆโ•ณโ•ฑโ–Ÿโ•ฑ๐Ÿฌ๐Ÿฌ›๐Ÿฌฌ๐Ÿฌถ๐Ÿฌปโ–ˆ ls | โ–ˆโ–ˆโ–ˆโ•ฑโ–ˆ๐Ÿฌบ๐Ÿฌบโ–ˆ๐Ÿฌ‡โ–™๐Ÿฌธ๐Ÿฌซ๐Ÿฌ™โ–ˆ๐Ÿฌดโ–™๐Ÿฌโ•ฑ๐Ÿฌบโ•ฑ pic.ppm | โ–ˆโ•ฑโ–™๐Ÿฌบโ–ˆโ–œโ•ฑโ–ˆ๐Ÿฌฌโ–œโ–ˆ๐Ÿฌ•โ•ฒ๐Ÿฌฉโ•ฒโ–ˆ๐Ÿฌโ”‚ | ๐ŸฌŒ๐Ÿฌธ๐Ÿฌด๐Ÿฌดโ–ˆโ–„๐Ÿฌฌโ–™โ–›๐Ÿฌซ๐Ÿฌ”โ”ผโ•ณโ–ˆ๐Ÿฌบโ•ณโ–ˆ @@ -125,7 +125,7 @@ == snap tag-edit grid=150x30 cursor=45,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | img /tmp/pardes-snap/images/cwd/pic.ppmZork New /tmp/pardes-snap/images/cwd New Del /tmp/pardes-snap/images/cwd New Del -| +| ls ls | pic.ppm pic.ppm | โ•ณโ•ฑโ•ฑ๐Ÿฌป๐Ÿฌซ๐Ÿฌด๐Ÿฌธโ”‚๐Ÿฌœ๐Ÿฌด๐Ÿฌฌโ–ˆโ–—โ•ฒโ”‚โ–ˆ๐Ÿฌทโ–ˆ๐Ÿฌด๐Ÿฌ™๐Ÿฌ‹โ”€๐Ÿฌฌ๐Ÿฌ‹โ•ณ๐Ÿฌบ๐Ÿฌฒโ”‚โ–ˆ๐Ÿฌซโ–œโ–žโ”‚๐Ÿฌช๐Ÿฌ๐Ÿฌด๐Ÿฌ๐Ÿฌธโ•ฒ๐Ÿฌฃโ–ˆโ–ˆ๐Ÿฌ›๐Ÿฌธ๐Ÿฌ›๐Ÿฌธโ”‚๐Ÿฌป | ๐Ÿฌ๐Ÿฌบโ”ผโ”€โ–œ๐Ÿฌฑ๐Ÿฌฌ๐Ÿฌป๐Ÿฌธ๐Ÿฌ”โ•ฒโ–ˆ๐Ÿฌปโ•ฑโ–ˆโ–ˆ๐Ÿฌโ•ฒโ–™๐Ÿฌป๐Ÿฌนโ–™โ–€๐Ÿฌบโ•ฒโ”ผ๐Ÿฌบโ•ณ๐Ÿฌทโ–œโ”€๐Ÿฌ™โ–ˆโ”‚โ”‚๐Ÿฌด๐ŸฌŽ๐Ÿฌนโ•ฒโ–ˆ๐Ÿฌบโ–œ๐Ÿฌดโ”€โ–™๐Ÿฌปโ•ฒ @@ -140,7 +140,7 @@ | ๐ŸฌŽโ•ฑโ”‚โ”€โ–ˆโ–ˆ๐Ÿฌณโ–€๐Ÿฌช๐Ÿฌบ๐ŸฌŽโ”‚โ–œโ–ˆ๐Ÿฌด๐Ÿฌธ๐Ÿฌป๐Ÿฌ†๐Ÿฌœโ–Ÿโ–ˆ๐Ÿฌป๐Ÿฌฌโ–€๐Ÿฌบโ•ฑโ–œ๐Ÿฌต | โ”‚โ–Ÿโ–๐Ÿฌปโ–ˆ๐Ÿฌฌ๐Ÿฌฅ๐Ÿฌฌ๐Ÿฌ•โ–ˆ๐Ÿฌป๐Ÿฌดโ”ผ๐Ÿฌ‘๐Ÿฌ๐Ÿฌฌโ–žโ•ฑโ–Ÿ๐Ÿฌฌโ•ฑ๐Ÿฌโ–œ๐Ÿฌฃโ–ˆโ•ณโ–ˆ | ๐Ÿฌฐโ–ˆโ”‚๐Ÿฌง๐Ÿฌฐโ–›โ•ฑ๐Ÿฌฌโ•ฒโ”€๐Ÿฌฌโ–ˆโ”ผ๐Ÿฌฉโ–ˆ๐Ÿฌฌโ–œโ”€๐Ÿฌดโ”‚๐Ÿฌ๐Ÿฌฒโ”€๐Ÿฌต /tmp/pardes-snap/images/cwd New Del -| ๐Ÿฌด๐Ÿฌท๐Ÿฌฐ๐Ÿฌ๐Ÿฌธโ–˜โ•ฑ๐Ÿฌโ–„โ”‚โ•ฒโ–žโ–ˆโ•ณโ•ฑโ–Ÿโ•ฑ๐Ÿฌ๐Ÿฌ›๐Ÿฌฌ๐Ÿฌถ๐Ÿฌปโ–ˆ +| ๐Ÿฌด๐Ÿฌท๐Ÿฌฐ๐Ÿฌ๐Ÿฌธโ–˜โ•ฑ๐Ÿฌโ–„โ”‚โ•ฒโ–žโ–ˆโ•ณโ•ฑโ–Ÿโ•ฑ๐Ÿฌ๐Ÿฌ›๐Ÿฌฌ๐Ÿฌถ๐Ÿฌปโ–ˆ ls | โ–ˆโ–ˆโ–ˆโ•ฑโ–ˆ๐Ÿฌบ๐Ÿฌบโ–ˆ๐Ÿฌ‡โ–™๐Ÿฌธ๐Ÿฌซ๐Ÿฌ™โ–ˆ๐Ÿฌดโ–™๐Ÿฌโ•ฑ๐Ÿฌบโ•ฑ pic.ppm | โ–ˆโ•ฑโ–™๐Ÿฌบโ–ˆโ–œโ•ฑโ–ˆ๐Ÿฌฌโ–œโ–ˆ๐Ÿฌ•โ•ฒ๐Ÿฌฉโ•ฒโ–ˆ๐Ÿฌโ”‚ | ๐ŸฌŒ๐Ÿฌธ๐Ÿฌด๐Ÿฌดโ–ˆโ–„๐Ÿฌฌโ–™โ–›๐Ÿฌซ๐Ÿฌ”โ”ผโ•ณโ–ˆ๐Ÿฌบโ•ณโ–ˆ diff --git a/test/snapshots/jumps.golden b/test/snapshots/jumps.golden index a557ce1f..5e8cbbab 100644 --- a/test/snapshots/jumps.golden +++ b/test/snapshots/jumps.golden @@ -32,7 +32,7 @@ == snap to-shell grid=150x30 cursor=79,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 1 line 1 +| 1 line 1 ls | 2 line 2 big.txt | 3 line 3 | 4 line 4 @@ -63,7 +63,7 @@ == snap to-file grid=150x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 1 line 1 +| 1 line 1 ls | 2 line 2 big.txt | 3 line 3 | 4 line 4 @@ -94,7 +94,7 @@ == snap goto-100 grid=150x30 cursor=7,26 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 76 line 76 +| 76 line 76 ls | 77 line 77 big.txt | 78 line 78 | 79 line 79 @@ -125,7 +125,7 @@ == snap back-in-file grid=150x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 1 line 1 +| 1 line 1 ls | 2 line 2 big.txt | 3 line 3 | 4 line 4 @@ -156,7 +156,7 @@ == snap back-to-shell grid=150x30 cursor=79,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 1 line 1 +| 1 line 1 ls | 2 line 2 big.txt | 3 line 3 | 4 line 4 @@ -187,7 +187,7 @@ == snap forward-file grid=150x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 1 line 1 +| 1 line 1 ls | 2 line 2 big.txt | 3 line 3 | 4 line 4 @@ -218,7 +218,7 @@ == snap forward-100 grid=150x30 cursor=7,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 86 line 86 +| 86 line 86 ls | 87 line 87 big.txt | 88 line 88 | 89 line 89 @@ -249,7 +249,7 @@ == snap last grid=150x30 cursor=79,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 86 line 86 +| 86 line 86 ls | 87 line 87 big.txt | 88 line 88 | 89 line 89 @@ -280,7 +280,7 @@ == snap last-back grid=150x30 cursor=7,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 86 line 86 +| 86 line 86 ls | 87 line 87 big.txt | 88 line 88 | 89 line 89 @@ -311,7 +311,7 @@ == snap jumplist grid=150x30 cursor=7,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 86 line 86 +| 86 line 86 ls | 87 line 87 big.txt | 88 line 88 | 89 line 89 @@ -339,10 +339,10 @@ | 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1 | 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd | 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100 -== snap step1-shell grid=150x30 cursor=7,16 +== snap step1-shell grid=150x30 cursor=79,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 86 line 86 +| 86 line 86 ls | 87 line 87 big.txt | 88 line 88 | 89 line 89 @@ -372,7 +372,7 @@ | 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100 == style step1-shell |0: 0-56 #949494,#121212, 57-149 d,#121212, -|1: 0-1 #ffffff,#626262, 2-54 #949494,#121212, 55-74 d,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212, +|1: 0-1 #ffffff,#262626, 2-54 #949494,#121212, 55-74 d,#121212, 75-76 #ffffff,#626262, 77-129 #949494,#121212, 130-149 d,#121212, |2: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, @@ -387,7 +387,7 @@ |13: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |14: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |15: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, -|16: 0-0 d,#121212, 1-1 d,#080808, 2-6 #949494,#121212, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, +|16: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |17: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |18: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |19: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, @@ -397,14 +397,14 @@ |23: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |24: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |25: 0-1 #ffffff,#262626, 2-54 #949494,#121212, 55-74 d,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, -|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-74 #080808,#80a0ff, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, +|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-40 #bdbdbd,#080808, 41-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-51 #bdbdbd,#080808, 52-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-40 #bdbdbd,#080808, 41-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, |29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-55 #bdbdbd,#080808, 56-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808, == snap step2-file grid=150x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 1 line 1 +| 1 line 1 ls | 2 line 2 big.txt | 3 line 3 | 4 line 4 @@ -435,7 +435,7 @@ == snap step4-line100 grid=150x30 cursor=7,13 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 89 line 89 +| 89 line 89 ls | 90 line 90 big.txt | 91 line 91 | 92 line 92 @@ -459,14 +459,14 @@ | 110 line 110 | 111 line 111 | /tmp/pardes-snap/jumps/cwd/+Jumps New Del -| 1 @p1:3:3 /tmp/pardes-snap/jumps/cwd | 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1 | 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd | 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100 -== snap step-back grid=150x30 cursor=7,13 +| 5 +== snap step-back grid=150x30 cursor=79,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 89 line 89 +| 89 line 89 ls | 90 line 90 big.txt | 91 line 91 | 92 line 92 @@ -490,14 +490,14 @@ | 110 line 110 | 111 line 111 | /tmp/pardes-snap/jumps/cwd/+Jumps New Del -| 1 @p1:3:3 /tmp/pardes-snap/jumps/cwd | 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1 | 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd | 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100 +| 5 == snap look-row grid=150x30 cursor=7,13 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del -| 89 line 89 +| 89 line 89 ls | 90 line 90 big.txt | 91 line 91 | 92 line 92 @@ -521,7 +521,7 @@ | 110 line 110 | 111 line 111 | /tmp/pardes-snap/jumps/cwd/+Jumps New Del -| 1 @p1:3:3 /tmp/pardes-snap/jumps/cwd | 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1 | 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd | 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100 +| 5 diff --git a/test/snapshots/jumps.snap b/test/snapshots/jumps.snap index 1e2a9075..db131bd4 100644 --- a/test/snapshots/jumps.snap +++ b/test/snapshots/jumps.snap @@ -64,36 +64,58 @@ snap last-back key space j l stable 700 15000 snap jumplist -# n/N step the rows and look them, exactly as they do a +Search: the stepped -# row is selected in the buffer (snapstyle) and the pane it names follows. -# Row 1 is the shell (no path, so `@pN`), row 2 the file at line 1, row 4 the -# file at line 100 โ€” so the body visibly rides the list. +# n/N select the next/prev look-able span and Enter looks it, exactly as they +# do a +Search: the stepped span is selected in the buffer (snapstyle) and the +# Enter after it moves the pane the row names. Row 1 is the shell (no path, so +# `@pN`), row 2 the file at line 1, row 4 the file at line 100 โ€” so the body +# visibly rides the list. # -# ponytail: stepping onto an `@pN` row selects it but does NOT focus that pane โ€” -# the cursor stays where it was, which is why step1-shell's header is still the -# file's. Only rows with a PATH move focus. Nothing tested this before, because -# until the swap above the shell never survived on the stack to be listed at -# all. Fix belongs in the location-list step, next to the path case. +# SPANS, not rows, and this buffer is the one place in the suite where the two +# differ: an `@pN` row's trailing text is the pane's DIRECTORY, which is a +# look-able word of its own, so row 1 and row 3 each hold TWO stops and +# reaching the next row takes two steps. A file row's text is its content line +# (`line 1`), which resolves to nothing, so those hold one. Stepping words +# rather than rows is what makes the walk the same motion in a results buffer +# and in the middle of a paragraph, and this is the price of that. +# +# An `@pN` row moves focus like any other, which it did not use to: the STEP +# only selects now, and the look Enter runs goes to the pane by the same route +# a path takes. key n +key enter stable 700 15000 snap step1-shell snapstyle step1-shell +# past the directory on row 1, then onto row 2 +key n +stable 400 5000 key n +key enter stable 700 15000 snap step2-file +# row 3 is the shell again, both its spans, and then row 4 key n -stable 700 15000 +stable 400 5000 key n +stable 400 5000 +key n +key enter stable 700 15000 snap step4-line100 +# N is the exact inverse: the same two spans of row 3 in the other order, so +# two presses land back on its location and Enter follows it to the shell +key N +stable 400 5000 key N +key enter stable 700 15000 snap step-back # and an ordinary LOOK on a row goes there too โ€” the leading word IS a # location, so the right-click look resolves it like any other path. Row 4 -# again, this time by clicking it: the buffer's four rows are the last four -# screen rows, so row 4 is the bottom one. -press right 16 30 -release right 16 30 +# again, this time by clicking it: the walk above scrolled the list by one, so +# the last four screen rows are its rows 2 through 5 and row 4 is the second +# from the bottom. +press right 16 29 +release right 16 29 stable 700 15000 snap look-row diff --git a/test/snapshots/layout-close.golden b/test/snapshots/layout-close.golden index e809621e..5e4faba0 100644 --- a/test/snapshots/layout-close.golden +++ b/test/snapshots/layout-close.golden @@ -1,19 +1,19 @@ == snap built grid=140x40 cursor=4,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-close/cwd New Del /tmp/pardes-snap/layout-close/cwd New Del -| +| ls ls | marker.txt marker.txt | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | @@ -21,7 +21,7 @@ | | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | @@ -42,15 +42,15 @@ == snap altc grid=140x40 cursor=98,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-close/cwd New Del /tmp/pardes-snap/layout-close/cwd New Del /tmp/pardes-snap/layout-close/cwd New Del -| +| ls ls ls | marker.txt marker.txt marker.txt | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | @@ -62,7 +62,7 @@ | | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | @@ -83,7 +83,7 @@ == snap del grid=140x40 cursor=98,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-close/cwd New Del /tmp/pardes-snap/layout-close/cwd New Del /tmp/pardes-snap/layout-close/cwd New Del -| +| ls ls ls | marker.txt marker.txt marker.txt | | @@ -91,7 +91,7 @@ | | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | @@ -103,7 +103,7 @@ | | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | @@ -124,7 +124,7 @@ == snap exit grid=140x40 cursor=98,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-close/cwd New Del /tmp/pardes-snap/layout-close/cwd New Del /tmp/pardes-snap/layout-close/cwd New Del -| +| ls ls ls | marker.txt marker.txt marker.txt | | @@ -144,7 +144,7 @@ | | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | @@ -165,7 +165,7 @@ == snap colclose grid=140x40 cursor=4,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-close/cwd New Del /tmp/pardes-snap/layout-close/cwd New Del -| +| ls ls | marker.txt marker.txt | | @@ -185,7 +185,7 @@ | | | /tmp/pardes-snap/layout-close/cwd New Del -| +| ls | marker.txt | | diff --git a/test/snapshots/layout-open.golden b/test/snapshots/layout-open.golden index 9631f223..cb6c5f6a 100644 --- a/test/snapshots/layout-open.golden +++ b/test/snapshots/layout-open.golden @@ -1,7 +1,7 @@ == snap before grid=100x30 cursor=2,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-open/cwd New Del /tmp/pardes-snap/layout-open/cwd New Del -| +| ls ls | sub sub | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/layout-open/cwd New Del -| +| ls | sub | | @@ -32,11 +32,11 @@ == snap altn-left grid=100x30 cursor=4,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-open/cwd New Del /tmp/pardes-snap/layout-open/cwd New Del -| +| ls ls | sub sub | | /tmp/pardes-snap/layout-open/cwd New Del -| +| ls | sub | | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/layout-open/cwd New Del -| +| ls | sub | | @@ -63,11 +63,11 @@ == snap altn-right grid=100x30 cursor=54,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-open/cwd New Del /tmp/pardes-snap/layout-open/cwd New Del -| +| ls ls | sub sub | | /tmp/pardes-snap/layout-open/cwd New Del /tmp/pardes-snap/layout-open/cwd New Del -| +| ls ls | sub sub | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/layout-open/cwd New Del -| +| ls | sub | | @@ -94,11 +94,11 @@ == snap file-open grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-open/cw /tmp/pardes-snap/layout-open/cw /tmp/pardes-snap/layout-open/cwd -| 1 echo 'TTY'OK +| 1 echo 'TTY'OK ls ls | sub sub | | /tmp/pardes-snap/layout-open/cw /tmp/pardes-snap/layout-open/cwd -| +| ls ls | sub sub | | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/layout-open/cw -| +| ls | sub | | @@ -125,22 +125,22 @@ == snap ttydir grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/layout-open/cw /tmp/pardes-snap/layout-open/cw /tmp/pardes-snap/layout-open/cwd -| 1 echo 'TTY'OK +| 1 echo 'TTY'OK ls ls | sub sub | | /tmp/pardes-snap/layout-open/cw /tmp/pardes-snap/layout-open/cwd -| +| ls ls | sub sub | | /tmp/pardes-snap/layout-open/cwd | echo 'TTY'OK -| +| echo 'TTY'OK | TTYOK | | | | /tmp/pardes-snap/layout-open/cw -| +| ls | sub | | diff --git a/test/snapshots/leader.golden b/test/snapshots/leader.golden index d58e8d6c..10907b99 100644 --- a/test/snapshots/leader.golden +++ b/test/snapshots/leader.golden @@ -189,20 +189,20 @@ | 2 SPC and its keys, a chord, a button, the | 3 topbar - or the name, executed anywhere. | 4 -| 5 SPC ? Help topbar -| 6 SPC c d Delcol -| 7 SPC c n Newcol topbar -| 8 SPC d Del -| 9 SPC f c Config -| 10 SPC f f Find topbar -| 11 SPC f g Grep topbar -| 12 SPC f n New topbar -| 13 SPC f s Save -| 14 SPC h t Tutor topbar -| 15 SPC j i Forward C-i -| 16 SPC j j Last -| 17 SPC j l Jumplist -| 18 SPC j o Back C-o +| 5 SPC ? Help topbar +| 6 SPC P ClipPasteBefore +| 7 SPC R ClipReplace +| 8 SPC Y ClipYankMain +| 9 SPC c d Delcol +| 10 SPC c n Newcol topbar +| 11 SPC d Del +| 12 SPC f c Config +| 13 SPC f f Find topbar +| 14 SPC f g Grep topbar +| 15 SPC f n New topbar +| 16 SPC f s Save +| 17 SPC h t Tutor topbar +| 18 SPC j i Forward C-i == snap help-group grid=100x40 cursor=7,22 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del @@ -228,7 +228,7 @@ | /tmp/pardes-snap/leader/cwd/+Help New Del | 1 pardes builtins under SPC h | 2 -| 3 SPC h t Tutor topbar +| 3 SPC h t Tutor topbar | 4 | | @@ -269,7 +269,7 @@ | /tmp/pardes-snap/leader/cwd/+Help New Del | 1 pardes builtins under SPC h | 2 -| 3 SPC h t Tutor topbar +| 3 SPC h t Tutor topbar | 4 | | @@ -310,7 +310,7 @@ | /tmp/pardes-snap/leader/cwd/+Help New Del | 1 pardes builtins under SPC h | 2 -| 3 SPC h t Tutor topbar +| 3 SPC h t Tutor topbar | 4 | | @@ -353,20 +353,20 @@ | 2 SPC and its keys, a chord, a button, the | 3 topbar - or the name, executed anywhere. | 4 -| 5 SPC ? Help topbar -| 6 SPC c d Delcol -| 7 SPC c n Newcol topbar -| 8 SPC d Del -| 9 SPC f c Config -| 10 SPC f f Find topbar -| 11 SPC f g Grep topbar -| 12 SPC f n New topbar -| 13 SPC f s Save -| 14 SPC h t Tutor topbar -| 15 SPC j i Forward C-i -| 16 SPC j j Last -| 17 SPC j l Jumplist -| 18 SPC j o Back C-o +| 5 SPC ? Help topbar +| 6 SPC P ClipPasteBefore +| 7 SPC R ClipReplace +| 8 SPC Y ClipYankMain +| 9 SPC c d Delcol +| 10 SPC c n Newcol topbar +| 11 SPC d Del +| 12 SPC f c Config +| 13 SPC f f Find topbar +| 14 SPC f g Grep topbar +| 15 SPC f n New topbar +| 16 SPC f s Save +| 17 SPC h t Tutor topbar +| 18 SPC j i Forward C-i == snap help-toggles grid=100x40 cursor=7,22 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del @@ -395,10 +395,10 @@ | 3 SPC t a Ascii | 4 SPC t b Tagbottom | 5 SPC t c Colors -| 6 SPC t d Debug topbar +| 6 SPC t d Debug topbar | 7 SPC t i PdfTint | 8 SPC t l Palette -| 9 SPC t n NextColor topbar +| 9 SPC t n NextColor topbar | 10 SPC t p Petscii | 11 SPC t r Crt | 12 SPC t s PdfSections @@ -433,10 +433,10 @@ | /tmp/pardes-snap/leader/cwd/+Help New Del | 1 pardes builtins under SPC w | 2 -| 3 SPC w h Left C-w h, C-w left -| 4 SPC w j Down C-w j, C-w down -| 5 SPC w k Up C-w k, C-w up -| 6 SPC w l Right C-w l, C-w right +| 3 SPC w h Left C-w h, C-w left +| 4 SPC w j Down C-w j, C-w down +| 5 SPC w k Up C-w k, C-w up +| 6 SPC w l Right C-w l, C-w right | 7 | | diff --git a/test/snapshots/load.golden b/test/snapshots/load.golden index 7b6bfab5..c33b79cd 100644 --- a/test/snapshots/load.golden +++ b/test/snapshots/load.golden @@ -1,7 +1,7 @@ == snap loaded grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/load/cwd New Del /tmp/pardes-snap/load/cwd New Del -| +| echo LOAD''MARK; seq 1 40 ls | LOADMARK d.txt | 1 | 2 @@ -16,7 +16,7 @@ | 11 | 12 | /tmp/pardes-snap/load/cwd New Del -| +| ls | d.txt | | diff --git a/test/snapshots/look-center.golden b/test/snapshots/look-center.golden index 199379a1..da1fbfed 100644 --- a/test/snapshots/look-center.golden +++ b/test/snapshots/look-center.golden @@ -1,7 +1,7 @@ == snap center-open grid=150x30 cursor=7,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/look-center/cwd/big.txt Save Ne /tmp/pardes-snap/look-center/cwd New Del /tmp/pardes-snap/look-center/cwd New Del -| 86 line 86 +| 86 line 86 ls ls | 87 line 87 big.txt big.txt | 88 line 88 | 89 line 89 @@ -16,7 +16,7 @@ | 98 line 98 | 99 line 99 | 100 line 100 /tmp/pardes-snap/look-center/cwd New Del -| 101 line 101 +| 101 line 101 ls | 102 line 102 big.txt | 103 line 103 | 104 line 104 @@ -32,7 +32,7 @@ == snap center-dedup grid=150x30 cursor=17,14 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/look-center/cwd/big.txt Save Ne /tmp/pardes-snap/look-center/cwd New Del /tmp/pardes-snap/look-center/cwd New Del -| 86 line 86 +| 86 line 86 ls ls | 87 line 87 big.txt big.txt | 88 line 88 | 89 line 89 @@ -47,7 +47,7 @@ | 98 line 98 | 99 line 99 | 100 line 100 /tmp/pardes-snap/look-center/cwd New Del -| 101 line 101 +| 101 line 101 ls | 102 line 102 big.txt | 103 line 103 | 104 line 104 @@ -63,7 +63,7 @@ == snap center-clamp grid=150x30 cursor=29,14 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/look-center/cwd/big.txt Save Ne /tmp/pardes-snap/look-center/cwd New Del /tmp/pardes-snap/look-center/cwd New Del -| 86 line 86 +| 86 line 86 ls ls | 87 line 87 big.txt big.txt | 88 line 88 | 89 line 89 @@ -78,7 +78,7 @@ | 98 line 98 | 99 line 99 | 100 line 100 /tmp/pardes-snap/look-center/cwd New Del -| 101 line 101 +| 101 line 101 ls | 102 line 102 big.txt | 103 line 103 | 104 line 104 diff --git a/test/snapshots/look-dir.golden b/test/snapshots/look-dir.golden index a29b1cf1..9ee71ba3 100644 --- a/test/snapshots/look-dir.golden +++ b/test/snapshots/look-dir.golden @@ -1,11 +1,11 @@ == snap dir-open grid=100x30 cursor=4,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/look-dir/cwd New Del /tmp/pardes-snap/look-dir/cwd New Del -| +| ls ls | sub top.txt sub top.txt | | /tmp/pardes-snap/look-dir/cwd/sub New Del -| +| ls | inner.txt | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/look-dir/cwd New Del -| +| ls | sub top.txt | | diff --git a/test/snapshots/look-file-1col.golden b/test/snapshots/look-file-1col.golden index 09af247f..1e957fb8 100644 --- a/test/snapshots/look-file-1col.golden +++ b/test/snapshots/look-file-1col.golden @@ -1,7 +1,7 @@ == snap file-open-1col grid=100x30 cursor=7,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/look-file-1col/cwd/big.txt Save /tmp/pardes-snap/look-file-1col/cwd New Del -| 26 line 26 +| 26 line 26 ls | 27 line 27 big.txt | 28 line 28 | 29 line 29 diff --git a/test/snapshots/look-file.golden b/test/snapshots/look-file.golden index b95cd54c..fa674003 100644 --- a/test/snapshots/look-file.golden +++ b/test/snapshots/look-file.golden @@ -1,7 +1,7 @@ == snap file-open grid=150x30 cursor=7,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/look-file/cwd/big.txt Save New /tmp/pardes-snap/look-file/cwd New Del /tmp/pardes-snap/look-file/cwd New Del -| 26 line 26 +| 26 line 26 ls ls | 27 line 27 big.txt big.txt | 28 line 28 | 29 line 29 @@ -16,7 +16,7 @@ | 38 line 38 | 39 line 39 | 40 line 40 /tmp/pardes-snap/look-file/cwd New Del -| 41 line 41 +| 41 line 41 ls | 42 line 42 big.txt | 43 line 43 | 44 line 44 diff --git a/test/snapshots/lookloaded.golden b/test/snapshots/lookloaded.golden index 311d7a66..1d09b582 100644 --- a/test/snapshots/lookloaded.golden +++ b/test/snapshots/lookloaded.golden @@ -1,7 +1,7 @@ == snap file-open grid=100x30 cursor=7,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookloaded/cwd /tmp/pardes-snap/lookloaded/cwd /tmp/pardes-snap/lookloaded/cwd -| 26 line 26 +| 26 line 26 ls ls | 27 line 27 big.txt big.txt | 28 line 28 | 29 line 29 @@ -16,7 +16,7 @@ | 38 line 38 | 39 line 39 | 40 line 40 /tmp/pardes-snap/lookloaded/cwd -| 41 line 41 +| 41 line 41 ls | 42 line 42 big.txt | 43 line 43 | 44 line 44 @@ -32,9 +32,9 @@ == snap removed grid=100x30 cursor=37,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookloaded/cwd /tmp/pardes-snap/lookloaded/cwd /tmp/pardes-snap/lookloaded/cwd -| 26 line 26 +| 26 line 26 ls ls | 27 line 27 big.txt big.txt -| 28 line 28 +| 28 line 28 rm big.txt; echo GO''NE | 29 line 29 GONE | 30 line 30 | 31 line 31 big.txt:40 big.txt:10 @@ -47,7 +47,7 @@ | 38 line 38 | 39 line 39 | 40 line 40 /tmp/pardes-snap/lookloaded/cwd -| 41 line 41 +| 41 line 41 ls | 42 line 42 big.txt | 43 line 43 | 44 line 44 @@ -63,9 +63,9 @@ == snap look-noFS grid=100x30 cursor=7,11 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookloaded/cwd /tmp/pardes-snap/lookloaded/cwd /tmp/pardes-snap/lookloaded/cwd -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 big.txt big.txt -| 3 line 3 +| 3 line 3 rm big.txt; echo GO''NE | 4 line 4 GONE | 5 line 5 | 6 line 6 big.txt:40 big.txt:10 @@ -78,7 +78,7 @@ | 13 line 13 | 14 line 14 | 15 line 15 /tmp/pardes-snap/lookloaded/cwd -| 16 line 16 +| 16 line 16 ls | 17 line 17 big.txt | 18 line 18 | 19 line 19 diff --git a/test/snapshots/lookpanes.golden b/test/snapshots/lookpanes.golden index d049ff5a..302f357e 100644 --- a/test/snapshots/lookpanes.golden +++ b/test/snapshots/lookpanes.golden @@ -1,11 +1,11 @@ == snap shells grid=130x50 cursor=122,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del -| 1 both.txt +| 1 both.txt ls | 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt | | /tmp/pardes-snap/lookpanes/cwd/alpha New Del -| +| ls | amark.txt both.txt pick.txt twin.txt zqonly.txt | | @@ -52,11 +52,11 @@ == snap other-dir grid=130x50 cursor=7,27 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del -| 1 both.txt +| 1 both.txt ls | 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt | | /tmp/pardes-snap/lookpanes/cwd/alpha New Del -| +| ls | amark.txt both.txt pick.txt twin.txt zqonly.txt | | @@ -103,11 +103,11 @@ == snap clicked-wins grid=130x50 cursor=7,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del -| 1 both.txt +| 1 both.txt ls | 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt | | /tmp/pardes-snap/lookpanes/cwd/alpha New Del -| +| ls | amark.txt both.txt pick.txt twin.txt zqonly.txt | | @@ -154,11 +154,11 @@ == snap mru-alpha grid=130x50 cursor=7,21 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del -| 1 both.txt +| 1 both.txt ls | 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt | | /tmp/pardes-snap/lookpanes/cwd/alpha New Del -| +| ls | amark.txt both.txt pick.txt twin.txt zqonly.txt | | @@ -205,11 +205,11 @@ == snap mru-beta grid=130x50 cursor=7,9 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del -| 1 both.txt +| 1 both.txt ls | 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt | | /tmp/pardes-snap/lookpanes/cwd/alpha New Del -| +| ls | amark.txt both.txt pick.txt twin.txt zqonly.txt | /tmp/pardes-snap/lookpanes/cwd/beta/twin.txt Save New Del | 1 TWIN-FROM-BETA diff --git a/test/snapshots/lookrange.golden b/test/snapshots/lookrange.golden index 6e292431..d1fc0bea 100644 --- a/test/snapshots/lookrange.golden +++ b/test/snapshots/lookrange.golden @@ -368,7 +368,7 @@ |25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808, |26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808, |27: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212, -|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 #080808,#80a0ff, +|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808, |29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808, == snap hit2 grid=150x30 cursor=17,22 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill @@ -431,7 +431,7 @@ |26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808, |27: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212, |28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808, -|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 #080808,#80a0ff, +|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808, == snap back grid=150x30 cursor=15,22 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del @@ -492,5 +492,5 @@ |25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808, |26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808, |27: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212, -|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 #080808,#80a0ff, +|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808, |29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808, diff --git a/test/snapshots/lookrange.snap b/test/snapshots/lookrange.snap index d1a86e0c..29f88d7f 100644 --- a/test/snapshots/lookrange.snap +++ b/test/snapshots/lookrange.snap @@ -6,7 +6,8 @@ # r.txt:7:4-9 line 7, columns 4 through 9 # r.txt:3:2-5:3 line 3 column 2 through line 5 column 3 # ...and only then presses `/`, whose result rows are exactly this syntax โ€” -# which is how n/N step to a hit with the matched text selected. +# which is how n/N select a hit and Enter lands on it with the matched text +# selected. # # `snapstyle` is the assertion that matters: the grid TEXT after a ranged look # is the same text a plain `:LINE:COL` look leaves, so the selection only shows @@ -47,8 +48,8 @@ stable 700 15000 snap stale snapstyle stale # --- and now the first consumer. The look above left r.txt focused, so `/` -# arms on it: the rows it writes carry the match's span, and n/N therefore step -# to each hit with the word itself selected. +# arms on it: the rows it writes carry the match's span, so n selects a row +# and the Enter after it goes to that hit with the word itself selected. key / text NEEDLE key enter @@ -56,15 +57,18 @@ wait 10000 r.txt:7:4-9 gg NEEDLE stable 700 15000 snap results key n +key enter stable 700 15000 snap hit1 snapstyle hit1 key n +key enter stable 700 15000 snap hit2 snapstyle hit2 -# N walks back onto the first hit, still selected +# N walks back onto the first hit; Enter looks it, still selected key N +key enter stable 700 15000 snap back snapstyle back diff --git a/test/snapshots/lsp.snap b/test/snapshots/lsp.snap index 79acaee8..2eb17735 100644 --- a/test/snapshots/lsp.snap +++ b/test/snapshots/lsp.snap @@ -36,14 +36,15 @@ key k stable 700 15000 snap hover # SPC l s lists the file's own symbols. Several rows, so it opens a +Search -# buffer โ€” which IS the picker: n steps a row and looks it, exactly as the Find -# and `/` results already do, with no picker code of its own. +# buffer โ€” which IS the picker: n selects a row and Enter looks it, exactly as +# the Find and `/` results already do, with no picker code of its own. key space key l key s stable 700 15000 snap symbols key n +key enter stable 700 15000 snap step # gd on something with no declaration behind it (a keyword) answers nothing, diff --git a/test/snapshots/lspcomplete.snap b/test/snapshots/lspcomplete.snap index 8b7854cd..8baa870e 100644 --- a/test/snapshots/lspcomplete.snap +++ b/test/snapshots/lspcomplete.snap @@ -87,9 +87,11 @@ snap refill key esc settle 100 # Several rows, so the buffer IS the picker and n walks it; completion does not -# jump the way a goto with one row does. The first step looks row 1 and lands -# SELECTING `verdigris` on line 2 of a.zig. +# jump the way a goto with one row does. The first step selects row 1, and the +# Enter after it looks that row and lands SELECTING `verdigris` on line 2 of +# a.zig. key n +key enter stable 700 15000 snap step # A pane the backend does not speak: same keystrokes, same dot before the diff --git a/test/snapshots/lsprelpath.golden b/test/snapshots/lsprelpath.golden index 885860b3..4fd48958 100644 --- a/test/snapshots/lsprelpath.golden +++ b/test/snapshots/lsprelpath.golden @@ -33,7 +33,7 @@ | /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Del | 1 /tmp/pardes-snap/lsprelpath/cwd/shade.zig:2:5-13 verdigris verdigris, | 2 /tmp/pardes-snap/lsprelpath/cwd/shade.zig:3:5-12 cinnabar cinnabar, -== snap abslook grid=100x34 cursor=16,6 +== snap abslook grid=100x34 cursor=19,18 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lsprelpath/cwd/sub/parent.zig Save New Del | 1 const shade = @import("../shade.zig"); @@ -70,12 +70,12 @@ | 2 /tmp/pardes-snap/lsprelpath/cwd/shade.zig:3:5-12 cinnabar cinnabar, == style abslook |0: 0-56 #949494,#121212, 57-99 d,#121212, -|1: 0-1 #ffffff,#626262, 2-79 #949494,#121212, 80-99 d,#121212, +|1: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212, |2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-27 #cf87e8,#080808,b 28-28 #bdbdbd,#080808, 29-42 #e3c78a,#080808, 43-44 #bdbdbd,#080808, 45-99 d,#080808, |3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-12 #cf87e8,#080808,b 13-38 #bdbdbd,#080808, 39-99 d,#080808, |5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-16 #cf87e8,#080808,b 17-17 #bdbdbd,#080808, 18-23 #cf87e8,#080808,b 24-29 #bdbdbd,#080808, 30-99 d,#080808, -|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-15 #bdbdbd,#080808, 16-99 d,#080808, +|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-99 d,#080808, |7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808, |8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-99 d,#080808, |9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, @@ -85,9 +85,9 @@ |13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, -|16: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212, +|16: 0-1 #ffffff,#626262, 2-79 #949494,#121212, 80-99 d,#121212, |17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-28 #cf87e8,#080808,b 29-30 #bdbdbd,#080808, 31-99 d,#080808, -|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-19 #080808,#80a0ff, 20-20 #bdbdbd,#080808, 21-99 d,#080808, +|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-10 #bdbdbd,#080808, 11-19 #080808,#80a0ff, 20-20 #bdbdbd,#080808, 21-99 d,#080808, |19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-99 d,#080808, |20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-99 d,#080808, |21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, @@ -101,7 +101,7 @@ |29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |30: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |31: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212, -|32: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 #080808,#80a0ff, +|32: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-76 #bdbdbd,#080808, 77-99 d,#080808, |33: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-74 #bdbdbd,#080808, 75-99 d,#080808, == snap subrow grid=100x34 cursor=16,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill @@ -138,7 +138,7 @@ | /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Del | 1 inner/tint.zig:2:5-9 ochre ochre, | 2 inner/tint.zig:3:5-10 indigo indigo, -== snap sublook grid=100x34 cursor=16,6 +== snap sublook grid=100x34 cursor=15,18 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/lsprelpath/cwd/sub/subdir.zig Save New Del | 1 const tint = @import("inner/tint.zig"); @@ -175,12 +175,12 @@ | 2 inner/tint.zig:3:5-10 indigo indigo, == style sublook |0: 0-56 #949494,#121212, 57-99 d,#121212, -|1: 0-1 #ffffff,#626262, 2-79 #949494,#121212, 80-99 d,#121212, +|1: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212, |2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-26 #cf87e8,#080808,b 27-27 #bdbdbd,#080808, 28-43 #e3c78a,#080808, 44-45 #bdbdbd,#080808, 46-99 d,#080808, |3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-12 #cf87e8,#080808,b 13-35 #bdbdbd,#080808, 36-99 d,#080808, |5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-16 #cf87e8,#080808,b 17-17 #bdbdbd,#080808, 18-23 #cf87e8,#080808,b 24-29 #bdbdbd,#080808, 30-99 d,#080808, -|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-15 #bdbdbd,#080808, 16-99 d,#080808, +|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-99 d,#080808, |7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808, |8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-99 d,#080808, |9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, @@ -190,9 +190,9 @@ |13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, -|16: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212, +|16: 0-1 #ffffff,#626262, 2-79 #949494,#121212, 80-99 d,#121212, |17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-23 #bdbdbd,#080808, 24-27 #cf87e8,#080808,b 28-29 #bdbdbd,#080808, 30-99 d,#080808, -|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-15 #080808,#80a0ff, 16-16 #bdbdbd,#080808, 17-99 d,#080808, +|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-10 #bdbdbd,#080808, 11-15 #080808,#80a0ff, 16-16 #bdbdbd,#080808, 17-99 d,#080808, |19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-99 d,#080808, |20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-99 d,#080808, |21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, @@ -206,7 +206,7 @@ |29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |30: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808, |31: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212, -|32: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 #080808,#80a0ff, +|32: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-40 #bdbdbd,#080808, 41-99 d,#080808, |33: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-43 #bdbdbd,#080808, 44-99 d,#080808, == snap clicked grid=100x34 cursor=16,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill diff --git a/test/snapshots/lsprelpath.snap b/test/snapshots/lsprelpath.snap index dce26d1e..1ff6f549 100644 --- a/test/snapshots/lsprelpath.snap +++ b/test/snapshots/lsprelpath.snap @@ -19,10 +19,10 @@ # strip that took the basename instead would produce a row that # resolves to nothing. # -# `n` is the assertion in both, not the row text: it looks row 1 and the right -# file opens with the member SELECTED on its own line. The style capture is -# where that selection shows, because focus goes back to the pane that asked, -# so the opened pane's cursor is not in the snap header. +# `n` and the Enter after it are the assertion in both, not the row text: the +# step selects row 1, the look opens the right file with the member SELECTED +# on its own line, and focus follows what opened โ€” so the snap header's cursor +# is that pane's, and the style capture is where the selection itself shows. dirmk sub dirmk sub/inner file shade.zig pub const Shade = enum {\n verdigris,\n cinnabar,\n};\n @@ -50,6 +50,7 @@ settle 100 # An absolute row has to keep resolving โ€” it is the spelling every row had # before this, and the one every hit outside the tree still has. key n +key enter stable 700 15000 snap abslook snapstyle abslook @@ -71,6 +72,7 @@ snap subrow key esc settle 100 key n +key enter stable 700 15000 snap sublook snapstyle sublook diff --git a/test/snapshots/modal.golden b/test/snapshots/modal.golden index 0a30d313..93ab4143 100644 --- a/test/snapshots/modal.golden +++ b/test/snapshots/modal.golden @@ -1,10 +1,10 @@ == snap top grid=100x30 cursor=2,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -29,13 +29,13 @@ | | | -== snap moved grid=100x30 cursor=5,6 +== snap moved grid=100x30 cursor=8,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -60,13 +60,13 @@ | | | -== snap xsel grid=100x30 cursor=15,6 +== snap xsel grid=100x30 cursor=48,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -96,9 +96,9 @@ |1: 0-1 #ffffff,#626262, 2-35 #949494,#121212, 36-49 d,#121212, 50-51 #ffffff,#262626, 52-85 #949494,#121212, 86-99 d,#121212, |2: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |3: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -|4: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, +|4: 0-0 d,#444444, 1-1 d,#080808, 2-48 #080808,#80a0ff, 49-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -|6: 0-0 d,#444444, 1-1 d,#080808, 2-15 #080808,#80a0ff, 16-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, +|6: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |7: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |8: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |9: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, @@ -122,13 +122,13 @@ |27: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |28: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |29: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -== snap xsel2 grid=100x30 cursor=15,7 +== snap xsel2 grid=100x30 cursor=13,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -153,13 +153,13 @@ | | | -== snap yanked grid=100x30 cursor=15,7 +== snap yanked grid=100x30 cursor=13,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -171,7 +171,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -184,13 +184,13 @@ | | | -== snap vsel grid=100x30 cursor=16,8 +== snap vsel grid=100x30 cursor=14,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -202,7 +202,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -220,11 +220,11 @@ |1: 0-1 #ffffff,#626262, 2-35 #949494,#121212, 36-49 d,#121212, 50-51 #ffffff,#262626, 52-85 #949494,#121212, 86-99 d,#121212, |2: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |3: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -|4: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -|5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -|6: 0-0 d,#444444, 1-1 d,#080808, 2-49 #080808,#80a0ff, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -|7: 0-0 d,#444444, 1-1 d,#080808, 2-49 #080808,#80a0ff, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -|8: 0-0 d,#444444, 1-1 d,#080808, 2-16 #080808,#80a0ff, 17-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, +|4: 0-0 d,#444444, 1-1 d,#080808, 2-49 #080808,#80a0ff, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, +|5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #080808,#80a0ff, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, +|6: 0-0 d,#444444, 1-1 d,#080808, 2-14 #080808,#80a0ff, 15-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, +|7: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, +|8: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |9: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |10: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |11: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, @@ -246,14 +246,14 @@ |27: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |28: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, |29: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808, -== snap typed grid=100x30 cursor=7,6 +== snap typed grid=100x30 cursor=7,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| -| TYPEDone two three +| TYPEDprintf 'one two three\nfour five six\nseven +| ght nine\n' +| one two three | four five six | seven eight nine | @@ -264,7 +264,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -277,13 +277,13 @@ | | | -== snap undone grid=100x30 cursor=16,8 +== snap undone grid=100x30 cursor=14,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -295,7 +295,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -308,14 +308,14 @@ | | | -== snap redone grid=100x30 cursor=7,6 +== snap redone grid=100x30 cursor=7,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| -| TYPEDone two three +| TYPEDprintf 'one two three\nfour five six\nseven +| ght nine\n' +| one two three | four five six | seven eight nine | @@ -326,7 +326,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | @@ -342,11 +342,11 @@ == snap bottom grid=100x30 cursor=2,9 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/modal/cwd New Del /tmp/pardes-snap/modal/cwd New Del -| +| ls ls | words.txt words.txt -| -| -| TYPEDone two three +| TYPEDprintf 'one two three\nfour five six\nseven +| ght nine\n' +| one two three | four five six | seven eight nine | @@ -357,7 +357,7 @@ | | | /tmp/pardes-snap/modal/cwd New Del -| +| ls | words.txt | | diff --git a/test/snapshots/multicursor.golden b/test/snapshots/multicursor.golden index 0e66f357..764ca170 100644 --- a/test/snapshots/multicursor.golden +++ b/test/snapshots/multicursor.golden @@ -1,7 +1,7 @@ == snap three-cursors grid=150x30 cursor=7,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/multicursor/cwd/f.txt Save New /tmp/pardes-snap/multicursor/cwd New Del /tmp/pardes-snap/multicursor/cwd New Del -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 f.txt f.txt | 3 line 3 | 4 line 4 @@ -16,7 +16,7 @@ | 13 | | /tmp/pardes-snap/multicursor/cwd New Del -| +| ls | f.txt | | @@ -63,7 +63,7 @@ == snap edited-at-three grid=150x30 cursor=9,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/multicursor/cwd/f.txt Save New /tmp/pardes-snap/multicursor/cwd New Del /tmp/pardes-snap/multicursor/cwd New Del -| 1 >>line 1 +| 1 >>line 1 ls ls | 2 >>line 2 f.txt f.txt | 3 >>line 3 | 4 line 4 @@ -78,7 +78,7 @@ | 13 | | /tmp/pardes-snap/multicursor/cwd New Del -| +| ls | f.txt | | @@ -94,7 +94,7 @@ == snap three-selections grid=150x30 cursor=8,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/multicursor/cwd/f.txt Save New /tmp/pardes-snap/multicursor/cwd New Del /tmp/pardes-snap/multicursor/cwd New Del -| 1 >>line 1 +| 1 >>line 1 ls ls | 2 >>line 2 f.txt f.txt | 3 >>line 3 | 4 line 4 @@ -109,7 +109,7 @@ | 13 | | /tmp/pardes-snap/multicursor/cwd New Del -| +| ls | f.txt | | @@ -156,7 +156,7 @@ == snap keep-primary grid=150x30 cursor=8,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/multicursor/cwd/f.txt Save New /tmp/pardes-snap/multicursor/cwd New Del /tmp/pardes-snap/multicursor/cwd New Del -| 1 >>line 1 +| 1 >>line 1 ls ls | 2 >>line 2 f.txt f.txt | 3 >>line 3 | 4 line 4 @@ -171,7 +171,7 @@ | 13 | | /tmp/pardes-snap/multicursor/cwd New Del -| +| ls | f.txt | | diff --git a/test/snapshots/nested.golden b/test/snapshots/nested.golden index 7b9ee1b5..b685a144 100644 --- a/test/snapshots/nested.golden +++ b/test/snapshots/nested.golden @@ -66,7 +66,7 @@ | $ $(readlink /proc/$PPID/exe) nestdir | $ | /tmp/pardes-snap/nested/cwd/nestdir New Del -| +| ls | inside-nested.txt | | diff --git a/test/snapshots/psearch.golden b/test/snapshots/psearch.golden index 25af2036..a3305345 100644 --- a/test/snapshots/psearch.golden +++ b/test/snapshots/psearch.golden @@ -1,7 +1,7 @@ == snap output grid=140x30 cursor=4,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/psearch/cwd New Del -| +| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' | x MARK a | zz | x MARK b @@ -32,7 +32,7 @@ == snap typing grid=140x30 cursor=8,29 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/psearch/cwd New Del -| +| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' | x MARK a | zz | x MARK b @@ -63,7 +63,7 @@ == snap results grid=140x30 cursor=4,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/psearch/cwd New Del -| +| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' | x MARK a | zz | x MARK b @@ -94,7 +94,7 @@ == snap first grid=140x30 cursor=7,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/psearch/cwd New Del -| +| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' | x MARK a | zz | x MARK b @@ -150,13 +150,13 @@ |24: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808, |25: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808, |26: 0-1 #ffffff,#262626, 2-119 #949494,#121212, 120-139 d,#121212, -|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-139 #080808,#80a0ff, +|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-139 d,#080808, |28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-139 d,#080808, |29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-139 d,#080808, == snap second grid=140x30 cursor=7,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/psearch/cwd New Del -| +| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' | x MARK a | zz | x MARK b @@ -187,7 +187,7 @@ == snap back grid=140x30 cursor=7,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/psearch/cwd New Del -| +| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' | x MARK a | zz | x MARK b @@ -215,10 +215,10 @@ | 1 @p0:2:3-6 x MARK a | 2 @p0:4:3-6 x MARK b | 3 @p0:6:3-6 x MARK c -== snap nomatch grid=140x30 cursor=7,3 +== snap nomatch grid=140x30 cursor=7,28 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/psearch/cwd New Del -| +| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' | x MARK a | zz | x MARK b @@ -280,7 +280,7 @@ == snap rightsearch grid=140x30 cursor=7,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/psearch/cwd New Del -| +| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' | x MARK a | zz | x MARK b diff --git a/test/snapshots/psearch.snap b/test/snapshots/psearch.snap index 11316ea9..1b9eac61 100644 --- a/test/snapshots/psearch.snap +++ b/test/snapshots/psearch.snap @@ -2,9 +2,10 @@ # the shell's own scrollback (the plain text view Look reads, prompt rows # hidden). Results land in a +Search OUTPUT BUFFER โ€” a file pane with no file # behind it, so its tag has no Save โ€” and point at `@p0:LINE:COL-ENDCOL`, the -# look target that names a live pane, since a terminal has no path. n/N walk -# the buffer and look each row, scrolling the terminal to that line of its -# scrollback and selecting the span the row names. +# look target that names a live pane, since a terminal has no path. n/N SELECT +# the next/prev row in the buffer and open nothing; Enter โ€” the look chord โ€” +# is what scrolls the terminal to that line of its scrollback and selects the +# span the row names. # PLACEMENT, and this script is the proof: an output buffer is NOT a document # โ€” it is the result list of the pane that asked for it โ€” so even here, with no # doc pane in the session for it to join, it does NOT take a column of its own. @@ -35,21 +36,27 @@ key enter wait 10000 @p0:2:3 stable 700 15000 snap results -# n looks result 1: the terminal's cursor lands on that scrollback line, on -# the matched SPAN (cols 3..6, past the leading "x ") โ€” not the start of the -# line, and selected rather than merely parked on +# n selects result 1 and Enter looks it: the terminal's cursor lands on that +# scrollback line, on the matched SPAN (cols 3..6, past the leading "x ") โ€” +# not the start of the line, and selected rather than merely parked on key n +key enter stable 700 15000 snap first snapstyle first key n +key enter stable 700 15000 snap second -# N walks back +# N walks back one row, Enter looks it key N +key enter stable 700 15000 snap back -# a no-match search opens an empty buffer of its own; n has nowhere to go +# a no-match search opens an empty buffer of its own โ€” and n does not stop +# there. The walk is a RING across panes, not one buffer's rows, so with +# nothing look-able in the empty list it carries on into the one that does +# have rows and resumes it a row past where the N above left off. key / text zzqq key enter @@ -62,6 +69,12 @@ snap nomatch # so the buffer stays empty. Col 5 row 4 is the `M` of the first `x MARK a`, # in the shell's body in both modes (normal hides the prompt row, leaving it # blank, so the output rows sit at the same place either way). +# The left click first is the price of the step above: it left the cursor in +# the results buffer, and c-b is read by the ACTIVE pane โ€” there is no tty +# behind a +Search to toggle. +press left 5 4 +release left 5 4 +stable 400 5000 key c-b stable 600 8000 press right 5 4 diff --git a/test/snapshots/respawn.golden b/test/snapshots/respawn.golden index be7be117..fe565d56 100644 --- a/test/snapshots/respawn.golden +++ b/test/snapshots/respawn.golden @@ -1,7 +1,7 @@ == snap respawn grid=100x30 cursor=4,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/respawn/cwd New Del /tmp/pardes-snap/respawn/cwd New Del -| +| ls ls | |$ /tmp/pardes-snap/respawn/cwd New Del | $ ls diff --git a/test/snapshots/restore.golden b/test/snapshots/restore.golden index dea5e81f..ee9eae46 100644 --- a/test/snapshots/restore.golden +++ b/test/snapshots/restore.golden @@ -32,8 +32,8 @@ == snap restored grid=100x30 cursor=4,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/restore/cwd New Del -| -| +| ls +| echo KEEP''ME | KEEPME | | diff --git a/test/snapshots/rsearch.golden b/test/snapshots/rsearch.golden index 953634af..99820250 100644 --- a/test/snapshots/rsearch.golden +++ b/test/snapshots/rsearch.golden @@ -1,7 +1,7 @@ == snap opened grid=180x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/rsearch/cwd New Del -| +| ls | code.txt sub | | @@ -32,7 +32,7 @@ == snap search grid=180x30 cursor=13,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/rsearch/cwd New Del -| +| ls | code.txt sub | | @@ -63,7 +63,7 @@ == snap select grid=180x30 cursor=14,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/rsearch/cwd New Del -| +| ls | code.txt sub | | @@ -94,7 +94,7 @@ == snap path-open grid=180x30 cursor=7,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -109,7 +109,7 @@ | 1 d1 | 2 d2 | 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del -| 4 d4 +| 4 d4 ls | 5 d5 code.txt sub | 6 d6 | @@ -125,7 +125,7 @@ == snap step1 grid=180x30 cursor=13,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -140,7 +140,7 @@ | 1 d1 | 2 d2 | 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del -| 4 d4 +| 4 d4 ls | 5 d5 code.txt sub | 6 d6 | @@ -156,7 +156,7 @@ == snap step2 grid=180x30 cursor=17,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -171,7 +171,7 @@ | 1 d1 | 2 d2 | 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del -| 4 d4 +| 4 d4 ls | 5 d5 code.txt sub | 6 d6 | @@ -187,7 +187,7 @@ == snap step3 grid=180x30 cursor=17,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -202,7 +202,7 @@ | 1 d1 | 2 d2 | 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del -| 4 d4 +| 4 d4 ls | 5 d5 code.txt sub | 6 d6 | @@ -218,7 +218,7 @@ == snap selclick grid=180x30 cursor=14,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -233,7 +233,7 @@ | 1 d1 | 2 d2 | 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del -| 4 d4 +| 4 d4 ls | 5 d5 code.txt sub | 6 d6 | @@ -249,7 +249,7 @@ == snap outside grid=180x30 cursor=20,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/rsearch/cwd/code.txt Save New Del /tmp/pardes-snap/rsearch/cwd New Del /tmp/pardes-snap/rsearch/cwd New Del -| 1 run count_x now +| 1 run count_x now ls ls | 2 open sub/dep.txt:3 here code.txt sub code.txt sub | 3 count_x again | 4 pick two words @@ -264,7 +264,7 @@ | 1 d1 | 2 d2 | 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del -| 4 d4 +| 4 d4 ls | 5 d5 code.txt sub | 6 d6 | diff --git a/test/snapshots/scroll.golden b/test/snapshots/scroll.golden index cd2167ba..55dd47c7 100644 --- a/test/snapshots/scroll.golden +++ b/test/snapshots/scroll.golden @@ -1,7 +1,7 @@ == snap bottom grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scroll/cwd New Del /tmp/pardes-snap/scroll/cwd New Del -| 188 +| 188 ls | 189 s.txt | 190 | 191 @@ -16,7 +16,7 @@ | 200 | | /tmp/pardes-snap/scroll/cwd New Del -| +| ls | s.txt | | @@ -32,7 +32,7 @@ == snap wheel3 grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scroll/cwd New Del /tmp/pardes-snap/scroll/cwd New Del -| 185 +| 185 ls | 186 s.txt | 187 | 188 @@ -47,7 +47,7 @@ | 197 | 198 | /tmp/pardes-snap/scroll/cwd New Del -| +| ls | s.txt | | @@ -63,7 +63,7 @@ == snap gutter-up grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scroll/cwd New Del /tmp/pardes-snap/scroll/cwd New Del -| 178 +| 178 ls | 179 s.txt | 180 | 181 @@ -78,7 +78,7 @@ | 190 | 191 | /tmp/pardes-snap/scroll/cwd New Del -| +| ls | s.txt | | @@ -94,7 +94,7 @@ == snap gutter-down grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scroll/cwd New Del /tmp/pardes-snap/scroll/cwd New Del -| 180 +| 180 ls | 181 s.txt | 182 | 183 @@ -109,7 +109,7 @@ | 192 | 193 | /tmp/pardes-snap/scroll/cwd New Del -| +| ls | s.txt | | @@ -125,7 +125,7 @@ == snap wheel-down grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scroll/cwd New Del /tmp/pardes-snap/scroll/cwd New Del -| 181 +| 181 ls | 182 s.txt | 183 | 184 @@ -140,7 +140,7 @@ | 193 | 194 | /tmp/pardes-snap/scroll/cwd New Del -| +| ls | s.txt | | diff --git a/test/snapshots/scrolloff.golden b/test/snapshots/scrolloff.golden index 90c84196..265d427d 100644 --- a/test/snapshots/scrolloff.golden +++ b/test/snapshots/scrolloff.golden @@ -1,84 +1,84 @@ == snap top grid=150x11 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scrolloff/cwd/g.txt Save New De /tmp/pardes-snap/scrolloff/cwd New Del /tmp/pardes-snap/scrolloff/cwd New Del -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 g.txt g.txt | 3 line 3 | 4 line 4 | 5 line 5 /tmp/pardes-snap/scrolloff/cwd New Del -| 6 line 6 +| 6 line 6 ls | 7 line 7 g.txt | 8 line 8 | 9 line 9 == snap edge grid=150x11 cursor=7,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scrolloff/cwd/g.txt Save New De /tmp/pardes-snap/scrolloff/cwd New Del /tmp/pardes-snap/scrolloff/cwd New Del -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 g.txt g.txt | 3 line 3 | 4 line 4 | 5 line 5 /tmp/pardes-snap/scrolloff/cwd New Del -| 6 line 6 +| 6 line 6 ls | 7 line 7 g.txt | 8 line 8 | 9 line 9 == snap scrolled1 grid=150x11 cursor=7,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scrolloff/cwd/g.txt Save New De /tmp/pardes-snap/scrolloff/cwd New Del /tmp/pardes-snap/scrolloff/cwd New Del -| 2 line 2 +| 2 line 2 ls ls | 3 line 3 g.txt g.txt | 4 line 4 | 5 line 5 | 6 line 6 /tmp/pardes-snap/scrolloff/cwd New Del -| 7 line 7 +| 7 line 7 ls | 8 line 8 g.txt | 9 line 9 | 10 line 10 == snap jdown grid=150x11 cursor=7,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scrolloff/cwd/g.txt Save New De /tmp/pardes-snap/scrolloff/cwd New Del /tmp/pardes-snap/scrolloff/cwd New Del -| 6 line 6 +| 6 line 6 ls ls | 7 line 7 g.txt g.txt | 8 line 8 | 9 line 9 | 10 line 10 /tmp/pardes-snap/scrolloff/cwd New Del -| 11 line 11 +| 11 line 11 ls | 12 line 12 g.txt | 13 line 13 | 14 line 14 == snap end grid=150x11 cursor=7,9 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scrolloff/cwd/g.txt Save New De /tmp/pardes-snap/scrolloff/cwd New Del /tmp/pardes-snap/scrolloff/cwd New Del -| 33 line 33 +| 33 line 33 ls ls | 34 line 34 g.txt g.txt | 35 line 35 | 36 line 36 | 37 line 37 /tmp/pardes-snap/scrolloff/cwd New Del -| 38 line 38 +| 38 line 38 ls | 39 line 39 g.txt | 40 line 40 | 41 == snap kup grid=150x11 cursor=7,5 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scrolloff/cwd/g.txt Save New De /tmp/pardes-snap/scrolloff/cwd New Del /tmp/pardes-snap/scrolloff/cwd New Del -| 29 line 29 +| 29 line 29 ls ls | 30 line 30 g.txt g.txt | 31 line 31 | 32 line 32 | 33 line 33 /tmp/pardes-snap/scrolloff/cwd New Del -| 34 line 34 +| 34 line 34 ls | 35 line 35 g.txt | 36 line 36 | 37 line 37 == snap top2 grid=150x11 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/scrolloff/cwd/g.txt Save New De /tmp/pardes-snap/scrolloff/cwd New Del /tmp/pardes-snap/scrolloff/cwd New Del -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 g.txt g.txt | 3 line 3 | 4 line 4 | 5 line 5 /tmp/pardes-snap/scrolloff/cwd New Del -| 6 line 6 +| 6 line 6 ls | 7 line 7 g.txt | 8 line 8 | 9 line 9 diff --git a/test/snapshots/selarg.golden b/test/snapshots/selarg.golden index 174ead70..5c81a3a0 100644 --- a/test/snapshots/selarg.golden +++ b/test/snapshots/selarg.golden @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/selarg/cwd New Del -| +| ls | s.txt | | @@ -33,7 +33,7 @@ |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/selarg/cwd New Del /tmp/pardes-snap/selarg/cwd New Del | ZZARG ZZVEE ./c.sh -| +| ./c.sh ZZARG | CHORDARG:ZZARG | | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/selarg/cwd New Del -| +| ls | s.txt | | @@ -64,9 +64,9 @@ |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/selarg/cwd New Del /tmp/pardes-snap/selarg/cwd New Del | ZZARG ZZVEE ./c.sh -| +| ./c.sh ZZARG | CHORDARG:ZZARG -| +| ./c.sh ZZVEE | CHORDARG:ZZVEE | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/selarg/cwd New Del -| +| ls | s.txt | | diff --git a/test/snapshots/shellset.golden b/test/snapshots/shellset.golden index 5cf503f7..8753d0d3 100644 --- a/test/snapshots/shellset.golden +++ b/test/snapshots/shellset.golden @@ -43,7 +43,7 @@ == snap fallback-shell grid=90x20 cursor=49,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/shellset/cwd/cmd.txt Save /tmp/pardes-snap/shellset/cwd New Del -| 1 Shell zznosuchshell +| 1 Shell zznosuchshell ls | cmd.txt zmarkfile.txt | | diff --git a/test/snapshots/shrinktag.golden b/test/snapshots/shrinktag.golden index 2ab4565c..bde1836e 100644 --- a/test/snapshots/shrinktag.golden +++ b/test/snapshots/shrinktag.golden @@ -1,7 +1,7 @@ == snap before grid=100x30 cursor=2,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/shrinktag/cwd New Del /tmp/pardes-snap/shrinktag/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/shrinktag/cwd New Del -| +| ls | w.txt | | @@ -32,8 +32,8 @@ == snap shrunk grid=100x30 cursor=2,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/shrinktag/cwd New Del /tmp/pardes-snap/shrinktag/cwd New Del -| /tmp/pardes-snap/shrinktag/cwd New Del -| w.txt +| /tmp/pardes-snap/shrinktag/cwd New Del ls +| ls w.txt | w.txt | | @@ -63,8 +63,8 @@ == snap move-preview grid=100x30 cursor=2,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/shrinktag/cwd New Del /tmp/pardes-snap/shrinktag/cwd New Del -| /tmp/pardes-snap/shrinktag/cwd New Del -| w.txt +| /tmp/pardes-snap/shrinktag/cwd New Del ls +| ls w.txt | w.txt | | @@ -94,7 +94,7 @@ == snap restored grid=100x30 cursor=2,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/shrinktag/cwd New Del /tmp/pardes-snap/shrinktag/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/shrinktag/cwd New Del -| +| ls | w.txt | | @@ -125,7 +125,7 @@ == snap bottom-shrunk grid=100x30 cursor=2,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/shrinktag/cwd New Del /tmp/pardes-snap/shrinktag/cwd New Del -| +| ls ls | w.txt w.txt | | diff --git a/test/snapshots/splitparent.golden b/test/snapshots/splitparent.golden index 281fb5ef..3cc2e6bc 100644 --- a/test/snapshots/splitparent.golden +++ b/test/snapshots/splitparent.golden @@ -1,8 +1,8 @@ == snap shrunk grid=100x30 cursor=4,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/splitparent/cwd New Del /tmp/pardes-snap/splitparent/cwd New Del -| /tmp/pardes-snap/splitparent/cwd New Del -| +| /tmp/pardes-snap/splitparent/cwd New Del ls +| ls | | | @@ -32,11 +32,11 @@ == snap swap-parent grid=100x30 cursor=4,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/splitparent/cwd New Del /tmp/pardes-snap/splitparent/cwd New Del -| /tmp/pardes-snap/splitparent/cwd New Del -| +| /tmp/pardes-snap/splitparent/cwd New Del ls +| ls | | /tmp/pardes-snap/splitparent/cwd New Del -| +| ls | | | @@ -69,11 +69,11 @@ == snap regrown grid=100x30 cursor=54,18 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/splitparent/cwd New Del /tmp/pardes-snap/splitparent/cwd New Del -| /tmp/pardes-snap/splitparent/cwd New Del -| +| /tmp/pardes-snap/splitparent/cwd New Del ls +| ls | | /tmp/pardes-snap/splitparent/cwd New Del -| +| ls | | | @@ -84,7 +84,7 @@ | | | /tmp/pardes-snap/splitparent/cwd New Del -| +| ls | | | diff --git a/test/snapshots/syntax.golden b/test/snapshots/syntax.golden index ac220610..5d6b85c7 100644 --- a/test/snapshots/syntax.golden +++ b/test/snapshots/syntax.golden @@ -1,7 +1,7 @@ == snap zig-open grid=150x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/syntax/cwd/demo.zig Save New De /tmp/pardes-snap/syntax/cwd New Del /tmp/pardes-snap/syntax/cwd New Del -| 1 const std = @import("std"); // greet +| 1 const std = @import("std"); // greet ls ls | 2 pub fn main() void { demo.zig demo.zig | 3 var x: u32 = 42; | 4 _ = x; @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/syntax/cwd New Del -| +| ls | demo.zig | | @@ -63,7 +63,7 @@ == style colors-off |0: 0-56 #949494,#121212, 57-149 d,#121212, |1: 0-1 #ffffff,#626262, 2-49 #949494,#121212, 50-51 #ffffff,#262626, 52-86 #949494,#121212, 87-99 d,#121212, 100-101 #ffffff,#262626, 102-136 #949494,#121212, 137-149 d,#121212, -|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-42 #bdbdbd,#080808, 43-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, +|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-42 #bdbdbd,#080808, 43-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-53 #bdbdbd,#080808, 54-99 d,#080808, 100-100 d,#444444, 101-101 d,#080808, 102-103 #bdbdbd,#080808, 104-149 d,#080808, |3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-59 #bdbdbd,#080808, 60-99 d,#080808, 100-100 d,#444444, 101-101 d,#080808, 102-109 #bdbdbd,#080808, 110-149 d,#080808, |4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, |5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, @@ -78,7 +78,7 @@ |14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, |15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, |16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-49 d,#080808, 50-51 #ffffff,#262626, 52-86 #949494,#121212, 87-99 d,#121212, 100-100 d,#444444, 101-149 d,#080808, -|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, +|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-53 #bdbdbd,#080808, 54-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, |18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-59 #bdbdbd,#080808, 60-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, |19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, |20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808, 100-100 d,#444444, 101-149 d,#080808, diff --git a/test/snapshots/tag.golden b/test/snapshots/tag.golden index f24790d2..13cb2e72 100644 --- a/test/snapshots/tag.golden +++ b/test/snapshots/tag.golden @@ -1,7 +1,7 @@ == snap tag-focus grid=150x30 cursor=39,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tag/cwd New Del /tmp/pardes-snap/tag/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/tag/cwd New Del -| +| ls | t.txt | | @@ -32,7 +32,7 @@ == snap tag-typed grid=150x30 cursor=45,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tag/cwd t.txt New Del /tmp/pardes-snap/tag/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/tag/cwd New Del -| +| ls | t.txt | | @@ -63,7 +63,7 @@ == snap tag-del grid=150x30 cursor=41,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tag/cwd t New Del /tmp/pardes-snap/tag/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/tag/cwd New Del -| +| ls | t.txt | | @@ -94,7 +94,7 @@ == snap tag-exit grid=150x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tag/cwd t.txt New Del /tmp/pardes-snap/tag/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/tag/cwd New Del -| +| ls | t.txt | | @@ -125,7 +125,7 @@ == snap tag-look grid=150x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tag/cwd/t.txt Save New Del /tmp/pardes-snap/tag/cwd t.txt /tmp/pardes-snap/tag/cwd New Del -| 1 ZZLOOKED +| 1 ZZLOOKED ls ls | t.txt t.txt | | @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/tag/cwd New Del -| +| ls | t.txt | | diff --git a/test/snapshots/tagalign.golden b/test/snapshots/tagalign.golden index a9dda3c7..867d4c2a 100644 --- a/test/snapshots/tagalign.golden +++ b/test/snapshots/tagalign.golden @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/tagalign/cwd New Del -| +| ls | deep | | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/tagalign/cwd New Del -| +| ls | deep | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/tagalign/cwd New Del -| +| ls | deep | | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/tagalign/cwd New Del -| +| ls | deep | | @@ -125,7 +125,7 @@ == snap alone grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagalign/cwd New Del -| +| ls | deep | | diff --git a/test/snapshots/tagalign2col.golden b/test/snapshots/tagalign2col.golden index d5d22935..2db32f08 100644 --- a/test/snapshots/tagalign2col.golden +++ b/test/snapshots/tagalign2col.golden @@ -1,7 +1,7 @@ == snap onecol grid=160x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Del /tmp/pardes-snap/tagalign2col/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta deep | 3 gamma | @@ -32,7 +32,7 @@ == snap aligned grid=160x30 cursor=4,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Del /tmp/pardes-snap/tagalign2col/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta deep | 3 gamma | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/tagalign2col/cwd New Del -| +| ls | deep | | @@ -63,7 +63,7 @@ == snap widened grid=160x30 cursor=4,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Del โ•Ž /tmp/pardes-snap/tagalign2col/cwd New Del -| 1 alpha โ•Ž +| 1 alpha โ•Ž ls | 2 beta โ•Ž deep | 3 gamma โ•Ž | โ•Ž @@ -78,7 +78,7 @@ | โ•Ž | โ•Ž | /tmp/pardes-snap/tagalign2col/cwd New Del โ•Ž -| โ•Ž +| ls โ•Ž | deep โ•Ž | โ•Ž | โ•Ž diff --git a/test/snapshots/tagbottomimage.golden b/test/snapshots/tagbottomimage.golden index 72b31809..9ba62909 100644 --- a/test/snapshots/tagbottomimage.golden +++ b/test/snapshots/tagbottomimage.golden @@ -1,7 +1,7 @@ == snap img-top grid=150x30 cursor=11,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | img /tmp/pardes-snap/tagbottomimage/cwd/pic.ppm New Del /tmp/pardes-snap/tagbottomimage/cwd New Del -| (f๐Ÿฌฑ]0V7R*%m๐Ÿฌถ๐ŸฌG๐ŸฌฌtN#XR9q๐ŸฌขtC#f/๐Ÿฌœ_GR(๐Ÿฌž๐Ÿฌ™tCRp$o*7^+[#H7s๐ŸฌขYDZ๐Ÿฌโ–Ÿ +| (f๐Ÿฌฑ]0V7R*%m๐Ÿฌถ๐ŸฌG๐ŸฌฌtN#XR9q๐ŸฌขtC#f/๐Ÿฌœ_GR(๐Ÿฌž๐Ÿฌ™tCRp$o*7^+[#H7s๐ŸฌขYDZ๐Ÿฌโ–Ÿ ls | iU)dSotT[r27T"\*Fhโ–๐Ÿฌ…g,๐Ÿฌฐp๐Ÿฌ›โ–™๐Ÿฌฒ&*3/9xy๐Ÿฌ›โ–€0kCgโ–›๐ŸฌฑC,>C}PC06m๐Ÿฌโ–Ÿโ–ˆ pic.ppm | "Sโ–„;$gs,Xaโ–ŸT๐Ÿฌ”sโ––โ”ผWโ–˜?by๐Ÿฌ‹๐ŸฌญuCR3/A3๐ŸฌถlOโ––โ–ž๐Ÿฌƒ๐Ÿฌ˜โ•ณ๐ŸฌŸ#=๐Ÿฌบ๐Ÿฌ•yoaJ@>4๐Ÿฌ๐Ÿฌต | โ”€m!fAAD๐Ÿฌ’jW>7JkRโ–„โ–œ๐Ÿฌซ๐Ÿฌž๐ŸฌขFWxโ•ฒโ–Ÿ2ZT๐Ÿฌฅ/โ––jteR?q๐Ÿฌถ^๐Ÿฌ…โ–€_@Nโ”€u4๐Ÿฌน๐Ÿฌ๐Ÿฌน @@ -31,7 +31,7 @@ | ๐Ÿฌ๐Ÿฌน == snap img-bottom grid=150x30 cursor=11,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill -| (f๐Ÿฌฑ]0V7R*%m๐Ÿฌถ๐ŸฌG๐ŸฌฌtN#XR9q๐ŸฌขtC#f/๐Ÿฌœ_GR(๐Ÿฌž๐Ÿฌ™tCRp$o*7^+[#H7s๐ŸฌขYDZ๐Ÿฌโ–Ÿ +| (f๐Ÿฌฑ]0V7R*%m๐Ÿฌถ๐ŸฌG๐ŸฌฌtN#XR9q๐ŸฌขtC#f/๐Ÿฌœ_GR(๐Ÿฌž๐Ÿฌ™tCRp$o*7^+[#H7s๐ŸฌขYDZ๐Ÿฌโ–Ÿ ls | iU)dSotT[r27T"\*Fhโ–๐Ÿฌ…g,๐Ÿฌฐp๐Ÿฌ›โ–™๐Ÿฌฒ&*3/9xy๐Ÿฌ›โ–€0kCgโ–›๐ŸฌฑC,>C}PC06m๐Ÿฌโ–Ÿโ–ˆ pic.ppm | "Sโ–„;$gs,Xaโ–ŸT๐Ÿฌ”sโ––โ”ผWโ–˜?by๐Ÿฌ‹๐ŸฌญuCR3/A3๐ŸฌถlOโ––โ–ž๐Ÿฌƒ๐Ÿฌ˜โ•ณ๐ŸฌŸ#=๐Ÿฌบ๐Ÿฌ•yoaJ@>4๐Ÿฌ๐Ÿฌต | โ”€m!fAAD๐Ÿฌ’jW>7JkRโ–„โ–œ๐Ÿฌซ๐Ÿฌž๐ŸฌขFWxโ•ฒโ–Ÿ2ZT๐Ÿฌฅ/โ––jteR?q๐Ÿฌถ^๐Ÿฌ…โ–€_@Nโ”€u4๐Ÿฌน๐Ÿฌ๐Ÿฌน @@ -93,7 +93,7 @@ |29: 0-1 #ffffff,#626262, 2-56 #949494,#121212, 57-74 d,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212, == snap search-prompt grid=150x30 cursor=6,28 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill -| (f๐Ÿฌฑ]0V7R*%m๐Ÿฌถ๐ŸฌG๐ŸฌฌtN#XR9q๐ŸฌขtC#f/๐Ÿฌœ_GR(๐Ÿฌž๐Ÿฌ™tCRp$o*7^+[#H7s๐ŸฌขYDZ๐Ÿฌโ–Ÿ +| (f๐Ÿฌฑ]0V7R*%m๐Ÿฌถ๐ŸฌG๐ŸฌฌtN#XR9q๐ŸฌขtC#f/๐Ÿฌœ_GR(๐Ÿฌž๐Ÿฌ™tCRp$o*7^+[#H7s๐ŸฌขYDZ๐Ÿฌโ–Ÿ ls | iU)dSotT[r27T"\*Fhโ–๐Ÿฌ…g,๐Ÿฌฐp๐Ÿฌ›โ–™๐Ÿฌฒ&*3/9xy๐Ÿฌ›โ–€0kCgโ–›๐ŸฌฑC,>C}PC06m๐Ÿฌโ–Ÿโ–ˆ pic.ppm | "Sโ–„;$gs,Xaโ–ŸT๐Ÿฌ”sโ––โ”ผWโ–˜?by๐Ÿฌ‹๐ŸฌญuCR3/A3๐ŸฌถlOโ––โ–ž๐Ÿฌƒ๐Ÿฌ˜โ•ณ๐ŸฌŸ#=๐Ÿฌบ๐Ÿฌ•yoaJ@>4๐Ÿฌ๐Ÿฌต | โ”€m!fAAD๐Ÿฌ’jW>7JkRโ–„โ–œ๐Ÿฌซ๐Ÿฌž๐ŸฌขFWxโ•ฒโ–Ÿ2ZT๐Ÿฌฅ/โ––jteR?q๐Ÿฌถ^๐Ÿฌ…โ–€_@Nโ”€u4๐Ÿฌน๐Ÿฌ๐Ÿฌน @@ -124,7 +124,7 @@ | img /tmp/pardes-snap/tagbottomimage/cwd/pic.ppm New Del /tmp/pardes-snap/tagbottomimage/cwd New Del == snap del-image grid=150x30 cursor=5,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill -| +| ls | pic.ppm | | diff --git a/test/snapshots/tagnav.golden b/test/snapshots/tagnav.golden index 1c9186be..075cf45d 100644 --- a/test/snapshots/tagnav.golden +++ b/test/snapshots/tagnav.golden @@ -1,7 +1,7 @@ == snap start grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -32,7 +32,7 @@ == snap colon grid=100x30 cursor=36,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -63,7 +63,7 @@ == snap right-tag grid=100x30 cursor=80,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -94,7 +94,7 @@ == snap left-tag grid=100x30 cursor=36,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -125,7 +125,7 @@ == snap down-tag grid=100x30 cursor=41,16 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -156,7 +156,7 @@ == snap up-tag grid=100x30 cursor=36,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -171,7 +171,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -187,7 +187,7 @@ == snap up-edge grid=100x30 cursor=0,0 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -202,7 +202,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -218,7 +218,7 @@ == snap topbar-word grid=100x30 cursor=3,0 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -233,7 +233,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -249,7 +249,7 @@ == snap topbar-graphemes grid=100x30 cursor=5,0 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -264,7 +264,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -280,7 +280,7 @@ == snap back-down grid=100x30 cursor=36,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -295,7 +295,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -311,7 +311,7 @@ == snap arrows-still-motion grid=100x30 cursor=38,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -326,7 +326,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -342,7 +342,7 @@ == snap back-to-body grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -357,7 +357,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -388,7 +388,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -404,7 +404,7 @@ == snap tty-tag grid=100x30 cursor=80,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del $ /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -419,7 +419,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -450,7 +450,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -481,7 +481,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -512,7 +512,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -543,7 +543,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -574,7 +574,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | @@ -590,7 +590,7 @@ == snap topbar-restored grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -605,7 +605,7 @@ | | | /tmp/pardes-snap/tagnav/cwd New Del -| +| ls | w.txt | | diff --git a/test/snapshots/theme.golden b/test/snapshots/theme.golden index b7d8d384..d1941f9b 100644 --- a/test/snapshots/theme.golden +++ b/test/snapshots/theme.golden @@ -1,7 +1,7 @@ == snap helix grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/theme/cwd New Del /tmp/pardes-snap/theme/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/theme/cwd New Del -| +| ls | t.txt | | @@ -63,7 +63,7 @@ == snap dark grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/theme/cwd New Del /tmp/pardes-snap/theme/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/theme/cwd New Del -| +| ls | t.txt | | @@ -125,7 +125,7 @@ == snap acme grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/theme/cwd New Del /tmp/pardes-snap/theme/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/theme/cwd New Del -| +| ls | t.txt | | @@ -187,7 +187,7 @@ == snap colors-off grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/theme/cwd New Del /tmp/pardes-snap/theme/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -202,7 +202,7 @@ | | | /tmp/pardes-snap/theme/cwd New Del -| +| ls | t.txt | | @@ -218,7 +218,7 @@ == style colors-off |0: 0-56 #000000,#eaffff, 57-99 d,#eaffff, |1: 0-1 #ffffff,#6e4fd0, 2-35 #000000,#eaffff, 36-49 d,#eaffff, 50-51 #ffffff,#383c54, 52-85 #000000,#eaffff, 86-99 d,#eaffff, -|2: 0-99 d,#ffffea, +|2: 0-1 d,#ffffea, 2-3 #000000,#ffffea, 4-51 d,#ffffea, 52-53 #000000,#ffffea, 54-99 d,#ffffea, |3: 0-1 d,#ffffea, 2-6 #000000,#ffffea, 7-51 d,#ffffea, 52-56 #000000,#ffffea, 57-99 d,#ffffea, |4: 0-99 d,#ffffea, |5: 0-99 d,#ffffea, @@ -233,7 +233,7 @@ |14: 0-99 d,#ffffea, |15: 0-99 d,#ffffea, |16: 0-1 #ffffff,#383c54, 2-35 #000000,#eaffff, 36-49 d,#eaffff, 50-99 d,#ffffea, -|17: 0-99 d,#ffffea, +|17: 0-1 d,#ffffea, 2-3 #000000,#ffffea, 4-99 d,#ffffea, |18: 0-1 d,#ffffea, 2-6 #000000,#ffffea, 7-99 d,#ffffea, |19: 0-99 d,#ffffea, |20: 0-99 d,#ffffea, @@ -249,7 +249,7 @@ == snap generated grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/theme/cwd New Del /tmp/pardes-snap/theme/cwd New Del -| +| ls ls | t.txt t.txt | | @@ -264,7 +264,7 @@ | | | /tmp/pardes-snap/theme/cwd New Del -| +| ls | t.txt | | diff --git a/test/snapshots/themesel.golden b/test/snapshots/themesel.golden index 08d5a271..7303ea55 100644 --- a/test/snapshots/themesel.golden +++ b/test/snapshots/themesel.golden @@ -60,7 +60,7 @@ | 11 Theme andromeda | 12 Theme ao | 13 Theme ashen -== snap step-helix grid=100x30 cursor=7,2 +== snap step-helix grid=100x30 cursor=7,17 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/themesel/cwd/t.txt Save New Del | 1 line 1 @@ -93,8 +93,8 @@ | 13 Theme ashen == style step-helix |0: 0-56 #949494,#121212, 57-99 d,#121212, -|1: 0-1 #ffffff,#626262, 2-79 #949494,#121212, 80-99 d,#121212, -|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-99 d,#080808, +|1: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212, +|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808, |3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808, |4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808, |5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808, @@ -108,8 +108,8 @@ |13: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-99 d,#080808, |14: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-99 d,#080808, |15: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-99 d,#080808, -|16: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212, -|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 #080808,#80a0ff, +|16: 0-1 #ffffff,#626262, 2-79 #949494,#121212, 80-99 d,#121212, +|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-17 #bdbdbd,#080808, 18-99 d,#080808, |18: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-99 d,#080808, |19: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-99 d,#080808, |20: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-99 d,#080808, @@ -122,7 +122,7 @@ |27: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-21 #bdbdbd,#080808, 22-99 d,#080808, |28: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-99 d,#080808, |29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-99 d,#080808, -== snap step-dark grid=100x30 cursor=7,2 +== snap step-dark grid=100x30 cursor=7,18 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/themesel/cwd/t.txt Save New Del | 1 line 1 @@ -155,8 +155,8 @@ | 13 Theme ashen == style step-dark |0: 0-56 #969696,#2c2a3e, 57-99 d,#2c2a3e, -|1: 0-1 #ffffff,#6e4fd0, 2-79 #969696,#2c2a3e, 80-99 d,#2c2a3e, -|2: 0-0 d,#525252, 1-1 d,d, 2-6 #969696,#2c2a3e, 7-99 d,d, +|1: 0-1 #ffffff,#383c54, 2-79 #969696,#2c2a3e, 80-99 d,#2c2a3e, +|2: 0-0 d,#525252, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |3: 0-0 d,#525252, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |4: 0-0 d,#525252, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |5: 0-0 d,#525252, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, @@ -170,9 +170,9 @@ |13: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |14: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |15: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, -|16: 0-1 #ffffff,#383c54, 2-79 #969696,#2c2a3e, 80-99 d,#2c2a3e, +|16: 0-1 #ffffff,#6e4fd0, 2-79 #969696,#2c2a3e, 80-99 d,#2c2a3e, |17: 0-0 d,#525252, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, -|18: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 #d8c8a8,#4a3a1e, +|18: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #969696,#2c2a3e, 7-99 d,d, |19: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |20: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |21: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, @@ -184,7 +184,7 @@ |27: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |28: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, |29: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d, -== snap step-acme grid=100x30 cursor=7,2 +== snap step-acme grid=100x30 cursor=7,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/themesel/cwd/t.txt Save New Del | 1 line 1 @@ -217,8 +217,8 @@ | 13 Theme ashen == style step-acme |0: 0-56 #000000,#eaffff, 57-99 d,#eaffff, -|1: 0-1 #ffffff,#6e4fd0, 2-79 #000000,#eaffff, 80-99 d,#eaffff, -|2: 0-1 d,#ffffea, 2-6 #000000,#eaffff, 7-12 #000000,#ffffea, 13-99 d,#ffffea, +|1: 0-1 #ffffff,#383c54, 2-79 #000000,#eaffff, 80-99 d,#eaffff, +|2: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea, |3: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea, |4: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea, |5: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea, @@ -232,10 +232,10 @@ |13: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-13 #000000,#ffffea, 14-99 d,#ffffea, |14: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-13 #000000,#ffffea, 14-99 d,#ffffea, |15: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-13 #000000,#ffffea, 14-99 d,#ffffea, -|16: 0-1 #ffffff,#383c54, 2-79 #000000,#eaffff, 80-99 d,#eaffff, +|16: 0-1 #ffffff,#6e4fd0, 2-79 #000000,#eaffff, 80-99 d,#eaffff, |17: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-17 #000000,#ffffea, 18-99 d,#ffffea, |18: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-16 #000000,#ffffea, 17-99 d,#ffffea, -|19: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-99 #000000,#eeee9e, +|19: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #000000,#eaffff, 7-16 #000000,#ffffea, 17-99 d,#ffffea, |20: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-16 #000000,#ffffea, 17-99 d,#ffffea, |21: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-22 #000000,#ffffea, 23-99 d,#ffffea, |22: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-24 #000000,#ffffea, 25-99 d,#ffffea, @@ -246,7 +246,7 @@ |27: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-21 #000000,#ffffea, 22-99 d,#ffffea, |28: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-14 #000000,#ffffea, 15-99 d,#ffffea, |29: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-17 #000000,#ffffea, 18-99 d,#ffffea, -== snap step-generated grid=100x30 cursor=7,2 +== snap step-generated grid=100x30 cursor=7,20 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/themesel/cwd/t.txt Save New Del | 1 line 1 @@ -279,8 +279,8 @@ | 13 Theme ashen == style step-generated |0: 0-56 #e0e0e0,#1e262e, 57-99 d,#1e262e, -|1: 0-1 #000000,#ffa060, 2-79 #e0e0e0,#1e262e, 80-99 d,#1e262e, -|2: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #e0e0e0,#1e262e, 7-12 #e0e0e0,#161e26, 13-99 d,#161e26, +|1: 0-1 #ffffff,#303840, 2-79 #e0e0e0,#1e262e, 80-99 d,#1e262e, +|2: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-12 #e0e0e0,#161e26, 13-99 d,#161e26, |3: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-12 #e0e0e0,#161e26, 13-99 d,#161e26, |4: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-12 #e0e0e0,#161e26, 13-99 d,#161e26, |5: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-12 #e0e0e0,#161e26, 13-99 d,#161e26, @@ -294,11 +294,11 @@ |13: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-13 #e0e0e0,#161e26, 14-99 d,#161e26, |14: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-13 #e0e0e0,#161e26, 14-99 d,#161e26, |15: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-13 #e0e0e0,#161e26, 14-99 d,#161e26, -|16: 0-1 #ffffff,#303840, 2-79 #e0e0e0,#1e262e, 80-99 d,#1e262e, +|16: 0-1 #000000,#ffa060, 2-79 #e0e0e0,#1e262e, 80-99 d,#1e262e, |17: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-17 #e0e0e0,#161e26, 18-99 d,#161e26, |18: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-16 #e0e0e0,#161e26, 17-99 d,#161e26, |19: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-16 #e0e0e0,#161e26, 17-99 d,#161e26, -|20: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-99 #e0e0e0,#303840, +|20: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #e0e0e0,#1e262e, 7-16 #e0e0e0,#161e26, 17-99 d,#161e26, |21: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-22 #e0e0e0,#161e26, 23-99 d,#161e26, |22: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-24 #e0e0e0,#161e26, 25-99 d,#161e26, |23: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-25 #e0e0e0,#161e26, 26-99 d,#161e26, @@ -308,7 +308,7 @@ |27: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-21 #e0e0e0,#161e26, 22-99 d,#161e26, |28: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-14 #e0e0e0,#161e26, 15-99 d,#161e26, |29: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-17 #e0e0e0,#161e26, 18-99 d,#161e26, -== snap step-back grid=100x30 cursor=7,2 +== snap step-back grid=100x30 cursor=7,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/themesel/cwd/t.txt Save New Del | 1 line 1 @@ -341,8 +341,8 @@ | 13 Theme ashen == style step-back |0: 0-56 #000000,#eaffff, 57-99 d,#eaffff, -|1: 0-1 #ffffff,#6e4fd0, 2-79 #000000,#eaffff, 80-99 d,#eaffff, -|2: 0-1 d,#ffffea, 2-6 #000000,#eaffff, 7-12 #000000,#ffffea, 13-99 d,#ffffea, +|1: 0-1 #ffffff,#383c54, 2-79 #000000,#eaffff, 80-99 d,#eaffff, +|2: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea, |3: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea, |4: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea, |5: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea, @@ -356,10 +356,10 @@ |13: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-13 #000000,#ffffea, 14-99 d,#ffffea, |14: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-13 #000000,#ffffea, 14-99 d,#ffffea, |15: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-13 #000000,#ffffea, 14-99 d,#ffffea, -|16: 0-1 #ffffff,#383c54, 2-79 #000000,#eaffff, 80-99 d,#eaffff, +|16: 0-1 #ffffff,#6e4fd0, 2-79 #000000,#eaffff, 80-99 d,#eaffff, |17: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-17 #000000,#ffffea, 18-99 d,#ffffea, |18: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-16 #000000,#ffffea, 17-99 d,#ffffea, -|19: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-99 #000000,#eeee9e, +|19: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #000000,#eaffff, 7-16 #000000,#ffffea, 17-99 d,#ffffea, |20: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-16 #000000,#ffffea, 17-99 d,#ffffea, |21: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-22 #000000,#ffffea, 23-99 d,#ffffea, |22: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-24 #000000,#ffffea, 25-99 d,#ffffea, diff --git a/test/snapshots/themesel.snap b/test/snapshots/themesel.snap index d714fa84..cff136f1 100644 --- a/test/snapshots/themesel.snap +++ b/test/snapshots/themesel.snap @@ -1,10 +1,14 @@ # RULE: a results buffer is a list of things you can RUN, and its traits say -# which verb runs them. Every list before this one held LOCATIONS, so stepping -# a row with n/N Looks it. `SPC t t` (ThemeSel) opens the first one whose rows -# are COMMANDS โ€” `Theme `, exactly the line you would type โ€” so n/N Exec -# each row instead. Walking the list therefore wears the themes as you pass -# them, and picking one is stopping on it: there is no preview state, nothing -# to confirm and nothing to cancel, because arriving already did it. +# what a ROW IS. Every list before this one held LOCATIONS โ€” a row with a +# `path:LINE:COL` word inside it โ€” so n/N select that word and Enter Looks it. +# `SPC t t` (ThemeSel) opens the first one whose rows are COMMANDS: `Theme +# `, exactly the line you would type, with no path in it to pick out, so +# n/N select the WHOLE ROW. One motion, two grains, and the same split either +# way โ€” the step only SELECTS, and Tab (Exec, or the middle button, which is +# the same builtin) is what RUNS what it left. Walking the list therefore +# wears nothing as you pass; the theme changes on the Tab, and picking one is +# running it and stopping. There is still no preview state, nothing to confirm +# and nothing to cancel: the row you ran is the theme you have. # # Both halves of the ring are in the buffer: the three pardes ships with come # first (helix, dark, acme), then everything tools/gen_themes.zig exported from @@ -16,25 +20,29 @@ start 30 100 t.txt wait 8000 t.txt stable 700 20000 snap boot -# SPC t t: the list lands below the pane that asked, focus stays HERE โ€” n/N are -# read in this pane and they step the buffer they just armed. +# SPC t t: the list lands below the pane that asked, focus stays HERE โ€” but a +# fresh output buffer is where the walk's ring starts, so the first n goes +# into the list and every one after it carries on down it. key space t t wait 10000 Theme helix stable 700 15000 snap list -# n selects row 1 and runs it: `Theme helix`, which is already the boot theme, -# so only the selection moves. That is the honest first step โ€” an idempotent -# command has to be safe to step onto. +# n selects row 1 whole and Tab runs it: `Theme helix`, which is already the +# boot theme, so only the selection moves. That is the honest first step โ€” an +# idempotent command has to be safe to run. key n +key tab stable 700 15000 snap step-helix snapstyle step-helix # ...and now the theme really does change under the cursor, one row at a time key n +key tab stable 700 15000 snap step-dark snapstyle step-dark key n +key tab stable 700 15000 snap step-acme snapstyle step-acme @@ -43,24 +51,27 @@ snapstyle step-acme # vendored first. That is the point of sorting: the ring is the same everywhere # whatever order the directory read handed the files over in. key n +key tab stable 700 15000 snap step-generated snapstyle step-generated -# N walks back the same way, running the row it lands on โ€” so the theme -# rewinds too +# N walks back the same way โ€” it is the exact inverse of n โ€” and the Tab after +# it runs the row it lands on, so the theme rewinds too key N +key tab stable 700 15000 snap step-back snapstyle step-back -# PICKING is just stopping. Walk down into the list and explicitly Del it: the -# theme the last step left behind is still on. Body-normal Esc is Last, -# so it deliberately leaves this document-like output buffer open. -key space w j -stable 400 5000 +# PICKING is just stopping: the theme the last Tab ran is still on, and the +# list is closed with an explicit Del. No window move is needed to get there โ€” +# the walk lands IN the pane it steps, so the cursor has been in the list +# since the first n. Body-normal Esc is Last, so it deliberately leaves this +# document-like output buffer open. # ...and the WHOLE ring is in there, all 228 rows: `ge` to the last line, which # only reaches `Theme zenburn` if nothing truncated the buffer on the way in. It -# is an ordinary file pane, so it scrolls like one; a motion is not a step, so -# no theme is run and the one step-back chose is still on. +# is an ordinary file pane, so it scrolls like one; a motion runs nothing and +# neither does a step, so no theme changes here and the one the last Tab chose +# is still on. key g e stable 700 15000 snap tail diff --git a/test/snapshots/tinywin.golden b/test/snapshots/tinywin.golden index 6e085aa9..36d1af12 100644 --- a/test/snapshots/tinywin.golden +++ b/test/snapshots/tinywin.golden @@ -3,16 +3,16 @@ |$ /tmp/pardes-snap/tinywin/cwd New Del | $ | /tmp/pardes-snap/tinywin/cwd New Del -| +| ls | | /tmp/pardes-snap/tinywin/cwd New Del -| +| ls | | /tmp/pardes-snap/tinywin/cwd New Del -| +| ls | | /tmp/pardes-snap/tinywin/cwd New Del -| +| ls | | | @@ -36,18 +36,18 @@ == snap columns grid=100x30 cursor=79,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/tinywi /tmp/pardes-snap/tinywi /tmp/pardes-snap/tinywi /tmp/pardes-snap/tinywi -| $ +| $ ls ls ls | /tmp/pardes-snap/tinywi -| +| ls | | /tmp/pardes-snap/tinywi -| +| ls | | /tmp/pardes-snap/tinywi -| +| ls | | /tmp/pardes-snap/tinywi -| +| ls | | | diff --git a/test/snapshots/topbarexec.golden b/test/snapshots/topbarexec.golden index ed996103..bed96fbd 100644 --- a/test/snapshots/topbarexec.golden +++ b/test/snapshots/topbarexec.golden @@ -1,7 +1,7 @@ == snap selected grid=90x20 cursor=14,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/topbarexec/cwd New Del /tmp/pardes-snap/topbarexec/cwd New Del -| +| ls ls | zmarkfile.txt zmarkfile.txt | | @@ -11,7 +11,7 @@ | | | /tmp/pardes-snap/topbarexec/cwd New Del -| +| ls | zmarkfile.txt | | @@ -22,7 +22,7 @@ == snap noarg-runs grid=90x20 cursor=14,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/topbarexec/cwd New Del /tmp/pardes-sโ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ -| โ”‚pardes resizes=1 โ”‚ +| ls ls โ”‚pardes resizes=1 โ”‚ | zmarkfile.txt zmarkfile.txtโ”‚terms 3 cols 2 โ”‚ | โ”‚active #0 43x9 โ”‚ | โ”‚scroll 0/9 โ”‚ @@ -32,7 +32,7 @@ | | | /tmp/pardes-snap/topbarexec/cwd New Del -| +| ls | zmarkfile.txt | | @@ -43,7 +43,7 @@ == snap arg-still-spliced grid=90x20 cursor=14,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/topbarexec/cwd New Del /tmp/pardes-snap/topbarexec/cwd New Del -| +| ls ls | zmarkfile.txt zmarkfile.txt | | @@ -53,7 +53,7 @@ | /tmp/pardes-snap/topbarexec/cwd/+Search New | 1 zmarkfile.txt | /tmp/pardes-snap/topbarexec/cwd New Del -| +| ls | zmarkfile.txt | | diff --git a/test/snapshots/tty.golden b/test/snapshots/tty.golden index f15afcb9..3b4d08c1 100644 --- a/test/snapshots/tty.golden +++ b/test/snapshots/tty.golden @@ -1,7 +1,7 @@ == snap tty-on grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/tty/cwd New Del /tmp/pardes-snap/tty/cwd New Del -| $ ls +| $ ls ls | m.txt m.txt | $ | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/tty/cwd New Del -| +| ls | m.txt | | @@ -32,7 +32,7 @@ == snap tty-echo grid=100x30 cursor=4,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/tty/cwd New Del /tmp/pardes-snap/tty/cwd New Del -| $ ls +| $ ls ls | m.txt m.txt | $ echo SNAP''OK | SNAPOK @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/tty/cwd New Del -| +| ls | m.txt | | @@ -63,9 +63,9 @@ == snap tty-off grid=100x30 cursor=4,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tty/cwd New Del /tmp/pardes-snap/tty/cwd New Del -| +| ls ls | m.txt m.txt -| +| echo SNAP''OK | SNAPOK | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/tty/cwd New Del -| +| ls | m.txt | | @@ -94,7 +94,7 @@ == snap shift-esc-on grid=100x30 cursor=4,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/tty/cwd New Del /tmp/pardes-snap/tty/cwd New Del -| $ ls +| $ ls ls | m.txt m.txt | $ echo SNAP''OK | SNAPOK @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/tty/cwd New Del -| +| ls | m.txt | | @@ -125,7 +125,7 @@ == snap shift-esc-nodoc grid=100x30 cursor=4,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/tty/cwd New Del /tmp/pardes-snap/tty/cwd New Del -| $ ls +| $ ls ls | m.txt m.txt | $ echo SNAP''OK | SNAPOK @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/tty/cwd New Del -| +| ls | m.txt | | @@ -156,9 +156,9 @@ == snap ctrl-b-off grid=100x30 cursor=4,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/tty/cwd New Del /tmp/pardes-snap/tty/cwd New Del -| +| ls ls | m.txt m.txt -| +| echo SNAP''OK | SNAPOK | | @@ -171,7 +171,7 @@ | | | /tmp/pardes-snap/tty/cwd New Del -| +| ls | m.txt | | diff --git a/test/snapshots/ttyclick.golden b/test/snapshots/ttyclick.golden index a2d579ec..149073f7 100644 --- a/test/snapshots/ttyclick.golden +++ b/test/snapshots/ttyclick.golden @@ -1,7 +1,7 @@ == snap tty-bodyclick grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/ttyclick/cwd New Del /tmp/pardes-snap/ttyclick/cwd New Del -| $ ls +| $ ls ls | probe.txt probe.txt | $ | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/ttyclick/cwd New Del -| +| ls | probe.txt | | @@ -32,7 +32,7 @@ == snap tty-tagedit grid=100x30 cursor=39,1 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/ttyclick/cwd New Del /tmp/pardes-snap/ttyclick/cwd New Del -| +| ls ls | probe.txt probe.txt | | @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/ttyclick/cwd New Del -| +| ls | probe.txt | | @@ -63,7 +63,7 @@ == snap tty-tagexit grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/ttyclick/cwd New Del /tmp/pardes-snap/ttyclick/cwd New Del -| $ ls +| $ ls ls | probe.txt probe.txt | $ | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/ttyclick/cwd New Del -| +| ls | probe.txt | | @@ -94,7 +94,7 @@ == snap ins-bodyclick grid=100x30 cursor=11,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |^ /tmp/pardes-snap/ttyclick/cwd New Del /tmp/pardes-snap/ttyclick/cwd New Del -| +| ls ls | probe.txt probe.txt | | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/ttyclick/cwd New Del -| +| ls | probe.txt | | diff --git a/test/snapshots/ttyedit.golden b/test/snapshots/ttyedit.golden index 37982bb4..c0a190d8 100644 --- a/test/snapshots/ttyedit.golden +++ b/test/snapshots/ttyedit.golden @@ -1,10 +1,10 @@ == snap before grid=100x30 cursor=7,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttyedit/cwd New Del /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls | words.txt | | @@ -32,10 +32,10 @@ == snap split grid=100x30 cursor=2,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |^ /tmp/pardes-snap/ttyedit/cwd New Del /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one t | wo three | four five six @@ -47,7 +47,7 @@ | | | /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls | words.txt | | @@ -63,10 +63,10 @@ == snap opened grid=100x30 cursor=6,8 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttyedit/cwd New Del /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one t | wo three | OPEN @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls | words.txt | | @@ -94,10 +94,10 @@ == snap joined grid=100x30 cursor=10,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttyedit/cwd New Del /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one t | wo threeOPEN | four five six @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls | words.txt | | @@ -125,10 +125,10 @@ == snap undone grid=100x30 cursor=7,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttyedit/cwd New Del /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls ls | words.txt words.txt -| -| +| printf 'one two three\nfour five six\nseven ei +| ght nine\n' | one two three | four five six | seven eight nine @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/ttyedit/cwd New Del -| +| ls | words.txt | | diff --git a/test/snapshots/ttyfollow.golden b/test/snapshots/ttyfollow.golden index b21549a0..4fcc0741 100644 --- a/test/snapshots/ttyfollow.golden +++ b/test/snapshots/ttyfollow.golden @@ -1,7 +1,7 @@ == snap held-pre grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttyfollow/cwd New Del /tmp/pardes-snap/ttyfollow/cwd New Del -| 185 +| 185 ls | 186 s.txt | 187 | 188 @@ -16,7 +16,7 @@ | 197 | 198 | /tmp/pardes-snap/ttyfollow/cwd New Del -| +| ls | s.txt | | @@ -47,7 +47,7 @@ | 197 | 198 | /tmp/pardes-snap/ttyfollow/cwd New Del -| +| ls | s.txt | | @@ -78,7 +78,7 @@ | 300 | $ | /tmp/pardes-snap/ttyfollow/cwd New Del -| +| ls | s.txt | | diff --git a/test/snapshots/ttyhelp.golden b/test/snapshots/ttyhelp.golden index a580263b..7895d83e 100644 --- a/test/snapshots/ttyhelp.golden +++ b/test/snapshots/ttyhelp.golden @@ -38,28 +38,28 @@ | 2 SPC and its keys, a chord, a button, the | 3 topbar - or the name, executed anywhere. | 4 -| 5 SPC ? Help topbar -| 6 SPC c d Delcol -| 7 SPC c n Newcol topbar -| 8 SPC d Del -| 9 SPC f c Config -| 10 SPC f f Find topbar -| 11 SPC f g Grep topbar -| 12 SPC f n New topbar -| 13 SPC f s Save -| 14 SPC h t Tutor topbar -| 15 SPC j i Forward C-i -| 16 SPC j j Last -| 17 SPC j l Jumplist -| 18 SPC j o Back C-o -| 19 SPC k Kill topbar -| 20 SPC l D WsDiagnostics -| 21 SPC l S WsSymbols -| 22 SPC l a CodeAction -| 23 SPC l d Diagnostics -| 24 SPC l h SelectRefs -| 25 SPC l i Lspinfo -| 26 SPC l k Hover +| 5 SPC ? Help topbar +| 6 SPC P ClipPasteBefore +| 7 SPC R ClipReplace +| 8 SPC Y ClipYankMain +| 9 SPC c d Delcol +| 10 SPC c n Newcol topbar +| 11 SPC d Del +| 12 SPC f c Config +| 13 SPC f f Find topbar +| 14 SPC f g Grep topbar +| 15 SPC f n New topbar +| 16 SPC f s Save +| 17 SPC h t Tutor topbar +| 18 SPC j i Forward C-i +| 19 SPC j j Last +| 20 SPC j l Jumplist +| 21 SPC j o Back C-o +| 22 SPC k Kill topbar +| 23 SPC l D WsDiagnostics +| 24 SPC l S WsSymbols +| 25 SPC l a CodeAction +| 26 SPC l d Diagnostics == snap leaderworks grid=100x30 cursor=7,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/ttyhelp/cwd New Del @@ -69,25 +69,25 @@ | 2 SPC and its keys, a chord, a button, the | 3 topbar - or the name, executed anywhere. | 4 -| 5 SPC ? Help topbar -| 6 SPC c d Delcol -| 7 SPC c n Newcol topbar -| 8 SPC d Del -| 9 SPC f c Config -| 10 SPC f f Find topbar -| 11 SPC f g Grep topbar -| 12 SPC f n New topbar -| 13 SPC f s Save -| 14 SPC h t Tutor topbar -| 15 SPC j i Forward C-i -| 16 SPC j j Last -| 17 SPC j l Jumplist -| 18 SPC j o Back C-o -| 19 SPC k Kill topbar -| 20 SPC l D WsDiagnostics -| 21 SPC l S WsSymbols -| 22 SPC l a CodeAction -| 23 SPC l d Diagnostics -| 24 SPC l h SelectRefs -| 25 SPC l i Lspinfo -| 26 SPC l k Hover +| 5 SPC ? Help topbar +| 6 SPC P ClipPasteBefore +| 7 SPC R ClipReplace +| 8 SPC Y ClipYankMain +| 9 SPC c d Delcol +| 10 SPC c n Newcol topbar +| 11 SPC d Del +| 12 SPC f c Config +| 13 SPC f f Find topbar +| 14 SPC f g Grep topbar +| 15 SPC f n New topbar +| 16 SPC f s Save +| 17 SPC h t Tutor topbar +| 18 SPC j i Forward C-i +| 19 SPC j j Last +| 20 SPC j l Jumplist +| 21 SPC j o Back C-o +| 22 SPC k Kill topbar +| 23 SPC l D WsDiagnostics +| 24 SPC l S WsSymbols +| 25 SPC l a CodeAction +| 26 SPC l d Diagnostics diff --git a/test/snapshots/ttylook.golden b/test/snapshots/ttylook.golden index 41e16c99..bf3785cc 100644 --- a/test/snapshots/ttylook.golden +++ b/test/snapshots/ttylook.golden @@ -1,7 +1,7 @@ == snap tok1 grid=120x30 cursor=2,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttylook/cwd New Del /tmp/pardes-snap/ttylook/cwd New Del -| +| ls ls | big.txt plain.txt sub big.txt plain.txt sub | | @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/ttylook/cwd New Del -| +| ls | big.txt plain.txt sub | | @@ -63,7 +63,7 @@ == snap tok2 grid=120x30 cursor=11,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttylook/cwd New Del /tmp/pardes-snap/ttylook/cwd New Del -| +| ls ls | big.txt plain.txt sub big.txt plain.txt sub | | @@ -78,7 +78,7 @@ | | | /tmp/pardes-snap/ttylook/cwd New Del -| +| ls | big.txt plain.txt sub | | @@ -94,7 +94,7 @@ == snap tokback grid=120x30 cursor=2,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttylook/cwd New Del /tmp/pardes-snap/ttylook/cwd New Del -| +| ls ls | big.txt plain.txt sub big.txt plain.txt sub | | @@ -109,7 +109,7 @@ | | | /tmp/pardes-snap/ttylook/cwd New Del -| +| ls | big.txt plain.txt sub | | @@ -125,7 +125,7 @@ == snap insert grid=120x30 cursor=4,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttylook/cwd New Del /tmp/pardes-snap/ttylook/cwd New Del -| +| ls ls | nnbig.txt plain.txt sub big.txt plain.txt sub | | @@ -140,7 +140,7 @@ | | | /tmp/pardes-snap/ttylook/cwd New Del -| +| ls | big.txt plain.txt sub | | @@ -156,7 +156,7 @@ == snap tok3 grid=120x30 cursor=22,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttylook/cwd New Del /tmp/pardes-snap/ttylook/cwd New Del -| +| ls ls | big.txt plain.txt sub big.txt plain.txt sub | | @@ -171,7 +171,7 @@ | | | /tmp/pardes-snap/ttylook/cwd New Del -| +| ls | big.txt plain.txt sub | | @@ -187,11 +187,11 @@ == snap diropen grid=120x30 cursor=4,7 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttylook/cwd New Del /tmp/pardes-snap/ttylook/cwd New Del -| +| ls ls | big.txt plain.txt sub big.txt plain.txt sub | | /tmp/pardes-snap/ttylook/cwd/sub New Del -| +| ls | | | @@ -202,7 +202,7 @@ | | | /tmp/pardes-snap/ttylook/cwd New Del -| +| ls | big.txt plain.txt sub | | @@ -215,14 +215,14 @@ | | | -== snap noop grid=120x30 cursor=4,7 +== snap noop grid=120x30 cursor=2,3 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttylook/cwd New Del /tmp/pardes-snap/ttylook/cwd New Del -| +| ls ls | big.txt plain.txt sub big.txt plain.txt sub | | /tmp/pardes-snap/ttylook/cwd/sub New Del -| +| ls | | | @@ -233,7 +233,7 @@ | | | /tmp/pardes-snap/ttylook/cwd New Del -| +| ls | big.txt plain.txt sub | | @@ -249,11 +249,11 @@ == snap fileopen grid=120x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/ttylook/cwd/big.txt S /tmp/pardes-snap/ttylook/cwd New Del /tmp/pardes-snap/ttylook/cwd New Del -| 1 line 1 +| 1 line 1 ls ls | 2 line 2 big.txt plain.txt sub big.txt plain.txt sub | 3 line 3 | 4 line 4 /tmp/pardes-snap/ttylook/cwd/sub New D -| 5 line 5 +| 5 line 5 ls | 6 line 6 | 7 line 7 | 8 line 8 @@ -264,7 +264,7 @@ | 13 line 13 | 14 line 14 | 15 line 15 /tmp/pardes-snap/ttylook/cwd New Del -| 16 line 16 +| 16 line 16 ls | 17 line 17 big.txt plain.txt sub | 18 line 18 | 19 line 19 diff --git a/test/snapshots/ttylook.snap b/test/snapshots/ttylook.snap index cc746970..66b178d7 100644 --- a/test/snapshots/ttylook.snap +++ b/test/snapshots/ttylook.snap @@ -2,9 +2,10 @@ # whitespace-separated token that look resolves โ€” several per line, so the # greet ls row hops big.txt -> plain.txt -> sub โ€” moving the cursor to the # token start and opening NOTHING. Return looks the selection (dir -> shell -# +ls there, file -> pane) and navigation continues in what opened. The first -# n wraps from the prompt row to the first token; insert-mode n still types; -# with nothing lookable n is a no-op. +# +ls there, file -> pane) and focus follows what opened. The first n wraps +# from the prompt row to the first token; insert-mode n still types; and a +# pane with nothing look-able in it never traps the walk, because the walk is +# a RING ACROSS PANES rather than a scan of the one you are in. lines big.txt 40 file plain.txt just text dirmk sub @@ -44,7 +45,10 @@ snap tok3 key enter stable 700 15000 snap diropen -# the fresh pane's dir is empty: n has nothing lookable, stays put +# the fresh pane's dir is empty, and that is not where n stops: the ring is +# spined on the panes that have LOOKED, so the step leaves this shell for the +# one it was looked out of. That pane's cursor is on its last token (`sub`), +# so the walk runs off the end and comes round to its first โ€” big.txt. key n stable 400 5000 snap noop diff --git a/test/snapshots/ttyprompt.golden b/test/snapshots/ttyprompt.golden new file mode 100644 index 00000000..c479f463 --- /dev/null +++ b/test/snapshots/ttyprompt.golden @@ -0,0 +1,93 @@ +== snap greeted grid=100x30 cursor=4,4 +|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill +| /tmp/pardes-snap/ttyprompt/cwd New Del /tmp/pardes-snap/ttyprompt/cwd New Del +| ls ls +| probe.txt probe.txt +| +| +| +| +| +| +| +| +| +| +| +| +| /tmp/pardes-snap/ttyprompt/cwd New Del +| ls +| probe.txt +| +| +| +| +| +| +| +| +| +| +| +== snap in-tty grid=100x30 cursor=17,4 +|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill +|$ /tmp/pardes-snap/ttyprompt/cwd New Del /tmp/pardes-snap/ttyprompt/cwd New Del +| $ ls ls +| probe.txt probe.txt +| $ echo ABCDEFGH +| +| +| +| +| +| +| +| +| +| +| +| /tmp/pardes-snap/ttyprompt/cwd New Del +| ls +| probe.txt +| +| +| +| +| +| +| +| +| +| +| +== snap out-of-tty grid=100x30 cursor=17,4 +|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill +| /tmp/pardes-snap/ttyprompt/cwd New Del /tmp/pardes-snap/ttyprompt/cwd New Del +| ls ls +| probe.txt probe.txt +| echo ABCDEFGH +| +| +| +| +| +| +| +| +| +| +| +| /tmp/pardes-snap/ttyprompt/cwd New Del +| ls +| probe.txt +| +| +| +| +| +| +| +| +| +| +| diff --git a/test/snapshots/ttyprompt.snap b/test/snapshots/ttyprompt.snap new file mode 100644 index 00000000..9cb377bf --- /dev/null +++ b/test/snapshots/ttyprompt.snap @@ -0,0 +1,35 @@ +# Leaving raw tty hides the shell's PROMPT and keeps the command typed at it. +# +# The two share one grid row, so blanking the row used to take the command with +# the prompt and a shell out of tty read as output only. OSC 133 marks the row +# CELL by cell, so config.tty_blank = .prompt cuts the prompt's own columns and +# left-hugs what is left: the command lands at column 0, in line with the +# output under it, rather than in a bay of blanks the prompt used to fill. +# +# `.prompt_and_input` is the old behaviour and blanks the whole row; it is a +# comptime choice, so what THIS script pins is the default. +file probe.txt marker +start 30 100 -n 3 +wait 8000 probe.txt +stable 700 20000 +# the greeting `ls` was typed at a prompt and already shows the rule: the +# command is there, the prompt in front of it is not +snap greeted +# into tty and type a command WITHOUT submitting it, so the shell is sitting at +# a prompt with input on it โ€” the case the old behaviour erased +key c-b +stable 600 8000 +text echo ABCDEFGH +stable 600 8000 +snap in-tty +# ...and out: the prompt goes, `echo ABCDEFGH` stays, hugging the left edge +key c-b +stable 600 8000 +snap out-of-tty +# The columns still have to reach the shell, and they do: the modal cursor's +# column on a hidden-prompt row is short by exactly the prompt's width, so +# enterTty adds it back before asking ghostty to walk the shell's own cursor +# there. That arithmetic is pinned by the "entering tty walks the shell cursor" +# unit test, which can put a pinned cursor on a known column; a click here +# cannot, because leaving tty unpins and a body click on a terminal does not +# pin it again. diff --git a/test/snapshots/tutor.golden b/test/snapshots/tutor.golden index 8bfb47fe..9973f04b 100644 --- a/test/snapshots/tutor.golden +++ b/test/snapshots/tutor.golden @@ -1,7 +1,7 @@ == snap tutor grid=150x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /Tutor Save New Del /tmp/pardes-snap/tutor/cwd New Del /tmp/pardes-snap/tutor/cwd New Del -| 1 +| 1 ls ls | 2 PARDES TUTOโ†ฉ | R | 3 tmux + vi + acme, froโ†ฉ @@ -16,7 +16,7 @@ | 8 | 9 | 10 ==========================================โ†ฉ /tmp/pardes-snap/tutor/cwd New Del -| ======================= +| ======================= ls | 11 = INTRODUCTION โ†ฉ | = | 12 ==========================================โ†ฉ diff --git a/test/snapshots/winch.golden b/test/snapshots/winch.golden index 125aae6d..cc613460 100644 --- a/test/snapshots/winch.golden +++ b/test/snapshots/winch.golden @@ -1,7 +1,7 @@ == snap storm grid=100x30 cursor=4,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/winch/cwd New Del /tmp/pardes-snap/winch/cwd New Del -| $ ls +| $ ls ls | $ for i in $(seq 600); do kill -WINCH $PPID; don | e; echo SUR''VIVED | SURVIVED @@ -16,7 +16,7 @@ | | | /tmp/pardes-snap/winch/cwd New Del -| +| ls | | | @@ -32,7 +32,7 @@ == snap resized grid=106x34 cursor=4,6 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill |$ /tmp/pardes-snap/winch/cwd New Del /tmp/pardes-snap/winch/cwd New Del -| $ ls +| $ ls ls | $ for i in $(seq 600); do kill -WINCH $PPID; done; | echo SUR''VIVED | SURVIVED @@ -49,7 +49,7 @@ | | | /tmp/pardes-snap/winch/cwd New Del -| +| ls | | | diff --git a/test/snapshots/windownav.golden b/test/snapshots/windownav.golden index ab8b76ec..0b27a26d 100644 --- a/test/snapshots/windownav.golden +++ b/test/snapshots/windownav.golden @@ -1,7 +1,7 @@ == snap start grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -32,7 +32,7 @@ == snap to-term grid=100x30 cursor=54,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -63,7 +63,7 @@ == snap back-to-file grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -94,7 +94,7 @@ == snap esc-to-term grid=100x30 cursor=54,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -125,7 +125,7 @@ == snap esc-back-to-file grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -156,7 +156,7 @@ == snap altn grid=100x30 cursor=4,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -171,7 +171,7 @@ | | | /tmp/pardes-snap/windownav/cwd New Del -| +| ls | w.txt | | @@ -187,7 +187,7 @@ == snap up grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -202,7 +202,7 @@ | | | /tmp/pardes-snap/windownav/cwd New Del -| +| ls | w.txt | | @@ -218,7 +218,7 @@ == snap right grid=100x30 cursor=54,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -233,7 +233,7 @@ | | | /tmp/pardes-snap/windownav/cwd New Del -| +| ls | w.txt | | @@ -249,7 +249,7 @@ == snap left grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -264,7 +264,7 @@ | | | /tmp/pardes-snap/windownav/cwd New Del -| +| ls | w.txt | | @@ -280,7 +280,7 @@ == snap down grid=100x30 cursor=4,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -295,7 +295,7 @@ | | | /tmp/pardes-snap/windownav/cwd New Del -| +| ls | w.txt | | @@ -311,7 +311,7 @@ == snap toggle-doc grid=100x30 cursor=7,2 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -326,7 +326,7 @@ | | | /tmp/pardes-snap/windownav/cwd New Del -| +| ls | w.txt | | @@ -342,7 +342,7 @@ == snap toggle-back grid=100x30 cursor=4,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del -| 1 alpha +| 1 alpha ls | 2 beta w.txt | 3 gamma | @@ -357,7 +357,7 @@ | | | /tmp/pardes-snap/windownav/cwd New Del -| +| ls | w.txt | | diff --git a/test/snapshots/windowops.golden b/test/snapshots/windowops.golden index 0f7e38f4..4101fa86 100644 --- a/test/snapshots/windowops.golden +++ b/test/snapshots/windowops.golden @@ -1,7 +1,7 @@ == snap hover-v grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del โ•Ž /tmp/pardes-snap/windowops/cwd New Del -| โ•Ž +| ls โ•Ž ls | w.txt โ•Ž w.txt | โ•Ž | โ•Ž @@ -16,7 +16,7 @@ | โ•Ž | โ•Ž | /tmp/pardes-snap/windowops/cwd New Del โ•Ž -| โ•Ž +| ls โ•Ž | w.txt โ•Ž | โ•Ž | โ•Ž @@ -32,7 +32,7 @@ == snap hover-h grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -47,7 +47,7 @@ | |โ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œ | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | @@ -63,7 +63,7 @@ == snap border-drag grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Deโ•Ž /tmp/pardes-snap/windowops/cwd New Del -| โ•Ž +| ls โ•Ž ls | w.txt โ•Ž w.txt | โ•Ž | โ•Ž @@ -78,7 +78,7 @@ | โ•Ž | โ•Ž | /tmp/pardes-snap/windowops/cwd New Deโ•Ž -| โ•Ž +| ls โ•Ž | w.txt โ•Ž | โ•Ž | โ•Ž @@ -94,7 +94,7 @@ == snap border-done grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Deโ•Ž /tmp/pardes-snap/windowops/cwd New Del -| โ•Ž +| ls โ•Ž ls | w.txt โ•Ž w.txt | โ•Ž | โ•Ž @@ -109,7 +109,7 @@ | โ•Ž | โ•Ž | /tmp/pardes-snap/windowops/cwd New Deโ•Ž -| โ•Ž +| ls โ•Ž | w.txt โ•Ž | โ•Ž | โ•Ž @@ -125,7 +125,7 @@ == snap hborder-done grid=100x30 cursor=4,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -136,7 +136,7 @@ | |โ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œโ•Œ | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | @@ -156,7 +156,7 @@ == snap move-preview grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -167,7 +167,7 @@ | | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | @@ -187,7 +187,7 @@ == snap moved grid=100x30 cursor=4,15 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -198,7 +198,7 @@ | | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | @@ -218,7 +218,7 @@ == snap altn grid=100x30 cursor=4,19 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -229,11 +229,11 @@ | | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | @@ -249,7 +249,7 @@ == snap focus-right grid=100x30 cursor=44,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -260,11 +260,11 @@ | | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | @@ -280,7 +280,7 @@ == snap debug-on grid=100x30 cursor=44,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cโ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ -| โ”‚pardes resizes=1 โ”‚ +| ls ls โ”‚pardes resizes=1 โ”‚ | w.txt w.txt โ”‚terms 4 cols 2 โ”‚ | โ”‚active #2 58x28 โ”‚ | โ”‚scroll 0/28 โ”‚ @@ -291,11 +291,11 @@ | | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | @@ -342,7 +342,7 @@ == snap debug-off grid=100x30 cursor=44,4 |New Newcol Find Grep Help Tutor Dump NextColor Debug Kill | /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del -| +| ls ls | w.txt w.txt | | @@ -353,11 +353,11 @@ | | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | /tmp/pardes-snap/windowops/cwd New Del -| +| ls | w.txt | | -- cgit v1.3