Repository: Textualize/textual
Pull request: Add Select.from_values class method for initializing with iterator
Added class method that can be used to create a Select control using an iterator.  Method takes the same inputs as the constructor and has been tested to work with and without specifying parameters.

Snapshot tests have been updated for this method, and all other tests passed.

Fixes #3691. 

**Please review the following checklist.**

- [x] Docstrings on all new or modified functions / classes 
- [x] Updated documentation
- [x] Updated CHANGELOG.md (where appropriate)


Problem statement:
Alternative method to initialise `Select`
I propose we extend `Select.__init__` or create a classmethod `Select.from_values` to accept an iterable of `SelectType` and automatically build the labels by converting them to strings.

I find that often we just want labels that are string representations of the values we want to select:

```py
Select.from_values(data_source)
# vs
Select([(str(datum), datum) for datum in data_source])
```

`data_source` is often just a list of strings or paths and the comprehension to create the tuple looks really awkward.

For example, in the `Select` docs we do this:

```py
# ...
yield Select((line, line) for line in LINES)
```

I personally don't like it at all.

Hints from issue discussion:
Can I work on this?

I have done a quick prototype solution following the class method approach you suggested.  Before I go forward with formalizing the prototype, I wanted to ask: is this preferrable to overloading the constructor?
Hey @azinneck0485 thanks for your interest!
I don't see any particular reason why you wouldn't be able to work on this. 🤷 

Let us just make sure that the class method is a good idea and then we'll let you know.
If you're working on this, make sure to read the [contributing guidelines](https://github.com/Textualize/textual/blob/main/CONTRIBUTING.md) for an experience as smooth as possible!
I think we should go ahead and add the classmethod. @azinneck0485 are you happy to contribute that?
Yes, I will contribute that change and get a PR in once I've tested it.
Excellent @azinneck0485!
I've assigned this to you. (I've also assigned it to me for bookkeeping purposes.)
Take your time and then make sure to ping me once your PR is in!
Hi @rodrigogiraoserrao -- I have made the code changes and done some testing on my own.  I have also updated the documentation by adding an example (which is just the existing example modified to use the new class method to create the select control).  All changes have been pushed to a branch on my fork.

However, I am not yet ready for a PR as I have run into some problems running `pytest`.  Although I have only added 3 tests (replicating the existing tests for Select()), 16 tests are failing in total.  13 of those failing tests are from `test_text_area_language_rendering` and `test_text_area_themes` and are due to missing syntax highlighting in the tests I have run.

I don't want to accidentally update snapshots erroneously, so I wanted to check and see if you had any tips on what I should look into to ensure these tests pass?
Hi @azinneck0485, thanks for the update!
If you're running Python 3.7, you won't be able to install the dependencies `tree-sitter` and `tree_sitter_languages`, which require Python 3.8 or greater.
If you're running Python 3.8 or greater, make sure you have the dependencies installed.

In my case, I'm running Python 3.7 and if I run `make test`, this is what the final output looks like:

![Screenshot 2023-11-23 at 11 01 48](https://github.com/Textualize/textual/assets/5621605/a70018e7-11d8-486d-8246-4d3e750c463d)

Notice how there's a red warning saying there are 13 unused snapshots, which makes it look like in the end the tests failed (see the Error 1 at the bottom).

However, at the same time, pytest reports that those tests were skipped.

In short, there's an issue with the snapshot tests reporting (which is a problem in the tool we use for the snapshots) and it's ok for those 13 snapshots to report that “error”.

In order to update _only_ the snapshot(s) you created, first make sure they look ok.
(I.e., run the test, open the snapshot report error, and make sure the snapshot looks like it is intended to look.)
Then, run the test again with the flag `--snapshot-update`, but _only_ on your tests.

For example, if you had a snapshot test called `test_azinneck_snap`, you could run `pytest -vv tests/snapshot_tests/test_snapshots.py::test_azinneck_snap --snapshot-update` and it would update only your snapshot.

Commit message: update changelog

Patch to review:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 57123114f3..2969bc4ff3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 - CSS error reporting will no longer provide links to the files in question https://github.com/Textualize/textual/pull/3582
 - inline CSS error reporting will report widget/class variable where the CSS was read from https://github.com/Textualize/textual/pull/3582
 
+### Added
+- Added `Select.from_values` class method that can be used to initialize a Select control with an iterator https://github.com/Textualize/textual/issues/3691
+
 ## [0.41.0] - 2023-10-31
 
 ### Fixed
@@ -43,7 +46,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 - Added HorizontalPad to pad.py https://github.com/Textualize/textual/pull/3571
 - Added `AwaitComplete` class, to be used for optionally awaitable return values https://github.com/Textualize/textual/pull/3498
 
-
 ### Changed
 
 - Breaking change: `Button.ACTIVE_EFFECT_DURATION` classvar converted to `Button.active_effect_duration` attribute https://github.com/Textualize/textual/pull/3498
diff --git a/docs/examples/widgets/select_from_values_widget.py b/docs/examples/widgets/select_from_values_widget.py
new file mode 100644
index 0000000000..23ba16acbc
--- /dev/null
+++ b/docs/examples/widgets/select_from_values_widget.py
@@ -0,0 +1,26 @@
+from textual import on
+from textual.app import App, ComposeResult
+from textual.widgets import Header, Select
+
+LINES = """I must not fear.
+Fear is the mind-killer.
+Fear is the little-death that brings total obliteration.
+I will face my fear.
+I will permit it to pass over me and through me.""".splitlines()
+
+
+class SelectApp(App):
+    CSS_PATH = "select.tcss"
+
+    def compose(self) -> ComposeResult:
+        yield Header()
+        yield Select.from_values(LINES)
+
+    @on(Select.Changed)
+    def select_changed(self, event: Select.Changed) -> None:
+        self.title = str(event.value)
+
+
+if __name__ == "__main__":
+    app = SelectApp()
+    app.run()
diff --git a/docs/widgets/select.md b/docs/widgets/select.md
index 6f9690cb24..d80f64849e 100644
--- a/docs/widgets/select.md
+++ b/docs/widgets/select.md
@@ -58,6 +58,32 @@ The following example presents a `Select` with a number of options.
     --8<-- "docs/examples/widgets/select.tcss"
     ```
 
+## Example
+
+The following example presents a `Select` created using the `from_values` class method.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/widgets/select_from_values_widget.py"}
+    ```
+
+=== "Output (expanded)"
+
+    ```{.textual path="docs/examples/widgets/select_from_values_widget.py" press="tab,enter,down,down"}
+    ```
+
+
+=== "select_from_values_widget.py"
+
+    ```python
+    --8<-- "docs/examples/widgets/select_from_values_widget.py"
+    ```
+
+=== "select.tcss"
+
+    ```sass
+    --8<-- "docs/examples/widgets/select.tcss"
+    ```
 
 ## Reactive Attributes
 
diff --git a/src/textual/widgets/_select.py b/src/textual/widgets/_select.py
index 508da0487d..1d4f01ab27 100644
--- a/src/textual/widgets/_select.py
+++ b/src/textual/widgets/_select.py
@@ -278,6 +278,44 @@ def __init__(
         self._value: SelectType | None = value
         self._options = options
 
+    @classmethod
+    def from_values(
+        cls,
+        opts: [SelectType],
+        *,
+        prompt: str = "Select",
+        allow_blank: bool = True,
+        value: SelectType | None = None,
+        name: str | None = None,
+        id: str | None = None,
+        classes: str | None = None,
+        disabled: bool = False,
+    ):
+        """Initialize the Select control with options specified by an iterator
+
+        Args:
+         options: Options to select from.
+         prompt: Text to show in the control when no option is select.
+         allow_blank: Allow the selection of a blank option.
+         value: Initial value (should be one of the values in `options`).
+         name: The name of the select control.
+         id: The ID of the control the DOM.
+         classes: The CSS classes of the control.
+         disabled: Whether the control is disabled or not.
+        """
+        opts_iterator = [(str(o), o) for o in opts]
+
+        return cls(
+            opts_iterator,
+            prompt=prompt,
+            allow_blank=allow_blank,
+            value=value,
+            name=name,
+            id=id,
+            classes=classes,
+            disabled=disabled,
+        )
+
     def set_options(self, options: Iterable[tuple[RenderableType, SelectType]]) -> None:
         """Set the options for the Select.
 
diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
index 65901f8f26..f5e3a44c21 100644
--- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
+++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
@@ -28243,6 +28243,490 @@
   
   '''
 # ---
+# name: test_select_from_values
+  '''
+  <svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
+      <!-- Generated with Rich https://www.textualize.io -->
+      <style>
+  
+      @font-face {
+          font-family: "Fira Code";
+          src: local("FiraCode-Regular"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
+          font-style: normal;
+          font-weight: 400;
+      }
+      @font-face {
+          font-family: "Fira Code";
+          src: local("FiraCode-Bold"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
+          font-style: bold;
+          font-weight: 700;
+      }
+  
+      .terminal-1161182100-matrix {
+          font-family: Fira Code, monospace;
+          font-size: 20px;
+          line-height: 24.4px;
+          font-variant-east-asian: full-width;
+      }
+  
+      .terminal-1161182100-title {
+          font-size: 18px;
+          font-weight: bold;
+          font-family: arial;
+      }
+  
+      .terminal-1161182100-r1 { fill: #c5c8c6 }
+  .terminal-1161182100-r2 { fill: #e3e3e3 }
+  .terminal-1161182100-r3 { fill: #e1e1e1 }
+  .terminal-1161182100-r4 { fill: #1e1e1e }
+  .terminal-1161182100-r5 { fill: #0178d4 }
+  .terminal-1161182100-r6 { fill: #787878 }
+  .terminal-1161182100-r7 { fill: #a8a8a8 }
+      </style>
+  
+      <defs>
+      <clipPath id="terminal-1161182100-clip-terminal">
+        <rect x="0" y="0" width="975.0" height="584.5999999999999" />
+      </clipPath>
+      <clipPath id="terminal-1161182100-line-0">
+      <rect x="0" y="1.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-1">
+      <rect x="0" y="25.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-2">
+      <rect x="0" y="50.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-3">
+      <rect x="0" y="74.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-4">
+      <rect x="0" y="99.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-5">
+      <rect x="0" y="123.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-6">
+      <rect x="0" y="147.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-7">
+      <rect x="0" y="172.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-8">
+      <rect x="0" y="196.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-9">
+      <rect x="0" y="221.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-10">
+      <rect x="0" y="245.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-11">
+      <rect x="0" y="269.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-12">
+      <rect x="0" y="294.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-13">
+      <rect x="0" y="318.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-14">
+      <rect x="0" y="343.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-15">
+      <rect x="0" y="367.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-16">
+      <rect x="0" y="391.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-17">
+      <rect x="0" y="416.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-18">
+      <rect x="0" y="440.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-19">
+      <rect x="0" y="465.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-20">
+      <rect x="0" y="489.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-21">
+      <rect x="0" y="513.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1161182100-line-22">
+      <rect x="0" y="538.3" width="976" height="24.65"/>
+              </clipPath>
+      </defs>
+  
+      <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/><text class="terminal-1161182100-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">SelectApp</text>
+              <g transform="translate(26,22)">
+              <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+              <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+              <circle cx="44" cy="0" r="7" fill="#28c840"/>
+              </g>
+          
+      <g transform="translate(9, 41)" clip-path="url(#terminal-1161182100-clip-terminal)">
+      <rect fill="#282828" x="0" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="12.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="24.4" y="1.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="85.4" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="97.6" y="1.5" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="414.8" y="1.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="524.6" y="1.5" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="854" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="866.2" y="1.5" width="0" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="866.2" y="1.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="963.8" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="25.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="50.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="74.7" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="74.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="158.6" y="99.1" width="73.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="231.8" y="99.1" width="561.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="793" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="805.2" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="817.4" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="99.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="123.5" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="123.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="976" height="24.65" shape-rendering="crispEdges"/>
+      <g class="terminal-1161182100-matrix">
+      <text class="terminal-1161182100-r2" x="12.2" y="20" textLength="12.2" clip-path="url(#terminal-1161182100-line-0)">⭘</text><text class="terminal-1161182100-r2" x="414.8" y="20" textLength="109.8" clip-path="url(#terminal-1161182100-line-0)">SelectApp</text><text class="terminal-1161182100-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1161182100-line-0)">
+  </text><text class="terminal-1161182100-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1161182100-line-1)">
+  </text><text class="terminal-1161182100-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1161182100-line-2)">
+  </text><text class="terminal-1161182100-r4" x="122" y="93.2" textLength="12.2" clip-path="url(#terminal-1161182100-line-3)">▊</text><text class="terminal-1161182100-r5" x="134.2" y="93.2" textLength="707.6" clip-path="url(#terminal-1161182100-line-3)">▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔</text><text class="terminal-1161182100-r5" x="841.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1161182100-line-3)">▎</text><text class="terminal-1161182100-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1161182100-line-3)">
+  </text><text class="terminal-1161182100-r4" x="122" y="117.6" textLength="12.2" clip-path="url(#terminal-1161182100-line-4)">▊</text><text class="terminal-1161182100-r6" x="158.6" y="117.6" textLength="73.2" clip-path="url(#terminal-1161182100-line-4)">Select</text><text class="terminal-1161182100-r7" x="805.2" y="117.6" textLength="12.2" clip-path="url(#terminal-1161182100-line-4)">▼</text><text class="terminal-1161182100-r5" x="841.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1161182100-line-4)">▎</text><text class="terminal-1161182100-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1161182100-line-4)">
+  </text><text class="terminal-1161182100-r4" x="122" y="142" textLength="12.2" clip-path="url(#terminal-1161182100-line-5)">▊</text><text class="terminal-1161182100-r5" x="134.2" y="142" textLength="707.6" clip-path="url(#terminal-1161182100-line-5)">▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁</text><text class="terminal-1161182100-r5" x="841.8" y="142" textLength="12.2" clip-path="url(#terminal-1161182100-line-5)">▎</text><text class="terminal-1161182100-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1161182100-line-5)">
+  </text><text class="terminal-1161182100-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1161182100-line-6)">
+  </text><text class="terminal-1161182100-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1161182100-line-7)">
+  </text><text class="terminal-1161182100-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1161182100-line-8)">
+  </text><text class="terminal-1161182100-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1161182100-line-9)">
+  </text><text class="terminal-1161182100-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1161182100-line-10)">
+  </text><text class="terminal-1161182100-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1161182100-line-11)">
+  </text><text class="terminal-1161182100-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1161182100-line-12)">
+  </text><text class="terminal-1161182100-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1161182100-line-13)">
+  </text><text class="terminal-1161182100-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1161182100-line-14)">
+  </text><text class="terminal-1161182100-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1161182100-line-15)">
+  </text><text class="terminal-1161182100-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1161182100-line-16)">
+  </text><text class="terminal-1161182100-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1161182100-line-17)">
+  </text><text class="terminal-1161182100-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1161182100-line-18)">
+  </text><text class="terminal-1161182100-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1161182100-line-19)">
+  </text><text class="terminal-1161182100-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1161182100-line-20)">
+  </text><text class="terminal-1161182100-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1161182100-line-21)">
+  </text><text class="terminal-1161182100-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1161182100-line-22)">
+  </text>
+      </g>
+      </g>
+  </svg>
+  
+  '''
+# ---
+# name: test_select_from_values_expanded
+  '''
+  <svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
+      <!-- Generated with Rich https://www.textualize.io -->
+      <style>
+  
+      @font-face {
+          font-family: "Fira Code";
+          src: local("FiraCode-Regular"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
+          font-style: normal;
+          font-weight: 400;
+      }
+      @font-face {
+          font-family: "Fira Code";
+          src: local("FiraCode-Bold"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
+          font-style: bold;
+          font-weight: 700;
+      }
+  
+      .terminal-2035490498-matrix {
+          font-family: Fira Code, monospace;
+          font-size: 20px;
+          line-height: 24.4px;
+          font-variant-east-asian: full-width;
+      }
+  
+      .terminal-2035490498-title {
+          font-size: 18px;
+          font-weight: bold;
+          font-family: arial;
+      }
+  
+      .terminal-2035490498-r1 { fill: #c5c8c6 }
+  .terminal-2035490498-r2 { fill: #e3e3e3 }
+  .terminal-2035490498-r3 { fill: #e1e1e1 }
+  .terminal-2035490498-r4 { fill: #1e1e1e }
+  .terminal-2035490498-r5 { fill: #0178d4 }
+  .terminal-2035490498-r6 { fill: #787878 }
+  .terminal-2035490498-r7 { fill: #a8a8a8 }
+  .terminal-2035490498-r8 { fill: #121212 }
+  .terminal-2035490498-r9 { fill: #ddedf9;font-weight: bold }
+  .terminal-2035490498-r10 { fill: #85beea;font-weight: bold }
+  .terminal-2035490498-r11 { fill: #e2e3e3 }
+      </style>
+  
+      <defs>
+      <clipPath id="terminal-2035490498-clip-terminal">
+        <rect x="0" y="0" width="975.0" height="584.5999999999999" />
+      </clipPath>
+      <clipPath id="terminal-2035490498-line-0">
+      <rect x="0" y="1.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-1">
+      <rect x="0" y="25.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-2">
+      <rect x="0" y="50.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-3">
+      <rect x="0" y="74.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-4">
+      <rect x="0" y="99.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-5">
+      <rect x="0" y="123.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-6">
+      <rect x="0" y="147.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-7">
+      <rect x="0" y="172.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-8">
+      <rect x="0" y="196.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-9">
+      <rect x="0" y="221.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-10">
+      <rect x="0" y="245.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-11">
+      <rect x="0" y="269.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-12">
+      <rect x="0" y="294.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-13">
+      <rect x="0" y="318.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-14">
+      <rect x="0" y="343.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-15">
+      <rect x="0" y="367.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-16">
+      <rect x="0" y="391.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-17">
+      <rect x="0" y="416.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-18">
+      <rect x="0" y="440.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-19">
+      <rect x="0" y="465.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-20">
+      <rect x="0" y="489.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-21">
+      <rect x="0" y="513.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-2035490498-line-22">
+      <rect x="0" y="538.3" width="976" height="24.65"/>
+              </clipPath>
+      </defs>
+  
+      <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/><text class="terminal-2035490498-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">SelectApp</text>
+              <g transform="translate(26,22)">
+              <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+              <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+              <circle cx="44" cy="0" r="7" fill="#28c840"/>
+              </g>
+          
+      <g transform="translate(9, 41)" clip-path="url(#terminal-2035490498-clip-terminal)">
+      <rect fill="#282828" x="0" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="12.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="24.4" y="1.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="85.4" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="97.6" y="1.5" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="414.8" y="1.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="524.6" y="1.5" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="854" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="866.2" y="1.5" width="0" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="866.2" y="1.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="963.8" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="25.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="50.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="74.7" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="74.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="158.6" y="99.1" width="73.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="231.8" y="99.1" width="561.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="793" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="805.2" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="817.4" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="99.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="123.5" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="123.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="147.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="147.9" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="147.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="147.9" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="146.4" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="158.6" y="172.3" width="73.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="231.8" y="172.3" width="585.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="817.4" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="829.6" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="172.3" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="146.4" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="158.6" y="196.7" width="195.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="353.8" y="196.7" width="463.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="817.4" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="829.6" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="196.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="146.4" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="158.6" y="221.1" width="292.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="451.4" y="221.1" width="366" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="817.4" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="829.6" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="221.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="146.4" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="158.6" y="245.5" width="524.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="683.2" y="245.5" width="134.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="817.4" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="829.6" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="245.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="146.4" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="158.6" y="269.9" width="158.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="317.2" y="269.9" width="500.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="817.4" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="829.6" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="269.9" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="146.4" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="158.6" y="294.3" width="244" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="402.6" y="294.3" width="414.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="817.4" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="829.6" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="294.3" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="146.4" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="158.6" y="318.7" width="585.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="744.2" y="318.7" width="73.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="817.4" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="829.6" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="318.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#121212" x="122" y="343.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="134.2" y="343.1" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="343.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="343.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="976" height="24.65" shape-rendering="crispEdges"/>
+      <g class="terminal-2035490498-matrix">
+      <text class="terminal-2035490498-r2" x="12.2" y="20" textLength="12.2" clip-path="url(#terminal-2035490498-line-0)">⭘</text><text class="terminal-2035490498-r2" x="414.8" y="20" textLength="109.8" clip-path="url(#terminal-2035490498-line-0)">SelectApp</text><text class="terminal-2035490498-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-2035490498-line-0)">
+  </text><text class="terminal-2035490498-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-1)">
+  </text><text class="terminal-2035490498-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-2)">
+  </text><text class="terminal-2035490498-r4" x="122" y="93.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-3)">▊</text><text class="terminal-2035490498-r5" x="134.2" y="93.2" textLength="707.6" clip-path="url(#terminal-2035490498-line-3)">▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔</text><text class="terminal-2035490498-r5" x="841.8" y="93.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-3)">▎</text><text class="terminal-2035490498-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-3)">
+  </text><text class="terminal-2035490498-r4" x="122" y="117.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-4)">▊</text><text class="terminal-2035490498-r6" x="158.6" y="117.6" textLength="73.2" clip-path="url(#terminal-2035490498-line-4)">Select</text><text class="terminal-2035490498-r7" x="805.2" y="117.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-4)">▲</text><text class="terminal-2035490498-r5" x="841.8" y="117.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-4)">▎</text><text class="terminal-2035490498-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-4)">
+  </text><text class="terminal-2035490498-r4" x="122" y="142" textLength="12.2" clip-path="url(#terminal-2035490498-line-5)">▊</text><text class="terminal-2035490498-r5" x="134.2" y="142" textLength="707.6" clip-path="url(#terminal-2035490498-line-5)">▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁</text><text class="terminal-2035490498-r5" x="841.8" y="142" textLength="12.2" clip-path="url(#terminal-2035490498-line-5)">▎</text><text class="terminal-2035490498-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-2035490498-line-5)">
+  </text><text class="terminal-2035490498-r4" x="122" y="166.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-6)">▊</text><text class="terminal-2035490498-r8" x="134.2" y="166.4" textLength="707.6" clip-path="url(#terminal-2035490498-line-6)">▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔</text><text class="terminal-2035490498-r8" x="841.8" y="166.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-6)">▎</text><text class="terminal-2035490498-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-6)">
+  </text><text class="terminal-2035490498-r4" x="122" y="190.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-7)">▊</text><text class="terminal-2035490498-r10" x="158.6" y="190.8" textLength="73.2" clip-path="url(#terminal-2035490498-line-7)">Select</text><text class="terminal-2035490498-r8" x="841.8" y="190.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-7)">▎</text><text class="terminal-2035490498-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-7)">
+  </text><text class="terminal-2035490498-r4" x="122" y="215.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-8)">▊</text><text class="terminal-2035490498-r11" x="158.6" y="215.2" textLength="195.2" clip-path="url(#terminal-2035490498-line-8)">I&#160;must&#160;not&#160;fear.</text><text class="terminal-2035490498-r8" x="841.8" y="215.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-8)">▎</text><text class="terminal-2035490498-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-8)">
+  </text><text class="terminal-2035490498-r4" x="122" y="239.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-9)">▊</text><text class="terminal-2035490498-r11" x="158.6" y="239.6" textLength="292.8" clip-path="url(#terminal-2035490498-line-9)">Fear&#160;is&#160;the&#160;mind-killer.</text><text class="terminal-2035490498-r8" x="841.8" y="239.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-9)">▎</text><text class="terminal-2035490498-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-9)">
+  </text><text class="terminal-2035490498-r4" x="122" y="264" textLength="12.2" clip-path="url(#terminal-2035490498-line-10)">▊</text><text class="terminal-2035490498-r11" x="158.6" y="264" textLength="524.6" clip-path="url(#terminal-2035490498-line-10)">Fear&#160;is&#160;the&#160;little-death&#160;that&#160;brings&#160;total&#160;</text><text class="terminal-2035490498-r8" x="841.8" y="264" textLength="12.2" clip-path="url(#terminal-2035490498-line-10)">▎</text><text class="terminal-2035490498-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-2035490498-line-10)">
+  </text><text class="terminal-2035490498-r4" x="122" y="288.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-11)">▊</text><text class="terminal-2035490498-r11" x="158.6" y="288.4" textLength="158.6" clip-path="url(#terminal-2035490498-line-11)">obliteration.</text><text class="terminal-2035490498-r8" x="841.8" y="288.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-11)">▎</text><text class="terminal-2035490498-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-11)">
+  </text><text class="terminal-2035490498-r4" x="122" y="312.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-12)">▊</text><text class="terminal-2035490498-r11" x="158.6" y="312.8" textLength="244" clip-path="url(#terminal-2035490498-line-12)">I&#160;will&#160;face&#160;my&#160;fear.</text><text class="terminal-2035490498-r8" x="841.8" y="312.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-12)">▎</text><text class="terminal-2035490498-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-12)">
+  </text><text class="terminal-2035490498-r4" x="122" y="337.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-13)">▊</text><text class="terminal-2035490498-r11" x="158.6" y="337.2" textLength="585.6" clip-path="url(#terminal-2035490498-line-13)">I&#160;will&#160;permit&#160;it&#160;to&#160;pass&#160;over&#160;me&#160;and&#160;through&#160;me.</text><text class="terminal-2035490498-r8" x="841.8" y="337.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-13)">▎</text><text class="terminal-2035490498-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-13)">
+  </text><text class="terminal-2035490498-r4" x="122" y="361.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-14)">▊</text><text class="terminal-2035490498-r8" x="134.2" y="361.6" textLength="707.6" clip-path="url(#terminal-2035490498-line-14)">▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁</text><text class="terminal-2035490498-r8" x="841.8" y="361.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-14)">▎</text><text class="terminal-2035490498-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-14)">
+  </text><text class="terminal-2035490498-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-2035490498-line-15)">
+  </text><text class="terminal-2035490498-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-16)">
+  </text><text class="terminal-2035490498-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-17)">
+  </text><text class="terminal-2035490498-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-2035490498-line-18)">
+  </text><text class="terminal-2035490498-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-2035490498-line-19)">
+  </text><text class="terminal-2035490498-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-2035490498-line-20)">
+  </text><text class="terminal-2035490498-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-2035490498-line-21)">
+  </text><text class="terminal-2035490498-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-2035490498-line-22)">
+  </text>
+      </g>
+      </g>
+  </svg>
+  
+  '''
+# ---
+# name: test_select_from_values_expanded_changed
+  '''
+  <svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
+      <!-- Generated with Rich https://www.textualize.io -->
+      <style>
+  
+      @font-face {
+          font-family: "Fira Code";
+          src: local("FiraCode-Regular"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
+          font-style: normal;
+          font-weight: 400;
+      }
+      @font-face {
+          font-family: "Fira Code";
+          src: local("FiraCode-Bold"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
+          font-style: bold;
+          font-weight: 700;
+      }
+  
+      .terminal-4010426174-matrix {
+          font-family: Fira Code, monospace;
+          font-size: 20px;
+          line-height: 24.4px;
+          font-variant-east-asian: full-width;
+      }
+  
+      .terminal-4010426174-title {
+          font-size: 18px;
+          font-weight: bold;
+          font-family: arial;
+      }
+  
+      .terminal-4010426174-r1 { fill: #c5c8c6 }
+  .terminal-4010426174-r2 { fill: #e3e3e3 }
+  .terminal-4010426174-r3 { fill: #e1e1e1 }
+  .terminal-4010426174-r4 { fill: #1e1e1e }
+  .terminal-4010426174-r5 { fill: #0178d4 }
+  .terminal-4010426174-r6 { fill: #e2e2e2 }
+  .terminal-4010426174-r7 { fill: #a8a8a8 }
+      </style>
+  
+      <defs>
+      <clipPath id="terminal-4010426174-clip-terminal">
+        <rect x="0" y="0" width="975.0" height="584.5999999999999" />
+      </clipPath>
+      <clipPath id="terminal-4010426174-line-0">
+      <rect x="0" y="1.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-1">
+      <rect x="0" y="25.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-2">
+      <rect x="0" y="50.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-3">
+      <rect x="0" y="74.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-4">
+      <rect x="0" y="99.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-5">
+      <rect x="0" y="123.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-6">
+      <rect x="0" y="147.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-7">
+      <rect x="0" y="172.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-8">
+      <rect x="0" y="196.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-9">
+      <rect x="0" y="221.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-10">
+      <rect x="0" y="245.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-11">
+      <rect x="0" y="269.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-12">
+      <rect x="0" y="294.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-13">
+      <rect x="0" y="318.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-14">
+      <rect x="0" y="343.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-15">
+      <rect x="0" y="367.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-16">
+      <rect x="0" y="391.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-17">
+      <rect x="0" y="416.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-18">
+      <rect x="0" y="440.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-19">
+      <rect x="0" y="465.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-20">
+      <rect x="0" y="489.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-21">
+      <rect x="0" y="513.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-4010426174-line-22">
+      <rect x="0" y="538.3" width="976" height="24.65"/>
+              </clipPath>
+      </defs>
+  
+      <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/><text class="terminal-4010426174-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">SelectApp</text>
+              <g transform="translate(26,22)">
+              <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+              <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+              <circle cx="44" cy="0" r="7" fill="#28c840"/>
+              </g>
+          
+      <g transform="translate(9, 41)" clip-path="url(#terminal-4010426174-clip-terminal)">
+      <rect fill="#282828" x="0" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="12.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="24.4" y="1.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="85.4" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="97.6" y="1.5" width="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="378.2" y="1.5" width="195.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="573.4" y="1.5" width="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="854" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="866.2" y="1.5" width="0" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="866.2" y="1.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#282828" x="963.8" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="25.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="50.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="74.7" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="74.7" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="158.6" y="99.1" width="195.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="353.8" y="99.1" width="439.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="793" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="805.2" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="817.4" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="99.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="134.2" y="123.5" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="841.8" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="854" y="123.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="976" height="24.65" shape-rendering="crispEdges"/>
+      <g class="terminal-4010426174-matrix">
+      <text class="terminal-4010426174-r2" x="12.2" y="20" textLength="12.2" clip-path="url(#terminal-4010426174-line-0)">⭘</text><text class="terminal-4010426174-r2" x="378.2" y="20" textLength="195.2" clip-path="url(#terminal-4010426174-line-0)">I&#160;must&#160;not&#160;fear.</text><text class="terminal-4010426174-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-4010426174-line-0)">
+  </text><text class="terminal-4010426174-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-4010426174-line-1)">
+  </text><text class="terminal-4010426174-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-4010426174-line-2)">
+  </text><text class="terminal-4010426174-r4" x="122" y="93.2" textLength="12.2" clip-path="url(#terminal-4010426174-line-3)">▊</text><text class="terminal-4010426174-r5" x="134.2" y="93.2" textLength="707.6" clip-path="url(#terminal-4010426174-line-3)">▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔</text><text class="terminal-4010426174-r5" x="841.8" y="93.2" textLength="12.2" clip-path="url(#terminal-4010426174-line-3)">▎</text><text class="terminal-4010426174-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-4010426174-line-3)">
+  </text><text class="terminal-4010426174-r4" x="122" y="117.6" textLength="12.2" clip-path="url(#terminal-4010426174-line-4)">▊</text><text class="terminal-4010426174-r6" x="158.6" y="117.6" textLength="195.2" clip-path="url(#terminal-4010426174-line-4)">I&#160;must&#160;not&#160;fear.</text><text class="terminal-4010426174-r7" x="805.2" y="117.6" textLength="12.2" clip-path="url(#terminal-4010426174-line-4)">▼</text><text class="terminal-4010426174-r5" x="841.8" y="117.6" textLength="12.2" clip-path="url(#terminal-4010426174-line-4)">▎</text><text class="terminal-4010426174-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-4010426174-line-4)">
+  </text><text class="terminal-4010426174-r4" x="122" y="142" textLength="12.2" clip-path="url(#terminal-4010426174-line-5)">▊</text><text class="terminal-4010426174-r5" x="134.2" y="142" textLength="707.6" clip-path="url(#terminal-4010426174-line-5)">▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁</text><text class="terminal-4010426174-r5" x="841.8" y="142" textLength="12.2" clip-path="url(#terminal-4010426174-line-5)">▎</text><text class="terminal-4010426174-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-4010426174-line-5)">
+  </text><text class="terminal-4010426174-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-4010426174-line-6)">
+  </text><text class="terminal-4010426174-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-4010426174-line-7)">
+  </text><text class="terminal-4010426174-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-4010426174-line-8)">
+  </text><text class="terminal-4010426174-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-4010426174-line-9)">
+  </text><text class="terminal-4010426174-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-4010426174-line-10)">
+  </text><text class="terminal-4010426174-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-4010426174-line-11)">
+  </text><text class="terminal-4010426174-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-4010426174-line-12)">
+  </text><text class="terminal-4010426174-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-4010426174-line-13)">
+  </text><text class="terminal-4010426174-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-4010426174-line-14)">
+  </text><text class="terminal-4010426174-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-4010426174-line-15)">
+  </text><text class="terminal-4010426174-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-4010426174-line-16)">
+  </text><text class="terminal-4010426174-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-4010426174-line-17)">
+  </text><text class="terminal-4010426174-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-4010426174-line-18)">
+  </text><text class="terminal-4010426174-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-4010426174-line-19)">
+  </text><text class="terminal-4010426174-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-4010426174-line-20)">
+  </text><text class="terminal-4010426174-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-4010426174-line-21)">
+  </text><text class="terminal-4010426174-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-4010426174-line-22)">
+  </text>
+      </g>
+      </g>
+  </svg>
+  
+  '''
+# ---
 # name: test_select_rebuild
   '''
   <svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py
index 6856c89d74..ff87c81bf8 100644
--- a/tests/snapshot_tests/test_snapshots.py
+++ b/tests/snapshot_tests/test_snapshots.py
@@ -331,6 +331,10 @@ def test_select(snap_compare):
     assert snap_compare(WIDGET_EXAMPLES_DIR / "select_widget.py")
 
 
+def test_select_from_values(snap_compare):
+    assert snap_compare(WIDGET_EXAMPLES_DIR / "select_from_values_widget.py")
+
+
 def test_selection_list_selected(snap_compare):
     assert snap_compare(WIDGET_EXAMPLES_DIR / "selection_list_selected.py")
 
@@ -349,6 +353,12 @@ def test_select_expanded(snap_compare):
     )
 
 
+def test_select_from_values_expanded(snap_compare):
+    assert snap_compare(
+        WIDGET_EXAMPLES_DIR / "select_from_values_widget.py", press=["tab", "enter"]
+    )
+
+
 def test_select_expanded_changed(snap_compare):
     assert snap_compare(
         WIDGET_EXAMPLES_DIR / "select_widget.py",
@@ -356,6 +366,13 @@ def test_select_expanded_changed(snap_compare):
     )
 
 
+def test_select_from_values_expanded_changed(snap_compare):
+    assert snap_compare(
+        WIDGET_EXAMPLES_DIR / "select_from_values_widget.py",
+        press=["tab", "enter", "down", "enter"],
+    )
+
+
 def test_sparkline_render(snap_compare):
     assert snap_compare(WIDGET_EXAMPLES_DIR / "sparkline.py")
 


Code review comments:
diff_hunk: @@ -278,6 +278,44 @@ def __init__(
         self._value: SelectType | None = value
         self._options = options
 
+    @classmethod
+    def from_values(
+        cls,
+        opts: [SelectType],
path: src/textual/widgets/_select.py
text: @user1:
I don't think I've ever seen this syntax `opts: [SelectType]` to declare a list of `SelectType` objects, but we don't want to restrict ourselves to lists as inputs!

Please consider changing the typing to accept a sequence of `SelectType`, instead of only a list.

@author:
I changed to Iterator[SelectType], which I think is more general than a list?  Let me know if this is correct or if it should be something else.

@user1:
`Iterable[SelectType]` was the correct choice, I think. Thanks.

diff_hunk: @@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 - CSS error reporting will no longer provide links to the files in question https://github.com/Textualize/textual/pull/3582
 - inline CSS error reporting will report widget/class variable where the CSS was read from https://github.com/Textualize/textual/pull/3582
 
+### Added
+- Added `Select.from_values` class method that can be used to initialize a Select control with an iterator https://github.com/Textualize/textual/issues/3691
path: CHANGELOG.md
text: @user1:
This needs to be moved under the correct place once you pull in the updated changelog.

diff_hunk: @@ -278,6 +278,44 @@ def __init__(
         self._value: SelectType | None = value
         self._options = options
 
+    @classmethod
+    def from_values(
+        cls,
+        opts: [SelectType],
+        *,
+        prompt: str = "Select",
+        allow_blank: bool = True,
+        value: SelectType | None = None,
+        name: str | None = None,
+        id: str | None = None,
+        classes: str | None = None,
+        disabled: bool = False,
+    ):
+        """Initialize the Select control with options specified by an iterator
+
+        Args:
+         options: Options to select from.
+         prompt: Text to show in the control when no option is select.
+         allow_blank: Allow the selection of a blank option.
+         value: Initial value (should be one of the values in `options`).
+         name: The name of the select control.
+         id: The ID of the control the DOM.
+         classes: The CSS classes of the control.
+         disabled: Whether the control is disabled or not.
+        """
+        opts_iterator = [(str(o), o) for o in opts]
+
+        return cls(
+            opts_iterator,
path: src/textual/widgets/_select.py
text: @user1:
We avoid shortening names as much as possible, so feel free to type out `options_iterator`, `options`, and `option`, or rename to something else if you prefer.