ソースを参照

Merge branch 'ttyshot'

Qi Xiao 1 年間 前
コミット
41fc578002
87 ファイル変更1139 行追加360 行削除
  1. 3 0
      0.19.0-release-notes.md
  2. 2 2
      pkg/edit/key_binding.go
  3. 84 44
      pkg/eval/builtin_fn_styled.go
  4. 41 38
      pkg/eval/builtin_fn_styled_test.go
  5. 8 8
      pkg/ui/color_test.go
  6. 1 1
      pkg/ui/key.go
  7. 4 0
      pkg/ui/parse_sgr.go
  8. 7 3
      pkg/ui/style.go
  9. 9 9
      pkg/ui/style_test.go
  10. 24 4
      pkg/ui/text.go
  11. 4 3
      pkg/ui/text_segment.go
  12. 1 0
      pkg/ui/text_test.go
  13. 4 3
      website/.gitignore
  14. 8 3
      website/Makefile
  15. 51 0
      website/README.md
  16. 1 2
      website/cmd/macros/macros.go
  17. 45 0
      website/cmd/ttyshot/apply_dir.go
  18. 310 0
      website/cmd/ttyshot/interp.go
  19. 79 0
      website/cmd/ttyshot/main.go
  20. 50 0
      website/cmd/ttyshot/parse.go
  21. 69 0
      website/cmd/ttyshot/rc.elv
  22. 1 0
      website/go.mod
  23. 2 0
      website/go.sum
  24. 5 5
      website/home.md
  25. 13 0
      website/home/control-structures.ttyshot
  26. 15 0
      website/home/control-structures.ttyshot.html
  27. 1 0
      website/home/histlist-mode.ttyshot
  28. 15 0
      website/home/histlist-mode.ttyshot.html
  29. 0 0
      website/home/home.css
  30. 0 0
      website/home/home.js
  31. 1 0
      website/home/location-mode.ttyshot
  32. 15 0
      website/home/location-mode.ttyshot.html
  33. 3 0
      website/home/navigation-mode.ttyshot
  34. 15 0
      website/home/navigation-mode.ttyshot.html
  35. 4 0
      website/home/pipelines.ttyshot
  36. 15 0
      website/home/pipelines.ttyshot.html
  37. 2 2
      website/index.toml
  38. 2 2
      website/learn/fundamentals.md
  39. 3 0
      website/learn/fundamentals/history-1.ttyshot
  40. 4 0
      website/learn/fundamentals/history-1.ttyshot.html
  41. 5 0
      website/learn/fundamentals/history-2.ttyshot
  42. 5 0
      website/learn/fundamentals/history-2.ttyshot.html
  43. 18 23
      website/learn/tour.md
  44. 3 0
      website/learn/tour/completion-filter.ttyshot
  45. 5 0
      website/learn/tour/completion-filter.ttyshot.html
  46. 3 0
      website/learn/tour/completion.ttyshot
  47. 9 0
      website/learn/tour/completion.ttyshot.html
  48. 1 0
      website/learn/tour/history-list.ttyshot
  49. 15 0
      website/learn/tour/history-list.ttyshot.html
  50. 1 0
      website/learn/tour/history-walk-prefix.ttyshot
  51. 2 0
      website/learn/tour/history-walk-prefix.ttyshot.html
  52. 1 0
      website/learn/tour/history-walk.ttyshot
  53. 2 0
      website/learn/tour/history-walk.ttyshot.html
  54. 3 0
      website/learn/tour/lastcmd.ttyshot
  55. 8 0
      website/learn/tour/lastcmd.ttyshot.html
  56. 1 0
      website/learn/tour/location-filter.ttyshot
  57. 6 0
      website/learn/tour/location-filter.ttyshot.html
  58. 1 0
      website/learn/tour/location.ttyshot
  59. 15 0
      website/learn/tour/location.ttyshot.html
  60. 3 0
      website/learn/tour/navigation.ttyshot
  61. 15 0
      website/learn/tour/navigation.ttyshot.html
  62. 9 0
      website/learn/tour/unicode-prompts.ttyshot
  63. 7 0
      website/learn/tour/unicode-prompts.ttyshot.html
  64. 1 1
      website/ref/edit.md
  65. 3 0
      website/ref/edit/completion-mode.ttyshot
  66. 9 0
      website/ref/edit/completion-mode.ttyshot.html
  67. 66 47
      website/style.css
  68. 1 1
      website/tools/extra-deps
  69. 0 27
      website/ttyshot/README.md
  70. 0 5
      website/ttyshot/completion-mode.html
  71. 0 15
      website/ttyshot/control-structures.html
  72. 0 2
      website/ttyshot/fundamentals/history-1.html
  73. 0 2
      website/ttyshot/fundamentals/history-2.html
  74. 0 15
      website/ttyshot/histlist-mode.html
  75. 0 15
      website/ttyshot/location-mode.html
  76. 0 15
      website/ttyshot/navigation-mode.html
  77. 0 14
      website/ttyshot/pipelines.html
  78. 0 5
      website/ttyshot/tour/completion-filter.html
  79. 0 6
      website/ttyshot/tour/completion.html
  80. 0 7
      website/ttyshot/tour/history-list.html
  81. 0 2
      website/ttyshot/tour/history-walk-prefix.html
  82. 0 2
      website/ttyshot/tour/history-walk.html
  83. 0 5
      website/ttyshot/tour/lastcmd.html
  84. 0 7
      website/ttyshot/tour/location-filter.html
  85. 0 7
      website/ttyshot/tour/location.html
  86. 0 7
      website/ttyshot/tour/navigation.html
  87. 0 1
      website/ttyshot/tour/unicode-prompts.html

+ 3 - 0
0.19.0-release-notes.md

@@ -3,6 +3,9 @@ This is the draft release notes for 0.19.0, scheduled to be released around
 
 # Breaking changes
 
+-   When a `styled` or `styled-segment` is printed to terminal, the resulting
+    sequence will now always ignore any existing SGR state.
+
 # Deprecated features
 
 Deprecated features will be removed in 0.20.0.

+ 2 - 2
pkg/edit/key_binding.go

@@ -51,8 +51,8 @@ func indexLayeredBindings(k ui.Key, maps ...bindingsMap) eval.Callable {
 		}
 	}
 	for _, m := range maps {
-		if m.HasKey(ui.Default) {
-			return m.GetKey(ui.Default)
+		if m.HasKey(ui.DefaultKey) {
+			return m.GetKey(ui.DefaultKey)
 		}
 	}
 	return nil

+ 84 - 44
pkg/eval/builtin_fn_styled.go

@@ -24,23 +24,38 @@ func init() {
 // styled-segment $object &fg-color=default &bg-color=default &bold=$false &dim=$false &italic=$false &underlined=$false &blink=$false &inverse=$false
 // ```
 //
-// Constructs a styled segment and is a helper function for styled transformers.
-// `$object` can be a plain string, a styled segment or a concatenation thereof.
-// Probably the only reason to use it is to build custom style transformers:
-//
-// ```elvish
-// fn my-awesome-style-transformer {|seg| styled-segment $seg &bold=(not $seg[dim]) &dim=(not $seg[italic]) &italic=$seg[bold] }
-// styled abc $my-awesome-style-transformer~
+// Constructs a styled segment, a building block for styled texts.
+//
+// - If `$object` is a string, constructs a styled segment with `$object` as the
+//   content, and the properties specified by the options.
+//
+// - If `$object` is a styled segment, constructs a styled segment that is a
+//   copy of `$object`, with the properties specified by the options overridden.
+//
+// The properties of styled segments can be inspected by indexing into it. Valid
+// keys are the same as the options to `styled-segment`, plus `text` for the
+// string content:
+//
+// ```elvish-transcript
+// ~> var s = (styled-segment abc &bold)
+// ~> put $s[text]
+// ▶ abc
+// ~> put $s[fg-color]
+// ▶ default
+// ~> put $s[bold]
+// ▶ $true
 // ```
 //
-// As just seen the properties of styled segments can be inspected by indexing into
-// it. Valid indices are the same as the options to `styled-segment` plus `text`.
+// Prefer the high-level [`styled`](#styled) command to build and transform
+// styled texts. Styled segments are a low-level construct, and you only have to
+// deal with it when building custom style transformers.
+//
+// In the following example, a custom transformer sets the `inverse` property
+// for every bold segment:
 //
 // ```elvish
-// var s = (styled-segment abc &bold)
-// put $s[text]
-// put $s[fg-color]
-// put $s[bold]
+// styled foo(styled bar bold) {|x| styled-segment $x &inverse=$x[bold] }
+// # transforms "foo" + bold "bar" into "foo" + bold and inverse "bar"
 // ```
 
 // Turns a string or ui.Segment into a new ui.Segment with the attributes
@@ -76,61 +91,86 @@ func styledSegment(options RawOptions, input any) (*ui.Segment, error) {
 // styled $object $style-transformer...
 // ```
 //
-// Construct a styled text by applying the supplied transformers to the supplied
-// object. `$object` can be either a string, a styled segment (see below), a styled
-// text or an arbitrary concatenation of them. A `$style-transformer` is either:
+// Constructs a **styled text** by applying the supplied transformers to the
+// supplied `$object`, which may be a string, a [styled
+// segment](#styled-segment), or an existing styled text.
 //
-// -   The name of a builtin style transformer, which may be one of the following:
+// Each `$style-transformer` can be one of the following:
 //
-//     -   One of the attribute names `bold`, `dim`, `italic`, `underlined`,
-//     `blink` or `inverse` for setting the corresponding attribute.
+// - A boolean attribute name:
 //
-//     -   An attribute name prefixed by `no-` for unsetting the attribute.
+//   - One of `bold`, `dim`, `italic`, `underlined`, `blink` and `inverse` for
+//     setting the corresponding attribute.
 //
-//     -   An attribute name prefixed by `toggle-` for toggling the attribute
-//     between set and unset.
+//   - An attribute name prefixed by `no-` for unsetting the attribute.
 //
-// -   A color name for setting the text color, which may be one of the
-// following:
+//   - An attribute name prefixed by `toggle-` for toggling the attribute
+//     between set and unset.
 //
-//     -   One of the 8 basic ANSI colors: `black`, `red`, `green`, `yellow`,
-//    `blue`, `magenta`, `cyan` and `white`.
+// - A color name for setting the text color, which may be one of the
+//   following:
 //
-//     -   The bright variant of the 8 basic ANSI colors, with a `bright-`
-//    prefix.
+//   - One of the 8 basic ANSI colors: `black`, `red`, `green`, `yellow`,
+//     `blue`, `magenta`, `cyan` and `white`.
 //
-//     -   Any color from the xterm 256-color palette, as `colorX` (such as
-//    `color12`).
+//   - The bright variant of the 8 basic ANSI colors, with a `bright-` prefix.
 //
-//     -   A 24-bit RGB color written as `#RRGGBB` such as `'#778899'`.
+//   - Any color from the xterm 256-color palette, as `colorX` (such as
+//     `color12`).
 //
-//		   **Note**: You need to quote such values since an unquoted `#` char
-//		   introduces a comment. So use `'bg-#778899'` not `bg-#778899`. If
-//		   you omit the quotes the text after the `#` char is ignored which
-//		   will result in an error or unexpected behavior.
+//   - A 24-bit RGB color written as `#RRGGBB` (such as `'#778899'`).
 //
-// -   A color name prefixed by `bg-` to set the background color.
+//     **Note**: You need to quote such values, since an unquoted `#` introduces
+//     a comment (e.g. use `'bg-#778899'` instead of `bg-#778899`).
 //
-// -   A color name prefixed by `fg-` to set the foreground color. This has
-// the same effect as specifying the color name without the `fg-` prefix.
+// - A color name prefixed by `fg-` to set the foreground color. This has
+//   the same effect as specifying the color name without the `fg-` prefix.
 //
-// -   A lambda that receives a styled segment as the only argument and returns a
-// single styled segment.
+// - A color name prefixed by `bg-` to set the background color.
 //
-// -   A function with the same properties as the lambda (provided via the
-// `$transformer~` syntax).
+// - A function that receives a styled segment as the only argument and outputs
+//   a single styled segment, which will be applied to all the segments.
 //
 // When a styled text is converted to a string the corresponding
 // [ANSI SGR code](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_.28Select_Graphic_Rendition.29_parameters)
 // is built to render the style.
 //
-// A styled text is nothing more than a wrapper around a list of styled segments.
-// They can be accessed by indexing into it.
+// Examples:
+//
+// ```elvish
+// echo (styled foo red bold) # prints red bold "foo"
+// echo (styled (styled foo red bold) green) # prints green bold "foo"
+// ```
+//
+// A styled text can contain multiple [segments](#styled-segment) with different
+// styles. Such styled texts can be constructed by concatenating multiple styled
+// texts with the [compounding](language.html#compounding) syntax. Strings and
+// styled segments are automatically "promoted" to styled texts when
+// concatenating. Examples:
+//
+// ```elvish
+// echo foo(styled bar red) # prints "foo" + red "bar"
+// echo (styled foo bold)(styled bar red) # prints bold "foo" + red "bar"
+// ```
+//
+// The individual segments in a styled text can be extracted by indexing:
 //
 // ```elvish
 // var s = (styled abc red)(styled def green)
 // put $s[0] $s[1]
 // ```
+//
+// When printed to the terminal, a styled text is not affected by any existing
+// SGR styles in effect, and it will always reset the SGR style afterwards. For
+// example:
+//
+// ```elvish
+// print "\e[1m"
+// echo (styled foo red)
+// echo bar
+// # "foo" will be printed as red, but not bold
+// # "bar" will be printed without any style
+// ```
 
 func styled(fm *Frame, input any, stylings ...any) (ui.Text, error) {
 	var text ui.Text

+ 41 - 38
pkg/eval/builtin_fn_styled_test.go

@@ -10,17 +10,17 @@ import (
 func TestStyledSegment(t *testing.T) {
 	Test(t,
 		That("print (styled (styled-segment abc &fg-color=cyan) bold)").
-			Prints("\033[1;36mabc\033[m"),
+			Prints("\033[;1;36mabc\033[m"),
 		That("print (styled (styled-segment (styled-segment abc &fg-color=magenta) &dim=$true) cyan)").
-			Prints("\033[2;36mabc\033[m"),
+			Prints("\033[;2;36mabc\033[m"),
 		That("print (styled (styled-segment abc &inverse=$true) inverse)").
-			Prints("\033[7mabc\033[m"),
+			Prints("\033[;7mabc\033[m"),
 		That("print (styled (styled-segment abc) toggle-inverse)").
-			Prints("\033[7mabc\033[m"),
+			Prints("\033[;7mabc\033[m"),
 		That("print (styled (styled-segment abc &inverse=$true) no-inverse)").
-			Prints("abc"),
+			Prints("\033[mabc"),
 		That("print (styled (styled-segment abc &inverse=$true) toggle-inverse)").
-			Prints("abc"),
+			Prints("\033[mabc"),
 
 		That("styled-segment []").Throws(ErrorWithMessage(
 			"argument to styled-segment must be a string or a styled segment")),
@@ -32,26 +32,29 @@ func TestStyledSegment(t *testing.T) {
 func TestStyled(t *testing.T) {
 	Test(t,
 		// Transform string
-		That("print (styled abc bold)").Prints("\033[1mabc\033[m"),
-		That("print (styled abc red cyan)").Prints("\033[36mabc\033[m"),
-		That("print (styled abc bg-green)").Prints("\033[42mabc\033[m"),
-		That("print (styled abc no-dim)").Prints("abc"),
+		That("print (styled abc bold)").Prints("\033[;1mabc\033[m"),
+		That("print (styled abc red cyan)").Prints("\033[;36mabc\033[m"),
+		That("print (styled abc bg-green)").Prints("\033[;42mabc\033[m"),
+		That("print (styled abc no-dim)").Prints("\033[mabc"),
 
 		// Transform already styled text
 		That("print (styled (styled abc red) blue)").
-			Prints("\033[34mabc\033[m"),
+			Prints("\033[;34mabc\033[m"),
 		That("print (styled (styled abc italic) red)").
-			Prints("\033[3;31mabc\033[m"),
+			Prints("\033[;3;31mabc\033[m"),
 		That("print (styled (styled abc inverse) inverse)").
-			Prints("\033[7mabc\033[m"),
-		That("print (styled (styled abc inverse) no-inverse)").Prints("abc"),
-		That("print (styled (styled abc inverse) toggle-inverse)").Prints("abc"),
-		That("print (styled (styled abc inverse) toggle-inverse toggle-inverse)").Prints("\033[7mabc\033[m"),
+			Prints("\033[;7mabc\033[m"),
+		That("print (styled (styled abc inverse) no-inverse)").
+			Prints("\033[mabc"),
+		That("print (styled (styled abc inverse) toggle-inverse)").
+			Prints("\033[mabc"),
+		That("print (styled (styled abc inverse) toggle-inverse toggle-inverse)").
+			Prints("\033[;7mabc\033[m"),
 
 		// Function as transformer
-		That("print (styled abc {|s| put $s })").Prints("abc"),
-		That("print (styled abc {|s| styled-segment $s &bold=$true &italic=$false })").Prints("\033[1mabc\033[m"),
-		That("print (styled abc italic {|s| styled-segment $s &bold=$true &italic=$false })").Prints("\033[1mabc\033[m"),
+		That("print (styled abc {|s| put $s })").Prints("\033[mabc"),
+		That("print (styled abc {|s| styled-segment $s &bold=$true &italic=$false })").Prints("\033[;1mabc\033[m"),
+		That("print (styled abc italic {|s| styled-segment $s &bold=$true &italic=$false })").Prints("\033[;1mabc\033[m"),
 
 		That("styled abc {|_| fail bad }").Throws(eval.FailError{"bad"}),
 		That("styled abc {|_| put a b }").Throws(ErrorWithMessage(
@@ -81,36 +84,36 @@ func TestStyled_DoesNotModifyArgument(t *testing.T) {
 func TestStyledConcat(t *testing.T) {
 	Test(t,
 		// string+segment
-		That("print abc(styled-segment abc &fg-color=red)").Prints("abc\033[31mabc\033[m"),
+		That("print abc(styled-segment abc &fg-color=red)").Prints("\033[mabc\033[31mabc\033[m"),
 		// segment+string
-		That("print (styled-segment abc &fg-color=red)abc").Prints("\033[31mabc\033[mabc"),
+		That("print (styled-segment abc &fg-color=red)abc").Prints("\033[;31mabc\033[mabc"),
 		// segment+segment
-		That("print (styled-segment abc &bg-color=red)(styled-segment abc &fg-color=red)").Prints("\033[41mabc\033[m\033[31mabc\033[m"),
+		That("print (styled-segment abc &bg-color=red)(styled-segment abc &fg-color=red)").Prints("\033[;41mabc\033[;31mabc\033[m"),
 		// segment+text
-		That("print (styled-segment abc &underlined=$true)(styled abc bright-cyan)").Prints("\033[4mabc\033[m\033[96mabc\033[m"),
+		That("print (styled-segment abc &underlined=$true)(styled abc bright-cyan)").Prints("\033[;4mabc\033[;96mabc\033[m"),
 		// segment+num
-		That("print (num 99.0)(styled-segment abc &blink)").Prints("99.0\033[5mabc\033[m"),
-		That("print (num 66)(styled-segment abc &blink)").Prints("66\033[5mabc\033[m"),
-		That("print (num 3/2)(styled-segment abc &blink)").Prints("3/2\033[5mabc\033[m"),
+		That("print (num 99.0)(styled-segment abc &blink)").Prints("\033[m99.0\033[5mabc\033[m"),
+		That("print (num 66)(styled-segment abc &blink)").Prints("\033[m66\033[5mabc\033[m"),
+		That("print (num 3/2)(styled-segment abc &blink)").Prints("\033[m3/2\033[5mabc\033[m"),
 		// num+segment
-		That("print (styled-segment abc &blink)(float64 88)").Prints("\033[5mabc\033[m88.0"),
-		That("print (styled-segment abc &blink)(num 44/3)").Prints("\033[5mabc\033[m44/3"),
-		That("print (styled-segment abc &blink)(num 42)").Prints("\033[5mabc\033[m42"),
+		That("print (styled-segment abc &blink)(float64 88)").Prints("\033[;5mabc\033[m88.0"),
+		That("print (styled-segment abc &blink)(num 44/3)").Prints("\033[;5mabc\033[m44/3"),
+		That("print (styled-segment abc &blink)(num 42)").Prints("\033[;5mabc\033[m42"),
 		// string+text
-		That("print abc(styled abc blink)").Prints("abc\033[5mabc\033[m"),
+		That("print abc(styled abc blink)").Prints("\033[mabc\033[5mabc\033[m"),
 		// text+string
-		That("print (styled abc blink)abc").Prints("\033[5mabc\033[mabc"),
+		That("print (styled abc blink)abc").Prints("\033[;5mabc\033[mabc"),
 		// number+text
-		That("print (num 13)(styled abc blink)").Prints("13\033[5mabc\033[m"),
-		That("print (num 4/3)(styled abc blink)").Prints("4/3\033[5mabc\033[m"),
+		That("print (num 13)(styled abc blink)").Prints("\033[m13\033[5mabc\033[m"),
+		That("print (num 4/3)(styled abc blink)").Prints("\033[m4/3\033[5mabc\033[m"),
 		// text+number
-		That("print (styled abc blink)(float64 127)").Prints("\033[5mabc\033[m127.0"),
-		That("print (styled abc blink)(num 13)").Prints("\033[5mabc\033[m13"),
-		That("print (styled abc blink)(num 3/4)").Prints("\033[5mabc\033[m3/4"),
+		That("print (styled abc blink)(float64 127)").Prints("\033[;5mabc\033[m127.0"),
+		That("print (styled abc blink)(num 13)").Prints("\033[;5mabc\033[m13"),
+		That("print (styled abc blink)(num 3/4)").Prints("\033[;5mabc\033[m3/4"),
 		// text+segment
-		That("print (styled abc inverse)(styled-segment abc &bg-color=white)").Prints("\033[7mabc\033[m\033[47mabc\033[m"),
+		That("print (styled abc inverse)(styled-segment abc &bg-color=white)").Prints("\033[;7mabc\033[;47mabc\033[m"),
 		// text+text
-		That("print (styled abc bold)(styled abc dim)").Prints("\033[1mabc\033[m\033[2mabc\033[m"),
+		That("print (styled abc bold)(styled abc dim)").Prints("\033[;1mabc\033[;2mabc\033[m"),
 	)
 }
 

+ 8 - 8
pkg/ui/color_test.go

@@ -9,17 +9,17 @@ func TestColorSGR(t *testing.T) {
 	// Test the SGR sequences of colors indirectly via VTString of Text, since
 	// that is how they are used.
 	testTextVTString(t, []textVTStringTest{
-		{T("foo", FgRed), "\033[31mfoo\033[m"},
-		{T("foo", BgRed), "\033[41mfoo\033[m"},
+		{T("foo", FgRed), "\033[;31mfoo\033[m"},
+		{T("foo", BgRed), "\033[;41mfoo\033[m"},
 
-		{T("foo", FgBrightRed), "\033[91mfoo\033[m"},
-		{T("foo", BgBrightRed), "\033[101mfoo\033[m"},
+		{T("foo", FgBrightRed), "\033[;91mfoo\033[m"},
+		{T("foo", BgBrightRed), "\033[;101mfoo\033[m"},
 
-		{T("foo", Fg(XTerm256Color(30))), "\033[38;5;30mfoo\033[m"},
-		{T("foo", Bg(XTerm256Color(30))), "\033[48;5;30mfoo\033[m"},
+		{T("foo", Fg(XTerm256Color(30))), "\033[;38;5;30mfoo\033[m"},
+		{T("foo", Bg(XTerm256Color(30))), "\033[;48;5;30mfoo\033[m"},
 
-		{T("foo", Fg(TrueColor(30, 40, 50))), "\033[38;2;30;40;50mfoo\033[m"},
-		{T("foo", Bg(TrueColor(30, 40, 50))), "\033[48;2;30;40;50mfoo\033[m"},
+		{T("foo", Fg(TrueColor(30, 40, 50))), "\033[;38;2;30;40;50mfoo\033[m"},
+		{T("foo", Bg(TrueColor(30, 40, 50))), "\033[;48;2;30;40;50mfoo\033[m"},
 	})
 }
 

+ 1 - 1
pkg/ui/key.go

@@ -26,7 +26,7 @@ func K(r rune, mods ...Mod) Key {
 }
 
 // Default is used in the key binding table to indicate a default binding.
-var Default = Key{DefaultBindingRune, 0}
+var DefaultKey = Key{DefaultBindingRune, 0}
 
 // Mod represents a modifier key.
 type Mod byte

+ 4 - 0
pkg/ui/parse_sgr.go

@@ -131,6 +131,10 @@ func StylingFromSGR(s string) Styling {
 			moreStyling = Bg(trueColor{
 				uint8(codes[2]), uint8(codes[3]), uint8(codes[4])})
 			consume = 5
+		case code == 39:
+			moreStyling = FgDefault
+		case code == 49:
+			moreStyling = BgDefault
 		default:
 			// Do nothing; skip this code
 		}

+ 7 - 3
pkg/ui/style.go

@@ -17,8 +17,8 @@ type Style struct {
 	Inverse    bool
 }
 
-// SGR returns SGR sequence for the style.
-func (s Style) SGR() string {
+// SGRValues returns an array of the individual SGR values for the style.
+func (s Style) SGRValues() []string {
 	var sgr []string
 
 	addIf := func(b bool, code string) {
@@ -38,8 +38,12 @@ func (s Style) SGR() string {
 	if s.Background != nil {
 		sgr = append(sgr, s.Background.bgSGR())
 	}
+	return sgr
+}
 
-	return strings.Join(sgr, ";")
+// SGR returns, for the Style, a string that can be included in an ANSI X3.64 SGR sequence.
+func (s Style) SGR() string {
+	return strings.Join(s.SGRValues(), ";")
 }
 
 // MergeFromOptions merges all recognized values from a map to the current

+ 9 - 9
pkg/ui/style_test.go

@@ -8,15 +8,15 @@ func TestStyleSGR(t *testing.T) {
 	// Test the SGR sequences of style attributes indirectly via VTString of
 	// Text, since that is how they are used.
 	testTextVTString(t, []textVTStringTest{
-		{T("foo", Bold), "\033[1mfoo\033[m"},
-		{T("foo", Dim), "\033[2mfoo\033[m"},
-		{T("foo", Italic), "\033[3mfoo\033[m"},
-		{T("foo", Underlined), "\033[4mfoo\033[m"},
-		{T("foo", Blink), "\033[5mfoo\033[m"},
-		{T("foo", Inverse), "\033[7mfoo\033[m"},
-		{T("foo", FgRed), "\033[31mfoo\033[m"},
-		{T("foo", BgRed), "\033[41mfoo\033[m"},
-		{T("foo", Bold, FgRed, BgBlue), "\033[1;31;44mfoo\033[m"},
+		{T("foo", Bold), "\033[;1mfoo\033[m"},
+		{T("foo", Dim), "\033[;2mfoo\033[m"},
+		{T("foo", Italic), "\033[;3mfoo\033[m"},
+		{T("foo", Underlined), "\033[;4mfoo\033[m"},
+		{T("foo", Blink), "\033[;5mfoo\033[m"},
+		{T("foo", Inverse), "\033[;7mfoo\033[m"},
+		{T("foo", FgRed), "\033[;31mfoo\033[m"},
+		{T("foo", BgRed), "\033[;41mfoo\033[m"},
+		{T("foo", Bold, FgRed, BgBlue), "\033[;1;31;44mfoo\033[m"},
 	})
 }
 

+ 24 - 4
pkg/ui/text.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"math/big"
 	"strconv"
+	"strings"
 
 	"src.elv.sh/pkg/eval/vals"
 	"src.elv.sh/pkg/wcwidth"
@@ -202,11 +203,30 @@ func (t Text) String() string {
 	return t.VTString()
 }
 
-// VTString renders the styled text using VT-style escape sequences.
+// VTString renders the styled text using VT-style escape sequences. Any
+// existing SGR state will be cleared.
 func (t Text) VTString() string {
-	var buf bytes.Buffer
+	var sb strings.Builder
+	clean := false
 	for _, seg := range t {
-		buf.WriteString(seg.VTString())
+		sgr := seg.SGR()
+		if sgr == "" {
+			if !clean {
+				sb.WriteString("\033[m")
+			}
+			clean = true
+		} else {
+			if clean {
+				sb.WriteString("\033[" + sgr + "m")
+			} else {
+				sb.WriteString("\033[;" + sgr + "m")
+			}
+			clean = false
+		}
+		sb.WriteString(seg.Text)
+	}
+	if !clean {
+		sb.WriteString("\033[m")
 	}
-	return buf.String()
+	return sb.String()
 }

+ 4 - 3
pkg/ui/text_segment.go

@@ -144,11 +144,12 @@ func (s *Segment) String() string {
 	return s.VTString()
 }
 
-// VTString renders the styled segment using VT-style escape sequences.
+// VTString renders the styled segment using VT-style escape sequences. Any
+// existing SGR state will be cleared.
 func (s *Segment) VTString() string {
 	sgr := s.SGR()
 	if sgr == "" {
-		return s.Text
+		return "\033[m" + s.Text
 	}
-	return fmt.Sprintf("\033[%sm%s\033[m", sgr, s.Text)
+	return fmt.Sprintf("\033[;%sm%s\033[m", sgr, s.Text)
 }

+ 1 - 0
pkg/ui/text_test.go

@@ -139,6 +139,7 @@ type textVTStringTest struct {
 }
 
 func testTextVTString(t *testing.T, tests []textVTStringTest) {
+	t.Helper()
 	for _, test := range tests {
 		vtString := test.text.VTString()
 		if vtString != test.wantVTString {

+ 4 - 3
website/.gitignore

@@ -1,6 +1,7 @@
-/home.html
-/*/*.html
-!/ttyshot/*.html
+*.html
+!/template.html
+!*.ttyshot.html
+*.raw
 /tools/*.bin
 /_*
 /Elvish.docset

+ 8 - 3
website/Makefile

@@ -29,8 +29,13 @@ check-rellinks: gen
 clean:
 	rm -rf tools/*.bin $(HTMLS) $(DST_DIR) $(DOCSET_TMP_DIR) $(DOCSET_DST_DIR)
 
-ttyshot/%.html:
-	@echo Exclude ttyshots from the pattern rule for %.html
+ifdef TTYSHOT
+%.ttyshot.html: %.ttyshot tools/ttyshot.bin
+	tools/ttyshot.bin -o $@ $<
+else
+%.ttyshot.html:
+	@: ttyshot generation disabled by default
+endif
 
 .PHONY: gen docset publish check-rellinks clean
 
@@ -39,7 +44,7 @@ ttyshot/%.html:
 
 .SECONDEXPANSION:
 
-tools/%.bin: cmd/% $$(wildcard cmd/%/*.go)
+tools/%.bin: cmd/% $$(wildcard cmd/%/*)
 	go build -o $@ ./$<
 
 %.html: %.md tools/md-to-html $(MD_TO_HTML_TOOLS) $$(shell tools/extra-deps $$@)

+ 51 - 0
website/README.md

@@ -34,6 +34,57 @@ Building the docset requires the following additional dependencies:
 
 -   SQLite3 CLI.
 
+To build the docset, run `make docset`. The generated docset is in
+`Elvish.docset`.
+
+# Ttyshots
+
+Some of the pages include "ttyshots" that show the content of Elvish sessions.
+They are HTML files with terminal attributes converted to CSS classes, generated
+from corresponding instruction files. By convention, the instruction files have
+names ending in `.ttyshot`, and the generated HTML files have names ending in
+`.ttyshot.html`.
+
+The generation process depends on [`tmux`](https://github.com/tmux/tmux) and a
+built `elvish` in `PATH`. Windows is not supported.
+
+## Instruction syntax
+
+Each line in a ttyshot instruction file is one of the following:
+
+-   `#prompt` instructs waiting for a new shell prompt.
+
+-   `#`_`command`_, where `command` is a string that does **not** start with a
+    space and is not `prompt`, is a command sent to `tmux`. The most useful one
+    (and only one being used now) is `send-keys`.
+
+-   Anything else is treated as text that should be sent directly to the Elvish
+    prompt.
+
+For example, the following instructions runs `cd /tmp`, waits for the next
+prompt, and sends Ctrl-N to trigger navigation mode:
+
+```
+cd /tmp
+#prompt
+#send-keys ctrl-L
+```
+
+## Generating ttyshots
+
+Unlike other generated website artifacts, generated ttyshots are committed into
+the repository, and the `Makefile` rule to generate them is disabled by default.
+This is because the process to generate ttyshots is relatively slow and may have
+network dependencies.
+
+To turn on ttyshot generation, pass `TTYSHOT=1` to `make`. For example, to
+generate a single ttyshot, run `make TTYSHOT=1 foo.ttyshot.html`. To build the
+website with ttyshot generation enabled, run `make TTYSHOT=1`.
+
+The first time you generate ttyshots, `make` will build the `ttyshot` tool, and
+regenerate all ttyshots. Subsequent runs will only regenerate ttyshots whose
+instruction files have changed.
+
 # Commit History
 
 These files used to live in a

+ 1 - 2
website/cmd/macros/macros.go

@@ -11,7 +11,6 @@ import (
 	"log"
 	"os"
 	"os/exec"
-	"path"
 	"path/filepath"
 	"strings"
 )
@@ -107,7 +106,7 @@ func callElvdoc(out io.Writer, module, path string) {
 }
 
 func (f *filterer) expandTtyshot(name string) string {
-	content, err := os.ReadFile(path.Join("ttyshot", name+".html"))
+	content, err := os.ReadFile(name + ".ttyshot.html")
 	if err != nil {
 		log.Fatal(err)
 	}

+ 45 - 0
website/cmd/ttyshot/apply_dir.go

@@ -0,0 +1,45 @@
+package main
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+)
+
+// TODO: Add unit test and move this file to pkg/fsutil.
+
+// Dir describes the layout of a directory. The keys of the map represent
+// filenames. Each value is either a string (for the content of a regular file
+// with permission 0644), a File, or a Dir.
+type Dir map[string]any
+
+// File describes a file to create.
+type File struct {
+	Perm    os.FileMode
+	Content string
+}
+
+// ApplyDir creates a given filesystem layout.
+func ApplyDir(dir Dir, root string) error {
+	for name, file := range dir {
+		path := filepath.Join(root, name)
+		var err error
+		switch file := file.(type) {
+		case string:
+			err = os.WriteFile(path, []byte(file), 0644)
+		case File:
+			err = os.WriteFile(path, []byte(file.Content), file.Perm)
+		case Dir:
+			err = os.MkdirAll(path, 0755)
+			if err == nil {
+				err = ApplyDir(file, path)
+			}
+		default:
+			panic(fmt.Sprintf("file must be string, Dir, or File, got %T", file))
+		}
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}

+ 310 - 0
website/cmd/ttyshot/interp.go

@@ -0,0 +1,310 @@
+//go:build !windows && !plan9 && !js
+
+package main
+
+import (
+	"bytes"
+	_ "embed"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"syscall"
+	"time"
+
+	"github.com/creack/pty"
+	"src.elv.sh/pkg/sys/eunix"
+	"src.elv.sh/pkg/ui"
+)
+
+const (
+	terminalRows = 100
+	terminalCols = 58
+)
+
+const (
+	cutMarker    = "[CUT]"
+	promptMarker = "[PROMPT]"
+)
+
+//go:embed rc.elv
+var rcElv string
+
+// Creates a temporary home directory for running tmux and elvish in. The caller
+// is responsible for removing the directory.
+func setupHome() (string, error) {
+	homePath, err := os.MkdirTemp("", "ttyshot-*")
+	if err != nil {
+		return "", fmt.Errorf("create temp home: %w", err)
+	}
+
+	// The temporary directory may include symlinks in the path. Expand them so
+	// that commands like tilde-abbr behaves as expected.
+	resolvedHomePath, err := filepath.EvalSymlinks(homePath)
+	if err != nil {
+		return homePath, fmt.Errorf("resolve symlinks in homePath: %w", err)
+	}
+	homePath = resolvedHomePath
+
+	err = ApplyDir(Dir{
+		// Directories to be used in navigation mode.
+		"bash": Dir{},
+		"elvish": Dir{
+			"1.0-release.md":  "1.0 has not been released yet.",
+			"CONTRIBUTING.md": "",
+			"Dockerfile":      "",
+			"LICENSE":         "",
+			"Makefile":        "",
+			"PACKAGING.md":    "",
+			"README.md":       "",
+			"SECURITY.md":     "",
+			"cmd":             Dir{},
+			"go.mod":          "",
+			"go.sum":          "",
+			"pkg":             Dir{},
+			"syntaxes":        Dir{},
+			"tools":           Dir{},
+			"vscode":          Dir{},
+			"website":         Dir{},
+		},
+		"zsh": Dir{},
+
+		// Will keep tmux and elvish's sockets, and raw output of capture-pane
+		".tmp": Dir{},
+
+		".config": Dir{
+			"elvish": Dir{
+				"rc.elv": rcElv,
+			},
+		},
+	}, homePath)
+	return homePath, err
+}
+
+func createTtyshot(homePath string, script []op, saveRaw string) ([]byte, error) {
+	ctrl, tty, err := pty.Open()
+	if err != nil {
+		return nil, err
+	}
+	defer ctrl.Close()
+	defer tty.Close()
+	winsize := pty.Winsize{Rows: terminalRows, Cols: terminalCols}
+	pty.Setsize(ctrl, &winsize)
+
+	rawPath := filepath.Join(homePath, ".tmp", "ttyshot.raw")
+	if saveRaw != "" {
+		saveRaw, err := filepath.Abs(saveRaw)
+		if err != nil {
+			return nil, fmt.Errorf("resolve path to raw dump file: %w", err)
+		}
+		os.Symlink(saveRaw, rawPath)
+	}
+
+	doneCh, err := spawnElvish(homePath, tty)
+	if err != nil {
+		return nil, err
+	}
+	executeScript(script, ctrl, homePath)
+	log.Println("executed script, waiting for tmux to exit")
+
+	// Drain outputs from the terminal. This is needed so that tmux can exit
+	// properly without blocking on flushing outputs.
+	go io.Copy(io.Discard, ctrl)
+
+	err = <-doneCh
+	if err != nil {
+		return nil, err
+	}
+
+	rawBytes, err := os.ReadFile(rawPath)
+	if err != nil {
+		return nil, err
+	}
+
+	ttyshot := string(rawBytes)
+	// Remove all content before the last cutMarker.
+	segments := strings.Split(ttyshot, cutMarker+"\n")
+	ttyshot = segments[len(segments)-1]
+
+	// Strip all the prompt markers, and the content after the last prompt
+	// marker if the last instruction was #prompt (in which case the content
+	// will just be an empty prompt).
+	segments = strings.Split(ttyshot, promptMarker+"\n")
+	if len(script) > 0 && script[len(script)-1].typ == opPrompt {
+		segments = segments[:len(segments)-1]
+	}
+	ttyshot = strings.Join(segments, "")
+
+	ttyshot = strings.TrimRight(ttyshot, "\n")
+	return []byte(sgrTextToHTML(ttyshot) + "\n"), nil
+}
+
+func spawnElvish(homePath string, tty *os.File) (<-chan error, error) {
+	elvishPath, err := exec.LookPath("elvish")
+	if err != nil {
+		return nil, fmt.Errorf("find elvish: %w", err)
+	}
+	tmuxPath, err := exec.LookPath("tmux")
+	if err != nil {
+		return nil, fmt.Errorf("find tmux: %w", err)
+	}
+
+	tmuxSock := filepath.Join(homePath, ".tmp", "tmux.sock")
+	elvSock := filepath.Join(homePath, ".tmp", "elv.sock")
+
+	// Start tmux and have it start a hermetic Elvish session.
+	tmuxCmd := exec.Cmd{
+		Path: tmuxPath,
+		Args: []string{
+			tmuxPath,
+			"-S", tmuxSock, "-f", "/dev/null", "-u", "-T", "256,RGB",
+			"new-session", elvishPath, "-sock", elvSock},
+		Dir: homePath,
+		Env: []string{
+			"HOME=" + homePath,
+			"PATH=" + os.Getenv("PATH"),
+			// The actual value doesn't matter here, as long as it can be looked
+			// up in terminfo. We rely on the -T flag above to force tmux to
+			// support certain terminal features.
+			"TERM=xterm",
+		},
+		Stdin:  tty,
+		Stdout: tty,
+		Stderr: tty,
+	}
+	log.Println("started tmux, socket", tmuxSock)
+
+	doneCh := make(chan error, 1)
+	go func() {
+		doneCh <- tmuxCmd.Run()
+		log.Println("tmux exited")
+	}()
+
+	return doneCh, nil
+}
+
+func executeScript(script []op, ctrl *os.File, homePath string) {
+	for _, op := range script {
+		log.Println("executing", op)
+		switch op.typ {
+		case opText:
+			text := op.val.(string)
+			ctrl.WriteString(text)
+			ctrl.WriteString("\r")
+		case opPrompt:
+			err := waitForOutput(ctrl, promptMarker,
+				func(bs []byte) bool { return bytes.HasSuffix(bs, []byte(promptMarker)) })
+			if err != nil {
+				// TODO: Handle the error properly
+				panic(err)
+			}
+		case opTmux:
+			tmuxSock := filepath.Join(homePath, ".tmp", "tmux.sock")
+			tmuxCmd := exec.Command("tmux",
+				append([]string{"-S", tmuxSock}, op.val.([]string)...)...)
+			tmuxCmd.Env = []string{}
+			err := tmuxCmd.Run()
+			if err != nil {
+				// TODO: Handle the error properly
+				panic(err)
+			}
+		default:
+			panic("unhandled op")
+		}
+	}
+	log.Println("sending Alt-q")
+	// Alt-q is bound to a function that captures the content of the pane and
+	// exits
+	ctrl.Write([]byte{'\033', 'q'})
+}
+
+func waitForOutput(f *os.File, expected string, matcher func([]byte) bool) error {
+	var buf bytes.Buffer
+	// It shouldn't take more than a couple of seconds to see the expected
+	// output, so use a timeout an order of magnitude longer to allow for
+	// overloaded systems.
+	deadline := time.Now().Add(30 * time.Second)
+	for {
+		budget := time.Until(deadline)
+		if budget <= 0 {
+			break
+		}
+		ready, err := eunix.WaitForRead(budget, f)
+		if err != nil {
+			if err == syscall.EINTR {
+				continue
+			}
+			return fmt.Errorf("waiting for tmux output: %w", err)
+		}
+		if !ready[0] {
+			break
+		}
+		_, err = io.CopyN(&buf, f, 1)
+		if err != nil {
+			return fmt.Errorf("reading tmux output: %w", err)
+		}
+		if matcher(buf.Bytes()) {
+			return nil
+		}
+	}
+	return fmt.Errorf("timed out waiting for %s in tmux output; output so far: %q", expected, buf)
+}
+
+var htmlEscaper = strings.NewReplacer("&", "&amp;", "<", "&lt;", ">", "&gt;")
+
+func sgrTextToHTML(ttyshot string) string {
+	t := ui.ParseSGREscapedText(ttyshot)
+
+	var sb strings.Builder
+	for i, line := range t.SplitByRune('\n') {
+		if i > 0 {
+			sb.WriteRune('\n')
+		}
+		for j, seg := range line {
+			style := seg.Style
+			var classes []string
+			if style.Inverse {
+				// The inverse attribute means that the foreground and
+				// background colors should be swapped, which cannot be
+				// expressed in pure CSS. To work around this, this code swaps
+				// the foreground and background colors, and uses two special
+				// CSS classes to indicate that the foreground/background should
+				// take the inverse of the default color.
+				style.Inverse = false
+				style.Foreground, style.Background = style.Background, style.Foreground
+				if style.Foreground == nil {
+					classes = append(classes, "sgr-7fg")
+				}
+				if style.Background == nil {
+					classes = append(classes, "sgr-7bg")
+				}
+			}
+
+			for _, c := range style.SGRValues() {
+				classes = append(classes, "sgr-"+c)
+			}
+			text := seg.Text
+			// We pass -N to tmux capture-pane in order to correctly preserve
+			// trailing spaces that have background colors. However, this
+			// preserves unstyled trailing spaces too, which makes the ttyshot
+			// harder to copy-paste, so strip it.
+			if len(classes) == 0 && j == len(line)-1 {
+				text = strings.TrimRight(text, " ")
+			}
+			if text == "" {
+				continue
+			}
+			escapedText := htmlEscaper.Replace(text)
+			if len(classes) == 0 {
+				sb.WriteString(escapedText)
+			} else {
+				fmt.Fprintf(&sb, `<span class="%s">%s</span>`, strings.Join(classes, " "), escapedText)
+			}
+		}
+	}
+
+	return sb.String()
+}

+ 79 - 0
website/cmd/ttyshot/main.go

@@ -0,0 +1,79 @@
+//go:build !windows && !plan9 && !js
+
+// Generate a ttyshot HTML image from a ttyshot specification.
+//
+// Usage: ./ttyshot website/ttyshot/*.spec
+//
+// You can recreate all the ttyshots by running the following from the project top-level directory:
+//
+//   make ttyshot
+//   for f [website/ttyshot/**.spec] { put $f; ./ttyshot $f >/dev/tty 2>&1 }
+//
+// This assumes working `elvish` and `tmux` programs in $E:PATH.
+package main
+
+import (
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"os"
+)
+
+func main() {
+	err := run(os.Args[1:])
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+}
+
+func run(args []string) error {
+	fs := flag.NewFlagSet("ttyshot", flag.ExitOnError)
+	outFlag := fs.String("o", "", "output file (defaults to spec-path + .html)")
+	verboseFlag := fs.Bool("v", false, "enable verbose logging")
+	saveRawFlag := fs.String("save-raw", "", "if non-empty, save output of capture-pane to this file")
+	fs.Usage = func() {
+		fmt.Fprintln(fs.Output(), "Usage: ttyshot [flags] spec-path")
+		fs.PrintDefaults()
+	}
+
+	fs.Parse(args)
+	if len(fs.Args()) != 1 {
+		fs.Usage()
+		os.Exit(1)
+	}
+
+	if !*verboseFlag {
+		log.SetOutput(io.Discard)
+	}
+
+	specPath := fs.Args()[0]
+	content, err := os.ReadFile(specPath)
+	if err != nil {
+		return err
+	}
+	spec := parseSpec(string(content))
+
+	homePath, err := setupHome()
+	if err != nil {
+		return fmt.Errorf("set up temporary home: %w", err)
+	}
+	defer func() {
+		err := os.RemoveAll(homePath)
+		if err != nil {
+			fmt.Fprintln(os.Stderr, "Warning: unable to remove temp HOME:", err)
+		}
+	}()
+
+	out, err := createTtyshot(homePath, spec, *saveRawFlag)
+	if err != nil {
+		return err
+	}
+
+	outPath := *outFlag
+	if outPath == "" {
+		outPath = specPath + ".html"
+	}
+	return os.WriteFile(outPath, out, 0o644)
+}

+ 50 - 0
website/cmd/ttyshot/parse.go

@@ -0,0 +1,50 @@
+//go:build !windows && !plan9 && !js
+
+package main
+
+import (
+	"strings"
+)
+
+type opType int
+
+// Operations for driving a demo ttyshot.
+const (
+	opText   opType = iota // send the provided text, optionally followed by Enter
+	opPrompt               // wait for prompt marker
+	opTmux                 // run tmux command
+)
+
+type op struct {
+	typ opType
+	val any
+}
+
+func parseSpec(content string) []op {
+	lines := strings.Split(content, "\n")
+	ops := make([]op, 1, len(lines)+2)
+	ops[0] = op{opPrompt, nil}
+
+	for _, line := range lines {
+		if len(line) == 0 {
+			continue // ignore empty lines
+		}
+		var newOp op
+		if line == "#prompt" {
+			newOp = op{opPrompt, nil}
+		} else if strings.HasPrefix(line, "#") && !strings.HasPrefix(line, "# ") {
+			newOp = op{opTmux, strings.Fields(line[1:])}
+		} else {
+			newOp = op{opText, line}
+		}
+		ops = append(ops, newOp)
+	}
+
+	if len(ops) > 0 && ops[len(ops)-1].typ == opText {
+		// The termination of the ttyshot process relies on the editor to be
+		// active, so add an implicit #prompt.
+		ops = append(ops, op{opPrompt, nil})
+	}
+
+	return ops
+}

+ 69 - 0
website/cmd/ttyshot/rc.elv

@@ -0,0 +1,69 @@
+# This is the interactive configuration for generating Elvish "ttyshots".
+
+{
+
+use store
+# Populate the interactive location history.
+store:add-dir ~
+store:add-dir ~/tmp
+store:add-dir ~/bash
+store:add-dir ~/zsh
+store:add-dir /tmp
+store:add-dir /usr
+store:add-dir /usr/local/bin
+store:add-dir /usr/local/share
+store:add-dir /usr/local
+store:add-dir /opt
+store:add-dir ~/elvish/pkg/eval
+store:add-dir ~/elvish/pkg/edit
+store:add-dir ~/.config/elvish
+store:add-dir ~/elvish/website
+store:add-dir ~/.local/share/elvish
+store:add-dir ~/elvish
+
+# Populate the interactive command history.
+set @_ = (
+    store:add-cmd 'randint 1 10'
+    store:add-cmd 'echo (styled warning: red) bumpy road'
+    store:add-cmd 'echo "hello\nbye" > /tmp/x'
+    store:add-cmd 'from-lines < /tmp/x'
+    store:add-cmd 'cd /tmp'
+    store:add-cmd 'cd ~/elvish'
+    store:add-cmd 'git branch'
+    store:add-cmd 'git checkout .'
+    store:add-cmd 'git commit'
+    range 10 | each {|_|
+        store:add-cmd 'git status'
+    }
+    store:add-cmd 'cd /usr/local/bin'
+    store:add-cmd 'echo $pwd'
+    store:add-cmd '* (+ 3 4) (- 100 94)'
+    range 9 | each {|_|
+        store:add-cmd 'make'
+    }
+    store:add-cmd 'math:min 3 1 30'
+)
+
+} # use store
+
+# Sync the history we just manufactured with this elvish process.
+edit:history:fast-forward
+
+set edit:global-binding[Alt-q] = {
+    tmux capture-pane -epN > ~/.tmp/ttyshot.raw
+    exit
+}
+
+set edit:max-height = 15
+set edit:navigation:width-ratio = [8 18 30]
+
+set edit:before-readline = [$@edit:before-readline {
+    echo '[PROMPT]'
+}]
+
+set edit:rprompt = (constantly (styled 'elf@host' inverse))
+
+# These functions are used in some of the ttyshot scripts to ensure consistent
+# output that doesn't leak info about the machine used to create the ttyshot.
+fn whoami { echo elf }
+fn hostname { echo host.example.com }

+ 1 - 0
website/go.mod

@@ -4,6 +4,7 @@ go 1.18
 
 require (
 	github.com/BurntSushi/toml v1.0.0
+	github.com/creack/pty v1.1.15
 	src.elv.sh v0.17.0
 )
 

+ 2 - 0
website/go.sum

@@ -1,3 +1,5 @@
+github.com/creack/pty v1.1.15 h1:cKRCLMj3Ddm54bKSpemfQ8AtYFBhAI2MPmdys22fBdc=
+github.com/creack/pty v1.1.15/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
 github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
 github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=

+ 5 - 5
website/home.md

@@ -27,7 +27,7 @@ Windows.
       </p>
     </div>
     <div class="demo-col demo-ttyshot">
-      @ttyshot pipelines
+      @ttyshot home/pipelines
     </div>
   </div> </div>
 
@@ -46,7 +46,7 @@ Windows.
       </p>
     </div>
     <div class="demo-col demo-ttyshot">
-      @ttyshot control-structures
+      @ttyshot home/control-structures
     </div>
   </div> </div>
 
@@ -65,7 +65,7 @@ Windows.
       </p>
     </div>
     <div class="demo-col demo-ttyshot">
-      @ttyshot location-mode
+      @ttyshot home/location-mode
     </div>
   </div> </div>
 
@@ -84,7 +84,7 @@ Windows.
       </p>
     </div>
     <div class="demo-col demo-ttyshot">
-      @ttyshot histlist-mode
+      @ttyshot home/histlist-mode
     </div>
   </div> </div>
 
@@ -103,7 +103,7 @@ Windows.
       </p>
     </div>
     <div class="demo-col demo-ttyshot">
-      @ttyshot navigation-mode
+      @ttyshot home/navigation-mode
     </div>
   </div> </div>
 </div> </div>

+ 13 - 0
website/home/control-structures.ttyshot

@@ -0,0 +1,13 @@
+if $true { echo good } else { echo bad }
+#prompt
+for x [lorem ipsum] {
+  echo $x.pdf
+}
+#prompt
+try {
+  fail 'bad error'
+} catch e {
+  echo error $e
+} else {
+  echo ok
+}

+ 15 - 0
website/home/control-structures.ttyshot.html

@@ -0,0 +1,15 @@
+~&gt; <span class="sgr-32">if</span> <span class="sgr-35">$true</span> <span class="sgr-1">{</span> <span class="sgr-32">echo</span> good <span class="sgr-1">}</span> <span class="sgr-33">else</span> <span class="sgr-1">{</span> <span class="sgr-32">echo</span> bad <span class="sgr-1">}</span>
+good
+~&gt; <span class="sgr-32">for</span> <span class="sgr-35">x</span> <span class="sgr-1">[</span>lorem ipsum<span class="sgr-1">]</span> <span class="sgr-1">{</span>
+     <span class="sgr-32">echo</span> <span class="sgr-35">$x</span>.pdf
+   <span class="sgr-1">}</span>
+lorem.pdf
+ipsum.pdf
+~&gt; <span class="sgr-32">try</span> <span class="sgr-1">{</span>
+     <span class="sgr-32">fail</span> <span class="sgr-33">'bad error'</span>
+   <span class="sgr-1">}</span> catch e <span class="sgr-1">{</span>
+     <span class="sgr-32">echo</span> error <span class="sgr-35">$e</span>
+   <span class="sgr-1">}</span> else <span class="sgr-1">{</span>
+     <span class="sgr-32">echo</span> ok
+   <span class="sgr-1">}</span>
+error [&amp;reason=[&amp;content='bad error' &amp;type=fail]]

+ 1 - 0
website/home/histlist-mode.ttyshot

@@ -0,0 +1 @@
+#send-keys C-R Up Up

+ 15 - 0
website/home/histlist-mode.ttyshot.html

@@ -0,0 +1,15 @@
+~&gt;                                                <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> HISTORY (dedup on) </span>
+   3 echo "hello\nbye" &gt; /tmp/x                          <span class="sgr-35">│</span>
+   4 from-lines &lt; /tmp/x                                 <span class="sgr-35">│</span>
+   5 cd /tmp                                             <span class="sgr-7fg sgr-45"> </span>
+   6 cd ~/elvish                                         <span class="sgr-7fg sgr-45"> </span>
+   7 git branch                                          <span class="sgr-7fg sgr-45"> </span>
+   8 git checkout .                                      <span class="sgr-7fg sgr-45"> </span>
+   9 git commit                                          <span class="sgr-7fg sgr-45"> </span>
+  19 git status                                          <span class="sgr-7fg sgr-45"> </span>
+  20 cd /usr/local/bin                                   <span class="sgr-7fg sgr-45"> </span>
+  21 echo $pwd                                           <span class="sgr-7fg sgr-45"> </span>
+<span class="sgr-7fg sgr-7bg">  22 * (+ 3 4) (- 100 94)                                </span><span class="sgr-7fg sgr-45"> </span>
+  31 make                                                <span class="sgr-7fg sgr-45"> </span>
+  32 math:min 3 1 30                                     <span class="sgr-7fg sgr-45"> </span>

+ 0 - 0
website/home.css → website/home/home.css


+ 0 - 0
website/home.js → website/home/home.js


+ 1 - 0
website/home/location-mode.ttyshot

@@ -0,0 +1 @@
+#send-keys C-L

+ 15 - 0
website/home/location-mode.ttyshot.html

@@ -0,0 +1,15 @@
+~&gt;                                                <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> LOCATION </span>
+<span class="sgr-7fg sgr-7bg"> 10 ~/elvish                                             </span><span class="sgr-7fg sgr-45"> </span>
+ 10 ~/.local/share/elvish                                <span class="sgr-7fg sgr-45"> </span>
+ 10 ~/elvish/website                                     <span class="sgr-7fg sgr-45"> </span>
+ 10 ~/.config/elvish                                     <span class="sgr-7fg sgr-45"> </span>
+  9 ~/elvish/pkg/edit                                    <span class="sgr-7fg sgr-45"> </span>
+  9 ~/elvish/pkg/eval                                    <span class="sgr-7fg sgr-45"> </span>
+  9 /opt                                                 <span class="sgr-7fg sgr-45"> </span>
+  9 /usr/local                                           <span class="sgr-7fg sgr-45"> </span>
+  9 /usr/local/share                                     <span class="sgr-7fg sgr-45"> </span>
+  9 /usr/local/bin                                       <span class="sgr-7fg sgr-45"> </span>
+  9 /usr                                                 <span class="sgr-7fg sgr-45"> </span>
+  9 /tmp                                                 <span class="sgr-35">│</span>
+  8 ~/zsh                                                <span class="sgr-35">│</span>

+ 3 - 0
website/home/navigation-mode.ttyshot

@@ -0,0 +1,3 @@
+cd elvish; echo '[CUT]'
+#prompt
+#send-keys C-N

+ 15 - 0
website/home/navigation-mode.ttyshot.html

@@ -0,0 +1,15 @@
+~/elvish&gt;                                         <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> NAVIGATING </span>
+<span class="sgr-1 sgr-34"> bash   </span> <span class="sgr-7fg sgr-7bg"> 1.0-release.md  </span><span class="sgr-7fg sgr-45"> </span> 1.0 has not been released yet.
+<span class="sgr-7fg sgr-1 sgr-44"> elvish </span>  CONTRIBUTING.md <span class="sgr-7fg sgr-45"> </span>
+<span class="sgr-1 sgr-34"> zsh    </span>  Dockerfile      <span class="sgr-7fg sgr-45"> </span>
+          LICENSE         <span class="sgr-7fg sgr-45"> </span>
+          Makefile        <span class="sgr-7fg sgr-45"> </span>
+          PACKAGING.md    <span class="sgr-7fg sgr-45"> </span>
+          README.md       <span class="sgr-7fg sgr-45"> </span>
+          SECURITY.md     <span class="sgr-7fg sgr-45"> </span>
+         <span class="sgr-1 sgr-34"> cmd             </span><span class="sgr-7fg sgr-45"> </span>
+          go.mod          <span class="sgr-7fg sgr-45"> </span>
+          go.sum          <span class="sgr-7fg sgr-45"> </span>
+         <span class="sgr-1 sgr-34"> pkg             </span><span class="sgr-35">│</span>
+         <span class="sgr-1 sgr-34"> syntaxes        </span><span class="sgr-35">│</span>

+ 4 - 0
website/home/pipelines.ttyshot

@@ -0,0 +1,4 @@
+curl -sL api.github.com/repos/elves/elvish/issues |
+  all (from-json) |
+  each {|x| echo (exact-num $x[number]): $x[title] } |
+  head -n 10

+ 15 - 0
website/home/pipelines.ttyshot.html

@@ -0,0 +1,15 @@
+~&gt; <span class="sgr-32">curl</span> -sL api.github.com/repos/elves/elvish/issues <span class="sgr-32">|</span>
+     <span class="sgr-32">all</span> <span class="sgr-1">(</span><span class="sgr-32">from-json</span><span class="sgr-1">)</span> <span class="sgr-32">|</span>
+     <span class="sgr-32">each</span> <span class="sgr-1">{</span><span class="sgr-32">|</span>x<span class="sgr-32">|</span> <span class="sgr-32">echo</span> <span class="sgr-1">(</span><span class="sgr-32">exact-num</span> <span class="sgr-35">$x</span><span class="sgr-1">[</span>number<span class="sgr-1">])</span>: <span class="sgr-35">$x</span><span class="sgr-1">[</span>title<span class="sgr-1">]</span> <span class="sgr-1">}</span> <span class="sgr-32">|</span>
+     <span class="sgr-32">head</span> -n 10
+1593: A mechanism to trap "interrupts" would be useful
+1592: Should `make style` implicitly run the `codespell` t
+arget?
+1591: Add a &amp;benchmark option to the time command
+1590: Correct the documentation for the `try` command
+1588: Support comparing booleans
+1587: vi append command binding
+1586: Add a `&amp;benchmark` option to the `time` command
+1585: boolean values are not comparable
+1584: Documentation fixups
+1583: Implement a `help` command

+ 2 - 2
website/index.toml

@@ -7,8 +7,8 @@ rootURL = "https://elv.sh"
 
 [index]
 name = "home"
-extraCSS = ["home.css"]
-extraJS = ["home.js"]
+extraCSS = ["home/home.css"]
+extraJS = ["home/home.js"]
 
 [[categories]]
 name = "get"

+ 2 - 2
website/learn/fundamentals.md

@@ -132,7 +132,7 @@ The command is short, but still, it can become a chore if you want to run it
 repeatedly. Fortunately, Elvish remembers all the commands you have typed; you
 can just ask Elvish to recall it by pressing <kbd>Up</kbd>:
 
-@ttyshot fundamentals/history-1
+@ttyshot learn/fundamentals/history-1
 
 This will give you the last command you have run. However, it may have been a
 while when you have last run the `randint` command, and this will not give you
@@ -140,7 +140,7 @@ what you need. You can either continue pressing <kbd>Up</kbd> until you find the
 command, or you can give Elvish a hint by typing some characters from the
 command line you want, e.g. `ra`, before pressing <kbd>Up</kbd>:
 
-@ttyshot fundamentals/history-2
+@ttyshot learn/fundamentals/history-2
 
 Another way to rerun commands is saving them in a **script**, which is simply a
 text file containing the commands you want to run. Using your favorite text

+ 3 - 0
website/learn/fundamentals/history-1.ttyshot

@@ -0,0 +1,3 @@
+randint 1 7
+#prompt
+#send-keys Up

+ 4 - 0
website/learn/fundamentals/history-1.ttyshot.html

@@ -0,0 +1,4 @@
+~&gt; <span class="sgr-32">randint</span> 1 7
+▶ (num 6)
+~&gt; <span class="sgr-4 sgr-32">randint</span><span class="sgr-4"> 1 7</span>                                    <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> HISTORY #33 </span>

+ 5 - 0
website/learn/fundamentals/history-2.ttyshot

@@ -0,0 +1,5 @@
+randint 1 7
+#prompt
+# more commands ...
+#prompt
+#send-keys ra Up

+ 5 - 0
website/learn/fundamentals/history-2.ttyshot.html

@@ -0,0 +1,5 @@
+~&gt; <span class="sgr-32">randint</span> 1 7
+▶ (num 4)
+~&gt; <span class="sgr-36"># more commands ...</span>
+~&gt; <span class="sgr-32">ra</span><span class="sgr-4 sgr-32">ndint</span><span class="sgr-4"> 1 7</span>                                    <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> HISTORY #33 </span>

+ 18 - 23
website/learn/tour.md

@@ -855,7 +855,7 @@ UI customization options.
 Press <kbd>Tab</kbd> to start completion. For example, after typing `vim` and
 <kbd>Space</kbd>, press <kbd>Tab</kbd> to complete filenames:
 
-@ttyshot tour/completion
+@ttyshot learn/tour/completion
 
 Basic operations should be quite intuitive:
 
@@ -873,7 +873,7 @@ You may have noticed that the cursor has moved to the right of "COMPLETING
 argument". This indicates that you can continue typing to filter candidates. For
 example, after typing `.md`, the UI looks like this:
 
-@ttyshot tour/completion-filter
+@ttyshot learn/tour/completion-filter
 
 Read the reference on [completion API](../ref/edit.html#completion-api) to learn
 how to program and customize tab completion.
@@ -887,7 +887,7 @@ Elvish has several UI features for working with command history.
 Press <kbd>▲</kbd> to fetch the last command. This is called **history walking**
 mode:
 
-@ttyshot tour/history-walk
+@ttyshot learn/tour/history-walk
 
 Press <kbd>▲</kbd> to go further back, <kbd>▼</kbd> to go forward, or
 <kbd>Escape</kbd> to cancel.
@@ -896,13 +896,13 @@ To restrict to commands that start with a prefix, simply type the prefix before
 pressing <kbd>▲</kbd>. For example, to walk through commands starting with
 `echo`, type `echo` before pressing <kbd>▲</kbd>:
 
-@ttyshot tour/history-walk-prefix
+@ttyshot learn/tour/history-walk-prefix
 
 ### History listing
 
 Press <kbd>Ctrl-R</kbd> to list the full command history:
 
-@ttyshot tour/history-list
+@ttyshot learn/tour/history-list
 
 Like in completion mode, type to filter the list, press <kbd>▲</kbd> and
 <kbd>▼</kbd> to navigate the list, <kbd>Enter</kbd> to insert the selected
@@ -913,7 +913,7 @@ entry, or <kbd>Escape</kbd> to cancel.
 Finally, Elvish has a **last command** mode dedicated to inserting parts of the
 last command. Press <kbd>Alt-,</kbd> to trigger it:
 
-@ttyshot tour/lastcmd
+@ttyshot learn/tour/lastcmd
 
 ## Directory history
 
@@ -922,18 +922,17 @@ list visited directories. Use <kbd>▲</kbd> and <kbd>▼</kbd> to navigate the
 list, <kbd>Enter</kbd> to change to that directory, or <kbd>Escape</kbd> to
 cancel.
 
-@ttyshot tour/location
+@ttyshot learn/tour/location
 
 Type to filter:
 
-@ttyshot tour/location-filter
+@ttyshot learn/tour/location-filter
 
 ## Navigation mode
 
-Press <kbd>Ctrl-N</kbd> to start the builtin filesystem navigator, or
-**navigation mode**.
+Press <kbd>Ctrl-N</kbd> to start the builtin filesystem navigator.
 
-@ttyshot tour/navigation
+@ttyshot learn/tour/navigation
 
 Unlike other modes, the cursor stays in the main buffer in navigation mode. This
 allows you to continue typing commands; while doing that, you can press
@@ -961,20 +960,16 @@ will be called. Otherwise this definition will result in infinite recursion.
 ### Prompt customization
 
 The left and right prompts can be customized by assigning functions to
-`edit:prompt` and `edit:rprompt`. The following configuration simulates the
-default prompts, but uses fancy Unicode:
+[`edit:prompt`](../ref/edit.html#edit:prompt) and
+[`edit:rprompt`](../ref/edit.html#edit:rprompt). The following example defines
+prompts similar to the default, but uses fancy Unicode.
 
-```elvish
-# "tilde-abbr" abbreviates home directory to a tilde.
-set edit:prompt = { tilde-abbr $pwd; put '❱ ' }
-# "constantly" returns a function that always writes the same value(s) to
-# output; "styled" writes styled output.
-set edit:rprompt = (constantly (styled (whoami)✸(hostname) inverse))
-```
-
-This is how it looks:
+@ttyshot learn/tour/unicode-prompts
 
-@ttyshot tour/unicode-prompts
+The [`tilde-abbr`](../ref/builtin.html#tilde-abbr) command abbreviates home
+directory to a tilde. The [`constantly`](../ref/builtin.html#constantly) command
+returns a function that always writes the same value(s) to the value output. The
+[`styled`](../ref/builtin.html#styled) command writes styled output.
 
 ### Changing PATH
 

+ 3 - 0
website/learn/tour/completion-filter.ttyshot

@@ -0,0 +1,3 @@
+cd elvish
+#prompt
+#send-keys echo Space Tab .md

+ 5 - 0
website/learn/tour/completion-filter.ttyshot.html

@@ -0,0 +1,5 @@
+~&gt; <span class="sgr-32">cd</span> elvish
+~/elvish&gt; <span class="sgr-32">echo</span> <span class="sgr-4">1.0-release.md </span>                    <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> COMPLETING argument </span> .md
+<span class="sgr-7fg sgr-7bg">1.0-release.md </span>  PACKAGING.md  SECURITY.md
+CONTRIBUTING.md  README.md

+ 3 - 0
website/learn/tour/completion.ttyshot

@@ -0,0 +1,3 @@
+cd elvish
+#prompt
+#send-keys echo Space Tab

+ 9 - 0
website/learn/tour/completion.ttyshot.html

@@ -0,0 +1,9 @@
+~&gt; <span class="sgr-32">cd</span> elvish
+~/elvish&gt; <span class="sgr-32">echo</span> <span class="sgr-4">1.0-release.md </span>                    <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> COMPLETING argument </span>
+<span class="sgr-7fg sgr-7bg">1.0-release.md </span>  README.md    <span class="sgr-1 sgr-34">syntaxes/</span>
+CONTRIBUTING.md  SECURITY.md  <span class="sgr-1 sgr-34">tools/   </span>
+Dockerfile       <span class="sgr-1 sgr-34">cmd/       </span>  <span class="sgr-1 sgr-34">vscode/  </span>
+LICENSE          go.mod       <span class="sgr-1 sgr-34">website/ </span>
+Makefile         go.sum
+PACKAGING.md     <span class="sgr-1 sgr-34">pkg/       </span>

+ 1 - 0
website/learn/tour/history-list.ttyshot

@@ -0,0 +1 @@
+#send-keys C-R

+ 15 - 0
website/learn/tour/history-list.ttyshot.html

@@ -0,0 +1,15 @@
+~&gt;                                                <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> HISTORY (dedup on) </span>
+   3 echo "hello\nbye" &gt; /tmp/x                          <span class="sgr-35">│</span>
+   4 from-lines &lt; /tmp/x                                 <span class="sgr-35">│</span>
+   5 cd /tmp                                             <span class="sgr-7fg sgr-45"> </span>
+   6 cd ~/elvish                                         <span class="sgr-7fg sgr-45"> </span>
+   7 git branch                                          <span class="sgr-7fg sgr-45"> </span>
+   8 git checkout .                                      <span class="sgr-7fg sgr-45"> </span>
+   9 git commit                                          <span class="sgr-7fg sgr-45"> </span>
+  19 git status                                          <span class="sgr-7fg sgr-45"> </span>
+  20 cd /usr/local/bin                                   <span class="sgr-7fg sgr-45"> </span>
+  21 echo $pwd                                           <span class="sgr-7fg sgr-45"> </span>
+  22 * (+ 3 4) (- 100 94)                                <span class="sgr-7fg sgr-45"> </span>
+  31 make                                                <span class="sgr-7fg sgr-45"> </span>
+<span class="sgr-7fg sgr-7bg">  32 math:min 3 1 30                                     </span><span class="sgr-7fg sgr-45"> </span>

+ 1 - 0
website/learn/tour/history-walk-prefix.ttyshot

@@ -0,0 +1 @@
+#send-keys echo Up Up Up

+ 2 - 0
website/learn/tour/history-walk-prefix.ttyshot.html

@@ -0,0 +1,2 @@
+~&gt; <span class="sgr-32">echo</span><span class="sgr-4"> </span><span class="sgr-1 sgr-4">(</span><span class="sgr-4 sgr-32">styled</span><span class="sgr-4"> warning: red</span><span class="sgr-1 sgr-4">)</span><span class="sgr-4"> bumpy road</span>          <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> HISTORY #2 </span>

+ 1 - 0
website/learn/tour/history-walk.ttyshot

@@ -0,0 +1 @@
+#send-keys Up

+ 2 - 0
website/learn/tour/history-walk.ttyshot.html

@@ -0,0 +1,2 @@
+~&gt; <span class="sgr-4 sgr-31">math:min</span><span class="sgr-4"> 3 1 30</span>                                <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> HISTORY #32 </span>

+ 3 - 0
website/learn/tour/lastcmd.ttyshot

@@ -0,0 +1,3 @@
+echo abc def
+#prompt
+#send-keys vim Space M-,

+ 8 - 0
website/learn/tour/lastcmd.ttyshot.html

@@ -0,0 +1,8 @@
+~&gt; <span class="sgr-32">echo</span> abc def
+abc def
+~&gt; <span class="sgr-32">vim</span>                                            <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> LASTCMD </span>
+<span class="sgr-7fg sgr-7bg">    echo abc def                                          </span>
+  0 echo
+  1 abc
+  2 def

+ 1 - 0
website/learn/tour/location-filter.ttyshot

@@ -0,0 +1 @@
+#send-keys C-L local

+ 6 - 0
website/learn/tour/location-filter.ttyshot.html

@@ -0,0 +1,6 @@
+~&gt;                                                <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> LOCATION </span> local
+<span class="sgr-7fg sgr-7bg"> 10 ~/.local/share/elvish                                 </span>
+  9 /usr/local
+  9 /usr/local/share
+  9 /usr/local/bin

+ 1 - 0
website/learn/tour/location.ttyshot

@@ -0,0 +1 @@
+#send-keys C-L

+ 15 - 0
website/learn/tour/location.ttyshot.html

@@ -0,0 +1,15 @@
+~&gt;                                                <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> LOCATION </span>
+<span class="sgr-7fg sgr-7bg"> 10 ~/elvish                                             </span><span class="sgr-7fg sgr-45"> </span>
+ 10 ~/.local/share/elvish                                <span class="sgr-7fg sgr-45"> </span>
+ 10 ~/elvish/website                                     <span class="sgr-7fg sgr-45"> </span>
+ 10 ~/.config/elvish                                     <span class="sgr-7fg sgr-45"> </span>
+  9 ~/elvish/pkg/edit                                    <span class="sgr-7fg sgr-45"> </span>
+  9 ~/elvish/pkg/eval                                    <span class="sgr-7fg sgr-45"> </span>
+  9 /opt                                                 <span class="sgr-7fg sgr-45"> </span>
+  9 /usr/local                                           <span class="sgr-7fg sgr-45"> </span>
+  9 /usr/local/share                                     <span class="sgr-7fg sgr-45"> </span>
+  9 /usr/local/bin                                       <span class="sgr-7fg sgr-45"> </span>
+  9 /usr                                                 <span class="sgr-7fg sgr-45"> </span>
+  9 /tmp                                                 <span class="sgr-35">│</span>
+  8 ~/zsh                                                <span class="sgr-35">│</span>

+ 3 - 0
website/learn/tour/navigation.ttyshot

@@ -0,0 +1,3 @@
+cd elvish; echo '[CUT]'
+#prompt
+#send-keys C-N

+ 15 - 0
website/learn/tour/navigation.ttyshot.html

@@ -0,0 +1,15 @@
+~/elvish&gt;                                         <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> NAVIGATING </span>
+<span class="sgr-1 sgr-34"> bash   </span> <span class="sgr-7fg sgr-7bg"> 1.0-release.md  </span><span class="sgr-7fg sgr-45"> </span> 1.0 has not been released yet.
+<span class="sgr-7fg sgr-1 sgr-44"> elvish </span>  CONTRIBUTING.md <span class="sgr-7fg sgr-45"> </span>
+<span class="sgr-1 sgr-34"> zsh    </span>  Dockerfile      <span class="sgr-7fg sgr-45"> </span>
+          LICENSE         <span class="sgr-7fg sgr-45"> </span>
+          Makefile        <span class="sgr-7fg sgr-45"> </span>
+          PACKAGING.md    <span class="sgr-7fg sgr-45"> </span>
+          README.md       <span class="sgr-7fg sgr-45"> </span>
+          SECURITY.md     <span class="sgr-7fg sgr-45"> </span>
+         <span class="sgr-1 sgr-34"> cmd             </span><span class="sgr-7fg sgr-45"> </span>
+          go.mod          <span class="sgr-7fg sgr-45"> </span>
+          go.sum          <span class="sgr-7fg sgr-45"> </span>
+         <span class="sgr-1 sgr-34"> pkg             </span><span class="sgr-35">│</span>
+         <span class="sgr-1 sgr-34"> syntaxes        </span><span class="sgr-35">│</span>

+ 9 - 0
website/learn/tour/unicode-prompts.ttyshot

@@ -0,0 +1,9 @@
+set edit:rprompt = (constantly ^
+  (styled (whoami)✸(hostname) inverse))
+#prompt
+set edit:prompt = {
+  tilde-abbr $pwd
+  styled '❱ ' bright-red
+}
+#prompt
+#send-keys # Space Fancy Space unicode Space prompts!

+ 7 - 0
website/learn/tour/unicode-prompts.ttyshot.html

@@ -0,0 +1,7 @@
+~&gt; <span class="sgr-32">set</span> <span class="sgr-35">edit:rprompt</span> <span class="sgr-33">=</span> <span class="sgr-1">(</span><span class="sgr-32">constantly</span> ^
+     <span class="sgr-1">(</span><span class="sgr-32">styled</span> <span class="sgr-1">(</span><span class="sgr-32">whoami</span><span class="sgr-1">)</span>✸<span class="sgr-1">(</span><span class="sgr-32">hostname</span><span class="sgr-1">)</span> inverse<span class="sgr-1">))</span>
+~&gt; <span class="sgr-32">set</span> <span class="sgr-35">edit:prompt</span> <span class="sgr-33">=</span> <span class="sgr-1">{</span>
+     <span class="sgr-32">tilde-abbr</span> <span class="sgr-35">$pwd</span>
+     <span class="sgr-32">styled</span> <span class="sgr-33">'❱ '</span> bright-red
+   <span class="sgr-1">}</span>
+~<span class="sgr-91">❱ </span><span class="sgr-36"># Fancy unicode prompts!</span>           <span class="sgr-7fg sgr-7bg">elf✸host.example.com</span>

+ 1 - 1
website/ref/edit.md

@@ -19,7 +19,7 @@ same time. Each mode has its own UI and keybindings. For instance, the default
 (triggered by <kbd>Tab</kbd> by default) shows you all candidates for
 completion, and you can use arrow keys to navigate those candidates.
 
-@ttyshot completion-mode
+@ttyshot ref/edit/completion-mode
 
 Each mode has its own submodule under `edit:`. For instance, builtin functions
 and configuration variables for the completion mode can be found in the

+ 3 - 0
website/ref/edit/completion-mode.ttyshot

@@ -0,0 +1,3 @@
+cd elvish
+#prompt
+#send-keys vim Space Tab

+ 9 - 0
website/ref/edit/completion-mode.ttyshot.html

@@ -0,0 +1,9 @@
+~&gt; <span class="sgr-32">cd</span> elvish
+~/elvish&gt; <span class="sgr-32">vim</span> <span class="sgr-4">1.0-release.md </span>                     <span class="sgr-7fg sgr-7bg">elf@host</span>
+<span class="sgr-1 sgr-37 sgr-45"> COMPLETING argument </span>
+<span class="sgr-7fg sgr-7bg">1.0-release.md </span>  README.md    <span class="sgr-1 sgr-34">syntaxes/</span>
+CONTRIBUTING.md  SECURITY.md  <span class="sgr-1 sgr-34">tools/   </span>
+Dockerfile       <span class="sgr-1 sgr-34">cmd/       </span>  <span class="sgr-1 sgr-34">vscode/  </span>
+LICENSE          go.mod       <span class="sgr-1 sgr-34">website/ </span>
+Makefile         go.sum
+PACKAGING.md     <span class="sgr-1 sgr-34">pkg/       </span>

+ 66 - 47
website/style.css

@@ -346,61 +346,78 @@ pre.ttyshot, pre.ttyshot code {
     }
 }
 
-/* SGR classes, used in ttyshots. */
+/* SGR classes used in ttyshots. */
 .sgr-1 {
-    font-weight: bold;
+    /*
+     * Bold text is wider than regular text in most fonts, and can break
+     * vertical alignment in ttyshots. Emulate bold font with text-shadow.
+     */
+    text-shadow: 0.05em 0 0;
 }
 .sgr-4 {
     text-decoration: underline;
 }
-.sgr-7 {
+/*
+ * SGR 7 (inverse) has some special handling by the ttyshot program; see
+ * comments there.
+ */
+.sgr-7fg {
     color: white;
-    background-color: black;
-}
-.sgr-31 {
-    color: darkred; /* red in tty */
-}
-.sgr-41 {
-    background-color: darkred; /* red in tty */
-}
-.sgr-32 {
-    color: green; /* green in tty */
-}
-.sgr-42, .sgr-7.sgr-32 {
-    background-color: green; /* green in tty */
-}
-.sgr-33 {
-    color: goldenrod; /* yellow in tty */
-}
-.sgr-43, .sgr-7.sgr-33 {
-    background-color: goldenrod; /* yellow in tty */
-}
-.sgr-34 {
-    color: blue;
 }
-.sgr-44, .sgr-7.sgr-34 {
-    color: white; /* Hacky hacky, just to make the nav ttyshot work */
-    background-color: blue;
-}
-.sgr-35 {
-    color: darkorchid; /* magenta in tty */
-}
-.sgr-45, .sgr-7.sgr-35 {
-    background-color: darkorchid; /* magenta in tty */
-}
-.sgr-36 {
-    color: darkcyan; /* cyan in tty */
-}
-.sgr-46, .sgr-7.sgr-36 {
-    background-color: darkcyan; /* cyan in tty */
-}
-.sgr-37 {
-    color: lightgray;
-}
-.sgr-47, .sgr-7.sgr-37 {
-    background-color: gray;
+.sgr-7bg {
+    background-color: black;
 }
 
+/* black */
+.sgr-30 { color: black; }
+.sgr-40 { background-color: black; }
+/* red */
+.sgr-31 { color: maroon; }
+.sgr-41 { background-color: maroon; }
+/* green */
+.sgr-32 { color: green; }
+.sgr-42 { background-color: green; }
+/* yellow */
+.sgr-33 { color: goldenrod; }
+.sgr-43 { background-color: goldrenrod; }
+/* blue */
+.sgr-34 { color: navy; }
+.sgr-44 { background-color: navy; }
+/* magenta */
+.sgr-35 { color: darkorchid; }
+.sgr-45 { background-color: darkorchid; }
+/* cyan */
+.sgr-36 { color: darkcyan; }
+.sgr-46 { background-color: darkcyan; }
+/* white */
+.sgr-37 { color: lightgrey; }
+.sgr-47 { background-color: lightgrey; }
+
+/* bright black */
+.sgr-90 { color: grey; }
+.sgr-100 { background-color: grey; }
+/* bright red */
+.sgr-91 { color: red; }
+.sgr-101 { background-color: red; }
+/* bright green */
+.sgr-92 { color: lime; }
+.sgr-102 { background-color: lime; }
+/* light yellow */
+.sgr-93 { color: yellow; }
+.sgr-103 { background-color: yellow; }
+/* light blue */
+.sgr-94 { color: blue; }
+.sgr-104 { background-color: blue; }
+/* bright magenta */
+.sgr-95 { color: fuchsia; }
+.sgr-105 { background-color: fuchsia; }
+/* bright cyan */
+.sgr-96 { color: aqua; }
+.sgr-106 { background-color: aqua; }
+/* bright white */
+.sgr-97 { color: white; }
+.sgr-107 { background-color: white; }
+
 /** Header anchors. */
 .anchor {
     opacity: 0;
@@ -459,8 +476,10 @@ pre.ttyshot, pre.ttyshot code {
 .dark pre.ttyshot, .dark pre.ttyshot code {
     background: black;
 }
-.dark .sgr-7 {
+.dark .sgr-7fg {
     color: black;
+}
+.dark .sgr-7bg {
     background-color: #eee;
 }
 

+ 1 - 1
website/tools/extra-deps

@@ -12,4 +12,4 @@ cat ${1%.html}.md |
   done
 
 cat ${1%.html}.md |
-  awk '$1 == "@ttyshot" { print "ttyshot/" $2 ".html" }'
+  awk '$1 == "@ttyshot" { print $2 ".ttyshot.html" }'

+ 0 - 27
website/ttyshot/README.md

@@ -1,27 +0,0 @@
-This directory contains "ttyshots" -- they are like screenshots, but taken on
-terminals. They are taken with Elvish's `edit:-dump-buf` function. To take one,
-use the following procedure:
-
-1.  Modify `edit:rprompt` to pretend that the username is `elf` and the hostname
-    is `host`:
-
-    ```elvish
-    set edit:rprompt = (constantly (styled 'elf@host' inverse))
-    ```
-
-2.  Add a keybinding for taking ttyshots:
-
-    ```elvish
-    var header = '<!-- Follow website/ttyshot/README.md to regenerate -->'
-    edit:global-binding[Alt-x] = { print $header(edit:-dump-buf) > ~/ttyshot.html }
-    ```
-
-3.  Make sure that the terminal width is 58, to be consistent with existing
-    ttyshots.
-
-4.  Put Elvish in the state you want, and press Alt-X. The ttyshot is saved at
-    `~/ttyshot.html`.
-
-Some of the ttyshots also show the output of commands. Since `edit:-dump-buf`
-only captures the Elvish UI, you need to manually append the command output when
-updating such ttyshots.

+ 0 - 5
website/ttyshot/completion-mode.html

@@ -1,5 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/go/src/github.com/elves/elvish&gt; <span class="sgr-32">vim</span> <span class="sgr-4">CONTRIBUTING.md </span>
-<span class="sgr-1 sgr-37 sgr-45"> COMPLETING argument </span> 
-<span class="sgr-7">CONTRIBUTING.md</span>  LICENSE   NEXT-RELEASE.md  <span class="sgr-1 sgr-34">cmd/  </span>  go.su
-Dockerfile       Makefile  README.md        go.mod  main.
-<span class="sgr-7 sgr-35">                                            </span><span class="sgr-35">━━━━━━━━━━━━━</span>

+ 0 - 15
website/ttyshot/control-structures.html

@@ -1,15 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~&gt; <span class="sgr-32">if</span><span class="sgr-"> </span><span class="sgr-35">$true</span><span class="sgr-"> </span><span class="sgr-1">{</span><span class="sgr-"> </span><span class="sgr-32">echo</span><span class="sgr-"> good </span><span class="sgr-1">}</span><span class="sgr-"> </span><span class="sgr-33">else</span><span class="sgr-"> </span><span class="sgr-1">{</span><span class="sgr-"> </span><span class="sgr-32">echo</span><span class="sgr-"> bad </span><span class="sgr-1">}</span>               
-good
-~&gt; <span class="sgr-32">for</span><span class="sgr-"> </span><span class="sgr-35">x</span><span class="sgr-"> </span><span class="sgr-1">[</span><span class="sgr-">lorem ipsum</span><span class="sgr-1">]</span><span class="sgr-"> </span><span class="sgr-1">{</span>
-     <span class="sgr-32">echo</span><span class="sgr-"> </span><span class="sgr-35">$x</span><span class="sgr-">.pdf</span>
-   <span class="sgr-1">}</span>
-lorem.pdf
-ipsum.pdf
-~&gt; <span class="sgr-32">try</span><span class="sgr-"> </span><span class="sgr-1">{</span>
-     <span class="sgr-32">fail</span><span class="sgr-"> </span><span class="sgr-33">&#39;bad error&#39;</span>
-   <span class="sgr-1">}</span><span class="sgr-"> </span><span class="sgr-33">except</span><span class="sgr-"> </span><span class="sgr-35">e</span><span class="sgr-"> </span><span class="sgr-1">{</span>
-     <span class="sgr-32">echo</span><span class="sgr-"> error </span><span class="sgr-35">$e</span>
-   <span class="sgr-1">}</span><span class="sgr-"> </span><span class="sgr-33">else</span><span class="sgr-"> </span><span class="sgr-1">{</span>
-     <span class="sgr-32">echo</span><span class="sgr-"> ok</span>
-   <span class="sgr-1">}</span>
-error ?(fail 'bad error')

+ 0 - 2
website/ttyshot/fundamentals/history-1.html

@@ -1,2 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~&gt; <span class="sgr-4">randint 1 7</span><span class="sgr-">                                    </span><span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> HISTORY #59321 </span><span class="sgr-"> </span>

+ 0 - 2
website/ttyshot/fundamentals/history-2.html

@@ -1,2 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~&gt; <span class="sgr-31">ra</span><span class="sgr-4">ndint 1 7</span><span class="sgr-">                                    </span><span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> HISTORY #59321 </span><span class="sgr-"> </span>

+ 0 - 15
website/ttyshot/histlist-mode.html

@@ -1,15 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~&gt;                                           <span class="sgr-7">xiaq@xiaqsmbp</span>
-<span class="sgr-1 sgr-37 sgr-45"> HISTORY </span><span class="sgr-"> </span>
-13345 make tools/ttyshot                                 <span class="sgr-35">│</span>
-13346 make                                               <span class="sgr-35">│</span>
-13347 ./assets/                                          <span class="sgr-35">│</span>
-13348 ls                                                 <span class="sgr-35">│</span>
-13349 ls                                                 <span class="sgr-35">│</span>
-13350 rm *.png                                           <span class="sgr-35">│</span>
-<span class="sgr-7">13351 git st                                             </span><span class="sgr-35">│</span>
-13352 ..                                                 <span class="sgr-35">│</span>
-13353 git st                                             <span class="sgr-35">│</span>
-13354 git add .                                          <span class="sgr-35">│</span>
-13355 git st                                             <span class="sgr-35">│</span>
-13356 git commit                                         <span class="sgr-35">│</span>
-13357 git push                                           <span class="sgr-35">│</span>

+ 0 - 15
website/ttyshot/location-mode.html

@@ -1,15 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~&gt;                                           <span class="sgr-7">xiaq@xiaqsmbp</span>
-<span class="sgr-1 sgr-37 sgr-45"> LOCATION </span><span class="sgr-"> </span>
-<span class="sgr-7">  * ~                                                    </span><span class="sgr-35 sgr-7"> </span>
-  * ~/go/src/github.com/elves/elvish                     <span class="sgr-35">│</span>
-110 ~/on/elvish-site/code                                <span class="sgr-35">│</span>
- 62 ~/on/elvish-site/code/src                            <span class="sgr-35">│</span>
- 52 ~/go/src/github.com/elves/elvish/edit                <span class="sgr-35">│</span>
- 34 ~/on/elvish-site/code/tty                            <span class="sgr-35">│</span>
- 33 ~/on/elvish-site/code/assets                         <span class="sgr-35">│</span>
- 32 ~/go/src/github.com/elves/elvish/eval                <span class="sgr-35">│</span>
- 26 ~/on/chat-app/code                                   <span class="sgr-35">│</span>
- 24 ~/on/elvish-site/code/dst                            <span class="sgr-35">│</span>
- 20 ~/go/src/github.com/elves/md-highlighter             <span class="sgr-35">│</span>
- 14 ~/on/chat-app/code/public                            <span class="sgr-35">│</span>
- 13 ~/.elvish                                            <span class="sgr-35">│</span>

+ 0 - 15
website/ttyshot/navigation-mode.html

@@ -1,15 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/go/src/github.com/elves/elvish&gt;            <span class="sgr-7">xiaq@xiaqsmbp</span>
-<span class="sgr-1 sgr-37 sgr-45"> NAVIGATING </span><span class="sgr-"> </span>
-<span class="sgr-01 sgr-34 sgr-7"> elvish         </span><span class="sgr-">  CONTRIBUTING.md </span><span class="sgr-35 sgr-7"> </span><span class="sgr-">  FROM golang:onbuild </span>
-<span class="sgr-01 sgr-34"> fix-for-0.7    </span><span class="sgr-"> </span><span class="sgr- sgr-7"> Dockerfile      </span><span class="sgr-35 sgr-7"> </span><span class="sgr-">                      </span>
-<span class="sgr-01 sgr-34"> images         </span><span class="sgr-">  Gopkg.lock      </span><span class="sgr-35 sgr-7"> </span>
-<span class="sgr-01 sgr-34"> md-highlighter </span><span class="sgr-">  Gopkg.toml      </span><span class="sgr-35 sgr-7"> </span>
-                  LICENSE         <span class="sgr-35 sgr-7"> </span>
-                  Makefile        <span class="sgr-35 sgr-7"> </span>
-                  README.md       <span class="sgr-35 sgr-7"> </span>
-                 <span class="sgr-01 sgr-34"> cover           </span><span class="sgr-35">│</span>
-                 <span class="sgr-01 sgr-34"> daemon          </span><span class="sgr-35">│</span>
-                 <span class="sgr-01 sgr-34"> edit            </span><span class="sgr-35">│</span>
-                 <span class="sgr-01 sgr-34"> errors          </span><span class="sgr-35">│</span>
-                 <span class="sgr-01 sgr-34"> eval            </span><span class="sgr-35">│</span>
-                 <span class="sgr-01 sgr-34"> getopt          </span><span class="sgr-35">│</span>

+ 0 - 14
website/ttyshot/pipelines.html

@@ -1,14 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~&gt; <span class="sgr-32">curl</span> https://api.github.com/repos/elves/elvish/issues <span class="sgr-32">|</span>
-     <span class="sgr-32">from-json</span> <span class="sgr-32">|</span> <span class="sgr-32">all</span> <span class="sgr-1">(</span><span class="sgr-32">one</span><span class="sgr-1">)</span> <span class="sgr-32">|</span>
-     <span class="sgr-32">each</span> <span class="sgr-1">{</span><span class="sgr-32">|</span>x<span class="sgr-32">|</span> <span class="sgr-32">echo</span> <span class="sgr-1">(</span><span class="sgr-32">exact-num</span> <span class="sgr-35">$x</span><span class="sgr-1">[</span>number<span class="sgr-1">])</span>: <span class="sgr-35">$x</span><span class="sgr-1">[</span>title<span class="sgr-1">]</span> <span class="sgr-1">}</span> <span class="sgr-32">|</span>
-     <span class="sgr-32">head</span> -n 7
-1465: Pipelines.html still using legacy syntax.
-1464: Ability to change the initial filter for completion
-1463: No filtering when constructing the candidate list du
-ring completion
-1462: Add language.html and command.html to docset search
-index
-1460: Symbols Clobbered by Elvish?
-1453: Add a `&uniq` option to the `builtin:order` command
-and a `builtin:uniq` command
-1449: Hard crash with an Alias module alias with closure

+ 0 - 5
website/ttyshot/tour/completion-filter.html

@@ -1,5 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt; <span class="sgr-32">vim</span> <span class="sgr-4">0.18.0-release-notes.md </span>         <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> COMPLETING argument </span> .md
-<span class="sgr-7">0.18.0-release-notes.md</span>  README.md  
-CONTRIBUTING.md          SECURITY.md
-PACKAGING.md           

+ 0 - 6
website/ttyshot/tour/completion.html

@@ -1,6 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt; <span class="sgr-32">vim</span> <span class="sgr-4">0.18.0-release-notes.md </span>         <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> COMPLETING argument </span> 
-<span class="sgr-7">0.18.0-release-notes.md</span>  Makefile      <span class="sgr-1 sgr-34">cmd/  </span>  <span class="sgr-1 sgr-34">pkg/    </span>
-CONTRIBUTING.md          PACKAGING.md  cover   <span class="sgr-1 sgr-34">tools/  </span>
-Dockerfile               README.md     go.mod  <span class="sgr-1 sgr-34">website/</span>
-LICENSE                  SECURITY.md   go.sum

+ 0 - 7
website/ttyshot/tour/history-list.html

@@ -1,7 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt;                                      <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> HISTORY (dedup on) </span> 
-20286 demo                                               <span class="sgr-35">│</span>
-20288 cd ~                                               <span class="sgr-35">│</span>
-20289 ls                                                 <span class="sgr-35">│</span>
-20290 echo foo bar                                       <span class="sgr-35">│</span>
-<span class="sgr-7">20291 vim README.md                                      </span><span class="sgr-7 sgr-35"> </span>

+ 0 - 2
website/ttyshot/tour/history-walk-prefix.html

@@ -1,2 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt; <span class="sgr-32">echo</span> <span class="sgr-4">foo bar</span>                         <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> HISTORY #20279 </span>

+ 0 - 2
website/ttyshot/tour/history-walk.html

@@ -1,2 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt; <span class="sgr-4 sgr-32">vim</span><span class="sgr-4"> README.md </span>                       <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> HISTORY #20280 </span>

+ 0 - 5
website/ttyshot/tour/lastcmd.html

@@ -1,5 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt;                                      <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> LASTCMD </span> 
-<span class="sgr-7">    vim README.md                                         </span>
-  0 vim
-  1 README.md

+ 0 - 7
website/ttyshot/tour/location-filter.html

@@ -1,7 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt;                                      <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> LOCATION </span> ev
-<span class="sgr-7"> 52 ~/on/elvish/pkg/eval                                 </span><span class="sgr-7 sgr-35"> </span>
- 11 ~/on/elvish/pkg/eval/vals                            <span class="sgr-35">│</span>
-  2 ~/on/elvish/pkg/eval/errs                            <span class="sgr-35">│</span>
-  1 ~/on/elvish/pkg/eval/vars                            <span class="sgr-35">│</span>
-  0 ~/on/elvish/pkg/eval/evaltest                        <span class="sgr-35">│</span>

+ 0 - 7
website/ttyshot/tour/location.html

@@ -1,7 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt;                                      <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> LOCATION </span> 
-<span class="sgr-7">148 ~                                                    </span><span class="sgr-7 sgr-35"> </span>
- 52 ~/on/elvish/pkg/eval                                 <span class="sgr-35">│</span>
- 49 ~/on/elvish/pkg                                      <span class="sgr-35">│</span>
- 34 ~/.config/kak/plugins                                <span class="sgr-35">│</span>
- 27 ~/on/elvish/pkg/edit                                 <span class="sgr-35">│</span>

+ 0 - 7
website/ttyshot/tour/navigation.html

@@ -1,7 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~/on/elvish&gt;                                      <span class="sgr-7">elf@host</span>
-<span class="sgr-1 sgr-37 sgr-45"> NAVIGATING </span> 
-<span class="sgr-1 sgr-34"> cmdg </span><span class="sgr-35">│</span> <span class="sgr-7"> 0.18.0-release-not </span><span class="sgr-7 sgr-35"> </span> This is the draft release n<span class="sgr-7 sgr-35"> </span>
-<span class="sgr-1 sgr-34"> duan </span><span class="sgr-7 sgr-35"> </span>  CONTRIBUTING.md    <span class="sgr-7 sgr-35"> </span> 2022-03-01.                <span class="sgr-7 sgr-35"> </span>
-<span class="sgr-1 sgr-7 sgr-34"> elvi </span><span class="sgr-35">│</span>  Dockerfile         <span class="sgr-35">│</span>                            <span class="sgr-35">│</span>
-<span class="sgr-1 sgr-34"> elvi </span><span class="sgr-35">│</span>  LICENSE            <span class="sgr-35">│</span> # Notable bugfixes         <span class="sgr-35">│</span>
-<span class="sgr-1 sgr-34"> elvi </span><span class="sgr-35">│</span>  Makefile           <span class="sgr-35">│</span>                            <span class="sgr-35">│</span>

+ 0 - 1
website/ttyshot/tour/unicode-prompts.html

@@ -1 +0,0 @@
-<!-- Follow website/ttyshot/README.md to regenerate -->~❱ <span class="sgr-36"># Fancy unicode prompts!</span>                       <span class="sgr-7">elv✸host</span>