summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/site/media/captions.txt3
-rw-r--r--docs/site/media/clips.toml18
-rw-r--r--docs/site/media/columns.mp4bin0 -> 294124 bytes
-rw-r--r--docs/site/media/columns.pngbin0 -> 157329 bytes
-rw-r--r--docs/site/media/columns.webmbin0 -> 416479 bytes
-rw-r--r--docs/site/media/search.mp4bin0 -> 280626 bytes
-rw-r--r--docs/site/media/search.pngbin0 -> 89899 bytes
-rw-r--r--docs/site/media/search.webmbin0 -> 343657 bytes
-rw-r--r--docs/site/media/where-commands-run.mp4bin0 -> 199240 bytes
-rw-r--r--docs/site/media/where-commands-run.pngbin0 -> 64070 bytes
-rw-r--r--docs/site/media/where-commands-run.webmbin0 -> 239871 bytes
-rw-r--r--test/record_demos.py116
12 files changed, 136 insertions, 1 deletions
diff --git a/docs/site/media/captions.txt b/docs/site/media/captions.txt
index 6a1a2274..c8b59699 100644
--- a/docs/site/media/captions.txt
+++ b/docs/site/media/captions.txt
@@ -6,3 +6,6 @@ terminals-are-panes: A terminal is a pane: Ctrl-b, then move over its output.
scripting-over-9p: A script drives the session through its virtual filesystem (9P).
diff-review: Right-click a diff line to open that line of the file.
chords: Hold left, click middle to cut; click right to paste.
+columns: Newcol adds a column; a look opens there; Alt-c moves a pane.
+search: Grep lists the hits; n and N walk them; right-click opens one.
+where-commands-run: A file's tag runs in its directory; the column tag, in the session's.
diff --git a/docs/site/media/clips.toml b/docs/site/media/clips.toml
index 37dc9db9..e6cee9bd 100644
--- a/docs/site/media/clips.toml
+++ b/docs/site/media/clips.toml
@@ -45,3 +45,21 @@ name = "chords"
caption = "Hold left, click middle to cut; click right to paste."
ready = true
landing = false
+
+[[clip]]
+name = "columns"
+caption = "Newcol adds a column; a look opens there; Alt-c moves a pane."
+ready = true
+landing = false
+
+[[clip]]
+name = "search"
+caption = "Grep lists the hits; n and N walk them; right-click opens one."
+ready = true
+landing = false
+
+[[clip]]
+name = "where-commands-run"
+caption = "A file's tag runs in its directory; the column tag, in the session's."
+ready = true
+landing = false
diff --git a/docs/site/media/columns.mp4 b/docs/site/media/columns.mp4
new file mode 100644
index 00000000..48bc462b
--- /dev/null
+++ b/docs/site/media/columns.mp4
Binary files differ
diff --git a/docs/site/media/columns.png b/docs/site/media/columns.png
new file mode 100644
index 00000000..f8cc1801
--- /dev/null
+++ b/docs/site/media/columns.png
Binary files differ
diff --git a/docs/site/media/columns.webm b/docs/site/media/columns.webm
new file mode 100644
index 00000000..ddb6bdfc
--- /dev/null
+++ b/docs/site/media/columns.webm
Binary files differ
diff --git a/docs/site/media/search.mp4 b/docs/site/media/search.mp4
new file mode 100644
index 00000000..6c9c9445
--- /dev/null
+++ b/docs/site/media/search.mp4
Binary files differ
diff --git a/docs/site/media/search.png b/docs/site/media/search.png
new file mode 100644
index 00000000..40e5bed5
--- /dev/null
+++ b/docs/site/media/search.png
Binary files differ
diff --git a/docs/site/media/search.webm b/docs/site/media/search.webm
new file mode 100644
index 00000000..e1581570
--- /dev/null
+++ b/docs/site/media/search.webm
Binary files differ
diff --git a/docs/site/media/where-commands-run.mp4 b/docs/site/media/where-commands-run.mp4
new file mode 100644
index 00000000..c4bd83fe
--- /dev/null
+++ b/docs/site/media/where-commands-run.mp4
Binary files differ
diff --git a/docs/site/media/where-commands-run.png b/docs/site/media/where-commands-run.png
new file mode 100644
index 00000000..5af438cc
--- /dev/null
+++ b/docs/site/media/where-commands-run.png
Binary files differ
diff --git a/docs/site/media/where-commands-run.webm b/docs/site/media/where-commands-run.webm
new file mode 100644
index 00000000..c9d35176
--- /dev/null
+++ b/docs/site/media/where-commands-run.webm
Binary files differ
diff --git a/test/record_demos.py b/test/record_demos.py
index 7ab22d95..9ee5ba53 100644
--- a/test/record_demos.py
+++ b/test/record_demos.py
@@ -959,6 +959,110 @@ def chords(s):
s.chord_release(after=1.0)
+def column(s, serial):
+ """Column `serial`'s (first cell, width) from /layout."""
+ for line in s.read('/layout').splitlines():
+ parts = line.split()
+ if parts and parts[0] == str(serial):
+ return int(parts[2]), int(parts[3])
+ raise LookupError(f'no column {serial}')
+
+
+def col_tag_px(s, serial, at, offset=.5):
+ """The pixel over character `at` of column `serial`'s tag (row 1 of the
+ window, wrapping at the column's width in the tagline font)."""
+ x0, width = column(s, serial)
+ w, h = s.size()
+ cw, ch = w / s.cols, h / s.rows
+ per_row = int((width * cw - 3 * cw) // TAG_W)
+ return int((x0 + 3) * cw + (at % per_row + offset) * TAG_W), int((1 + at // per_row + .55) * ch)
+
+
+def columns_setup(s):
+ s.write('/pane/1/look', f'{PROJECT}/src/main.c\n')
+ s.wait(lambda: len(s.panes()) == 2, 'main.c')
+ s.mouse('motion', 0, *s.cell_px(s.cols - 2, s.rows - 1))
+
+
+def columns(s):
+ """Newcol makes a column; a name typed in its tag and looked at opens
+ there; Alt-c gives a pane a column of its own."""
+ s.pointer = s.cell_px(30, 12)
+ s.shot(1.0)
+ s.click(2, *s.tag_px(3, 0, start=0), done=lambda: len(s.read('/layout').splitlines()) == 3, what='Newcol',
+ after=.8)
+ new = s.read('/layout').splitlines()[1].split()[0]
+ tag = s.read(f'/col/{new}/tag').rstrip('\n')
+ # B1 just past the tag's last word puts the typing there.
+ s.click(1, *col_tag_px(s, new, len(tag), offset=.4), after=.2)
+ s.type(' Makefile', lambda typed: s.read(f'/col/{new}/tag').rstrip('\n').endswith(typed), per_key=.06)
+ s.shot(.3)
+ at = s.read(f'/col/{new}/tag').index('Makefile') + 4
+ s.click(3, *col_tag_px(s, new, at), done=lambda: len(s.panes()) == 3, what='the Makefile', after=1.3)
+ # Alt-c on main.c: it leaves for a column of its own.
+ main = next(n for n in s.panes() if s.read(f'/pane/{n}/name').strip().endswith('main.c'))
+ col, row = s.find('int main', 0)
+ s.click(1, *s.cell_px(col + 4, row), done=lambda: s.read('/focus').strip() == str(main), what='focus',
+ after=.3)
+ s.badge = 'Alt-c'
+ s.keys('\x1bc')
+ s.wait(lambda: len(s.read('/layout').splitlines()) == 4, 'the new column')
+ s.shot(2.2, poster=True)
+ s.badge = None
+
+
+def search_setup(s):
+ (PROJECT / 'tests').mkdir()
+ (PROJECT / 'tests/check.sh').write_text('#!/bin/sh\n# 1 + 4 + 9 + 16: the sum of the squares is 30\n'
+ './hello | grep -q "sum: 30"\n')
+ s.write('/pane/1/look', f'{PROJECT}/src/main.c\n')
+ s.wait(lambda: len(s.panes()) == 2, 'main.c')
+ s.write('/focus', '2\n')
+ s.mouse('motion', 0, *s.cell_px(COLS - 2, ROWS - 1))
+
+
+def search(s):
+ """Grep (SPC f g) lists the hits in +Search; n and N walk them; B3 on
+ one opens its file there."""
+ s.pointer = s.cell_px(44, 8)
+ s.shot(1.0)
+ s.press([(' ', 'SPC'), ('f', 'SPC f'), ('g', 'SPC f g')], per_key=.35)
+ s.badge = 'SPC f g square'
+ s.type('square', lambda typed: True, per_key=.07)
+ s.badge = 'Enter'
+ s.keys('\r')
+ s.wait(lambda: any(s.read(f'/pane/{n}/name').strip().endswith('+Search') for n in s.panes()), '+Search')
+ s.shot(1.0)
+ s.press([('n', 'n'), ('n', 'n n'), ('N', 'n n N')], per_key=.7)
+ s.shots[-2]['poster'] = True # the listing whole, the second hit current
+ s.badge = None
+ col, row = s.find('check.sh:', 0)
+ s.click(3, *s.cell_px(col + 3, row), done=lambda: len(s.panes()) == 4, what='check.sh', after=2.2)
+
+
+def where_setup(s):
+ """main.c, with pwd in the column's tag and in main.c's."""
+ s.write('/col/1/tag', ' pwd')
+ s.write('/pane/1/tag', ' pwd')
+ s.mouse('motion', 0, *s.cell_px(COLS - 2, ROWS - 1))
+
+
+def where_commands_run(s):
+ """pwd from the column's tag prints the session's directory; from
+ main.c's tag, main.c's."""
+ s.pointer = s.cell_px(40, 12)
+ s.shot(1.2)
+ tag = s.read('/col/1/tag')
+ s.click(2, *col_tag_px(s, 1, tag.index('pwd') + 1),
+ done=lambda: any(kind == 'cmd' and 'exit' in s.tag(n) for n, kind in s.panes().items()), what='pwd',
+ after=1.6)
+ s.click(2, *s.tag_word(1, 'pwd'),
+ done=lambda: any(kind == 'cmd' and s.read(f'/pane/{n}/body').startswith('% pwd\n/tmp/hello/src')
+ and 'exit' in s.tag(n) for n, kind in s.panes().items()),
+ what='pwd in src', after=2.6)
+ s.shots[-1]['poster'] = True
+
+
CLIPS = {
'pdf-navigation': dict(
setup=pdf_setup, run=pdf_navigation, args=pdf_args,
@@ -984,6 +1088,15 @@ CLIPS = {
'chords': dict(
setup=chords_setup, run=chords, args=[PROJECT / 'notes.txt'],
caption='Hold left, click middle to cut; click right to paste.'),
+ 'columns': dict(
+ setup=columns_setup, run=columns, args=[PROJECT / 'README'], cols=80, rows=26,
+ caption='Newcol adds a column; a look opens there; Alt-c moves a pane.'),
+ 'search': dict(
+ setup=search_setup, run=search, args=[PROJECT / 'README'],
+ caption='Grep lists the hits; n and N walk them; right-click opens one.'),
+ 'where-commands-run': dict(
+ setup=where_setup, run=where_commands_run, args=[PROJECT / 'src/main.c'],
+ caption="A file's tag runs in its directory; the column tag, in the session's."),
}
@@ -991,7 +1104,8 @@ def record(binary, work, name):
clip = CLIPS[name]
make_project()
args = clip['args']() if callable(clip['args']) else clip['args']
- s = Session(binary, work / name, 'rec-' + name, args, init=clip.get('init', ''))
+ s = Session(binary, work / name, 'rec-' + name, args, init=clip.get('init', ''),
+ cols=clip.get('cols', COLS), rows=clip.get('rows', ROWS))
try:
if 'setup' in clip:
clip['setup'](s)