Compare commits

..

1896 commits

Author SHA1 Message Date
6f2b13bd5b
Add new failing test for #1743 2023-12-15 10:30:19 -06:00
Rodrigo Girão Serrão
e819e97c29
Merge pull request #3659 from Textualize/off-by-one
Be consistent with line/col numbers.
2023-11-15 13:46:55 +00:00
Rodrigo Girão Serrão
9c89524c6b
Merge branch 'main' into off-by-one 2023-11-15 13:33:10 +00:00
Rodrigo Girão Serrão
7a25bb1998
Merge pull request #3678 from Textualize/fix-docs-mouse-move-example
Fix docs example by deleting code.
2023-11-15 10:46:01 +00:00
Dave Pearson
998cbe4122
Add missing parameter type hint (#3682) 2023-11-15 09:51:24 +00:00
Dave Pearson
87a489e4e4
Merge pull request #3681 from davep/tidy-up-get-option-index 2023-11-15 09:20:58 +00:00
Dave Pearson
ec670450f0
Add missing return type and return detail for OptionList.get_option_index
a3590ac192
added this but it looks like the type hint for the return value, and the
return value explanation were left off in the PR.
2023-11-15 08:55:28 +00:00
Rodrigo Girão Serrão
d091b4b620
Merge pull request #3614 from Textualize/select-improvements
Validate `Select.value` and minor `Select` improvements.
2023-11-14 16:32:01 +00:00
Rodrigo Girão Serrão
3f54a93ef4
Merge branch 'main' into select-improvements 2023-11-14 16:19:00 +00:00
Rodrigo Girão Serrão
570c35cb5e
Fix docs example by deleting code. 2023-11-14 15:59:30 +00:00
Darren Burns
0a0832c9a2
Fix for CSS outline issues (#3656)
* Fix `line_trim` only handling a single empty segment. It now removes any number of empty segments before performing the trim.

* Update the lockfile

* Tidy up

* Rewriting line_trim to support empty cells correctly

* Regression snapshot test for case where outline was applied to `Button` and did not render correctly.

* Update the changelog

* Add unit test for empty segments case

* Turn off AUTO_FOCUS on button outline snapshot test

* Remove debugging prints

* Fix issue with alignment generating empty segments

* Validate and update snapshots

* Revert some changes relating to trimming empty segments

* _styles_cache.py - In DEBUG mode, inspect Strips for non-control Segments which contain no text. There should be no empty Segments in Textual. If any are detected, we should investigate the source of them.

* _styles_cache.py - In DEBUG mode, inspect Strips for non-control Segments which contain no text. There should be no empty Segments in Textual. If any are detected, we should investigate the source of them.

* Remove types from docs
2023-11-14 11:43:45 +00:00
Darren Burns
81531e8764
Improve get_child_by_type docstring (#3670) 2023-11-13 15:31:26 +00:00
TomJGooding
b99f143e9b
fix: replace textlog references (#3663) 2023-11-13 10:54:09 +00:00
Will McGugan
c0f299b593
input restriction (#3657)
* input restriction

* types

* tweak

* tests

* docstring

* fix lock

* words

* add valid empty

* another test

* fix regex

* doc

* name change

* Fix regex

* force initial value

* force reactive

* test fix

* add plus

* input type literal

* export InputType
2023-11-10 16:16:42 +00:00
Rodrigo Girão Serrão
c1204bbf5a
Be consistent with line/col numbers.
I added some comments so that we know what line/column numbers are 0-based and which ones are 1-based.

Related issue: #3625.
2023-11-09 17:48:39 +00:00
Rodrigo Girão Serrão
eb9b4bcb00
Merge branch 'main' into select-improvements 2023-11-09 12:59:56 +00:00
Rodrigo Girão Serrão
65bf94a54d
Merge pull request #3654 from Textualize/live-reloading-screen-css
Fix live-reloading of screen CSS.
2023-11-09 12:57:54 +00:00
Dave Pearson
b22fb71c15
Merge pull request #3653 from davep/runnable-styles-references 2023-11-08 17:12:20 +00:00
Dave Pearson
20865a47d3
Fix up highlights for the tint example 2023-11-08 15:44:38 +00:00
Dave Pearson
bc241726bc
Fix up highlights for the link styling example 2023-11-08 15:33:58 +00:00
Dave Pearson
061f8a9bc4
Fix up highlights for the link hover example 2023-11-08 15:32:45 +00:00
Dave Pearson
53e864262a
Fix up highlights for the link hover example 2023-11-08 15:31:09 +00:00
Rodrigo Girão Serrão
1a641e1347
Fix live-reloading of screen CSS. 2023-11-08 15:28:55 +00:00
Dave Pearson
ba6a25aac7
More an -> a 2023-11-08 15:28:03 +00:00
Dave Pearson
65e55ecaaa
Fix up highlights for the link hover example 2023-11-08 15:25:52 +00:00
Dave Pearson
e47c55520b
An -> a 2023-11-08 15:25:31 +00:00
Dave Pearson
6c46ed4c96
Fix up highlights for the link colour example 2023-11-08 15:24:04 +00:00
Dave Pearson
e252d67131
Fix up highlights for height comparison example 2023-11-08 15:08:46 +00:00
Dave Pearson
6a76a7e221
Fix up highlights for border subtitle align example 2023-11-08 15:02:54 +00:00
Dave Pearson
0540ccce41
Remove the highlights from the border_all example
They don't seem to be highlighting anything particular at all; I suspect a
copy/paste-o here.
2023-11-08 14:56:37 +00:00
Dave Pearson
77ba89647b
Fix up highlights for link background 2023-11-08 14:52:49 +00:00
Dave Pearson
414096233b
Make all styles reference examples capable of being run standalone
Also move the declarations of the stylesheets into the app classes.

See #3650
2023-11-08 14:37:01 +00:00
Dave Pearson
38e4cc08e4
Merge pull request #3648 from davep/more-makefile-tweaks
More `Makefile` tweaks
2023-11-08 11:14:10 +00:00
Will McGugan
e8e2a07ad7
optimization (#3646)
* optimization

* further optimization
2023-11-08 10:18:26 +00:00
Dave Pearson
30cecf3f5b
Add make repl
I use this in so many other projects, and I keep doing it within the textual
development environment, and get annoyed every time it isn't there. It's
handy so...
2023-11-08 06:55:22 +00:00
Dave Pearson
25c5658a01
Add setting up of the syntax extra in "make setup"
Yes, this does mean it'll fail when using Python 3.7; but it hardly seems
worth going to all the effort of trying to detect this inside the Makefile
when 3.7-support can't be that long for this world.
2023-11-08 06:52:56 +00:00
Will McGugan
c667c86107
Blur (#3645)
* added blur

* add blur pseudo class

* added blur psuedo class

* added test
2023-11-07 16:22:40 +00:00
Dave Pearson
c7cf0286f1
Merge pull request #3644 from davep/chunk-writes-on-windows
Chunk writes on Windows
2023-11-07 15:32:35 +00:00
Dave Pearson
7dcf01427d
Update the ChangeLog 2023-11-07 15:09:05 +00:00
Dave Pearson
6293fe1b24
Switch to chunking Windows terminal sequences based on buffer size
First we tested this by splitting the output by lines; that worked but it
could be faster. So now we're going to take the problematic buffer
size (32KiB), assume a reasonable worst case of every character heading out
being 3 bytes in size, and chunking the output based on that.

In other words, experiment for #2548 take two.
2023-11-07 14:49:34 +00:00
Will McGugan
f0fd8d47e1
bump lock file (#3643)
* bump lock file

* pin aiohttp

* drop 3.12 for now

* try bump setup-python

* drop 3.7

* bump aiohttp

* lock

* drop macos
2023-11-07 14:37:31 +00:00
Dave Pearson
357268e93c
Chunk driver writes on Windows per-line
This is experimental. I think, ideally, we'll do this by finding an optimal
buffer size and writing based on that, but for the moment let's just try
line-by-line as that's easy.

This will be used to test against the tool I've made that lets me recreate
the issue documented in #2548; if this does the job we'll take this further.
2023-11-07 14:24:40 +00:00
Darren Burns
d958f5bf77
Set pycln pre-commit hook language_version to 3.8 (#3640)
* Fix pycln pre-commit hook

* Use Python 3.11 for pycln
2023-11-06 11:58:27 +00:00
Dave Pearson
9497b155ad
Merge pull request #3636 from davep/fix-markdown-docs
Fix the Focusable flag in the Markdown docs
2023-11-06 10:26:21 +00:00
Dave Pearson
b0a5009b04
Fix the Focusable flag in the Markdown docs
It said it was focusable; it isn't.
2023-11-03 12:45:10 +00:00
Dave Pearson
3bb8c464f0
Merge pull request #3624 from pawamoy/patch-1
Document CellKey being a RowKey, ColumnKey tuple
2023-11-02 09:46:28 +00:00
Rodrigo Girão Serrão
da70d837bc
Merge pull request #3616 from Textualize/duplicate-screen-css-errors
Deduplicate screen CSS errors.
2023-11-01 17:05:23 +00:00
Rodrigo Girão Serrão
8818f12692
Merge branch 'main' into duplicate-screen-css-errors 2023-11-01 16:47:48 +00:00
Timothée Mazzucotelli
fcd664e866 fixup! Document CellKey being a RowKey, ColumnKey tuple 2023-11-01 17:34:53 +01:00
Rodrigo Girão Serrão
ad83e91580
Merge pull request #3582 from Textualize/improve-css-error-reporting
Improve css error reporting
2023-11-01 15:43:51 +00:00
Rodrigo Girão Serrão
dfddeffabc
Merge branch 'main' into improve-css-error-reporting 2023-11-01 15:09:13 +00:00
Rodrigo Girão Serrão
1436dcbafd
Fix changelog. 2023-11-01 15:06:35 +00:00
Rodrigo Girão Serrão
c19ffe3f92
Merge pull request #3595 from Textualize/pre-commit
Add more pre-commit hooks.
2023-11-01 14:48:02 +00:00
Rodrigo Girão Serrão
8fef8000b5
Add snapshot history for new tests. 2023-11-01 14:45:34 +00:00
Rodrigo Girão Serrão
e73181680f
Merge branch 'main' into select-improvements 2023-11-01 14:35:14 +00:00
Rodrigo Girão Serrão
55be211415
Improve documentation. 2023-11-01 14:15:00 +00:00
Rodrigo Girão Serrão
8997615430
Improve Select.
Use a special value to flag a blank selection, add methods is_blank and clear, slightly refactor the way the widget is setup to avoid having attributes _initial_options and _options.
Implement exceptions to be raised when the widget is entering bad state.
2023-11-01 14:08:44 +00:00
Timothée Mazzucotelli
544058a39b
Document CellKey being a RowKey, ColumnKey tuple 2023-11-01 14:55:57 +01:00
Will McGugan
b3d60432f1
Version bump (#3621) 2023-10-31 13:24:03 +00:00
Josh Duncan
4f95d30619
DataTable sort by function (or other callable) (#3090)
* DataTable sort by function (or other callable)

The `DataTable` widget now takes the `by` argument instead of `columns`, allowing the table to also be sorted using a custom function (or other callable). This is a breaking change since it requires all calls to the `sort` method to include an iterable of key(s) (or a singular function/callable). Covers #2261 using [suggested function signature](https://github.com/Textualize/textual/pull/2512#issuecomment-1580277771) from @darrenburns on PR #2512.

* argument change and functionaloty update

Changed back to orinal `columns` argument and added a new `key` argument
which takes a function (or other callable). This allows the PR to NOT BE
a breaking change.

* better example for docs

- Updated the example file for the docs to better show the functionality
of the change (especially when using `columns` and `key` together).
- Added one new tests to cover a similar situation to the example
  changes

* removed unecessary code from example

- the sort by clicked column function was bloat in my opinion

* requested changes

* simplify method and terminology

* combine key_wrapper and default sort

* Removing some tests from DataTable.sort as duplicates. Ensure there is test coverage of the case where a key, but no columns, is passed to DataTable.sort.

* Remove unused import

* Fix merge issues in CHANGELOG, update DataTable sort-by-key changelog PR link

---------

Co-authored-by: Darren Burns <darrenburns@users.noreply.github.com>
Co-authored-by: Darren Burns <darrenb900@gmail.com>
2023-10-31 13:14:47 +00:00
Dave Pearson
665dca9cb8
Merge pull request #3618 from davep/command-palette-worker-nuke
Ensure that the command palette doesn't kill *all* workers when stoping command gathering
2023-10-31 09:54:23 +00:00
Dave Pearson
9cacf8cd7b
Update the ChangeLog 2023-10-31 09:04:56 +00:00
Dave Pearson
449d3a6b7c
Ensure that the command palette only cancels its own workers
See #3615.

Co-authored-by: Rodrigo Girão Serrão <rodrigogiraoserrao@gmail.com>
2023-10-31 08:58:27 +00:00
Dave Pearson
7cbba6636f
Add a test for the command palette not leaving workers behind 2023-10-31 08:54:25 +00:00
Dave Pearson
b939256007
Add a test that the command palette doesn't kill other workers
See #3615.
2023-10-31 08:47:33 +00:00
Rodrigo Girão Serrão
37aac01e93
Deduplicate screen CSS errors.
Related issue: #3581.
2023-10-30 17:02:18 +00:00
Rodrigo Girão Serrão
8bb247ea15
Merge branch 'main' into select-improvements 2023-10-30 15:39:09 +00:00
Rodrigo Girão Serrão
cb0b47359b
Changelog. 2023-10-30 15:37:48 +00:00
Rodrigo Girão Serrão
83c598ed17
Add tests. 2023-10-30 15:28:49 +00:00
Rodrigo Girão Serrão
b8533baa6e
Validate Select.value and revert 9c941130b.
Related issues: #3611, #3612.
Related commit: 9c941130b.
2023-10-30 15:28:16 +00:00
Darren Burns
efbb655313
Handle other Tabs widgets as DOM descendants of a TabbedContent (#3602)
* Handle other Tabs widgets as DOM descendants of a TabbedContent

* Update CHANGELOG.md

* Ensure TabbedContent can identify messages from the associated Tabs so that it can ignore messages from other, irrelevant Tabs instances that may exist as descendants deeper in the DOM. Also adds some tests to ensure corresponding issues are fixed.

* Improve docstrings for Tabs.Cleared and corresponding handler inside TabbedContent - it now includes a note that the Cleared message is sent when all tabs are hidden.
2023-10-30 13:10:53 +00:00
Rodrigo Girão Serrão
8362145e21
Tests & changelog. 2023-10-30 12:03:27 +00:00
Rodrigo Girão Serrão
9c941130bb
Select posts Changed when value is assigned.
Fix #3611.
2023-10-30 12:02:47 +00:00
Rodrigo Girão Serrão
3f33cd1f86
Merge pull request #3586 from Textualize/wokers-inside-workers
Workers inside workers
2023-10-30 10:26:42 +00:00
Dave Pearson
001881cc9a
Merge pull request #3607 from mholson/patch-1
fix typo 'that' -> 'than'
2023-10-28 08:50:17 +01:00
Mark Olson
a9704fddfa
fix typo 'that' -> 'than' 2023-10-28 09:16:24 +02:00
Darren Burns
f02cde2f83
Update CHANGELOG regarding LoadingIndicator crash (#3601) 2023-10-27 11:13:12 +01:00
Rodrigo Girão Serrão
841f726677
Update CHANGELOG.md
Co-authored-by: Dave Pearson <davep@davep.org>
2023-10-27 10:47:41 +01:00
Rodrigo Girão Serrão
33a1d34db7
Merge pull request #3499 from Textualize/typing-timer-callback
Be less strict about typing timer callbacks.
2023-10-27 10:47:12 +01:00
Dave Tapley
41cadfcbf1
Setter for TextArea load_text (#3545)
As discussed https://github.com/Textualize/textual/discussions/3525#discussioncomment-7277111
2023-10-26 14:47:52 +01:00
Rodrigo Girão Serrão
d9594f5adc
Comment what the hooks do. 2023-10-26 12:20:19 +01:00
Rodrigo Girão Serrão
6f00943c14
Fix imports. 2023-10-26 12:15:55 +01:00
Rodrigo Girão Serrão
ec44d17ccc
Remove trailing whitespace hook.
See https://github.com/Textualize/textual/pull/3595#discussion_r1372961156.
2023-10-26 11:55:22 +01:00
Rodrigo Girão Serrão
ecdf65385d
Add more pre-commit hooks. 2023-10-26 11:28:26 +01:00
Rodrigo Girão Serrão
a91f8b4385
Cleanup. 2023-10-26 11:11:26 +01:00
Rodrigo Girão Serrão
d755c92979
Rename variable. 2023-10-25 18:54:34 +01:00
Rodrigo Girão Serrão
777eb98097
Make run_worker thread-safe.
Move the change into run_worker to make that thread-safe as well, instead of just the decorator.
2023-10-25 18:52:57 +01:00
Rodrigo Girão Serrão
16cc9f549d
Changelog. 2023-10-25 17:14:06 +01:00
Rodrigo Girão Serrão
44e8a0cfc8
Merge tests. 2023-10-25 17:12:41 +01:00
Rodrigo Girão Serrão
98c34ccb52
Cleanup test. 2023-10-25 17:10:12 +01:00
Rodrigo Girão Serrão
f543010ddc
Test calling workers inside workers. 2023-10-25 17:05:47 +01:00
Rodrigo Girão Serrão
890b475dfa
Create workers in thread-safe way.
Previously you couldn't call a threaded worker from another threaded worker because creating a worker was not thread safe (see #3472). However, the second threaded worker could already be called with self.call_from_thread, so we bake that in.
2023-10-25 17:05:36 +01:00
Darren Burns
34fb596c56
Test flakiness investigation and attempted fixes ❄ (#3498)
* Modifying two flaky animation tests, hopefully removing flakiness :)

* Make switch_mode return an AwaitMount

* Fix event issue

* Add AwaitComplete - a more generalised optionally awaitable object

* Use AwaitComplete in Tabs.remove_tab() and update tests accordingly.

* Update TabbedContent to use AwaitComplete instead of AwaitTabbedContent

* Simplifying - dont use optional awaitables where not required

* Update variable name

* Update a comment

* Add watcher for cursor blink to ensure when blink is switched off, the cursor immediately becomes visible. Ensure we turn of cursor blink inside the input suggetions snapshot test.

* Fix cursor blink reactive and disable cursor blink in the command palette snapshot test

* More progress

* Reworking AwaitComplete

* Some more work on tabs flakiness/race-conditions

* Ensure active tab is set correctly

* Simplify next tab assignment

* Simplify removing tabs logic

* Make button animation duration configurable; Switch off button animation in snapshot test

* Remove a flawed test

* Add awaits in some tests

* Docstrings

* Make active_effect_duration an instance attribute

* Fix a Tabs crash

* Await the tree reload when the path changes in DirectoryTree

* Change AwaitComplete _instances class attr to a set from a list

* Make AwaitComplete generic, AwaitComplete._wait_all is now private, and exposes timeout parameter

* Actually make AwaitComplete instances a set, not a list

* Update CHANGELOG.md regarding flaky-test adjacent changes, AwaitComplete, etc..

* Remove whitespace

* Use list() instead of useless comprehension, remove unused import

* Ensure loading indicator _start_time is initialised correctly

* Switch from time.sleep to asyncio.sleep in a notifications test, rework numbers to try and prevent flakiness

* Resolve deadlock by awaiting event on the event loop instead of in the message pump

* Renaming for clarity

* Debugging for remove_tab test flakiness

* Running all tests

* Updating snapshots

* Remove debugging prints

* Fix broken docstring, remove unused import

* Rename variable to make it clearer

* Add missing return type annotation

* Update src/textual/widgets/_tabbed_content.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/widgets/_tabbed_content.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/widgets/_tabs.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Scroll datatable cursor after refresh

* Add comment explaining use of call_after_refresh when scrolling data table cursor into view

* Add repr to AwaitComplete (auto-repr_

* Remove use of generics from AwaitComplete

* Update changelog and improve docstring

* Add a missing parameter from DirectoryTree.reset_node docstring.

Signed-off-by: Darren Burns <darrenb900@gmail.com>

* Improve docstring in DirectoryTree

Signed-off-by: Darren Burns <darrenb900@gmail.com>

* Rename parameter coroutine to coroutines in await_complete.py, since it's a variable length param.

---------

Signed-off-by: Darren Burns <darrenb900@gmail.com>
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-10-25 14:41:02 +01:00
Rodrigo Girão Serrão
6c6eecfd10
Address review feedback. 2023-10-25 14:38:22 +01:00
Rodrigo Girão Serrão
d84498232a
Minor docstring/type hints cleanup. 2023-10-25 13:21:56 +01:00
Rodrigo Girão Serrão
8b16776afc
Drop links in CSS error reporting.
Instead of creating the link explicitly, we let terminal emulators auto-link to the file.
This came after a discussion about how/whether we should try to support linking to specific file lines/columns for TCSS files and after some research to see how that would be possible.
We decided to drop this feature when we couldn't find information in the standards for 'file://' regarding how to specify line/column numbers and after we found [this iTerm issue](https://gitlab.com/gnachman/iterm2/-/issues/9376) where the creator/maintainer of iTerm says that there is no standard API for opening a file to a particular line number.
2023-10-25 12:00:31 +01:00
Rodrigo Girão Serrão
5d7585c55f
Merge pull request #3584 from Textualize/fix-notifications
Remove changelog entry.
2023-10-25 11:41:58 +01:00
Rodrigo Girão Serrão
12f9e45701
Remove changelog entry.
See https://github.com/Textualize/textual/pull/3583#issuecomment-1778952499.
2023-10-25 11:39:13 +01:00
Rodrigo Girão Serrão
9e7117338d
Merge pull request #3583 from Textualize/fix-notifications
Fix notifications CSS.
2023-10-25 11:00:45 +01:00
Rodrigo Girão Serrão
87274cb111
Fix notifications CSS.
This was merged more or less at the same time as 'initial' was added to CSS but the tests weren't ran with that change.
Related PRs: #3566, #3531.
2023-10-25 10:16:14 +01:00
Rodrigo Girão Serrão
0f38ab7202
Link to correct file location in CSS errors. 2023-10-24 17:56:19 +01:00
Rodrigo Girão Serrão
55fe9d3891
Fix tests. 2023-10-24 17:51:34 +01:00
David Brochart
bc90a6a153
Add Document get_index_from_location / get_location_from_index (#3410)
Add Document get_index_from_location / get_location_from_index
2023-10-24 17:51:33 +01:00
TomJGooding
a413ee729c
fix(notifications): add link styles (#3531) 2023-10-24 17:44:00 +01:00
Rodrigo Girão Serrão
9076f41ce3
Keep track of what widget/class variable CSS is read from.
We already kept track of the file and widget CSS was read from. Now, we also keep track of the class variable it comes from and we create some structure to transfer that information across the program.
2023-10-24 17:16:58 +01:00
Darren Burns
0104385fc1
Docs table rendering change/cleanup (#3579) 2023-10-24 13:59:31 +01:00
Dave Pearson
24e42de10a
Merge pull request #3578 from davep/stop-more-command-palette-message-leakage
Stop `OptionList.OptionHighlighted` leaking to the `App`
2023-10-24 13:48:56 +01:00
Dave Pearson
e574c3fab4
Stop OptionList.OptionHighlighted leaking to the App 2023-10-24 13:13:11 +01:00
Rodrigo Girão Serrão
32fc617803
Merge pull request #3511 from Textualize/action-docs-fixes
Minor fixes on the actions guide.
2023-10-24 11:52:37 +01:00
Rodrigo Girão Serrão
2918011512
Fix link in CSS error reporting (#3569). 2023-10-24 10:52:05 +01:00
Rodrigo Girão Serrão
9e5bc82336
Remove unused function. 2023-10-24 10:51:15 +01:00
Will McGugan
b679afdab2
parse cache (#3575) 2023-10-24 10:11:36 +01:00
Will McGugan
0f0c4c020c doc tweak 2023-10-24 09:44:17 +01:00
Will McGugan
c41dd0a292 fix comment 2023-10-23 15:14:27 +01:00
Rodrigo Girão Serrão
2ccc06365b
Add a test and remove dead code (#3514)
* Remove dead code.

MouseScrollUp and MouseScrollDown inherit from MouseEvent so this branch is never taken.

* Add screen test.
2023-10-23 13:46:44 +01:00
Will McGugan
859cff3be3
CSS initial special value (#3566)
* CSS unset

* no need for panicked flag

* initial token

* initial token

* simplify initial token

* docstring

* defaults

* reset initial default

* typing hacks

* typing fix

* tests and docs

* Added xfail

* doc update

* changelog

* cache css

* fix for initial defaults

* Update src/textual/css/stylesheet.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/css/stylesheet.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* restore arrange

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-10-23 13:38:18 +01:00
Rodrigo Girão Serrão
375211ce38
Run CodeQL only on code changes. (#3573) 2023-10-23 13:36:26 +01:00
Will McGugan
2f8bb86767
button render (#3571)
* button render

* imports

* changelog

* simplify pad renderable

* docstring

* Button renderable

* snapshot
2023-10-23 13:02:04 +01:00
Rodrigo Girão Serrão
01be6dec9d
Merge pull request #3565 from RJ722/fix-discord-link
Update discord link in CONTRIBUTING.md
2023-10-23 11:46:24 +01:00
Dave Pearson
693b6e64f6
Merge pull request #3519 from davep/more-f3
Allow F3 with modifier keys
2023-10-23 09:23:37 +01:00
Dave Pearson
ea8f1cdd7f
Merge pull request #3372 from davep/move-markdown-change-in-changelog
Move `Markdown.goto_anchor` change to correct version in `CHANGELOG`
2023-10-22 22:20:02 +01:00
Dave Tapley
227e1416c7
Pass App ReturnType to Pilot in run_test (#3572) 2023-10-22 20:51:10 +01:00
RJ722
01adf9e94a Update discord link in CONTRIBUTING.md 2023-10-21 16:24:14 +05:30
Will McGugan
e68e6e37b5 fix highlighted lines 2023-10-19 12:15:32 +01:00
Darren Burns
3b170b0748
Scroll DataTable cursor after refresh (#3552)
* Scroll datatable cursor after refresh, since new rows may be measured in on_idle

* Update CHANGELOG.md regarding datatable cursor move scrolling fix
2023-10-17 16:43:39 +01:00
Darren Burns
d5456adbdc
Fix DataTable.update_cell not updating cell immediately (#3551)
* Reintroduce cache clear in DataTable update dimensions

* Update the CHANGELOG
2023-10-17 16:42:00 +01:00
Will McGugan
fdc96f8c0e
fix for cache (#3538) 2023-10-17 10:45:25 +01:00
Dave Pearson
9c1e89fcf0
Merge pull request #3540 from davep/ancestors-typo-fix
Tweak the docstrings of the ancestors properties
2023-10-16 13:36:30 +01:00
Dave Pearson
faf09a7bea
Talk about nodes, not the plural of Node 2023-10-16 13:35:15 +01:00
Will McGugan
6ed6011fa5
button tweak (#3539)
* button tweak

* changelog
2023-10-16 10:03:34 +01:00
Dave Pearson
6ff7f52146
Tweak the docstrings of the ancestors properties
Both look to have been a little bit mangled at some point.
2023-10-15 20:15:54 +01:00
Dave Pearson
8be3e37d89
Allow F3 with modifier keys
See https://github.com/Textualize/textual/issues/3440#issuecomment-1759245890
for some background context.
2023-10-12 11:45:49 +01:00
Will McGugan
ddbc91e31b
unused method (#3518)
* unused method

* typo
2023-10-12 11:16:38 +01:00
Will McGugan
7e25daa545 changelog 2023-10-11 16:54:56 +01:00
Will McGugan
cc5e14cbd6 version bump 2023-10-11 16:54:29 +01:00
Will McGugan
47af5e0402
Add loading reactive (#3509)
* Add loading reactive

* loading indicator example

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* into

* changelog

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-10-11 16:53:49 +01:00
Will McGugan
5cf0e1a69c fix for textual-web links 2023-10-11 15:36:30 +01:00
Rodrigo Girão Serrão
1a88e102ef
Encourage users to open issues about docs. 2023-10-11 15:10:37 +01:00
Rodrigo Girão Serrão
924ff5fbd9
Minor fixes on the actions guide.
Thanks to #3456.

Co-authored-by: Steve Holden <steve@holdenweb.com>
2023-10-11 14:57:25 +01:00
Rodrigo Girão Serrão
73795bf2e2
Restore original typing for the work decorator. 2023-10-11 14:32:18 +01:00
rndusr
08b49b1c8b
LinuxDriver: Exit if thread dies (#3431)
* LinuxDriver: Exit if thread dies

If `run_input_thread()` dies, the whole application keeps running but becomes
unresponsive. It has to be killed by the user, leaving the terminal in an
unusable state.

This commit terminates the application instead and prints a traceback.

* LinuxDriver: Handle any exception from input thread

* LinuxDriver: Simpler traceback construction in input thread handler

* LinuxDriver: Catch exception from run_input_thread() in _run_input_thread()

* LinuxDriver: Remove unneeded import: Callable

---------

Co-authored-by: Random User <rndusr@example.org>
2023-10-11 10:37:02 +01:00
Rodrigo Girão Serrão
e1c38002c8
Add will-change to excalidraw diagrams. (#3503)
Adding will-change: filter seems to fix the issue with the Excalidraw diagrams on dark mode and recent Safari versions.
This change was also tested on Firefox and Chrome and it didn't break the diagrams in those browsers.

This fixes #3497.
2023-10-10 17:13:03 +01:00
Will McGugan
927e59b001
version bump (#3501) 2023-10-10 15:47:30 +01:00
Darren Burns
1a0cd7792d
Allow scrollbar size of zero (scrollable containers without scrollbars) (#3488)
* Remove the guard code which protects against `scrollbar-size-*:0`, update error messages indicating its supported now.

* Fix scrollbar region calculation to support zero-thickness scrollbars

* Add test ensuring zero-width scrollbars dont blow up

* Updating CHANGELOG regarding zero-thickness scrollbars

* Add note to scrollbar_size.md about zero width scrollbar
2023-10-10 15:37:13 +01:00
Will McGugan
5e4067fd05 new logo asset 2023-10-10 15:37:00 +01:00
Will McGugan
7a9019adb1
add our new logo (#3500) 2023-10-10 15:36:28 +01:00
Rodrigo Girão Serrão
1ee6a48407
Update changelog. 2023-10-10 14:49:41 +01:00
Rodrigo Girão Serrão
1f2b09d8ba
Be less strict about typing timers. 2023-10-10 14:48:47 +01:00
Rodrigo Girão Serrão
d0f0d76f78
Merge pull request #3490 from TomJGooding/docs-radio-set-add-bindings
docs(radio set): add bindings
2023-10-10 10:25:49 +01:00
TomJGooding
e3d9bcd99c docs(radio set): add bindings 2023-10-09 18:27:13 +01:00
Darren Burns
321e2d6477
Capturing stdout/stderr in headless mode rework (#3486)
* Fix docstring typo

* Allow writing to stdout/stderr when in headless mode

* Update changelog

* Improve docstring
2023-10-09 15:54:07 +01:00
Darren Burns
4054667a23
Fix DataTable crash when removing and updating cell at the same time (#3487)
* Fix crash when removing rows/columns from datatable

* Regression tests for datatable crash

* Update CHANGELOG regarding datatable crash fix
2023-10-09 14:58:38 +01:00
laixintao
0ffa82a13e
fix doc: change rule: to text-align: in css_types (#3476) 2023-10-09 12:42:55 +01:00
Will McGugan
b8ac737cfd
Add wait_for_dismiss to push_screen (#3477)
* docstrings

* raises docstring

* fix for tests

* Formatting

* tests

* changelog

* simplify

* typing

* dot

* typing

* Update tests/test_screens.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-10-09 12:42:13 +01:00
Dave Pearson
005f556773
Merge pull request #3485 from davep/unknown-sequence-peek-support
Add a debug hook for getting sent unknown sequences from the XTerm parser
2023-10-09 11:54:40 +01:00
Dave Pearson
46ddf9ac0e
Add a debug hook for getting sent unknown sequences from the XTerm parser
This is here only for serving the keyboard checker/recorder tool.
2023-10-09 11:23:31 +01:00
TomJGooding
8e3108719c
fix: allow integer for fractional styles (#3432)
Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-10-09 11:20:37 +01:00
Darren Burns
d2320f11fc
Move tree-sitter and tree_sitter_languages to optional extras (#3398)
* Move tree-sitter and tree_sitter_languages to optional extras

* Update docs and GitHub action for moving syntax to extras

* Updating, remake lockfile

* Update snapshots from textual-dev change

* Improve warning when a language is set but tree-sitter not available

* Update CHANGELOG

* Add note on syntax extras

* Update lock
2023-10-09 10:57:13 +01:00
Dave Pearson
c88c031415
Merge pull request #3475 from davep/link-plotext-blog-post-to-repo-too 2023-10-07 15:38:08 +01:00
Dave Pearson
3825f6cdd4
Link to the repo rather than the pypi page
See https://github.com/Textualize/textual-plotext/issues/1
2023-10-07 13:42:11 +01:00
Dave Pearson
3aaecd3920
Merge pull request #3294 from davep/fix-print-console-location
Ensure that `print` reports the correct location in console
2023-10-05 16:00:36 +01:00
Dave Pearson
500857b5fb
Merge branch 'main' into fix-print-console-location 2023-10-05 15:50:22 +01:00
Darren Burns
864d6717c2
Fix IME pop-up issues (#3408)
* Fixing IME alignment for Input widget. TextArea remains unfixed.

* Fix TextArea IME

* Prefix unused unpacked variables with underscore

* Updating IME preview location on scrolling in TextArea

* Add CHANGELOG entry for IME positioning fix

* Add CHANGELOG entry for new methods on Input and TextArea

* Test TextArea terminal cursor position update

* Tests for Input widget terminal cursor position updating

* Test for IME when content scrolled
2023-10-05 15:37:34 +01:00
Dave Pearson
0a1fc697dd
Merge pull request #3469 from davep/dt-doc-fix
Fix a link in the DataTable docs
2023-10-05 15:00:21 +01:00
Dave Pearson
8f9eab1e10
Fix a link in the DataTable docs
Noticed this in passing.
2023-10-05 14:50:01 +01:00
Darren Burns
d7549d69ee
Add 3.12 to classifiers (#3465) 2023-10-05 13:48:44 +01:00
Dave Pearson
cc04d30b28
Merge pull request #3459 from davep/option-list-safe-duplicate-check
`OptionList` safe duplicate check
2023-10-05 12:31:28 +01:00
Dave Pearson
143067f060
Switch to using a set expression 2023-10-05 11:50:28 +01:00
Dave Pearson
55c83b4cba
Use a list rather than a set for the new options
Likely doesn't make a whole heap of difference, but the {} vs the [] was a
typo and really conceptually it is a list of new options with IDs.
2023-10-05 11:00:57 +01:00
Dave Pearson
ef4e5c3bf1
Add some missing words of explanation
Because apparently I can't type English.
2023-10-05 10:46:25 +01:00
Dave Pearson
3b16206bbb
Fix a typo 2023-10-05 10:45:31 +01:00
Dave Pearson
ed131a0276
Simplify _duplicate_id_check
In conversation we've decided that it's not that necessary to list all of
the IDs that are duplicates; with this in mind we can whittle down the work
being done to look for duplicates.

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-10-05 10:42:46 +01:00
Rodrigo Girão Serrão
5046d5bb0d
Merge pull request #3461 from joehakimrahme/patch-1
Fix a broken link in the documentation guide
2023-10-05 10:15:41 +01:00
Joe H. Rahme
4f67432b9f Fix a broken link in the documentation guide
The link in the doc[1] is not rendering properly,
because the method `textual.app.App.compose`
is ignored in the doc in the filter[2]. This commit
overrides the filter in the app.md file, generating
the doc for the "protocol" method and fixing the
link rendering in the guide.

[1]: https://textual.textualize.io/guide/app/#composing
[2]: textual/mkdocs-common.yml

Fix #3141
2023-10-04 23:34:20 +02:00
Dave Pearson
d0c5ef04d1
Move to testing with sets
This way there's less chance of a duplicate report of a duplicate.
2023-10-04 21:53:19 +01:00
Dave Pearson
5c4142a828
Add a test for adding duplicates that don't yet exist 2023-10-04 21:29:24 +01:00
Dave Pearson
4df3f1553c
Add a further test for adding non-dupes post-dupe 2023-10-04 21:27:02 +01:00
Dave Pearson
29157eaff6
Update the CHANGELOG 2023-10-04 21:25:11 +01:00
Dave Pearson
c98571bc04
Simplify OptionList._duplicate_id_check 2023-10-04 20:59:27 +01:00
Dave Pearson
c377f098cf
Check for duplicate option IDs in OptionList *before* adding
Simply put: until now the OptionList was adding the new options and then
checking if the ID was a duplicate. If some code was to then catch
DuplicateID and treat it as a pass this would then have an unintended
side-effect that the duplicate had been added anyway. The ultimate effect of
this being that once there was an attempt to add a duplicate, nothing more
could be added to that OptionList.

Fixes #3455.
2023-10-04 20:52:14 +01:00
Dave Pearson
8f3ea3cac9
Extend the OptionList DuplicateID test to test for #3455 2023-10-04 20:24:22 +01:00
Dave Pearson
6d79e7782d
Remove an unnecessary a (#3458)
This is feeling like a common theme this week.
2023-10-04 18:02:38 +01:00
Dave Pearson
9053b5a126
Merge pull request #3453 from davep/plotext-blog-typo-fix
Fix a typo in the textual-plotext blog post
2023-10-04 13:45:41 +01:00
Dave Pearson
af81e39091
Fix a typo in the textual-plotext blog post 2023-10-04 13:37:11 +01:00
Dave Pearson
66d45bff7d
Merge pull request #3452 from davep/textual-plotext-blog
`textual-plotext` announcement blogpost
2023-10-04 13:33:43 +01:00
Dave Pearson
7f8bbc1e73
Add a blog post announcing textual-plotext 2023-10-04 13:17:49 +01:00
Dave Pearson
e459be0b85
Add footnotes to the config
How the heck did we ever get by without footnotes on?!?
2023-10-04 11:47:31 +01:00
Rodrigo Girão Serrão
03e3a69561
Merge pull request #3447 from Textualize/query-overloads-fix
Improve typing for queries.
2023-10-03 16:37:21 +01:00
Rodrigo Girão Serrão
02fe3bfe97
Merge pull request #3450 from Textualize/query-code-coverage
query.py coverage 100%.
2023-10-03 16:24:57 +01:00
Rodrigo Girão Serrão
571ea7c529
Merge pull request #3443 from Textualize/data-table-cell-padding
Data table cell padding
2023-10-03 16:24:25 +01:00
Rodrigo Girão Serrão
00376a62d3
query.py coverage 100%.
Increase coverage on 'query.py'.
2023-10-03 16:04:00 +01:00
Rodrigo Girão Serrão
1936f10091
Improve cell_padding and fix bug.
Makes sure that cell padding can't be set to a negative value.
This also makes sure that we update the virtual size of the data table when the cell padding changes, otherwise it will go out of sync.
Related review comment: https://github.com/Textualize/textual/pull/3443#discussion_r1343910771
2023-10-03 14:31:25 +01:00
Rodrigo Girão Serrão
c9629b572d
Drop bound in ExpectType.
The bound isn't strictly necessary and it wasn't there in the first place, so we won't add it here either.
2023-10-03 11:32:13 +01:00
Rodrigo Girão Serrão
afd5ec15ba
Improve typing for queries.
ExpectType grew its Widget bound and then it was moved out of the body of the class so that it could be referenced inside methods, because it was needed inside the body of 'only_one'.
2023-10-03 11:28:24 +01:00
Dave Pearson
f4f83ee72b
Merge pull request #3446 from davep/remove-a-a
Remove an unnecessary a
2023-10-03 10:36:39 +01:00
Dave Pearson
d7b48c5f76
Remove an unnecessary a
Saw this in passing.
2023-10-03 10:27:32 +01:00
Rodrigo Girão Serrão
bbe5c85daa
Test cell_padding assignment refreshes data table. 2023-10-03 09:04:32 +01:00
Rodrigo Girão Serrão
b84334c23b
Rename render_width as get_render_width.
Related review comment: https://github.com/Textualize/textual/pull/3443#discussion_r1342917214
2023-10-02 17:51:03 +01:00
Darren Burns
e4d182d61f
Add TextArea.Changed and TextArea.SelectionChanged messages (#3442)
* Add TextArea Changed and SelectionChanged messages, and post them in relevant places.

* Add tests for TextArea messages

* Add docstrings for TextArea messages

* Update docs to mention TextArea messages

* Update CHANGELOG

* Update src/textual/app.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-10-02 17:17:08 +01:00
Rodrigo Girão Serrão
ab4da8e546
Remove magical constant from tests. 2023-10-02 17:11:47 +01:00
Rodrigo Girão Serrão
3bcca3883b
Improve docstring. 2023-10-02 17:06:21 +01:00
Rodrigo Girão Serrão
46b7c943a7
Docstrings. 2023-10-02 16:58:51 +01:00
Dave Pearson
efd00ded11
Merge pull request #3424 from davep/command-palette-lazy-show 2023-10-02 16:51:22 +01:00
Rodrigo Girão Serrão
84123c2853
Merge branch 'main' into data-table-cell-padding 2023-10-02 16:47:39 +01:00
Rodrigo Girão Serrão
abaa2d2f4e
Add customisable cell_padding to data table.
This fixes #3435.
2023-10-02 16:46:53 +01:00
Dave Pearson
4684632730
Merge pull request #3290 from davep/win32-emoji-paste-fix 2023-10-02 16:44:51 +01:00
Dave Pearson
8c8928dee1
Update snapshot tests 2023-10-02 09:26:49 +01:00
Dave Pearson
cb7e44322a
Merge branch 'main' into command-palette-lazy-show 2023-10-02 09:05:28 +01:00
Adam K
89991025e9
Update widgets.md (#3433)
typo fix, missing "as" before "a".
2023-09-30 16:25:44 +01:00
Will McGugan
b2a40a0abd fix url 2023-09-30 13:47:56 +01:00
Will McGugan
c2e6f3b2c5 restore ping 2023-09-29 16:08:59 +01:00
Will McGugan
92abb57e91 remove deprecated ping 2023-09-29 15:26:03 +01:00
Will McGugan
64703c04dd
interactive examples (#3418)
* interactive examples

* words

* remove log
2023-09-29 15:23:42 +01:00
TomJGooding
3f36989004
feat(input): add clear method (#3430)
* feat(input): add clear method

* update changelog

* fix method case in changelog
2023-09-29 15:22:57 +01:00
Dave Pearson
09274c4c94
Update snapshot tests 2023-09-28 15:41:36 +01:00
Dave Pearson
f339cb50e9
Only show the command palette command list when it's needed
Rather than open the command palette the moment we start looking for hits,
only show it when a hit comes in, or when we need to say that no matches
were found.

Fixes #3277.
2023-09-28 15:38:14 +01:00
Dave Pearson
7658bca0e9
Fix an old and incorrect comment 2023-09-28 15:28:13 +01:00
Dave Pearson
c881278fa1
Update snapshot tests 2023-09-28 14:28:16 +01:00
Dave Pearson
8d6d0bc5c3
Update the CHANGELOG 2023-09-28 14:05:56 +01:00
Dave Pearson
f75bdc19da
Upgrade to textual-dev 1.2.x 2023-09-28 14:02:27 +01:00
Dave Pearson
a0a6bcf3b7
Merge branch 'main' into fix-print-console-location 2023-09-28 13:35:05 +01:00
Dave Pearson
dee745929f
Merge pull request #3399 from guy-av/fix/palette-no-results-flicker
Add countdown to showing command palette `no matches` message
2023-09-28 09:37:41 +01:00
Dave Pearson
57237461a8
Update the CHANGELOG 2023-09-28 08:42:06 +01:00
Guy Avital
0289a208d2
test_no_results() wait for message to show
The "no matches found" message in the command palette show after a specific delay, so make the test wait the same delay
2023-09-27 22:51:41 +03:00
Guy Avital
ee5b37f1bf
Add countdown to showing command palette no matches message
The countdown protects from spamming the message and helping the palette feel smoother when there are no matches
2023-09-27 22:51:41 +03:00
Rodrigo Girão Serrão
5414f2fb1e
Merge pull request #3416 from Textualize/sparkline-component-classes-docs
Fix component classes section for sparkline widget.
2023-09-27 18:05:56 +01:00
Rodrigo Girão Serrão
43337422f6
Fix component classes section for sparkline widget. 2023-09-27 17:00:01 +01:00
Dave Pearson
14259bbfee
Merge pull request #3371 from davep/knock-text-area-off-the-roadmap
Tick off `TextArea`-related items on the roadmap
2023-09-27 15:40:59 +01:00
Dave Pearson
90637502ed
Untick "smart features"
Until we are sure what these actually are, I guess.
2023-09-27 15:33:35 +01:00
Dave Pearson
7d7259f4a6
Merge branch 'main' into win32-emoji-paste-fix 2023-09-27 13:50:06 +01:00
Dave Pearson
fb81ee9562
Merge pull request #3409 from joshbduncan/disabled-trees
fix Tree(disabled=True) breaking app
2023-09-27 09:46:06 +01:00
Josh Duncan
6698bbb3bc fix type error for GenericAlias 2023-09-26 23:07:14 -04:00
Josh Duncan
584f3fcaa6 fix Tree(disabled=True) breaking app
Fixes #3407 where `Tree` widget initialized/mounted with `disabled=True`
would break it's parent app
2023-09-26 22:51:49 -04:00
Darren Burns
d766bb9566
TextArea test fixes for 3.7 (#3397)
* TextArea test fixes for 3.7

* Update tests/snapshot_tests/test_snapshots.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update tests/snapshot_tests/test_snapshots.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update tests/text_area/test_languages.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update tests/text_area/test_languages.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-09-26 10:16:54 +01:00
Rodrigo Girão Serrão
8447192cb2
Merge pull request #3360 from Textualize/pilot-click-3349
Pilot.click/hover methods restricted to the visible area
2023-09-25 14:07:36 +01:00
Rodrigo Girão Serrão
7d11422697
Fix hover coordinate system. 2023-09-25 13:53:25 +01:00
Rodrigo Girão Serrão
31d95dd504
Add tests for click/hover coordinate system. 2023-09-25 13:53:14 +01:00
Rodrigo Girão Serrão
1b1513dd82
Add PR link to changelog. 2023-09-25 13:15:25 +01:00
Rodrigo Girão Serrão
d8bb333cb8
Changelog. 2023-09-25 13:04:14 +01:00
Rodrigo Girão Serrão
39ae29aa23
Fix for the screen coordinate system. 2023-09-25 13:01:48 +01:00
Rodrigo Girão Serrão
6d1b81f7bd
Merge branch 'main' into pilot-click-3349 2023-09-25 11:52:45 +01:00
Rodrigo Girão Serrão
8198801242
Merge pull request #3396 from Textualize/pilot-click-query-app
Pilot.click/hover can now target screen explicitly.
2023-09-25 11:31:02 +01:00
Rodrigo Girão Serrão
0d39206fc8
Fix #3395. 2023-09-25 10:56:19 +01:00
Dave Pearson
e889c95efb
Merge branch 'main' into win32-emoji-paste-fix 2023-09-25 10:26:21 +01:00
Will McGugan
4d1f057968 keep old title to retain slug 2023-09-23 14:06:20 +01:00
Will McGugan
ffbf119286 Tweak title to broaden appeal 2023-09-23 13:51:29 +01:00
Dave Pearson
356ce4f3ab
Merge pull request #3383 from davep/text-area-theme-type-tweak
Don't document `TextArea` `language` and `theme` twice
2023-09-23 09:25:01 +01:00
Dave Pearson
75bb733025
Don't document TextArea language and theme twice
Also don't confuse type checks with an incompatible type declaration for
theme.
2023-09-22 22:17:55 +01:00
Will McGugan
c8b388cd3d corrections pointed out by Darren 2023-09-22 18:41:32 +01:00
Will McGugan
c6bda703c2 testing words 2023-09-22 15:33:46 +01:00
Dave Pearson
0014da04cb
Move Markdown.goto_anchor change to correct version in CHANGELOG
Looks like this ended up dropped into the wrong version.
2023-09-21 18:05:25 +01:00
Dave Pearson
5f74384c7c
Tick off TextArea-related items on the roadmap
Not actually quite sure what indentation guides means here, so I'm leaving
that alone.
2023-09-21 18:01:26 +01:00
Will McGugan
9eb7b4c7c7 version bump 2023-09-21 17:16:49 +01:00
Darren Burns
a87bab823f
Include highlights files in distribution (#3370)
* Include highlights files in distribution

* Remove redundant line from pyproject

* Added CHANGELOG for text-area hotfix
2023-09-21 17:15:32 +01:00
Rodrigo Girão Serrão
78fae6cbb1
Finish docstrings. 2023-09-21 14:54:59 +01:00
Rodrigo Girão Serrão
4dd80e9122
Fix tests to comply with new API. 2023-09-21 14:50:02 +01:00
Rodrigo Girão Serrão
66073919fa
Address review feedback. 2023-09-21 14:49:50 +01:00
TomJGooding
5cf449cfc3
docs(blog): fix broken text area link (#3368) 2023-09-21 13:27:43 +01:00
Will McGugan
d09e2d4c91 fix link 2023-09-21 13:26:34 +01:00
Will McGugan
701cd25472
new release (#3365)
* new release

* more release

* words

* Changelog

* remove words

* words
2023-09-21 12:56:20 +01:00
Darren Burns
9c8a8df028
Snapshot testing guide (#3357)
* Snapshot testing guide

* Typo fixes

* Some more typo fixes

* Typo fixes

* Update docs/guide/testing.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Add clarifications, PR feedback

* Add clarifications, PR feedback

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-09-21 11:16:11 +01:00
Darren Burns
bbde62fc57
Text area (#2931)
* Add docstring and switch to tree-sitter-languages wheels - although the wheels arent working

* Adding highlights files

* Fix index error on SyntaxAwareDocument

* Narrowing highlighting scope

* Adding basic highlights for Markdown

* Using utf-8 byte length instead of codepoint count in syntax aware doc

* Start creating an ABC defining functionality required by Document impls

* Simplify tree-sitter logic

* Extracting more ABC

* Fix width calculation, add SyntaxTheme

* Ensure the highlight line style goes right to the very end

* Updating a docstring

* Renaming, and adding document width guide

* Ensuring that line number column toggling refreshes virtual size

* Ensuring that line number column toggling refreshes virtual size

* Width guide

* Fix focus event stopping

* Use release_mouse

* Improving a docstring

* Remove bash

* TextArea language snapshot testing

* Updating snapshots for TextArea since we now highlight more nodes

* Typing fixes

* Testing

* Adding tests

* Fixing language selection

* Refresh size on indent width change

* Testing, renaming, fixing display of selection

* Fix multibyte highlight glitch

* Fix deleting right with selection at end of document in TextArea

* Fixing utf-8 multibyte character issues

* Default location of text insertion is cursor position, add cursor_location properties

* Removing some debugging code

* Cursor location tests

* Updating snapshots

* Cached utf8 encoding

* TextArea selection snapshot testing

* Tidying docstrings and queries

* Updating selection snapshot output

* Binding for ESC to shift focus

* Only build the tree-sitter query once!

* Expand cursor scroll horizontal leeway in TextArea

* Property setter for cursor_location in TextArea shouldnt return value

* Avoiding NamedTuple subclassing - using type aliasing instead

* Tidying API, docstrings etc.

* Tidying the API and docstrings

* TextArea additional cursor tests

* Testing pageup and pagedown in TextArea

* Fix a faulty test

* Docstring in a test for TextArea edit

* Stop using DEFAULT_SYNTAX_THEME

* Docstrings

* Change cursor_destination to move_cursor, add more tests

* Remove faulty assertion

* Tidying cursor movement

* Tidying up, adding docstrings for component classes

* Fix a broken selection test

* Remove some unused highlighting machinery

* Fix some Python highlighting issues

* Make HTML syntax highlight nicely

* Create tag name for mismatching HTML end tag

* Add styling for YAML, update boolean styling

* Stylising toml types

* Styling floats

* JSON syntax highlighting

* Updating snapshots

* Syntax highlighting datetimes in TOML

* Namespace TOML errors in highlighting

* Add a move_cursor_relative method

* Update TOML TextArea snapshot for datetime highlighting support

* Adjusting selections

* At TextArea widget level, delete_range is insert_range of empty string

* Refactoring

* Dunder all, docstring fix

* Fix XFAIL

* Remove unused import

* More tests, tidying up

* Cleaning the API

* Docstrings for TextArea

* A bunch of docstrings, delete unused code

* More tidying and docstrings

* Cursor origin on document load, correctly handle delete word left/right when selection is non-empty, fix delete_line when selection spans multiple lines and is in reverse direction

* Moving things around

* Fixing dunder all to export DocumentBase

* Add docstring

* Record cursor width on programmatic insert since it can result in the cursor moving

* Typing fixes

* Fixing remaining typing issues with TextArea

* Add tree-sitter-languages stubs and fix typing issues in documents

* Fixing remaining typing issues with document

* Updating Syntax themes

* Improve highlighting, add initial TextArea docs page

* Add TextArea indent note

* Start TextArea guide inside reference

* Add TextArea to widget gallery

* Fleshing out TextArea docs

* Add note

* Fix TextArea programmatic insert/cursor interaction

* Improve a test

* Testing replacement within selection

* Testing double-width character keyboard navigation and deletion keybinds with active selections

* Testing "delete to start of line" TextArea binding

* Testing TextArea delete line methods and delete to end of line

* Testing shift selecting using keyboard in vertical direction

* Expand tests for home and end keybinds in TextArea

* Renaming tests, testing empty replace and insert

* Testing delete word left via API

* Testing delete word left via API

* Testing delete_word_left with tabs, and delete_word_right

* Remove unused variables

* Remove debugging width guide

* Fix snapshot report path

* Deleting word left/right interaction with line ends fixes, ensure cursor width recorded on all edits

* Docstring fixes

* Unpin textual snapshot library dependency (issue is fixed)

* Docstring fixes

* Fix recording cursor width

* Fix a docstring

* Add select_all to TextArea

* Remove unused tree-sitter stuff from .gitignore

* Line select

* Make word pattern private in TextArea

* Add blinking cursor to TextArea

* Renaming, adding missing return typing

* Add selection bindings

* Moving cursor left/right by word while selecting

* Change escape keybind description, TextArea

* Stripping whitespace when going word left/right

* Add missing annotation

* Cursor word right and left parity with PyCharm

* Use repaint=False for cursor blink

* Improve focus/blur styling

* A whole bunch of TextArea testing

* Simplify delete_left and delete_right

* Testing hiding line numbers in snapshot

* Adding snapshot test for unfocus styling

* Create initial snapshot for text-area unfocused

* Support shift+home, shift+end

* Document shift+home, shift+end

* Add Dracula syntax highlighting theme

* Small change to delete_line behaviour when multiple lines selected to match vscode/pycharm behaviour

* Add test for new delete line logic

* Delete line improvement

* Add extra test for delete_line multiple selection

* Test cursor "smart" home behaviour

* Fix typo

* Highlight matching brackets

* Update snapshot

* Update snapshot

* Fix xfails

* Simplify delete_word_left

* Catch correct exception to ensure support for Python 3.7

* Add styling for Markdown

* Add styles for Dracula for Markdown

* Remove unused _fix_direction.py

* Add docstring to EditResult

* Use default=0 in max inside Document

* Remove redundant actions

* Use cell-width aware expand tabs implementation from @willmcgugan

* Construct strip with cell length

* Some TextArea keyword-only arguments

* Begin moving over to TextAreaTheme #skipci

* Prepare queries inside document #skip-ci

* Add comment

* Refactoring

* TextAreaTheme styling

* Setting width of blank selected lines

* Building the highlight map in the text area

* Remove unused default css from TextArea

* Moving highlighting stylize into widget

* Moving syntax highlighting into TextArea widget

* Remove unused code

* Optimise imports

* Fix highlighting when initial text supplied to TextArea

* Rebuild highlight map when the theme changes

* Extending

* Restore themes

* Remove old comment, fix docstring

* Fixing docstrings

* Fixing mypy

* Fixing mypy issues in document

* Tidying things

* Updating version

* Add theme

* Fix VSCode theme bracket matching

* Only match brackets when theres no selection

* Highlighting tidying

* Fix markdown header highlighting

* Setting theme correctly in background

* Tidying module interface

* Merging main

* Fixing a bunch of typing problems

* Fixing more typing problems

* Correctly setting theme object

* mypy

* Small fix to bracket matching

* Improve a docstring

* Fix docstring

* Testing builtin and custom languages

* Unit testing theme stuff

* Reworking themes

* Error handling

* Improve error message

* Testing new theme setting approach, error handling

* Improvements/tests for theme and language setting

* Remove unused TextArea unfocus snapshot

* Update snapshot file

* Adding theme snapshot tests

* Add `function.call` style binding in dark vscode theme

* Renaming a test file

* Making active line clearer on vscode theme

* Renaming tests

* A whole lot of docs for TextArea

* Update wording in docs

* A bit more docs

* Example on adding Java as a custom language

* More custom language docs

* Finishing up custom themeing/syntax highlighting guide for TextArea

* Add note on potential issue

* Fix wording

* Add note on Apple Silicon Python 3.7 fallback

* Add another note on Apple Silicon Python 3.7 fallback

* Fix class names in example files

* Add some documentation for useful TextArea APIs

* TextArea docs improvements

* TextArea docs typo fix

* Note about extending TextArea

* Tab-stop support when spaces used for indent

* Docs update

* Text area blog post (#3356)

* Start blog post

* Add demo script to blog post

* Continuing the blog post

* Yet more writing for TextArea blog post

* Working on closing section

* Finishing up

* Update docs/blog/posts/text-area-learnings.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Update docs/blog/posts/text-area-learnings.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Typo fix

* Update docs/blog/posts/text-area-learnings.md

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>

* Remove redundant pass

* Add docstring

* Docs fix

* Simplify docs

* Improve docstring

* Add links in docstrings

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-09-21 11:10:14 +01:00
Will McGugan
d204ba86b5
Scoped css (#3358)
* Scoped css

* snapshot tests

* selector

* Update docs/guide/widgets.md

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-09-21 09:58:59 +01:00
Dave Pearson
0bef8fbf37
Merge pull request #3334 from pawamoy/goto-anchor-returns-bool
Return a boolean from `Markdown.goto_anchor`
2023-09-21 09:49:45 +01:00
Timothée Mazzucotelli
91ab82e8fa fixup! Return a boolean from Markdown.goto_anchor 2023-09-21 10:28:05 +02:00
Timothée Mazzucotelli
63d7fb0ea6 Merge branch 'main' into goto-anchor-returns-bool 2023-09-21 10:25:48 +02:00
Rodrigo Girão Serrão
8aab7c2520
Speed up tests a bit.
Turning off the animation will make the scrolling slightly snappier.
2023-09-20 17:45:23 +01:00
Rodrigo Girão Serrão
5914e03728
Pilot.click/hover are now aware of mistargets.
The methods click/hover will now raise an error if they target a region that is outside of the target widget or completely outside of the screen. Then, they return a Boolean that indicates whether the click/hover hit the intended widget or not.

Related issue: #3349.
2023-09-20 17:41:03 +01:00
Rodrigo Girão Serrão
8007031f61
Test Pilot.click and Pilot.hover. 2023-09-20 17:23:36 +01:00
Rodrigo Girão Serrão
5a6130af0b
Test Pilot.click/hover outside of screen. 2023-09-20 14:26:45 +01:00
Rodrigo Girão Serrão
79e9f3bc16
Tweak progress bar docs. (#3286)
* Tweak progress bar docs.

There is no good reason as to why the progress bar can't be set back to its indeterminate state (and you could actually do it with code) so this removes the docstring that says that a progress bar can't go back to its indeterminate state.

Related issue: #3268
Related Discord message: https://discord.com/channels/1026214085173461072/1033754296224841768/1149742624002023594

* Use a special sentinal in ProgressBar.update

To comply with https://github.com/Textualize/textual/pull/3286#pullrequestreview-1628601324 we create a new type around a sentinel object and check whether we're using the sentinel before modifying the progress bar reactives.

Things that didn't quite work well:
- directly checking 'if parameter is not _sentinel:' won't satisfy type checkers because that condition doesn't restrict the type of 'parameter' to _not_ be 'UnsetParameter'.
- checking 'isinstance(parameter, float)' isn't enough because the user may call the method with an integer like '3' and then the isinstance check would fail.

- checking 'isinstance(parameter, (int, float))' works but looks a bit odd, plus it is not very general.

* Rework ProgressBar.update with a sentinel value.
2023-09-20 13:51:01 +01:00
Rodrigo Girão Serrão
dfba992722
DataTable new rows can have auto height. (#3213)
* DataTable new rows can have auto height.

Related issue: #3122.

* Test auto height computation in DataTable.add_row

* Add snapshot test for add_row height=None.

* Extract some styles logic into auxiliary methods.

When adding a row with automatic height, I need to render the cells to compute their height. Instead of wasting that rendering, I want to do it well and then cache it, which means I need to reuse some of the logic of the other rendering methods. By extracting some logic, I'll be able to reuse it.

* Cache auxiliary cell renderings.

* Fix test import.

* Set row height to 0 when adding auto-height row.

* Remove superfluous cache clear.

* Fix cache/typing issue.

* Cache method to compute styles to render cell.

We extract this logic into a method for two reasons.
For one, having this as a method with an lru cache enables caching these auxiliary styles, which don't depend directly on the location of the cell, but instead depend on the values of 9 Boolean flags (making for a total of 512 possible combinations, versus the infinite number of different positions/states a cell can be in.
Secondly, having this as a method allows me to compute these styles more easily from within _update_dimensions when trying to salvage the renderings of the cells of a new row that may have been pre-rendered with the wrong height.
(See the following commits for more context.)

* Perform surgery on the datatable cache.

* Improve data table tests.

* Reduce cache size.

The first five parameters (is_header_cell, is_row_label_cell, is_fixed_style_cell, hover, and cursor) are the ones that change more frequently, so it is reasonable to fix the size of the cache at 32.

Related comment: https://github.com/Textualize/textual/pull/3213#discussion_r1326071862

* Clear cache with other caches.

Related comment: https://github.com/Textualize/textual/pull/3213#discussion_r1326071862.
2023-09-20 13:49:48 +01:00
Rodrigo Girão Serrão
732ea9d1f7
Fix #3312. (#3313) 2023-09-20 12:58:59 +01:00
Dave Pearson
6d3b506387
Mark the command palette as existing (#3348)
* Mark the comment palette as existing

I've not checked of "Command menu" as that sounds like something slightly
different from the command palette.

* Reword the command palette part of the roadmap
2023-09-19 17:54:29 +01:00
Rodrigo Girão Serrão
e936d50d62
Merge pull request #3292 from Textualize/contributing
Update CONTRIBUTING.md.
2023-09-19 14:20:36 +01:00
Rodrigo Girão Serrão
711d3dc0f0
Address review feedback. 2023-09-19 13:22:40 +01:00
Rodrigo Girão Serrão
73cac88bef
Update CONTRIBUTING.md
Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-09-19 13:16:52 +01:00
Will McGugan
e793dd81f1 blurb 2023-09-19 13:08:22 +01:00
Will McGugan
f187a420ef welcome tweak 2023-09-19 12:46:43 +01:00
Will McGugan
b1dfd11568 fixed line numbers 2023-09-19 12:03:44 +01:00
Rodrigo Girão Serrão
3825f43234
Tweak docs. (#3346) 2023-09-19 11:07:10 +01:00
Will McGugan
32a0091973 definsive repr 2023-09-19 10:57:58 +01:00
Will McGugan
c2a1d82741 fix links 2023-09-19 10:49:31 +01:00
Will McGugan
27ab81ef2e Module docs 2023-09-19 10:22:35 +01:00
Will McGugan
26ba3b15b9
Update lockfile (#3341) 2023-09-18 13:31:45 +01:00
Timothée Mazzucotelli
ae77c1df1c fixup! Return a boolean from Markdown.goto_anchor 2023-09-18 11:35:38 +02:00
Dave Pearson
b886ef4e45
Merge pull request #3337 from 1j01/patch-1
Fix heading in changelog for 0.37.0
2023-09-18 08:43:01 +01:00
Isaiah Odhner
34a2a1343b
Fix heading in changelog for 0.37.0 2023-09-18 02:09:11 -04:00
Timothée Mazzucotelli
f72f555872 Return a boolean from Markdown.goto_anchor 2023-09-17 11:36:51 +02:00
Will McGugan
b99da2d6b9
Testing guide (#3329)
* testing docs

* words

* words

* testing doc

* Apply suggestions from code review

Co-authored-by: Gobion <1312216+brokenshield@users.noreply.github.com>

---------

Co-authored-by: Gobion <1312216+brokenshield@users.noreply.github.com>
2023-09-17 10:34:32 +01:00
Dave Pearson
31eaf3ffb8
Fix command palette docs example (#3331) 2023-09-17 09:02:04 +01:00
Will McGugan
6d561d4ed0 fix changelog 2023-09-16 10:56:11 +01:00
Will McGugan
e14cdd0757 version bump 2023-09-16 10:54:37 +01:00
Dave Pearson
8002583fa1
Stop command palette Input message leakage (#3322)
* Fix Input event leakage from Command Palette to app

* Update the CHANGELOG
2023-09-16 10:53:44 +01:00
Will McGugan
427e45a945 changelog 2023-09-16 10:50:10 +01:00
Dave Pearson
bebadb0f02
Fix command palette TimeoutError error (#3321)
* Reinstate the import of TimeoutError from asyncio

Fixes #3320

It looks like eaa749665f9b8271eff45be8e5e1e72ac8729b9e smuggled this change
in and caused the command palette to cease to work correctly on any version
of Python before 3.11.

This should make it work on all Pythons from 3.7 onward again.

* Update the CHANGELOG
2023-09-16 10:44:15 +01:00
TomJGooding
137a98759d
docs: fix typos in release 0.37.0 blog (#3317) 2023-09-15 17:01:09 +01:00
Will McGugan
8b4ecb2bc7 words 2023-09-15 16:47:16 +01:00
Will McGugan
4dc8358c63
new release (#3316) 2023-09-15 16:40:05 +01:00
Will McGugan
ce32abd37e
Use active message pump in pop screen (#3315)
* Use active message pump in pop screen

* message pump
2023-09-15 14:08:41 +01:00
Will McGugan
149c5e2a1d
color command example (#3314)
* color command example

* Scroll to end
2023-09-15 13:11:34 +01:00
Dave Pearson
129163f624
Merge pull request #3309 from davep/tweak-command-palette-busy-indication
Tweak command palette busy indication
2023-09-14 21:22:01 +01:00
Dave Pearson
f8d3a98fb1
Regenerate snapshots 2023-09-14 21:02:02 +01:00
Dave Pearson
2f5b282589
Only stop the busy timer on a clean exit
Fixes #3299. Long story short: if a previous search was in the process of
stopping it looks like it could end up killing the timer for the next
search; given a fresh search resets the timer anyway there's no sense in
stopping the timer when we're being aborted.
2023-09-14 20:49:28 +01:00
Dave Pearson
a8820666ac
Remove double assignment
Looks like I was having a moment when I typed this line.
2023-09-14 20:48:43 +01:00
Will McGugan
983e33d547 fix title 2023-09-14 19:03:18 +01:00
TomJGooding
bb2a21e62a
docs: correct grid gutter type (#3307) 2023-09-14 18:52:25 +01:00
Will McGugan
9431890a7d
Collapsible style tweak (#3306)
* tweaks to style

* changelog

* snapshot

* add additional space for nested widgets

* tweak to nested collapsibles and snapshots

* remove superfluous rules
2023-09-14 17:34:15 +01:00
Will McGugan
1db9ecb302
Update Collapsible (#3305)
* Update Collapsible

* snapshot tests

* word

* Update docs/widgets/collapsible.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/widgets/collapsible.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* simplify render

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-09-14 16:26:41 +01:00
Will McGugan
ea6bf766e7
Cp shutdown (#3303)
* change hotkey

* binding

* rename Source to Provider

* name change

* name changes

* words

* docstring

* system commands

* add icon click

* replace dim with muted

* log shutdown errors

* Update src/textual/screen.py

Co-authored-by: Dave Pearson <davep@davep.org>

* fix tests

* Wee bit more source->provider rewording

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-09-14 15:21:51 +01:00
Sunyoung Yoo
3b2b9aaaf5
Widget collapsible (#2989)
* Collapsible container widget.

* Expose collapsible widget.

* Add collapsible container example

* Rename member variables as label and apply formatting

* Apply hover effect

* Apply formatting

* Add collapsible construction example with children.

* Wrap contents within Container and move _collapsed flag to Collapsible class from  Summary for easier access.

* Add collapsible example that is expanded by default.

* Update collapsed property to be reactive

* Add footer to collapse and expand all with bound keys.

* Expose summary property of Collapsible

* Assign ids of ollapsed, expanded label instead of classes

* Add unit tests of Collapsible

* Rename class Summary to Title

* Rename variables of expanded/collapsed symbols and add it to arguments..

* Add documentation for Collapsible

* Update symbol ids of Collapsible title

* Update src/textual/widgets/_collapsible.py

Correct import path

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Sort module names in alphabetical order

* Clarify that collapsible is non-focusable in documentation.

* Add version hint

* Fix documentation of Collapsible.

* Add snapshot test for collapsible widget

* Stop on click event from Collapsible.

* Handle Title.Toggle event to prevent event in Contents from propagating to the children or parents Collapsible widgets.

* Update Collapsible default css to have 1 fraction of width instead of 100%

* Update Collapsible custom symbol snapshot

* Add Collapsible custom symbol snapshot as an example

* Update docs/widgets/collapsible.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/widgets/_collapsible.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Fix typo in Collapsible docs

* Rework collapsible documentation.

---------

Co-authored-by: Sunyoung Yoo <luysunyoung@aifactory.page>
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-09-14 13:10:21 +01:00
Dave Pearson
ccc3e7a791
Merge pull request #3298 from davep/command-palette-visual-tweaks
Command palette visual tweaks
2023-09-13 22:10:16 +01:00
Dave Pearson
26e9833144
Merge pull request #3300 from davep/remove-screen-assert
Remove assertion that the calling screen is not None
2023-09-13 22:09:54 +01:00
Dave Pearson
9368e9e8ed
Merge pull request #3297 from davep/remove-unused-match-style
Remove unused grab of the match component style
2023-09-13 22:09:21 +01:00
Dave Pearson
767990eabe
Merge pull request #3296 from davep/remove-unused-command-import
Remove an unused import from command.py
2023-09-13 22:09:00 +01:00
Dave Pearson
5c9c6fcded
Update snapshits (redux) 2023-09-13 21:57:29 +01:00
Dave Pearson
0c75239ebc
Remove assertion that the calling screen is not None
The assert was for the benefit of type checkers; the code that needed that
hint was moved elsewhere by the recent tweak; but this wasn't tidied up.

This tidies that up.
2023-09-13 21:43:57 +01:00
Dave Pearson
60edeffff6
Update snapshits 2023-09-13 21:41:56 +01:00
Dave Pearson
22fa22e3a9
Make the placeholder text of the input more specific 2023-09-13 21:24:57 +01:00
Dave Pearson
460603aa43
Make the borders of the command palette more subtle 2023-09-13 21:23:49 +01:00
Dave Pearson
5cd020ed7c
Remove unused grab of the match component style
The recent tweak of the command palette code moved the acquisition of the
match style component class elsewhere, but seems to have left this dangling.
2023-09-13 21:10:03 +01:00
Dave Pearson
4445ce392b
Remove an unused import from command.py
Presumably a hangover from the recent tweak session.
2023-09-13 21:06:56 +01:00
Dave Pearson
057cb7f76f
Ensure that print reports the correct location in console
Fixes #3237 -- see also https://github.com/Textualize/textual-dev/pull/19
2023-09-13 17:20:27 +01:00
Dave Pearson
1a471fd19c
Merge pull request #3293 from davep/undocument-optionlist-default-css
Remove the docstring for `OptionList.DEFAULT_CSS`
2023-09-13 17:08:31 +01:00
Rodrigo Girão Serrão
7284e83df2
Reword issue instructions bit.
Related comment: https://github.com/Textualize/textual/pull/3292#discussion_r1324745448
2023-09-13 17:06:51 +01:00
Dave Pearson
6dfe017c52
Remove the docstring for OptionList.DEFAULT_CSS
We really don't need to document anything like this, I'll have done it by
habit, and having it there pulls it into the docs which then pollutes the
search results if someone is searching for what DEFAULT_CSS is all about.
2023-09-13 16:51:40 +01:00
Rodrigo Girão Serrão
b12fa2ac7e
Address review feedback. 2023-09-13 15:50:36 +01:00
Will McGugan
5d6a95dec5
Command Palette tweaks and docs (#3289)
* renames to command palette and docs

* docs

* simplifyt

* note

* docstring

* Update src/textual/command.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/examples/guide/command_palette/command01.py

Co-authored-by: Dave Pearson <davep@davep.org>

* populate text

* screen commands

* Update docs/guide/command_palette.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Update docs/guide/command_palette.md

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
Co-authored-by: Dave Pearson <davep@davep.org>
2023-09-13 15:03:25 +01:00
Rodrigo Girão Serrão
5ddeadc62e
Update contributing.
Related issue: #3229.
2023-09-13 14:55:04 +01:00
Dave Pearson
b6bbcb15f9
Recode incoming text on Windows before input event processing
See #3178.
2023-09-13 09:44:43 +01:00
Dave Pearson
0a14bf0549
Merge pull request #3287 from davep/blog-metadata-update
Update the blog author metadata.

WARNING: Be sure to do an update of dependencies before serving or building docs from this point on!
2023-09-12 14:18:38 +01:00
Dave Pearson
8e315a1cd1
Update the blog author metadata
As per the warning if you use the latest release of mkdocs-material:

WARNING -  Action required: the format of the authors file changed.
           All authors must now be located under the 'authors' key.
           Please adjust 'docs/blog/.authors.yml' to match:

           authors:
             squidfunk:
               avatar: https://avatars.githubusercontent.com/u/932156
               description: Creator
               name: Martin Donath

Note that this is for after:

  Updating mkdocs-material (8.5.9+insiders.4.26.2
  /Users/davep/develop/python/mkdocs-material-insiders -> 9.2.7)

It's also worth noting that our docs should now build regardless of
insiders' edition or not now; given that the blog module is part of the
mainstream release.
2023-09-12 13:04:49 +01:00
Dave Pearson
6d1967be7a
Merge pull request #3276 from TomJGooding/docs-add-datatable-supplementary-classes
docs: add datatable supplementary classes
2023-09-12 12:57:32 +01:00
Dave Pearson
0f9d189978
Merge pull request #3244 from davep/markdown-anchor-jump
Fix Markdown anchor load crash, and support going to an heading on document load
2023-09-12 12:38:47 +01:00
Dave Pearson
f19ed898ff
Merge pull request #3285 from TomJGooding/test-remove-dupe-directory-tree-test
test: remove dupe directory tree test
2023-09-12 12:38:21 +01:00
TomJGooding
0f18453b44
test: remove dupe directory tree test 2023-09-12 11:12:49 +01:00
Dave Pearson
31636e7679
Merge branch 'main' into markdown-anchor-jump 2023-09-12 11:10:31 +01:00
Dave Pearson
a83954e122
Actually link to the relevant PR 2023-09-12 11:08:13 +01:00
Rodrigo Girão Serrão
d31fb82239
Merge pull request #3203 from TomJGooding/feat-directory-tree-add-directory-selected-message
feat(directory tree): add directory selected message
2023-09-12 10:29:13 +01:00
TomJGooding
25ff8e791d
Merge branch 'main' into feat-directory-tree-add-directory-selected-message 2023-09-11 21:24:12 +01:00
Dave Pearson
460bbbad8d
Merge branch 'main' into markdown-anchor-jump 2023-09-11 20:18:53 +01:00
Dave Pearson
7ca5dd69ef
Merge pull request #3058 from davep/M-x
Command palette
2023-09-11 15:09:03 +01:00
Will McGugan
9ca0929099
Merge branch 'main' into M-x 2023-09-11 14:49:28 +01:00
Rodrigo Girão Serrão
cc8adeaba0
Merge pull request #3193 from Textualize/input-blur-validation
Customisable input validation (& validation on blur events)
2023-09-11 14:38:06 +01:00
Rodrigo Girão Serrão
d39c0c3a89
Improve documentation. 2023-09-11 14:28:23 +01:00
Rodrigo Girão Serrão
0c23aefcc0
Merge branch 'main' into input-blur-validation 2023-09-11 14:27:31 +01:00
Rodrigo Girão Serrão
7d4a47b253
Merge pull request #3199 from Textualize/screen-title-sub-title
Add title and sub-title to screens.
2023-09-11 13:49:28 +01:00
Will McGugan
9e29982ebb
Make notify thread-safe (#3275)
* Make notify thread-safe

* test fixes

* docstring

* Update tests/notifications/test_app_notifications.py

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-09-11 13:25:31 +01:00
TomJGooding
3d7f5e2c74 docs: add datatable supplementary classes 2023-09-11 13:16:07 +01:00
Rodrigo Girão Serrão
5a15e9c8aa
Add docstrings to properties.
Related comment: https://github.com/Textualize/textual/pull/3199#discussion_r1321288977
2023-09-11 11:37:44 +01:00
Rodrigo Girão Serrão
63ace0715e
Merge branch 'main' into input-blur-validation 2023-09-11 11:30:38 +01:00
Rodrigo Girão Serrão
a263072781
Invert logic to specify events for input validation.
Related review comment: https://github.com/Textualize/textual/pull/3193#discussion_r1321250339.
2023-09-11 11:30:00 +01:00
David Hallas
550f647e0f
Fixes missing fileno function (#3111) (#3239)
Adds missing fileno function to _PrintCapture class. This is needed
because _PrintCapture behaves like a normal stdin/stdout/stderr class
which provides this method.
2023-09-11 10:39:05 +01:00
Rodrigo Girão Serrão
53125ec7d4
Merge branch 'main' into screen-title-sub-title 2023-09-11 10:31:29 +01:00
Will McGugan
b9e1521835
Merge branch 'main' into feat-directory-tree-add-directory-selected-message 2023-09-11 10:30:02 +01:00
Rodrigo Girão Serrão
5ec3feafc7
Type Screen.(SUB_)TITLE as class var.
Related review comment: https://github.com/Textualize/textual/pull/3199/files#r1321216368.
2023-09-11 10:28:50 +01:00
Rodrigo Girão Serrão
4ed93d45c1
Add screen_(sub_)title properties to header.
Related review comment: https://github.com/Textualize/textual/pull/3199/files#r1321226453.
2023-09-11 10:27:24 +01:00
Dave Pearson
60d5005a68
Merge pull request #3274 from davep/fix-optionlist-hover-remove-crash
Fix an OptionList crash when removing an option during mouse hover
2023-09-11 09:59:27 +01:00
Dave Pearson
a107218064
Fix an OptionList crash when removing an option during mouse hover
If the mouse is hovering over the last option in an OptionList, and an
option is removed, the application will crash with an IndexError. The
problem was that the record of the hovered option needed to be cleared when
an option is removed (as it is during other changes).

Fixes #3270
2023-09-11 09:22:24 +01:00
Darren Burns
74aa90f5ac
Add Python 3.12 to CI suite (#3255) 2023-09-10 14:58:33 +01:00
Dave Pearson
1d120d91fc
Fix being asked to go to an anchor with no filename given
Co-authored-by: Timothée Mazzucotelli <pawamoy@pm.me>
2023-09-08 07:57:20 +01:00
Dave Pearson
4ac8df2574
Improve the test for file and string markdown viewing
Co-authored-by: Timothée Mazzucotelli <pawamoy@pm.me>
2023-09-07 17:24:53 +01:00
Dave Pearson
ea832b8a9a
Add tests for clicking on a link when markdown is from a string
Co-authored-by: Timothée Mazzucotelli <pawamoy@pm.me>
2023-09-07 16:43:09 +01:00
Dave Pearson
3b0e86bfef
Add more testing of clicking on links 2023-09-07 16:39:47 +01:00
TomJGooding
362684b63e merge main and resolve changelog conflict 2023-09-07 16:08:46 +01:00
Will McGugan
85970972d9
blog post (#3248)
* blog post

* bump timestamp

* words
2023-09-06 17:53:31 +01:00
Dave Pearson
63cbc52952
Remove screenshot as a system command for the command palette
While it's kinda cool... it's not really very helpful if you're doing things
via textual-web; all you're going to do is start to use storage on the host
machine, not the client machine (unless they're the same thing, of course).
2023-09-06 14:51:26 +01:00
Dave Pearson
5a272c539d
Bump predicted command palette escape to the wild to 0.37.0 2023-09-06 14:48:06 +01:00
Dave Pearson
85a3af320a
Merge branch 'main' into M-x 2023-09-06 14:46:33 +01:00
Dave Pearson
1c1836e7f4
Handle locations that are *just* the anchor
If just an anchor is given, it is assumed that we'll be finding it within
the current document.
2023-09-06 14:06:13 +01:00
Dave Pearson
db2a5853d8
Make sanitize_location a public API method 2023-09-06 13:29:52 +01:00
Dave Pearson
284a5b973f
Make goto_anchor public 2023-09-06 13:19:56 +01:00
Dave Pearson
a70235e42d
Update the CHANGELOG
Co-authored-by: Chakib Benziane <contact@blob42.xyz>
2023-09-06 10:18:47 +01:00
Dave Pearson
738eb7b9b7
After loading a Markdown document, jump to any matching anchor
Co-authored-by: Chakib Benziane <contact@blob42.xyz>
2023-09-06 10:13:37 +01:00
Dave Pearson
798f67f01d
Allow loading a different file into the markdown example
Not getting carried away with this -- frogmouth exists after all -- but
allowing passing a different file on the command line does make it easier to
quickly test the Markdown widget.
2023-09-06 09:27:22 +01:00
Dave Pearson
7f40287691
Persist the table of contents in the Markdown widget 2023-09-05 16:20:05 +01:00
Dave Pearson
fa7f6b3066
Remove any anchor that's included in a filename to load from a Markdown file
Fixes the issue reported in #3094.

There's more to come on this, as rather than just fix that error, we'd also
like to go to the header that the anchor relates to. See #3094 for an
initial approach to this. This PR builds on the idea in a different way.

But before doing that wider part, this simply starts out by fixing the
reported bug.
2023-09-05 15:35:24 +01:00
Dave Pearson
ac57633146
Add tests for loading a markdown file with an anchor included
Tests the problem reported in #3094
2023-09-05 15:33:50 +01:00
Dave Pearson
eb1fe6db71
Merge pull request #3236 from davep/markdown-homeless-snails
Add utility code for generating Markdown-oriented slugs
2023-09-05 14:36:31 +01:00
Will McGugan
2891fce71a date in changelog 2023-09-05 13:57:08 +01:00
Will McGugan
11ba91a275
version bump (#3235) 2023-09-05 13:54:56 +01:00
Dave Pearson
70ab4c7763
Add URL quoting as the final act of slugging 2023-09-05 13:51:17 +01:00
Dave Pearson
f50f4e1125
Docstring tidy 2023-09-05 12:43:12 +01:00
Dave Pearson
edc0420a5a
Simplify and improve the slugging code
This isn't 100% how GitHub's approach works, but the edge cases I can find
appear to be bugs or issues with how GitHub handle the more interesting
emoji when they appear in headers.

Long story short: they appear to just strip emoji for the most part, but if
an emoji is modified in some interesting way (think shrugging person vs
shrugging light-skinned woman with black hair) it looks like the final
codepoint "leaks" into the slug; nothing about this looks intentional, and
it's such a remote issue that it's hardly worth supporting.
2023-09-05 12:33:13 +01:00
Dave Pearson
418819c94e
General code tidying 2023-09-05 09:09:26 +01:00
TomJGooding
06b6426750
feat: add rule widget (#3209)
* feat: add rule widget

* add star to init

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* remove unnecessary validations

* update rule styles

* add tests for invalid rules

* add minimum heights and widths

* tidy up examples

* remove old example

* move examples styling to tcss

* modify examples to fit docs screenshots

* add docs first draft

* add snapshot tests

* add rule to widget gallery

* make non-widget rule classes available

* tentatively update changelog

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-09-04 17:57:10 +01:00
Will McGugan
cbed79c7eb
Modes docs (#3233)
* Modes docs

* Added current mode

* fix docstring

* diagrams

* Update docs/guide/screens.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/guide/screens.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* words

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-09-04 17:40:40 +01:00
Dave Pearson
4cbb4af807
Merge branch 'main' into markdown-homeless-snails 2023-09-04 16:40:53 +01:00
Dave Pearson
1fcf259e6d
Merge branch 'main' into M-x 2023-09-04 16:40:32 +01:00
Dave Pearson
80821155a6
Add a test for accents 2023-09-04 16:19:19 +01:00
Dave Pearson
6d4fcaa4c6
Merge pull request #3232 from davep/see-also-focus-blur
Add see-also entries to the various blur/focus messages
2023-09-04 15:46:48 +01:00
Dave Pearson
9f83145d70
Boring sort rather than exciting sort
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-09-04 15:40:33 +01:00
Dave Pearson
cd1b29fb2b
Add see-also entries to the various blur/focus messages
This question crops up from time to time, often with people looking for
"focus" or "blur" and wondering why they don't bubble and so then wondering
how they can catch such events in ancestors in the DOM.

The Descendant prefix isn't obvious (I always forget what it is and need to
go hunting), so having the focus and blur events link to the descendant
events should help make them easier to discover.
2023-09-04 15:33:44 +01:00
Dave Pearson
190a57c414
Initial work on figuring out how best to slug like GitHub Markdown
Still some work to do to figure out the rules, but this is a good starting
point.
2023-09-04 15:23:58 +01:00
Will McGugan
c63d8e05fa
return code docs (#3231)
* return code docs

* words

* words

* Update docs/guide/app.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Update docs/guide/app.md

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-09-04 14:03:25 +01:00
TomJGooding
c2fe5257bf Merge branch 'main' into feat-directory-tree-add-directory-selected-message 2023-09-04 11:45:31 +01:00
Will McGugan
229b8c4c7c
fix updating CSS on push_screen (#3218)
* fix udpating CSS on push_screen

* changelog

* lock file
2023-09-04 10:53:45 +01:00
TomJGooding
cb3b1286fc
chore: remove superfluous bubble=true from messages (#3225) 2023-09-04 10:32:49 +01:00
Dave Pearson
7434f977bb
Remove the "no matches" note as soon as possible
We've recently changed the way the command list is cleared down when the
search term is modified, thus removing a source of "flashing" as the user
types; this pretty much involves *not* clearing down the previous hits until
the first new hit comes in. This is fine in all situations expect where the
last search was a "no matches" search.

In that situation the next search stats out saying "no matches". That's
correct, that's the result of the previous search, but in this case it's
unhelpful and potentially confusing. So this commit checks if that's the
state of the command list up front and clears that option from the list.
2023-09-04 08:57:16 +01:00
Dave Pearson
e9b3e2dea5
Test for "no matches" using an ID, rather than just being disabled 2023-09-04 08:53:00 +01:00
Dave Pearson
c07ab4a7dd
Merge branch 'main' into M-x 2023-09-04 08:34:18 +01:00
Will McGugan
c5c51902e8
Fixes flicker on tree scroll (#3210)
* changelog

* changelog
2023-09-01 15:33:05 +01:00
TomJGooding
4db9a065bc import future for tests 2023-09-01 11:13:53 +01:00
TomJGooding
9e7e9ab1f4 fix too many messages and add tests 2023-09-01 09:17:16 +01:00
Dave Pearson
32ea9584a5
Add a note about retaining the default Textual command sources 2023-08-31 11:27:45 +01:00
Dave Pearson
70ee49b140
Add a wee note about what happens to unhandled exceptions 2023-08-31 11:24:07 +01:00
Dave Pearson
b5bea9b68c
Merge pull request #3212 from davep/tweak-radioset-wording
Reword the description of the buttons for a RadioSet
2023-08-31 10:41:50 +01:00
Dave Pearson
2c2c3fc92b
Reword the description of the buttons for a RadioSet
The use of collection was in the prose sense, not the technical sense, but
it could be misleading to many readers.
2023-08-31 10:29:31 +01:00
TomJGooding
6f8db6001d pop superfluous bubbles from messages 2023-08-30 18:15:03 +01:00
TomJGooding
11ec1da9ac merge main and resolve changlog conflicts 2023-08-30 18:10:48 +01:00
Dave Pearson
25a0d3b7ab
Tentatively mark the command palette as going into v0.36.0 2023-08-30 15:38:17 +01:00
Dave Pearson
f507fe09c6
Update snapshots 2023-08-30 15:21:41 +01:00
Dave Pearson
cbb3350d36
Add some extra documentation linkage 2023-08-30 15:11:40 +01:00
Dave Pearson
bb7bb238b8
Remove the colour of the highlight 2023-08-30 14:59:51 +01:00
Dave Pearson
0ce862bc9c
Move the "run" button leftward one cell 2023-08-30 14:28:48 +01:00
Dave Pearson
371048ffc2
Docstring and comment tidying 2023-08-30 14:05:40 +01:00
Dave Pearson
110ea786ae
Merge branch 'main' into M-x 2023-08-30 13:17:04 +01:00
Dave Pearson
fd3b72e093
Log command source errors rather than blow up because of them
See https://github.com/Textualize/textual/pull/3058#discussion_r1310051855
2023-08-30 12:56:01 +01:00
Rodrigo Girão Serrão
b74ac1e47f
Merge pull request #3202 from Textualize/return-codes
Add app return codes.
2023-08-30 11:18:27 +01:00
Rodrigo Girão Serrão
ecd7c93a03
Simplify return code logic.
Related comment: https://github.com/Textualize/textual/pull/3202#discussion_r1309027006
2023-08-30 11:06:33 +01:00
Will McGugan
ec6b23a2dc
add devtools_host env (#3204) 2023-08-30 09:54:47 +01:00
Dave Pearson
17351ba637
Squish the typing issue with asend
The asend back into the search routing was always showing a typing mismatch,
but I couldn't quite see what was going on; what made it even more confusing
was the code was working fine.

It looks like keeping hold of the "routine", and keeping that distinct from
the iterator of the results, is the trick here. It all still works *and* the
typing works out.
2023-08-29 20:46:21 +01:00
TomJGooding
680f167212 update changelog 2023-08-29 20:44:31 +01:00
Dave Pearson
0bd7d7fd5f
yield NotImplemented, not raise
There's one typing error that's been with me for weeks now, and nothing I
did seemed to get to the heart of it. Finally, I think it's dawned on me.
Raising NotImplemented from the abstract base implementation confuses the
type checker as it's not seeing any sort of yield going on. This... this
solves it.

I'm not 100% sure this is the correct thing to do, advice online seems
patchy at best and the couple of things I've seen that do seem to address
this sort of situation seem to introduce other typing issues (a bare yield
being the main suggestion, which won't work as then it'll be yielding the
wrong type).

Gonna sit on this for now and see how I feel about it, or see if I can find
something relevant to this.
2023-08-29 20:29:51 +01:00
TomJGooding
ce4285f315 feat(directory tree): add directory selected message 2023-08-29 20:11:41 +01:00
Dave Pearson
ad1fb4da0b
Improve the typing of the parent screen tracking 2023-08-29 15:53:58 +01:00
Rodrigo Girão Serrão
da0cd5e2c1
Return code is None before exiting.
Related comment: https://github.com/Textualize/textual/pull/3202#discussion_r1308883427
2023-08-29 15:49:48 +01:00
Yuval Moalem
6d24244b6a
Fix click on input with double width chars (#3066)
* Fix cursor position when clicking double-width char #2968

The cursor moved to the correct position only when clicking the first
index of the character. We now check if the click happened inside a
range of indices.

* Update changelog #2968
2023-08-29 15:19:49 +01:00
Rodrigo Girão Serrão
f8250dd428
Add tests for app return code. 2023-08-29 14:52:13 +01:00
Rodrigo Girão Serrão
41e5a42943
Add app return codes. 2023-08-29 14:49:47 +01:00
Dave Pearson
ecc1c11e9c
Delay showing the list until we really need it 2023-08-29 14:45:20 +01:00
Dave Pearson
aedba411ec
Stop the working on input, as soon as possible
While I don't think this really makes a difference to anything, it makes
sense in the flow of the code to make it clear we're stopping as soon as
possible. We don't need more commands from any source as we have a brand new
query.
2023-08-29 14:31:05 +01:00
Dave Pearson
74c532dabc
Don't catch a timeout we're not looking to raise any more
Vestigial seeking of forgiveness for an action that's no longer taking
place.
2023-08-29 12:43:45 +01:00
Rodrigo Girão Serrão
c63072f5bd
Link App (sub-)title to Screen respectives. 2023-08-29 12:08:57 +01:00
Rodrigo Girão Serrão
26e81c99e3
Test screen (sub-)title. 2023-08-29 12:07:09 +01:00
Rodrigo Girão Serrão
e48e0148b3
Add title and sub-title to screens.
Mimicking 'App', we provide class variables TITLE and SUB_TITLE for the screen defaults and those can then be changed via the title and sub_title reactive attributes.

Related issue: #3195
2023-08-29 12:04:39 +01:00
Dave Pearson
62bad31616
Actually use the command source in the test, in the test, redux 2023-08-29 11:37:23 +01:00
Dave Pearson
97790b461f
Actually use the command source in the test, in the test 2023-08-29 11:35:10 +01:00
Dave Pearson
6a73a2dce4
Update the pytest snapshot test library 2023-08-29 11:29:15 +01:00
Dave Pearson
d69f7f568c
Ensure the worker is cancelled when a selection is made
Helps to ensure that command sources don't carry on running longer than
necessary.
2023-08-29 10:35:20 +01:00
Dave Pearson
45c7c417da
Add back the check that a search is done
Wandered around a couple of ways of writing this, then somehow settled on a
final version that didn't do what I meant to do. O_o
2023-08-29 09:31:35 +01:00
Dave Pearson
c511b5af0e
Spell out gndn 2023-08-29 09:08:50 +01:00
Dave Pearson
d539b815c2
Bubble up any exception raised in a command source 2023-08-29 08:54:22 +01:00
Dave Pearson
f59655c463
Add a case_sensitive property to the fizzy.Matcher
Mostly useful with the repr.
2023-08-29 08:53:44 +01:00
Dave Pearson
6c55cefbf0
Tidy up the code that stops the command list flash 2023-08-29 08:19:21 +01:00
Dave Pearson
f6400a9d51
Comment tidy 2023-08-28 21:06:53 +01:00
Dave Pearson
65378cb92f
Reinstate the tracking of the very last update
Accidentally got rid if it in a recent commit.
2023-08-28 21:04:20 +01:00
Dave Pearson
7da6dc768c
Don't allow dropping the cursor into a list with zero matches
An empty command list isn't really empty, it has a single disabled option
that shows that no matches were found; there's no point in allowing that to
be highlighted by the user.
2023-08-28 19:57:31 +01:00
Dave Pearson
8caa9088b3
Don't isolate the star of the loop from the loop 2023-08-28 19:53:36 +01:00
Dave Pearson
100a9e3d03
Avoid the found commands list flashing while typing
For obvious reasons, every time the user typed a letter, the list of
already-completed commands needed to be cleared down before new ones got
added. While the code concerned with doing this was in the right place (when
a key was pressed), this had the unfortunate side-effect of making the list
appear to "flash" as the user typed the first few letters, especially if a
lot of hits were found near-instantly.

This commit delays the initial clearing-down of the content of the list,
keeping track of if the clear has been done already and only doing it at the
very last moment if it's needed.
2023-08-28 19:30:18 +01:00
Dave Pearson
e699752ffd
Make it clear what a couple of magic numbers are
Of course, they're not magic at all really, they're just fractional second
values that make sense in context; but giving them a name will help explain
what they're for.
2023-08-28 18:49:07 +01:00
Dave Pearson
6839c0393f
Batch up updates into fractions of a second 2023-08-28 16:28:44 +01:00
Rodrigo Girão Serrão
b427a8a41a
Update CHANGELOG.md 2023-08-28 16:00:05 +01:00
Rodrigo Girão Serrão
4826e436a8
Complete docs about customising validation. 2023-08-28 15:59:03 +01:00
Will McGugan
c133152f58
Pop flicker (#3194)
* reduce flicker on pop

* changelog

* changelog
2023-08-28 15:55:20 +01:00
Will McGugan
cb45dacb3a
refresh children on layout (#3192)
* refresh children on layout

* CHANGELOG [skipci]
2023-08-28 15:54:30 +01:00
Rodrigo Girão Serrão
da99114085
Test on blur /customisable input validation. 2023-08-28 15:50:26 +01:00
Rodrigo Girão Serrão
99e8e17376
Add mechanism to customise when input validation occurs.
Related issues: #3100.
2023-08-28 15:48:55 +01:00
Rodrigo Girão Serrão
71e5821b44
Validate input on blur events.
Related issues: #3100.
2023-08-28 15:48:12 +01:00
Dave Pearson
e8c159cc8d
Remove unnecessary break 2023-08-28 15:33:43 +01:00
Dave Pearson
6ce8429256
Explain the reasons behind the content of _search_for
There's a couple of "different" choices going on here, so I feel a good
helping of explanatory comments is called for.
2023-08-28 14:57:49 +01:00
Dave Pearson
9a1a29c3b5
Fix a typo 2023-08-28 14:48:56 +01:00
Dave Pearson
f7037697c7
Flush the queue faster 2023-08-28 14:48:12 +01:00
Dave Pearson
2aae0a26d9
Work harder to cancel running command search tasks
This commit takes the handling of running command search tasks a wee bit
further, sending "down" the aborted status and cancelling the tasks as soon
as possible. There are still situations where this won't really make a
difference, and depending on how the command source is coded it could carry
on running for a while, but if a command source is coded to handle being
cancelled as soon as possible this will provide what's needed to benefit
from such an approach.

Note that it *does* mean that a developer writing a command source, which
awaits something, will need to handle a CancelledError; we should probably
see about talking about this in the docs.
2023-08-28 14:34:29 +01:00
Will McGugan
be9efd971b changelog 2023-08-28 14:19:49 +01:00
Will McGugan
98168ae536 fix for textual-web flash 2023-08-28 14:19:47 +01:00
Aaron Stephens
6dd5439eac
feat(datatable): add cursor_type to constructor (#3183)
* feat(datatable): add cursor_type to constructor

* fix(datatable): formatting

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-08-28 13:56:17 +01:00
Rodrigo Girão Serrão
a50d27f712
Let layers be strings. (#3169)
* Let layers be strings.

* Changelog.
2023-08-28 13:55:14 +01:00
Rodrigo Girão Serrão
d5f07c26a1
Merge pull request #3065 from Textualize/reactive-callback
Schedule reactive callbacks on watcher.
2023-08-28 13:30:03 +01:00
Rodrigo Girão Serrão
57419aa134
Merge branch 'main' into reactive-callback 2023-08-28 11:24:54 +01:00
Dave Pearson
f929b5e569
Make the icon a string 2023-08-28 11:24:05 +01:00
Dave Pearson
7653c1133d
Remove unused imports 2023-08-28 11:20:37 +01:00
Rodrigo Girão Serrão
41006caffc
Consider visible children inside invisible containers when computing focus chain (#3070)
* Add regression tests for #3053

* Traverse invisible containers when computing focus chain.

At the moment, we were completely bypassing invisible containers which meant that their visible children wouldn't be included in the focus chain.

* Make note of removed property.

* Add regression test for #3071.

* Fix #3071.

* Fix regression test for #3053.

* Optimize computation of focus chain.

Computing the focus chain was relying on the property 'visible' of nodes which may traverse the DOM up to find the visibility of a given node. Instead, we cache the visibility of the nodes we traverse and keep them in a stack, saving some of that computation.
Related issues: #3071
Related comments: https://github.com/Textualize/textual/pull/3070#issuecomment-1669683285

* Make test more robust.

* Make test more robust.

* Short-circuit disabled portions of DOM.

If a node is disabled, we will not be focusable, nor will its children, so we can skip it altogether.
Related review comment: https://github.com/Textualize/textual/pull/3070/files#r1300292492

* Simplify traversal.

The traversal code could be simplified after reordering some lines of code.
We also get rid of the visibility stack and instead keep everything in the same stack.
Related comments: https://github.com/Textualize/textual/pull/3070#pullrequestreview-1587295458
2023-08-28 11:06:39 +01:00
Dave Pearson
e6b9a264a1
Rename search_for to search
As per this request:

  https://github.com/Textualize/textual/pull/3058#discussion_r1307135816
2023-08-28 11:05:39 +01:00
Claire-me
409363d974
Create CONTRIBUTING.md (#3115)
* Create CONTRIBUTING.md

* Update CONTRIBUTING.md
2023-08-28 11:02:13 +01:00
Dave Pearson
a807061e20
Merge pull request #3186 from davep/link-centre-faq-to-howto
Link the centring FAQ to the HOWTO
2023-08-28 08:53:09 +01:00
Dave Pearson
ab0126f672
Link the centring FAQ to the HOWTO
Keeping it as a FAQ makes sense, as it means that FAQtory will be able to
point to it, but now that we have the HOWTO, and it's more comprehensive, it
makes sense to direct the reader in that direction if they want something
more involved.
2023-08-28 08:39:57 +01:00
Dave Pearson
1b1e26cd16
Merge branch 'main' into M-x 2023-08-28 08:30:41 +01:00
Will McGugan
2519063389
version bump (#3181)
* version bump

* changelog

* snapshot update
2023-08-26 17:19:13 +01:00
Will McGugan
821a60fe3b
Win wait (#3151)
* input waiter

* waiter objects

* try signal handler for windows

* selectors

* fix win wait

* log meta

* log

* meta loop

* loop

* correct wait

* Waiter tweak

* timeout change

* restore loop

* change constant

* quit

* tweak

* loops

* debug

* debug

* exit on no data

* change wait

* loop tweak

* log

* change wait

* experiement

* wrap with handle

* experiment

* Debug

* handle

* DWORD

* another attempt

* test

* log

* reading

* stream

* tweak

* Restore

* input reader

* reader

* Remove debug

* input reader

* shutdown devtools after waiter

* flush

* fileno

* exit meta

* windows reader

* remove logging

* formatting

* docstring
2023-08-26 16:24:47 +01:00
Will McGugan
9ce1840889 Default to auto 2023-08-26 15:54:07 +01:00
Will McGugan
ee7d728399 color system override 2023-08-26 15:45:33 +01:00
Will McGugan
59646ff21a faq tweak 2023-08-26 10:57:44 +01:00
Will McGugan
d89871b045
update docs for tcss (#3179)
* update docs for tcss

* letter
2023-08-26 10:49:18 +01:00
Dave Pearson
888557747c
Reinstate the FAQtory-friendly links in the FAQ (#3142) 2023-08-26 08:35:41 +01:00
Rodrigo Girão Serrão
d674674b22
Update _styles_builder.py (#3168) 2023-08-24 19:40:22 +01:00
Rodrigo Girão Serrão
c01b868b00
Changelog. 2023-08-24 16:14:55 +01:00
Rodrigo Girão Serrão
9980148c26
Use call_next to invoke reactive watchers.
Related review comment: https://github.com/Textualize/textual/pull/3065#issuecomment-1670983082.
2023-08-24 16:07:31 +01:00
Rodrigo Girão Serrão
ac62096b80
Make call_next respect prevented messages.
Related issue: #3166.
2023-08-24 16:06:24 +01:00
Rodrigo Girão Serrão
19b24dd663
call_next preserves prevented messages information.
Provides a regression test for #3166.
2023-08-24 16:05:25 +01:00
Rodrigo Girão Serrão
f97fd81f56
Merge branch 'main' into reactive-callback
Fix CHANGELOG.md in the process.
2023-08-24 11:17:02 +01:00
Rodrigo Girão Serrão
7563a390e5
Merge pull request #3152 from Textualize/disable-tab-pane
Allow enabling/disabling tab via tab pane.
2023-08-23 14:51:43 +01:00
Rodrigo Girão Serrão
9ef644cd77
Add base class for TabPane messages.
Related review comment: https://github.com/Textualize/textual/pull/3152#discussion_r1302921959.
2023-08-23 14:43:38 +01:00
Dave Pearson
fa9a988032
Merge pull request #3155 from davep/handy-makefile-things
Add a couple of `Makefile` targets for things I'm forever typing
2023-08-23 14:41:23 +01:00
Rodrigo Girão Serrão
79f8ab05b7
Revert "Deactivate disabled tab."
This reverts commit 7aa40601ab.
2023-08-23 14:31:34 +01:00
Dave Pearson
6023e774ad
Add a couple of Makefile targets for things I'm forever typing
Well, completing in my shell but you get the idea...
2023-08-23 14:31:18 +01:00
Rodrigo Girão Serrão
7aa40601ab
Deactivate disabled tab.
Related issues: #3148.
2023-08-23 14:26:17 +01:00
Dave Pearson
c9d3e2d8b7
Merge branch 'main' into M-x 2023-08-23 14:22:28 +01:00
Rodrigo Girão Serrão
c8b06e073f
Merge pull request #3140 from Textualize/css-to-tcss
Rename CSS files to TCSS.
2023-08-23 14:13:58 +01:00
Rodrigo Girão Serrão
3f03743cd8
Merge branch 'main' into disable-tab-pane 2023-08-23 14:04:54 +01:00
Rodrigo Girão Serrão
695e59bd3a
Merge pull request #3150 from Textualize/fix-3145
Allow modifying tabs in nested contexts
2023-08-23 14:01:10 +01:00
Rodrigo Girão Serrão
a62302cf86
Tests/changelog. 2023-08-23 12:12:50 +01:00
Rodrigo Girão Serrão
7cf1b48f5b
Allow enabling/disabling tab via tab pane.
This allows one to use the 'disabled' attribute in tab panes to enable/disable a tab, which is particularly useful if you want to instantiate a tab that starts off as disabled, as seen in #3149.
2023-08-23 12:12:01 +01:00
Rodrigo Girão Serrão
22b63f6717
Simplify and generalise test.
We use the default IDs because that means the nested tabs get the same IDs.

Relevant review comment: https://github.com/Textualize/textual/pull/3150#discussion_r1302811660.
2023-08-23 11:40:55 +01:00
Rodrigo Girão Serrão
32007d78a2
Changelog. 2023-08-23 11:13:53 +01:00
Rodrigo Girão Serrão
0339879f1f
Query DOM correctly. 2023-08-23 11:12:23 +01:00
Rodrigo Girão Serrão
0353302216
Allow modifying tabs in nested tabbed contents.
Fixes #3145 with the fix in #3148.
2023-08-23 10:57:49 +01:00
Rodrigo Girão Serrão
4d0db5d13b
Add regression test for #3145. 2023-08-23 10:52:29 +01:00
Dave Pearson
a57ed16687
Simplify the command palette action 2023-08-22 20:34:48 +01:00
Dave Pearson
d09455d93b
Update the snapshots 2023-08-22 19:38:42 +01:00
Dave Pearson
34c739df78
Properly pad out the left side of the commands in the list 2023-08-22 19:29:21 +01:00
Will McGugan
f3c24db18d don't add signal handler on Windows 2023-08-22 16:20:53 +01:00
Rodrigo Girão Serrão
5ee0ebfef4
Rename CSS files to TCSS.
Related issue: #3137.
2023-08-22 13:21:17 +01:00
Will McGugan
bc1af586b5
version bump (#3139)
* version bump

* changelog
2023-08-22 13:05:09 +01:00
Will McGugan
59fa326e85 add prelude 2023-08-22 12:56:11 +01:00
Dave Pearson
135dac8633
Update snapshot tests 2023-08-22 12:42:28 +01:00
Will McGugan
65aeac361f Py37 fixes 2023-08-22 11:53:30 +01:00
Dave Pearson
99ff1ada7e
Remove some unused imports 2023-08-22 11:46:00 +01:00
Dave Pearson
e2573d92c9
Fix the highlight leakage into the left-pad of the commands 2023-08-22 11:45:31 +01:00
Dave Pearson
c10298021e
Provide a hook in OptionList via which a child can modify each line 2023-08-22 11:43:04 +01:00
Dave Pearson
f8b10482c1
Simplify the system command source code 2023-08-22 11:05:42 +01:00
Dave Pearson
fc4d3d755b
Improve the description of App.COMMAND_SOURCES 2023-08-22 10:59:08 +01:00
Dave Pearson
ec860fc274
Give a quick example of declaring a COMMAND_SOURCE 2023-08-22 10:57:03 +01:00
Dave Pearson
bb90b58312
Drop the run helper method in the command source 2023-08-22 10:48:02 +01:00
Dave Pearson
4abc92d7eb
Tweak the icon display
And also update the snapshot tests.
2023-08-22 10:30:07 +01:00
Dave Pearson
0129856c70
Delay showing that we're busy searching 2023-08-22 10:08:39 +01:00
Dave Pearson
5a3cd31ed8
Code tidy 2023-08-22 09:29:35 +01:00
Dave Pearson
a4d618103d
Make the search icon into its own widget 2023-08-22 08:50:12 +01:00
Dave Pearson
64354a35fd
Merge branch 'main' into M-x 2023-08-22 08:29:50 +01:00
Dave Pearson
061a88d7bd
Merge pull request #3129 from davep/faq-in-docs
Move the Textual FAQ into the main docs
2023-08-21 21:16:12 +01:00
Aaron Stephens
bf0c0252ab
feat(loadingindicator): default min height (#3132)
* feat(loadingindicator): default min height

* docs: changelog
2023-08-21 21:15:48 +01:00
TomJGooding
114b9c4d45
docs(changelog): correct release for pr 3012 (#3133) 2023-08-21 21:13:54 +01:00
Dave Pearson
98e145ae2c
Extend the command list highlight out to the edges of the list 2023-08-21 20:59:48 +01:00
Dave Pearson
53e379378b
Remove the border above the loading indicator 2023-08-21 20:41:22 +01:00
Dave Pearson
3867616486
Update snapshots 2023-08-21 20:32:46 +01:00
Dave Pearson
f6c6115869
Remove the border under the input when the list is dropped 2023-08-21 20:24:38 +01:00
Dave Pearson
7fb05fa320
Add a wee magnifying glass to the left of the input field 2023-08-21 20:07:16 +01:00
Dave Pearson
61fcc0bf5b
Correct the use of __lt__ and __eq__ 2023-08-21 19:43:19 +01:00
Dave Pearson
af4423166b
Rename hunt_for to search_for
Sounds a lot less dramatic but... okay, fair enough.
2023-08-21 19:37:24 +01:00
Dave Pearson
9c35c924ba
Correct the snapshot test
This is what happens when you break off to lecture half way through some
code...
2023-08-21 19:29:43 +01:00
Rodrigo Girão Serrão
900c372f10
Merge pull request #3112 from Textualize/tab-hide-disable
Tab hide disable
2023-08-21 17:20:15 +01:00
Rodrigo Girão Serrão
fa8f893a96
Merge branch 'main' into tab-hide-disable 2023-08-21 17:07:16 +01:00
Rodrigo Girão Serrão
8d83cd4abb
Add control to messages.
Related review comment: https://github.com/Textualize/textual/pull/3112#discussion_r1299951135
2023-08-21 17:06:32 +01:00
TomJGooding
eccb6e53f9
feat(listview): add method to append multiple items (#3012)
* feat(listview): add method to append multiple items

* update changelog

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-08-21 16:33:42 +01:00
Ren Jian Lee
fc0b5ccf9a
Fix page_up and page_down bug in DataTable when show_header is False (#3093) 2023-08-21 16:30:40 +01:00
Dave Pearson
0b18ebfc26
Provide a method to enable/disable the command palette via CLASSVAR 2023-08-21 15:53:03 +01:00
Dave Pearson
a507d3538b
Update the snapshot tests after CEO bikeshedding 2023-08-21 15:40:04 +01:00
Dave Pearson
77e01b8927
Ensure the screenshot path is escaped when telling on it (#3119)
See https://github.com/Textualize/textual/pull/3118#issuecomment-1683719311
2023-08-21 15:22:07 +01:00
Dave Pearson
a9de513a60
Drop the automatic generation of the FAQ (for now)
For this to work faqtory needs to be a development dependency of Textual.
Textual still maintains support for Python 3.7; faqtory is Python 3.8 or
greater. So, for the moment, we're going to cheat a little and make it so
that you have to remember to run faqtory to rebuild FAQ.md.

All hail the walrus!
2023-08-21 15:18:14 +01:00
Will McGugan
d0cd800893 style tweaks 2023-08-21 14:58:23 +01:00
Dave Pearson
bb20cdc2bf
Move the Textual FAQ into the main docs
See #3068.
2023-08-21 14:41:07 +01:00
Dave Pearson
3d2e126523
Merge pull request #3128 from davep/link-headder-to-app-title-in-docs 2023-08-21 13:54:09 +01:00
Dave Pearson
30bd82e25e
Link the Header docs to App.title and App.sub_title
Closes #3103.
2023-08-21 12:57:16 +01:00
Dave Pearson
b572ac0905
Link the general command palette docs from COMMAND_SOURCES
This should help make things a wee bit easier to discover.
2023-08-21 11:44:06 +01:00
Dave Pearson
4443a88a62
Remove the code browser with command palette example
This was useful for testing, but we don't want to maintain it.
2023-08-21 11:40:46 +01:00
Dave Pearson
87100db150
Add a snapshot test for the command palette 2023-08-21 11:21:06 +01:00
Dave Pearson
89980cc079
Ensure that the run-on-select tests restore the old state 2023-08-21 11:20:45 +01:00
Dave Pearson
67864c70ca
Downgrade the snapshot test library again
Just so I can get the failure report.
2023-08-21 11:20:19 +01:00
Rodrigo Girão Serrão
d5d8e81207
Add more tests for tab enabling/disabling/showing/hiding. 2023-08-21 11:09:32 +01:00
Dave Pearson
5e47ac0273
Add some more linking from within some docstrings 2023-08-21 09:39:05 +01:00
Dave Pearson
fa2c875e04
General language tidying
Fixes typos and awkward wording.
2023-08-21 09:17:09 +01:00
Rodrigo Girão Serrão
ec198974eb
Add tests for enabling/disabling tabs. 2023-08-18 17:35:37 +01:00
Rodrigo Girão Serrão
bf9ebb6466
Add ability to show/hide tabs. 2023-08-18 16:54:41 +01:00
Dave Pearson
39473fc17c
Merge pull request #3118 from davep/tweak-demo 2023-08-18 10:53:32 +01:00
Dave Pearson
c3e0d4b34f
Update snapshot tests
No material change will have been made, but the demo's DOM is slightly
different now as there's no notification container hidden in it any more.
2023-08-18 08:40:53 +01:00
Dave Pearson
37579cfab9
Don't override Ctrl+C as a non-priority key in the demo
See #3106.
2023-08-18 08:28:31 +01:00
Dave Pearson
bd94b48c53
Remove the demo's custom notification and use App.notify
See #3105.
2023-08-18 08:26:09 +01:00
Chakib Benziane
df145385e5
fix doc error in Bubble parameters for events.Focus and events.Blur (#3084)
Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-08-17 17:54:20 +01:00
Will McGugan
11ce101f15
fix for grid auto (#3113)
* fix for grid auto

* 3.7 fix
2023-08-17 17:23:28 +01:00
Rodrigo Girão Serrão
f0c01c1061
Add ability to enable/disable tabs.
Related issues: #3088.
2023-08-17 16:34:54 +01:00
Dave Pearson
c616e50d55
Start fleshing out the main command palette documentation 2023-08-17 16:20:16 +01:00
Rodrigo Girão Serrão
39b2e2a818
Fix docstring. 2023-08-17 15:46:02 +01:00
Dave Pearson
c1aba61349
Add the fuzzy matcher to the docs
While it isn't designed to be used directly, it is something a developer
will be exposed to via the command source for the command palette, so it
should appear in the docs so it can be linked to.
2023-08-17 15:33:31 +01:00
Dave Pearson
c074a39142
Tweak the module docstring for the command palette 2023-08-17 15:32:49 +01:00
Dave Pearson
eb6ac5fa8b
Allow kwags when using CommandSource.run 2023-08-17 15:17:11 +01:00
Dave Pearson
a976326c77
Docstring improvements 2023-08-17 14:19:46 +01:00
Dave Pearson
398b4343d6
Improve the docs for App.COMMAND_SOURCES 2023-08-17 14:19:13 +01:00
Dave Pearson
5fea151a7f
Add the system command sources into the docs 2023-08-17 14:18:54 +01:00
Dave Pearson
ee8dea2954
Explain run a wee bit better 2023-08-17 11:28:43 +01:00
Dave Pearson
7fc3604dfa
Pull the command palette into the API docs 2023-08-17 11:21:29 +01:00
Dave Pearson
4b84241c10
Rename SystemCommand.call to SystemCommand.run 2023-08-17 11:09:14 +01:00
Will McGugan
dda2cb2be2 auto grid docs and test 2023-08-17 10:46:57 +01:00
Dave Pearson
669cf0be61
Simplify the way the system command source works
Use the new run helper method.
2023-08-17 08:33:10 +01:00
Dave Pearson
edf513d968
Add a utility method to the command source for wrapping a callback
Some things the developer may want to call will be sync methods, some might
be async methods. I think it makes sense to provide a wee helper here to
wrap such a call up in the right way.

This might need expanding a bit, I might also want to look at and consider
Textual's invoke helper, but for the moment this is working well so let's
experiment with this.
2023-08-17 08:31:41 +01:00
Dave Pearson
f3442798d1
Wait for the command sources to complete after input, before moving on
Just in the problematic tests. As an experiment for the moment. I've still
not quite got to the bottom of the core problem, as I've been seeing, but
there is an issue with testing the command palette: how to ensure that
there's actually matched commands before going on to test interaction, when
the sourcing of command matches is concurrent with anything else.

Here I reach in into the workers of the command palette and wait for them to
finish and *then* I go on to use the result.

Having been able to recreate the surface error locally, on a nice fast M2Pro
Mac, with a significant async sleep in the source, this fixed the error in
that situation. So let's see if that makes a dent in CI...
2023-08-16 21:24:44 +01:00
Dave Pearson
356165b989
Ensure all test commands make it through 2023-08-16 20:48:58 +01:00
Dave Pearson
c76560b3d2
Swap to using Textual's wrapper for create_task 2023-08-16 20:41:34 +01:00
Dave Pearson
cc0faee5e0
Go harder on stopping any running worker
Also work a bit harder to detect if the worker has stopped.
2023-08-16 15:17:31 +01:00
Dave Pearson
091ef4e868
Remove experimental change to tests 2023-08-16 15:13:45 +01:00
Dave Pearson
c778ef7fea
Test if we can guard against pytest not doing a full teardown 2023-08-16 14:43:09 +01:00
Dave Pearson
6c86621fb6
Add some unit tests for bits of command palette UI interaction 2023-08-16 14:22:40 +01:00
Dave Pearson
efba40d336
Typo fix 2023-08-16 13:24:43 +01:00
Dave Pearson
5ebfb1bd07
Merge branch 'main' into M-x 2023-08-16 13:11:45 +01:00
Dave Pearson
7ed224901a
Various docstring improvements 2023-08-16 13:11:03 +01:00
Will McGugan
c1b611bac9
Grid auto (#3107)
* test

* snapshot

* changelog
2023-08-16 13:10:26 +01:00
Dave Pearson
8ff02a9302
Improve the explanation of CommandPalette._sources 2023-08-16 12:43:14 +01:00
Dave Pearson
ba9d33a67a
Simplify CommandPalette._sources 2023-08-16 11:38:01 +01:00
Will McGugan
5eb9182097 auto grid 2023-08-16 11:28:50 +01:00
Dave Pearson
e24d2add03
Allow for a double-tap of enter to get into selection mode
Also, in passing,rename _action_command to _action_command_list so it's more
obvious from the code what we're doing.
2023-08-16 11:01:54 +01:00
Dave Pearson
f9d102894d
Update the tests to take into account the new default source 2023-08-16 09:42:04 +01:00
Dave Pearson
08fdb477cf
Add a simple reference command source and make it app default
This is a simple command source for the command palette, that offers up some
of the more applicable actions within a Textual app. Here I also make it the
default source of commands for all Textual applications.
2023-08-16 09:20:52 +01:00
Dave Pearson
71dc0dea9e
Add a system-wide flag to disable the command palette 2023-08-16 08:47:07 +01:00
Will McGugan
d90b661978 changelog 2023-08-15 17:28:18 +01:00
Will McGugan
4e87a0f06e
version bump (#3102) 2023-08-15 17:06:02 +01:00
Rodrigo Girão Serrão
fbe1c416a4
Hide some members from the public docs. (#3080)
* Hide some members from the public docs.

See relevant issue: #3076.
Some methods need to be implemented to make the widget work but the user doesn't really care about them. For that matter, we can hide them from the public documentation.

* Use private handler to hide from docs.

Related comments: https://github.com/Textualize/textual/pull/3080#issuecomment-1671129733
2023-08-15 16:53:14 +01:00
Dave Pearson
878351564f
Simplify the no-results unit test for the command palette 2023-08-15 15:41:51 +01:00
Dave Pearson
8aad6b48a7
Don't work on a reference to the app's command sources
Work on a *copy*.
2023-08-15 15:41:12 +01:00
Dave Pearson
d46955b5e5
Add a test for getting no results 2023-08-15 15:24:21 +01:00
Dave Pearson
93b9372ac4
Add unit testing for the use of the escape key 2023-08-15 12:55:10 +01:00
Dave Pearson
5c4f7b3c3b
Remove an unused import 2023-08-15 12:45:04 +01:00
Dave Pearson
39f41b2b40
Add a test for dismissing the command palette via a click "outside" 2023-08-15 11:44:36 +01:00
Dave Pearson
e914049c63
Simply check the Input is not empty 2023-08-15 11:27:36 +01:00
Will McGugan
54ba3578a6
Event control (#3099)
* Add control

* added control

* post to parent
2023-08-15 11:06:18 +01:00
Dave Pearson
f27b68007b
Swap the tests to simply test we got something
It's looking like it's going to be almost impossible to test the exact
command chosen, every time, in CI, with all the timing issues. So let's make
life easier, for now anyway, and simply check that *something* was selected.
2023-08-15 11:05:32 +01:00
Dave Pearson
71643d7342
Add pauses between each keypress in the palette selection tests
These tests all work fine locally, but I'm getting the usual unpredictable
async results in CI. Let's see if pausing after each press helps.
2023-08-15 10:52:19 +01:00
Dave Pearson
e7ee82cef8
Add tests for auto-run on and off in the command palette 2023-08-15 10:43:43 +01:00
Will McGugan
a0be460921
border classvars (#3097)
* border classvars

* changelog

* copy

* remove whitespace

* copy
2023-08-15 10:34:24 +01:00
Dave Pearson
d7b8f5ad32
Add a test for command sources with no available app or screen 2023-08-15 09:40:32 +01:00
Dave Pearson
03ebd864c6
Add a test that app and screen command sources combine 2023-08-14 19:54:58 +01:00
Dave Pearson
4f9b30d74e
Have the sources always be a combination of the app and the current screen 2023-08-14 16:27:48 +01:00
Dave Pearson
3b41d4f8e5
Add unit tests for the command source environment information 2023-08-14 15:49:12 +01:00
Dave Pearson
85beb6ef48
Unpin the snapshot test library
This was pinned by Darren a wee while back, I think, due to some other
problem. But this kills coverage. Right now I want coverage so I can see
what needs testing with the command palette. So let's unpin with a view to
pinning back again (or solving the main problem I guess) once I'm done.
2023-08-14 15:47:42 +01:00
Dave Pearson
7451e9988a
Add unit tests for declaring command palette command sources 2023-08-14 14:19:22 +01:00
Dave Pearson
388afbe50d
Correctly get the calling screen from the stack
Unit tests are a wonderful thing...
2023-08-14 14:13:15 +01:00
Dave Pearson
df3f3e88e1
Remove an unused import 2023-08-14 13:34:33 +01:00
Dave Pearson
0fe692446f
Add a missing return type to a docstring 2023-08-14 13:30:20 +01:00
Dave Pearson
0df8148d79
Move the command sources on to the app and screens
Also add code to guard against pulling up the command palette while in the
command palette.
2023-08-14 13:21:35 +01:00
Dave Pearson
b9c9262325
Give the command palette screen an ID
This will help guard against anything causing two copies to be in the DOM at
once. It's unlikely, the code should work to make sure this doesn't happen,
but let's set this up to be a fail if it does.
2023-08-14 13:13:36 +01:00
Will McGugan
156e4c8f44
Update CHANGELOG.md 2023-08-14 12:18:08 +01:00
Dave Pearson
c602cd6f9b
Cancel command palette work when any edit happens
When a new search term was created by an edit, the previous worker would get
cancelled by the nature of _gather_commands being exclusive; but if the user
edited the input such that it was empty the work would carry on. This
ensures that isn't the case.
2023-08-14 10:22:48 +01:00
Dave Pearson
1f1aca6cdd
Tidy up the loading indicator 2023-08-14 10:15:58 +01:00
Dave Pearson
8e14b3c6fd
Tidy up the bindings and add a docstring to them 2023-08-14 09:22:22 +01:00
Dave Pearson
3e7f684d4c
Merge branch 'main' into M-x 2023-08-14 09:17:09 +01:00
Will McGugan
bcb4c1d582 signal handler 2023-08-13 12:42:00 +01:00
Will McGugan
bcd5760c67
calculator uses Digits (#3092)
* calculator uses Digits

* remove example
2023-08-11 17:49:30 +01:00
Rodrigo Girão Serrão
eccf746f5a
Merge pull request #3054 from dmunozv04/main
Fix links in documentation
2023-08-10 08:58:49 +01:00
David
63dff34af9
Update layer.md
Fix the link I managed to break
2023-08-09 19:57:35 +02:00
Will McGugan
d857d57a2e
fix markdown example (#3081) 2023-08-09 16:32:38 +01:00
Rodrigo Girão Serrão
b7dc046eeb
Merge pull request #2988 from gergely-elias/directorytree_reload_node
method for reloading single node of DirectoryTree
2023-08-09 14:23:18 +01:00
Will McGugan
1270b8d28f
Digits (#3077)
* Digits

* digits widget

* update requires str

* digits docs

* simplify

* tweak docs

* snapshot test

* change name

* simplify

* docs

* Update _digits.py superfluous import

* Update _digits.py docstring

* address review

* formatting

* change docstring
2023-08-09 10:49:13 +01:00
Will McGugan
49281b3f27
Digits (#3073)
* Digits

* digits widget

* update requires str

* digits docs

* simplify

* tweak docs

* snapshot test

* change name

* simplify

* docs

* Update _digits.py superfluous import

* Update _digits.py docstring

* address review

* formatting

* Update tests/snapshot_tests/snapshot_apps/digits.py

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-08-09 10:25:17 +01:00
Dave Pearson
385f919e90
Merge pull request #3038 from davep/kickstart-select-tests
Add a test for Select.value being set from the constructor
2023-08-09 10:14:31 +01:00
Dave Pearson
0d09514d66
Update the fuzzy matcher highlighting test
An actual style is used now, not just a text name.
2023-08-09 10:11:22 +01:00
Dave Pearson
c4a26add6d
Style tweaks
Still haven't decided on the final style for this, but this helps to make
the command palette and the command list pop a little for a background
screen of similar colours.
2023-08-09 09:35:58 +01:00
Dave Pearson
bea4e116fe
Code tidy 2023-08-09 08:59:57 +01:00
Dave Pearson
9f41c2084d
Swap to retaining the highlighted command, not the highlighted index
Now that OptionList.get_option_index is merged into `main` I can do this.
2023-08-09 08:57:30 +01:00
Dave Pearson
ed111bbc42
Merge branch 'main' into M-x 2023-08-09 08:53:06 +01:00
Dave Pearson
75f08da6f1
Add a missing return section to the compose docstring 2023-08-09 08:48:36 +01:00
Dave Pearson
aeb3b4737c
Add a missing docstring 2023-08-09 08:48:04 +01:00
Dave Pearson
3fa6f7bb85
Merge pull request #3075 from nmay231/fix-selection-clear-options
Fix clear_options() for SelectionList
2023-08-09 08:22:31 +01:00
Dave Pearson
01957a8bd4
Merge branch 'fix-selection-clear-options' of github.com:nmay231/textual into fix-selection-clear-options 2023-08-09 08:11:18 +01:00
Dave Pearson
0ee7c63346
Add a docstring to the new test 2023-08-09 08:11:00 +01:00
Dave Pearson
5ad19e6bc7
Merge branch 'main' into fix-selection-clear-options 2023-08-09 08:09:03 +01:00
Gergely Elias
9a343a6bd7 CHANGELOG.md update 2023-08-09 07:40:40 +02:00
Gergely Elias
9a3321b2a6 Tree.clear_line_cache renamed to Tree._clear_line_cache to mark privacy 2023-08-09 07:40:17 +02:00
Gergely Elias
cc096be151
Merge branch 'Textualize:main' into directorytree_reload_node 2023-08-09 07:35:13 +02:00
Noah May
8bf2d80fad Fix clear_options() for SelectionList 2023-08-08 16:17:23 -05:00
Rodrigo Girão Serrão
be2ec1daaf
Merge pull request #2987 from seifertm/2905-send-mouse-move-events-to-screen
MouseMove events bubble up and are posted by Screen
2023-08-08 16:44:13 +01:00
Rodrigo Girão Serrão
908a0aeb3d
Merge branch 'main' into 2905-send-mouse-move-events-to-screen 2023-08-08 16:35:00 +01:00
Rodrigo Girão Serrão
49612e3aa5
Merge pull request #2985 from nekeal/feature/extend-optionlist
Adds an interface for replacing prompt of an individual option in an `OptionList`
2023-08-08 16:31:18 +01:00
Will McGugan
af315a3af7
Merge branch 'main' into 2905-send-mouse-move-events-to-screen 2023-08-08 16:27:13 +01:00
Dave Pearson
39005b8075
Add a version of the code browser that has a command palette 2023-08-08 16:26:56 +01:00
Dave Pearson
f13e38826d
Allow the hits representation to be any sort of renderable 2023-08-08 16:26:25 +01:00
Dave Pearson
218a5df067
Make the command matches return type into a type alias
This will make it easier for people implementing their own command hunting
code to type things.
2023-08-08 13:10:43 +01:00
dmunozv04
41fe544a1f Fix broken link 2023-08-08 13:38:47 +02:00
dmunozv04
52d0586f5d Fix doc links 2023-08-08 13:27:13 +02:00
David
13680ae6d2
Merge branch 'Textualize:main' into main 2023-08-08 12:44:41 +02:00
Dave Pearson
5c7957ae36
Remove unnecessary parameter for on_mount 2023-08-08 11:39:32 +01:00
Dave Pearson
64c440ea4d
Add a simple ID for each gathered command 2023-08-08 11:07:35 +01:00
Dave Pearson
82cc3928ff
Make a note that we're waiting on an OptionList PR for highlight
To allow for maintaining the location of the highlight as we rebuild the
command list I'm probably going to need some method of tracking an ID for an
option, so I can find its new index back. There's no method in OptionList
right now for doing that; it's trivial, but it's not there. As it happens
the changes in #2985 actually has that, so here I note that I'll look to
making that happen once that gets added in.
2023-08-08 10:55:07 +01:00
Dave Pearson
ee638c3e61
Add support for sorting the commands in the command list 2023-08-08 10:16:12 +01:00
Dave Pearson
383c43e984
Add support for ordering command hits and command options
This will simply make any sorting code easier to read later on.
2023-08-08 10:06:54 +01:00
Dave Pearson
bc1d24f2be
Drop the import of re.NOFLAG
Turns out I can't read the docs and this didn't turn up until 3.11. Nice one
Python.
2023-08-08 09:12:32 +01:00
Szymon Cader
def26288e7 Add snapshot tests for replacing prompt in option list 2023-08-07 23:19:02 +02:00
Szymon Cader
3ff5b7b82a Add unit tests for multiline prompts 2023-08-07 23:19:02 +02:00
Szymon Cader
913dce7ef7 Make use of get_option_index
This simplifies error handling in a public interface
2023-08-07 23:19:02 +02:00
Szymon Cader
d63ac2c22e Minor fixes 2023-08-07 23:19:02 +02:00
Szymon Cader
a3590ac192 Move error handling for non-existing options to dedicated methods 2023-08-07 23:19:02 +02:00
Szymon Cader
22926cbd6e Make use of get_option_at_index instead of directly accessing _options 2023-08-07 23:19:02 +02:00
Szymon Cader
37bc2e587f Update the CHANGELOG.md 2023-08-07 23:19:02 +02:00
Szymon Cader
45b6973d85 Add ability to replace prompt of an individual option in OptionList 2023-08-07 23:16:51 +02:00
Rodrigo Girão Serrão
2ec10e04f2
Add regression tests for #3036. 2023-08-07 16:29:18 +01:00
Dave Pearson
07f12168f6
Add support for making matching case insensitive
Also make being case insensitive the default. I'd expect most people would
want this out of the box.
2023-08-07 15:33:02 +01:00
Rodrigo Girão Serrão
ff2a842b42
Schedule reactive callbacks on watcher.
The async reactive callbacks are now scheduled on the message pump of the watcher of the reactive instead of on the owner of the reactive attribute.
Related issues: #3036.
2023-08-07 15:01:58 +01:00
Dave Pearson
1b3f2a296f
Add a property for the matched style
Technically to unbork rich.repr.auto; but this will also potentially be
useful to access anyway.
2023-08-07 14:08:48 +01:00
Dave Pearson
0cdcebb8bf
Add some extra testing code to the fuzzy matcher
Not unit tests, just code for generally testing things when run as:

python -m textual._fuzzy
2023-08-07 14:00:47 +01:00
Dave Pearson
1da1a997e2
Make the matcher pattern publicly available 2023-08-07 13:58:46 +01:00
Dave Pearson
d60182c775
Improve some Matcher docstrings 2023-08-07 12:57:30 +01:00
Dave Pearson
0938fcedae
Don't shadow a Python builtin 2023-08-07 12:54:29 +01:00
Dave Pearson
db5bd1e426
Turn Matcher.query into a read-only attribute 2023-08-07 12:52:28 +01:00
Dave Pearson
e519c99e6e
Add missing parameter to the Matcher __init__ docstring 2023-08-07 12:49:48 +01:00
Dave Pearson
2e4ceeb5c6
Make the match style keyword-only 2023-08-07 12:48:05 +01:00
Dave Pearson
795f598b90
Merge branch 'main' into M-x 2023-08-07 12:42:16 +01:00
Will McGugan
5a662e68ae
fix for tabs (#3059)
* fix for tabs

* remove superfluous offset update

* optimize

* test

* comment

* restore auto height

* don't fix height of tabs

* height fix

* test

* changelog [skipci]

* Revert test
2023-08-07 10:39:59 +01:00
Will McGugan
d9d170d75e
Background refresh (#3062)
* enable background screen refresh

* background refresh

* more performant refresh

* remove full screen refresh
2023-08-07 10:22:41 +01:00
Dave Pearson
72b8dad5ff
Expose the Matcher object via the command palette
The design of the command source class is such that a developer providing
one doesn't have to use the Textual fuzzy matcher.
2023-08-07 10:18:24 +01:00
Will McGugan
ba91b42215 ifix highlight line 2023-08-07 10:17:10 +01:00
Dave Pearson
1ddf6908c8
Fix some terrible English in a comment 2023-08-07 09:52:35 +01:00
Dave Pearson
66da4e4868
Update the docstring for the command palette component classes 2023-08-07 09:50:45 +01:00
Dave Pearson
29c2041b51
Make a desired highlight style available to the command sources 2023-08-07 09:47:58 +01:00
Dave Pearson
a0aa143b11
Allow a highlight style to be passed into the fuzzy matcher 2023-08-07 09:13:28 +01:00
Dave Pearson
4b40fff53a
Complete the copying of all the non-bgcolor Style properties 2023-08-07 09:09:21 +01:00
Dave Pearson
19fa4eeef4
Move code to create a style with no background into its own method
At some point this should really go into Rich itself, I think, as utility
method of Style. For the moment though, let's keep it close to hand as we
figure out if it's a good idea or not.
2023-08-07 09:03:48 +01:00
Dave Pearson
65be8d7f69
Merge branch 'main' into M-x 2023-08-07 08:31:51 +01:00
Will McGugan
792e02e043 catch custom message error 2023-08-06 18:19:07 +01:00
Will McGugan
bbe779aede update to center-things howto 2023-08-06 13:24:01 +01:00
Dave Pearson
c65193cf27
Relock for textual-dev update 2023-08-06 07:57:11 +01:00
Dave Pearson
f4d269edb1
Merge branch 'main' into M-x 2023-08-05 18:22:55 +01:00
Will McGugan
d3897de7ee
Background refresh (#3061)
* enable background screen refresh

* background refresh
2023-08-05 18:07:17 +01:00
Dave Pearson
abc8fa9a50
Update the binding inheritance tests to add new global key
It remains to be seen if we'll keep it like this, but this is a useful
combination to use while I'm working on having the command palette a
"standard" part of a Textual application (I'm still minded to make it
optional and the develop binds it themselves -- we'll see where that
decision falls before final PR).
2023-08-05 09:29:03 +01:00
Dave Pearson
d3b0d96bcc
Update fuzzy matcher tests to handle the changed styling 2023-08-05 09:26:11 +01:00
Dave Pearson
0d4d00fb99
Hint the sources class variable as being a class variable 2023-08-04 20:13:53 +01:00
Dave Pearson
3bd7c058de
Add initial basic app-wide support for the command palette
This adds an action to the App, and binds it to Ctrl+@, which in Mac
terminals at least equates to ctrl+space. This might not be the final
resting place for this, I'm not even sure if we should find it by default at
all. But for the purposes of further testing as I develop this that's fine.

This also adds support to the App class for running the user's choice of
command. With this change nobody needs to hook up the command palette with
Textual on their own any more, it's "out of the box".

What's needed by them now is hooking up a command provider.
2023-08-04 08:42:41 +01:00
Dave Pearson
9e950f146c
Correct a comment 2023-08-03 21:05:12 +01:00
Dave Pearson
4c8f446fb4
Better explain a couple of reasons in the code 2023-08-03 20:48:15 +01:00
Dave Pearson
75ff507171
Flesh out the docstring for registering a command source 2023-08-03 20:43:21 +01:00
Dave Pearson
d2f939aa03
Allow easy access to the focused widget in the command providers 2023-08-03 20:33:35 +01:00
Dave Pearson
498060192c
Revert how we save off the active screen
So it turns out that App.screen gets updated before the mount event is
received, but the stack hasn't changed by that point. It's safer to work off
the stack.
2023-08-03 20:30:49 +01:00
Dave Pearson
fcf2c7cb13
Simply pull the screen from the app's screen property
No need to dumpster-dive the stack when it's right there.
2023-08-03 20:23:56 +01:00
Dave Pearson
49057d27df
Allow "click and go" vs "click, review, then go"
During 2023-08-03 standup it was suggested to me that the preference might
be to have this work in a "click and go" way rather than a "click, review
then go" way. My preference is more for the latter, but I can see the desire
for the former too.

So this makes the former the default, but allows for the latter to be
configured by the developer.
2023-08-03 20:16:59 +01:00
Dave Pearson
e2d0d4c71c
Add a component style for the help line 2023-08-03 16:23:57 +01:00
Dave Pearson
26e94ee289
Make the "internal" IDs a wee bit more "internal" 2023-08-03 14:36:41 +01:00
Dave Pearson
cce6433351
Fix a typo in the docstring for MessagePump.is_attached (#3051) 2023-08-03 12:22:05 +01:00
dmunozv04
e880ecd82b Fix width.md so the link to box_sizing.md works 2023-08-03 12:54:14 +02:00
Dave Pearson
d29ab70fdf
Introduce a "go" button
This helps make it possible for the user to mouse to select a command and
then further mouse to run the command.

In doing this, because I was introducing a new element, I've done a revamp
of the layout and styling of the command palette. The result is more or less
the same as I had to start with, but this solves a couple of cosmetic issues
I was running into until now.
2023-08-03 11:10:18 +01:00
Will McGugan
879c985296
Rich log (#3046)
* log

* tests

* snapshot tests

* change to richlog

* keep raw lines

* disable highlighting by default

* simplify

* superfluous test

* optimization

* update cell length

* add refresh

* write method

* version bump

* doc fix link

* makes lines private

* docstring

* relax dev dependancy

* remove superfluous code [skip ci]

* added FAQ [skipci]

* fix code in faq [skipci]

* fix typo

* max lines fix
2023-08-03 10:11:17 +01:00
Dave Pearson
a83a09fd12
Add an app property to the command source 2023-08-03 08:52:17 +01:00
Dave Pearson
6d3c660f23
Recognise that screens are generics when providing the screen 2023-08-03 08:48:39 +01:00
Dave Pearson
920d74a20c
Code tidy 2023-08-03 08:43:04 +01:00
Dave Pearson
87d5ea7f77
Improve a comment 2023-08-03 08:21:30 +01:00
Dave Pearson
6869e7ab2c
Make the code Python 3.7-friendly 2023-08-02 20:47:33 +01:00
Dave Pearson
ce5ad9ea53
Remove an unused import 2023-08-02 16:14:23 +01:00
Dave Pearson
3b8e7e0479
Update to take into account very fast command sources
The code as was worked fine for nicely slow command sources. In fact I
thought it was going to be the slow ones that would give me the worst
problem. But having managed to handle that, it was the really fast ones that
showed a few issues.

Here I'm swapping back to just showing/hiding the loading indicator as
mounting and removing so fast was an issue.

And also I'm making sure that I flush the queue after all the tasks are
finished, otherwise it was easy to lose a lot of commands.
2023-08-02 15:50:38 +01:00
Dave Pearson
0cebb96157
Add an initial take on getting a command to actually run
This is far from its final form, and right now to work it needs that the
calling code (which is in my test harness) receive the callable via the
screen callback system and make use of it. That's fine, it works, it just
means that as I get closer to making this part of Textual proper I'll need
to build such a mechanism into Screen.
2023-08-02 13:49:14 +01:00
Dave Pearson
2587c17cb6
Add a location into which the command's callable can go 2023-08-02 11:33:39 +01:00
Dave Pearson
94db135073
Merge branch 'main' into M-x 2023-08-02 10:35:33 +01:00
Dave Pearson
1ac7e8b396
Add some missing type hinting 2023-08-02 10:35:05 +01:00
Dave Pearson
f47b58e3b7
Provide access to home/end within the command list 2023-08-02 09:14:27 +01:00
Dave Pearson
9a619f126a
Allow clicking on the "background" to dismiss 2023-08-02 09:08:40 +01:00
Dave Pearson
d884e6898f
Explicitly export some symbols from the command palette module 2023-08-01 15:59:47 +01:00
Dave Pearson
027adc609c
Rename the command palette file
It's becoming clear that we do want to allow people to import from this
file, so it's time to drop the underscore.
2023-08-01 15:54:47 +01:00
Dave Pearson
2dd251bf19
Remove the placeholder reactive
I don't really see much need for this, now that development of this is well
under way. And even if we do want to expose this, I think we need to allow
setting it on the class, not on the instance.
2023-08-01 15:53:17 +01:00
Dave Pearson
a973945a9c
Add a missing docstring 2023-08-01 15:51:10 +01:00
Dave Pearson
26810b88b9
Move to allowing a collection of command sources 2023-08-01 15:07:02 +01:00
Dave Pearson
46174aced7
Work around the mount/render issue with LoadingIndicator
See #2912 and #2914 for some context.
2023-08-01 14:31:44 +01:00
Dave Pearson
25bf5712cf
Fix a typo in a docstring 2023-08-01 13:58:14 +01:00
Will McGugan
b045306c69 faq entry 2023-08-01 11:08:12 +01:00
Will McGugan
5a306e9c9f
Bump0310 (#3044)
* bump version

* changelog
2023-08-01 11:01:53 +01:00
Dave Pearson
3bede59493
Tidy up the notes in the stop_animation docstrings (#3019)
In one case there was a hangover from before we added the `complete` option;
in the other two cases it also needed to be made clear that it's only a
no-op if there's no animation running or also scheduled.
2023-08-01 10:48:44 +01:00
Dave Pearson
4faa620964
Fix the page up/down bindings for OptionList (#3024)
* Fix the page up/down bindings for OptionList

I'd had page_up and page_down bound when the actual names of the bindings
are pageup and pagedown. This has always worked by sheer fluke because of
where OptionList inherits from and by the coincidence of the action names.

In other words: this commit has no substantive impact; but it does fix code
that wasn't helpful and also makes the documentation more correct.

* Correct the page up/down keys in the option list movement tests

Turns out the pilot lets you press keys that don't actually exist. Who
knew?!?
2023-08-01 10:47:50 +01:00
Dave Pearson
c8021a95ac
Swap the busy indication to a mount/remove model
Doesn't seem to make sense to have a LoadingIndicator constantly running in
the background when it isn't needed.
2023-08-01 09:23:13 +01:00
Dave Pearson
8b1d2b448e
Merge branch 'M-x' of github.com:davep/textual into M-x 2023-08-01 08:53:49 +01:00
Dave Pearson
b0efe1a0e4
Tidy up a couple of docstrings 2023-08-01 08:52:42 +01:00
Dave Pearson
c48a824c6a
Add initial support for showing some help
It's not going to end up quite like this, but this gets it going.
2023-07-31 20:42:19 +01:00
Dave Pearson
51cbe2a220
Set things up for command help display 2023-07-31 19:42:41 +01:00
Will McGugan
080437ce03 fix code highlight 2023-07-31 17:58:09 +01:00
Dave Pearson
c922920fec
Remove unused import 2023-07-31 15:53:33 +01:00
Dave Pearson
7b264866e8
Make it obvious to the user when no matches are found 2023-07-31 15:48:16 +01:00
Dave Pearson
f2df52d494
Add a loading indicator to show if we're still loading hits 2023-07-31 15:43:28 +01:00
Dave Pearson
629d9c038f
Rename the method for hunting for commands 2023-07-31 15:06:31 +01:00
Dave Pearson
91c3b4a513
Add a test for Select.value being set from the constructor
As an illustration for
https://github.com/Textualize/textual/discussions/3037 and having written it
it makes sense to drop it into the tests. As it is, it looks like Select has
no tests so this is a handy kickstart.
2023-07-31 15:00:31 +01:00
Dave Pearson
143c0d8267
Start moving to an async generator approach
Not like this, but kinda like this. Just experimenting at the moment, hence
the random sleeps in the core of the generator (to sort of fake a slow
background source).
2023-07-31 14:40:07 +01:00
Dave Pearson
cf7d539ae2
Move the new request code into its own method
At the moment it does nothing more than grab a new UUID, but this gives us
scope for throwing in some sort of callout to the providers to let them know
we're done.
2023-07-31 13:28:15 +01:00
Will McGugan
ddda1c2592
fix for text alignment issue (#3033)
* fix for text alignment issue

* test for hot reloading

* unable to test

* restore dot
2023-07-31 13:19:47 +01:00
Dave Pearson
bcd6b78910
Tweak how the list can be closed and reopened 2023-07-31 13:00:33 +01:00
Dave Pearson
9be6bca264
Make CommandSource an abstract base class 2023-07-31 12:28:09 +01:00
Dave Pearson
bea570d2c0
Start fleshing out an interface for a command source 2023-07-31 11:37:12 +01:00
Dave Pearson
9e05bef356
Remove the original test options
These were there when I was first testing the layout. They're not needed any
more.
2023-07-31 10:32:57 +01:00
Dave Pearson
51ec91db81
Make the escape action an internal action 2023-07-31 10:27:53 +01:00
Dave Pearson
cb3acd76c4
Control the command list visibility from a reactive 2023-07-31 10:24:10 +01:00
Dave Pearson
b37dc7f089
Make the current event handlers internals 2023-07-31 10:18:15 +01:00
Dave Pearson
476dd5a2a0
Add the ability to select a command in the list 2023-07-31 10:17:24 +01:00
Will McGugan
dbd3644577
center how to (#3031)
* center how to

* words

* words
2023-07-31 09:56:46 +01:00
Will McGugan
3db6f85c79 added tip 2023-07-29 17:05:04 +01:00
Will McGugan
d94b38b3c0 words 2023-07-29 15:40:06 +01:00
Will McGugan
5c8ec2321d words 2023-07-29 15:32:44 +01:00
Will McGugan
19445614ab word 2023-07-29 15:23:16 +01:00
Will McGugan
c88bf306d6 words 2023-07-29 13:54:24 +01:00
Will McGugan
df50bf6983 words 2023-07-29 13:44:16 +01:00
Will McGugan
c4095715e7 blog 2023-07-29 13:23:45 +01:00
Gergely Elias
7e92053f5a separating tests, adding explanatory comments 2023-07-28 21:34:29 +02:00
Gergely Elias
b66d6b8b67 adding method for clearing cache to Tree class 2023-07-28 21:04:15 +02:00
Gergely Elias
5b12bcda88 preserving node's parent 2023-07-28 20:39:15 +02:00
Dave Pearson
e4e6adcff0
Mark fuzzy matches as reverse text
Just to help things stand out for the moment. At some point I think I'll
allow passing in custom styles, which will come from component classes or
something. For now though this makes it easier to see what's going on.
2023-07-27 20:43:08 +01:00
Gergely Elias
ed594748d1 replacing the term subtree with node 2023-07-27 21:29:02 +02:00
Dave Pearson
60befa8d7e
Make compatible with Python 3.7 2023-07-27 20:26:25 +01:00
Gergely Elias
6c9aeb0cdf Merge branch 'main' into directorytree_reload_node 2023-07-27 21:24:55 +02:00
Dave Pearson
12693c3956
Plug in the fuzzy matcher for a quick test
This isn't the interface. Nowhere near. But this helps kick off visualising
how it will all work.
2023-07-27 16:27:17 +01:00
Dave Pearson
4869e32df8
Initial WiP commit of comment palette UI test code 2023-07-27 15:19:53 +01:00
Will McGugan
6356be1f5f addendum to blog post 2023-07-27 12:34:46 +01:00
Will McGugan
8bf6673363
blog post (#3022)
* blog post

* words

* words

* more words

* Update docs/blog/posts/rich-inspect.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Update docs/blog/posts/rich-inspect.md

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-07-27 12:12:59 +01:00
Dave Pearson
5a55b11881
Gather up the latest changed items in the CHANGELOG under one heading (#3020) 2023-07-27 10:15:54 +01:00
TomJGooding
a8fcfaeb21
fix(datatable): unset hover cursor when no cell under mouse (#3018)
* fix(datatable): unset hover cursor when no cell under mouse

* update changelog
2023-07-27 10:15:20 +01:00
Will McGugan
8348a916d8
fix blank write (#3017)
* fix blank write

* snapshot
2023-07-26 20:39:50 +01:00
Dave Pearson
232e86d25a
Deanimate! (aka, provide a method of stopping application and widget animations) (#3000)
* Remove duplicated Added section in the CHANGELOG

* Add the ability to stop a running animation

Adds stop_animation to the core animator class, and then exposes it via the
same named methods on App and Widget. Note that a request to stop an
animation that isn't running is treated as a no-op.

* Fix tests so they actually work and test things

This is what happens when you save time using -k to run one test, then add
more but keep just hitting cursor up to rerun the tests. O_o

* Add the ability to stop an animation and jump to the final value

This doesn't address the issue of stopping scheduled animations, that's to
come next, first I just wanted to get the basic approach in place and then
build out from there.

* Add full stopping support to the ScalarAnimation

* Tidy up various bits of documentation in Animator

While I'm in here and moving things around: being various bits of
documentation more in line with how we document these days, and also add
some missing documentation.

* Allow for the full stopping (with end-seeking) of scheduled animations

* Don't spin up a scheduled animation to then not use it

* Be super-careful about getting keys when stopping

* Pop rather than acquire and delete

* Don't implement anything in Animation.stop

See https://github.com/Textualize/textual/pull/3000#discussion_r1275074716
2023-07-26 17:36:56 +01:00
Will McGugan
2086353b56
Docs tutorial tweak (#3016)
* docs

* words

* words

* words

* Words
2023-07-26 14:58:35 +01:00
Dave Pearson
6bd0d1b196
Merge pull request #3009 from davep/issue/2958/select-scroll-parent
Override can_view in Screen to check if a widget is overlay screen
2023-07-26 14:15:58 +01:00
Dave Pearson
0871dc57ce
Clean up the f-stringing of a string in ScalarAnimation.__call__ (#3014)
Noticed this unnecessary use of an f-string in passing.
2023-07-26 10:15:02 +01:00
Dave Pearson
ad8145f534
Merge pull request #2972 from davep/markdowner
Change Markdown.load so that load errors propagate
2023-07-25 13:43:29 +01:00
Dave Pearson
85a3dd5e7d
Extend Markdown.load's docstring to reflect the possible exceptions 2023-07-25 13:34:40 +01:00
Dave Pearson
18d5eb52af
Override can_view in Screen to check if a widget is overlay screen
This change is based on the idea that if a widget is "overlay: screen" it's
totally outside the normal flow of things and so trying to see if it's
visually within its ancestors doesn't make a whole lot of sense as it might
deliberately not be. At which point the only sensible question we can ask is
"can the screen see it?".

See #2958.
2023-07-25 12:55:41 +01:00
Dave Pearson
681dbf8c0d
Add App.action_switch_mode (#3001)
This makes it easier for people to switch modes from BINDINGS.
2023-07-25 10:45:49 +01:00
Dave Pearson
4f3bb3fe15
Set DataTable default style to max-height: 100% (#2974)
* Make the default max-height of a DataTable 100%

See #2959

* Fix the demo

Adding `max-height: 100%;` to DataTable has worked everywhere, except in the
demo, where it makes the table just plain flat out disappear. It looks like
it's down to a bug in Textual's CSS, possibly. This fixes the demo for now,
and a standalone issue will follow that dives into what's going on with this
particular combination of container and datatable styling.

* Update the ChangeLog

* Update the FAQ
2023-07-25 10:39:39 +01:00
Will McGugan
0ff435601e
expand tabs (#3008)
* expand tabs

* Test
2023-07-25 10:37:14 +01:00
Will McGugan
cb81b6d7a6
Gradient optimization (#2999)
* optimization

* further optimization

* maxsize defaults to 128

* App demo
2023-07-24 11:32:41 +01:00
Dave Pearson
f9fb1b1514
Remove the implementation of notify from Screen (#2996)
* Remove the implementation of notify on Screen

Screen inherits the one from Widget anyway. I always forget that Screen is a
Widget. O_o

* Remove imports that aren't needed any more
2023-07-24 10:24:21 +01:00
Sepehr Shirkhanlu
5153fe6c92
Fix docs (#2932)
* Fix line highlighting in docs

* fix docs: remove duplicated code
2023-07-23 16:49:59 +01:00
Dave Pearson
f78ffe04b6
Merge pull request #2938 from davep/unfootgun-worker-thread
Worker updates
2023-07-23 16:32:22 +01:00
Will McGugan
ed4eb2c7a7 copy 2023-07-23 16:14:29 +01:00
Will McGugan
381fde7212 update copy 2023-07-23 16:08:13 +01:00
Will McGugan
4406b9d608
capture print (#2971)
* capture print

* changelog

* docstring

* rename

* strings
2023-07-23 15:49:24 +01:00
Gergely Elias
e5ef25d4a0 further review comments addressed 2023-07-23 13:57:01 +02:00
Gergely Elias
6e783d07f0 updates based on review comments 2023-07-23 05:52:47 +02:00
Gergely Elias
5a9e3396c9 method for reloading single node of DirectoryTree 2023-07-22 16:44:24 +02:00
Michael Seifert
8b5f4fd03d Screen processes mouse move events after forwarding them to the child widget.
Signed-off-by: Michael Seifert <m.seifert@digitalernachschub.de>
2023-07-22 16:11:47 +02:00
Rodrigo Girão Serrão
40ba3347e5
Merge pull request #2984 from zormit/allow-empty-css-variables
allow empty css variables
2023-07-22 12:57:28 +01:00
Rodrigo Girão Serrão
abc745cb5f
Merge pull request #2977 from davep/verbose-typo
Typo fix in the module docstring for events.py
2023-07-22 11:34:19 +01:00
Moritz Neeb
7770f8de82 refactor: simplify css variable table creation 2023-07-22 12:28:59 +02:00
Moritz Neeb
2ab6ca364f explain change on changelog 2023-07-22 12:28:57 +02:00
Moritz Neeb
382b308393 allow empty css variables
fixes #1849

Co-authored-by: @eliasdorneles
2023-07-22 12:27:53 +02:00
Rodrigo Girão Serrão
42dc3af347
Merge pull request #2981 from seifertm/2366-switch-click-bubbling
Fixes a bug that causes Click events to bubble up from Switch widgets.
2023-07-22 11:04:15 +01:00
Michael Seifert
febe3631a7 Fixes a bug that causes Click events to bubble up from Switch widgets.
Signed-off-by: Michael Seifert <m.seifert@digitalernachschub.de>
2023-07-22 11:42:32 +02:00
Dave Pearson
e5dfc15106
Typo fix in the module docstring for events.py 2023-07-20 17:55:26 +01:00
Dave Pearson
3111ce7fe9
Change Markdown.load so that load errors propagate
See #2956.
2023-07-19 14:08:17 +01:00
Dave Pearson
95f204fbd8
Merge branch 'main' into unfootgun-worker-thread 2023-07-19 13:43:23 +01:00
Dave Pearson
2f055f6234
Merge pull request #2970 from davep/unbork-selection-list
Fix a crash caused by a prompt being wider than a `SelectionList`
2023-07-19 13:13:42 +01:00
Dave Pearson
fed1ed4848
Remove unnecessary copy of options 2023-07-19 12:37:39 +01:00
Dave Pearson
af51ad9a94
Add missing option from the OptionList.__init__ docstring 2023-07-19 11:34:41 +01:00
Dave Pearson
5431e49c0c
Update the ChangeLog 2023-07-19 11:28:17 +01:00
Dave Pearson
f02a69ff25
Don't wrap prompts in a SelectionList 2023-07-19 11:26:16 +01:00
Dave Pearson
cb819faa37
Add the ability to tell OptionList to not auto-wrap prompts 2023-07-19 11:25:42 +01:00
Dave Pearson
ad2b457348
Make the test a little more extreme 2023-07-19 11:14:03 +01:00
Dave Pearson
749f5c2d7a
Add unit test for #2900 2023-07-19 10:28:13 +01:00
Will McGugan
0b9b6772d9
web driver from textual-serve (#2967)
* web driver from textual-serve

* add future
2023-07-18 14:28:09 +01:00
Will McGugan
47a159c111
Added a max fps environment variable (#2966) 2023-07-18 14:26:09 +01:00
Dave Pearson
1aa2fcf567
Update the work decorator overloads to reduce type warnings
See #2946.
2023-07-18 10:51:40 +01:00
Dave Pearson
da0fd708ae
Update the CHANGELOG 2023-07-18 09:54:20 +01:00
Dave Pearson
17a31196e7
Merge branch 'main' into unfootgun-worker-thread 2023-07-18 09:51:44 +01:00
Dave Pearson
0789c24c76
Add missing notification docstrings and type hints (#2960)
* Add missing docstring for Toast.render

* Add missing type hint for COMPONENT_CLASSES

* Add missing Toast.COMPONENT_CLASSES docstring
2023-07-18 09:39:51 +01:00
Dave Pearson
7bd552a4ec
Make notification documentation and interface match changed rendering (notifications fix option 2) (#2963)
* Remove the empty title styling

The content of the style seems to have been removed, the class isn't
referenced any more, so it can go.

* Change the Notification interface and docs to reflect the changed code

A last-minute change to the notification PR changed the way that titles were
handled. If the intention is to take this new approach (as opposed to an
oversight in the change) then there's little point in allowing two forms of
empty title, while also documenting that an `None` title will default to the
severity.

This commit simplifies the interface for notifications and also modifies the
documentation to reflect the change that was made.
2023-07-18 09:39:11 +01:00
Dave Pearson
8e135e7afb
Tidy up the worker running code
Simplify a wee bit, and also tidy up some of the docstirngs.
2023-07-18 08:37:23 +01:00
Dave Pearson
6638958b20
Move worker tests into their own sub-directory
This makes it far easier to run this subset of tests all at once.
2023-07-18 08:34:46 +01:00
Dave Pearson
6a0ad92883
Merge branch 'main' into unfootgun-worker-thread 2023-07-17 16:23:39 +01:00
Dave Pearson
baa40e3bc9
Be explicit about how someone should decorate a non-async worker 2023-07-17 16:22:05 +01:00
Dave Pearson
d4583249db
Add support for running an async method in a thread worker 2023-07-17 15:59:49 +01:00
Will McGugan
ec58b914cf
version bump (#2955)
* version bump

* tweak toast style, release post

* snapshots
2023-07-17 14:08:32 +01:00
Jayghosh Rao
256e8ad608
Expose animation callback in scroll methods (#2903)
* Expose animation callback in scroll methods

* call on_complete after refresh
2023-07-17 11:50:24 +01:00
Dave Pearson
ca8eb3df7b
Notifications (#2866)
* Add a notification class and a class to hold notifications

This provides the core classes for holding information on a single
notification, and then on top of that a class for managing a collection of
notifications.

* WiP: End of day/week commit to pick up post-holiday

* Ask permission rather than forgiveness

Yes, this does go against all things Pythonic, but in this case it's likely
less costly to do the check first; moreover it works around the problem I
ran in to: https://github.com/Textualize/textual/issues/2863

* Move the handling of "I've seen this" into the toast rack

This way the interface becomes "here's a bunch of notifications, you go work
this out".

* Add a notify method to all widgets

* The removal time for a toast should be the time left

When it was per-screen, it made sense that it was the timeout; now that
we're carrying them over between screens we're going to make sure they're
only around for as long as they need to be.

* Carry notifications between screens

* Remove the test code

* Drop the borders from the toasts

Except for the title, keep that.

* Provide access to the notification timeout

* Remove the title panel from a Toast if the title is empty

* Make the Toast CSS classes "private"

Prefix with a - to reduce the chance of a clash with userspace.

* Refresh a docstring

* Stop widget leakage

The Toasts were removing themselves, but they're wrapped inside a helper
container that keeps them aligned right. So the problem was that the
alignment containers were leaking. This ensures that when a Toast goes away
it takes its parent with it.

* Make the alignment container hidden

This doesn't really make any difference, but it feels like it makes sense to
hide it if there's nothing to show -- it's purely for alignment.

* 🚚 Rename the toast container

This is about getting the toasts to align correctly (even when you do align
things, they don't really align as expected due to the way that a container
aligns the bounding box of all if its children, not the individual
children). However, I had this named after where it aligned them to; someone
using the system may wish to change that, so let's make the name more
generic.

* Improve ToastRack._toast_id

Add a docstring, and also change the format of the identity somewhat so that
it's even "more internal".

* Add some initial low-level notification testing

* Add initial testing of notifications within an application

* Add tests for notifying from the 3 main levels within the DOM

* Add a toast example to the docs and a snapshot test

This might not be the final form, but it'll do for the moment. I want to get
the snapshot test in place at least.

* Add a snapshot test for notifications persisting between screens

* Add some documentation for a Toast

This isn't going into the index, just yet. This is *technically* an internal
widget so I'm not sure how and where it makes sense to document it; if at
all. But let's get some documentation in here anyway.

* Flesh out the docstrings for the notify methods

* Add a missing docstring to the Notifications __init__ method

* Add snapshot tests for persisting notifications through mode switches

* Remove unused import

Looks like eglot/pyright tried to be "helpful" at some point and I didn't
notice.

* Correct the Toast severity level classes in the docs

Originally they weren't in the "internal" namespace, then I decided that
they should be so there's less chance of a clash with dev-space code; but I
forgot to reflect this in the docs.

This fixes that.

* Make the removal of notifications/toasts a two way thing

The addition of the ability to dismiss a toast by clicking on it had a flaw:
the notification->toast code had been written with things being one way. The
expiration of notifications happened in the notification handler, and the
expiration of Toasts was done in the Toast system, on purpose (notifications
might end up being routed via elsewhere so this needs to be done).

But... this meant that hand-removed Toasts kept coming back from the dead
when a new notification was raised iff the hand-removed ones hadn't yet
expired.

So here I add the ability the remove a notification from the notification
collection.

* Remove an unhelpful comment

Sort of a hangover from what was initially looking like it was going to be a
longer body of code. It doesn't really need explaining any more.

* Add in support to the notification collection

* Change the toast rack adder to be a general "show" method

This turns the method into one that further aids making the connection
between the notifications and the toasts two way. Now it makes sense that if
there are toasts for notifications that no longer exist, they also get
removed.

This makes it easier to add all sorts of clear options later on.

* Add a method to clear notifications

* Add an App method for clearing all existing notifications

* Add a missing docstring to _refresh_notifications

* Return the notification from the notify methods

It can be seen as, and used as, a handle of sorts (see unnotify); so return
it so people can use it.

* Add some more notifications unit testing

* Add some more app-level notification unit testing

* Style tweaks

* docs

* added notifications

* snapshots

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-07-17 11:47:17 +01:00
David
4d699c8364
Fix Toggle Buttons on a selection list (#2930)
* Fix Toggle Buttons on a selection list

* Update CHANGELOG.md

* Update dependencies

Mainly updating the now-external snapshot testing code so that the failure
report (which was to be expected) gets generated.

* Update snapshot tests

* Add testing for clicking on a SelectionList prompt or checkbox

* Cody tidy

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-07-17 11:33:09 +01:00
Alejandro Gaspar
062a0f26a1
Change vh to vw in min/max-width styles reference docs (#2943) 2023-07-17 11:32:04 +01:00
darrenburns
7cd07bc69d
Remove print call from OptionList (#2947) 2023-07-15 12:22:21 +01:00
Dave Pearson
c6cd18514c
Allow threaded async
Originally the request had been communicated as the following would be
errors:

- Non-async method, non-thread
- Async method, thread

As of
https://github.com/Textualize/textual/issues/2928#issuecomment-1634333775
it's been decided that the scope of the PR should be expanded to not only
guard against the first case, but also to extend the way the worker API
works to do the right thing in the second case.

This commit backs out the detection of the second case and flagging it as an
error.
2023-07-13 15:44:32 +01:00
Dave Pearson
50657ba295
Add tests for non-thread-non-async-worker 2023-07-13 15:43:34 +01:00
Dave Pearson
e20137af51
Typo fix 2023-07-13 14:45:29 +01:00
Dave Pearson
2dfb44f528
Update the CHANGELOG 2023-07-13 14:33:58 +01:00
Dave Pearson
17ae7175a5
Reword the text relating to the creation of thread workers 2023-07-13 14:08:56 +01:00
Dave Pearson
48ee8540bc
Add the thread argument to the example code in the docs 2023-07-13 14:08:33 +01:00
Dave Pearson
632aaf068f
Add thread parameter to the work docstring 2023-07-13 13:52:17 +01:00
Dave Pearson
47c7bbb54f
Merge pull request #2937 from davep/unrichreadme
Remove a copy of the Rich README that seemed to be kicking about
2023-07-13 13:50:00 +01:00
Dave Pearson
bc354b9454
Remove a copy of the Rich README that seemed to be kicking about
Perhaps a hangover from testing some version of the Markdown widget at some
point in the past. Running a ripgrep for it over the repo shows no reference
to it.
2023-07-13 13:42:10 +01:00
Dave Pearson
9fce998f09
Be explicit that _load_directory is a thread worker 2023-07-13 13:14:50 +01:00
Dave Pearson
e06f9ce7bd
Update the overloads for the work decorator 2023-07-13 13:14:25 +01:00
Dave Pearson
1b0f0017f4
Add a thread parameter to the work decorator and test the context 2023-07-13 13:06:39 +01:00
Dave Pearson
3b85382cb2
Add missing the (#2929)
Credit to ThatOtherAndrew on Discord.
2023-07-12 12:32:48 +01:00
darrenburns
7c6d3c9461
Update gitignore to refer to new default snapshot report location (#2927) 2023-07-12 11:08:33 +01:00
TomJGooding
2d0266550e
feat(datatable): add remove column method (#2899)
* feat(datatable): add remove column method

* add basic unit test

* improve test by checking row data

* update datatable docs

* update changelog
2023-07-12 10:59:25 +01:00
Travers Carter
7a802d4c27
DataTable key lookup enhancements (Closes #2586, Closes #2587) (#2876)
* Updated DataTable.get_cell type hints to accept string keys (#2586)
Added DataTable.get_cell_coordinate
Added DataTable.get_row_index (#2587)
Added DataTable.get_column_index

* Added changelog entries for new DataTable methods

* Fix code style issues identified by Black

* Add unit tests for new DataTable methods
2023-07-12 10:58:31 +01:00
Will McGugan
26573b9cff wrong package 2023-07-11 11:37:32 +01:00
Will McGugan
4937c85590
fuzzy matcher (#2906)
* fuzzy matcher

* ws

* Update src/textual/_fuzzy.py

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-07-11 09:45:43 +01:00
Will McGugan
2cfaf4691b
linear gradient (#2904)
* linear gradient

* revert post message

* tidy

* docstring
2023-07-10 09:54:53 +01:00
Dave Pearson
b9ca79f751
Update the setup target to take into account textual-dev (#2908)
There is no dev extra now.
2023-07-10 09:42:13 +01:00
mardanst
90a93e08ab
Fix intermittent exception in _progress_bar.py (#2892)
* Fix intermittent exception in _progress_bar.py 

Exception raised if percentage changes before the _refresh_timer is instantiated.

* Minor fixes to PR for best practices
2023-07-06 19:02:48 +01:00
Will McGugan
c2f0771322
Fix CancelledError (#2895)
* Rodrigo's test

* changelog

* comment oddity
2023-07-06 14:16:23 +01:00
Rodrigo Girão Serrão
a35e92b9fc
Merge pull request #2889 from Textualize/tweaks-docs-api
Tweak docs.
2023-07-04 16:02:55 +01:00
Rodrigo Girão Serrão
62da06d1ee
Tweak docs.
Removes 'API' entry from the API TOC and adds validation to the TOC.
2023-07-04 15:51:11 +01:00
Will McGugan
ab609a89ea docs update 2023-07-04 11:10:34 +01:00
David Brochart
fa85f5f254
Add install instructions for conda-forge (#2885) 2023-07-04 11:03:10 +01:00
Will McGugan
2ec219bd40 wrong version 2023-07-03 16:09:24 +01:00
Will McGugan
0235fc95da changelog 2023-07-03 15:42:00 +01:00
Will McGugan
65e81c58be
Textual dev (#2884)
* WiP: Move the devtools and related code to `textual-dev` (#2834)

* Remove the textual script from the project file

This is moving into the textual-dev package.

* Remove the textual CLI code from Textual

This has all gone to live in textual-dev.

* Remove the devtools testing from Textual's unit tests

They've moved over to textual-dev instead.

* Remove the devtools server from Textual itself

The start of the process to remove as much of the core devtools as possible
from Textual.

* Switch the console docs example screenshot over to textual_dev

* Remove rednerables.py from Textual

* Remove the last parts of devtools from Textual

This is the last step. It remains to be seen if this is sustainable, but for
testing purposes this is the extreme case we're aiming for. I *think* this
will work though.

Hereon we'll be needing to do an editable install of textual-dev into
textual, and more generally and once this is "live" we'll be needing to make
sure that textual[dev] is installed when doing development work on textual
apps.

The thing that remains to be seen however is how this all works
with *developing* Textual itself. Will I always need to do an editable
install? Still got to figure that one out.

* Start to whittle down the pyproject file

The next step is to try and work out what can come out of the pyproject
file.

* Remove aiohttp from Textual

* Remove some more development dependencies we don't need any more

* Relock

* Remove the pointer to the previews directory

* Reintroduce the border preview snapshot test

* Reintroduce the color preview snapshot test

* Reinstate the key press for the border preview snapshot test

* Reintroduce the easing preview snapshot test

* Reintroduce the keys tool snapshot test

* Add pytest-asyncio as a development dependency

* Relock

* Pin the textual-dev version to 0.1.0 or later

Mostly to try and get the tests kicked off properly.

* Relock dependencies

* Further `textual-dev` changes (#2850)

* Remove the textual script from the project file

This is moving into the textual-dev package.

* Remove the textual CLI code from Textual

This has all gone to live in textual-dev.

* Remove the devtools testing from Textual's unit tests

They've moved over to textual-dev instead.

* Remove the devtools server from Textual itself

The start of the process to remove as much of the core devtools as possible
from Textual.

* Switch the console docs example screenshot over to textual_dev

* Remove rednerables.py from Textual

* Remove the last parts of devtools from Textual

This is the last step. It remains to be seen if this is sustainable, but for
testing purposes this is the extreme case we're aiming for. I *think* this
will work though.

Hereon we'll be needing to do an editable install of textual-dev into
textual, and more generally and once this is "live" we'll be needing to make
sure that textual[dev] is installed when doing development work on textual
apps.

The thing that remains to be seen however is how this all works
with *developing* Textual itself. Will I always need to do an editable
install? Still got to figure that one out.

* Start to whittle down the pyproject file

The next step is to try and work out what can come out of the pyproject
file.

* Remove aiohttp from Textual

* Remove some more development dependencies we don't need any more

* Relock

* Remove the pointer to the previews directory

* Reintroduce the border preview snapshot test

* Reintroduce the color preview snapshot test

* Reinstate the key press for the border preview snapshot test

* Reintroduce the easing preview snapshot test

* Reintroduce the keys tool snapshot test

* Add pytest-asyncio as a development dependency

* Relock

* Pin the textual-dev version to 0.1.0 or later

Mostly to try and get the tests kicked off properly.

* Relock dependencies

* Whitespace cleaning

* Swap mentions of textual[dev] to textual-dev

* Remove the dev extra

* Tweak README.md in response to PR review

* Tweak animation.md in response to PR review

* Tweak getting_started.md in response to PR review

* bump version

* lock

* drop dev

* more

* version bump

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-07-03 15:37:40 +01:00
paul-ollis
6b3b1ce67f
Fix race condition during shutdoen under Windows (#2864)
The terminal writer thread could send escape sequences when the terminal
was unable to process then; i.e. when not in virtual mode.

The following fixes have been made.

- Switch the terminal to virtual mode before the writer thread is
  started and any control sequences are queued to the writer thread.

- Wait for the writer thread to finish before switching the terminal
  out of virtual mode.
2023-07-03 15:32:10 +01:00
Will McGugan
ac5e2d19a7 Dot 2023-07-03 14:21:01 +01:00
Jorge
e4523127a9
Add CodeQL workflow (#2882) 2023-07-03 14:17:16 +01:00
mardanst
101bf681d2
Add error property to worker.py (#2865)
worker.error is described in the worker guide documentation but the property is not present in the code.
2023-07-02 17:23:47 +01:00
Sepehr Shirkhanlu
9c4858a7b3
Fix typo (#2869) 2023-07-02 17:22:56 +01:00
Alex Iribarren
339505e8c7
Redirect output to /dev/null (#2880)
* Redirect output to devnull

Fixes #2877, #2878 and #2879.

* Rename file handle

* Reformat
2023-07-02 17:22:22 +01:00
Will McGugan
21d0916ca1 full stops 2023-06-30 16:41:51 +01:00
Will McGugan
733e50602b
inherit text-style (#2862) 2023-06-29 16:14:47 +01:00
TomJGooding
3bc4fb734b
fix(markdown): render softbreak split links (#2811)
* fix(markdown): render softbreak split links

* add test
2023-06-29 13:29:11 +01:00
Will McGugan
c6bfeeffed
Replace term 'transparency' with 'opacity' (#2861)
* Replace term 'transparency' with 'opacity'

* words

* docstring
2023-06-29 13:14:49 +01:00
Noah
70c4a959bd
docs: Clarify message in color.md (#2860) 2023-06-29 11:34:58 +01:00
darrenburns
ad4308562b
Moving snap_compare to external package (#2849)
* Remove snap_compare fixture, extracted into external plugin

* Remove syrupy and Jinja2 dependencies

* Remove unused dependency
2023-06-27 14:37:41 +01:00
darrenburns
59b5ab0a55
Relax dependency of markdown-it-py (#2844) 2023-06-27 13:45:43 +01:00
darrenburns
fbb11dcafb
Expose the AwaitMount from Markdown.update (#2838)
* Expose the AwaitMount from Markdown.update

* Update CHANGELOG.md

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-06-27 13:37:41 +01:00
darrenburns
d7721060fb
Allow adding columns to populated data table (#2836)
* Allow adding columns to populated data table

* Add snapshot test for adding columns/updating cells

* Update CHANGELOG.md

* Ensure we update virtual_size when cell updated
2023-06-27 13:36:15 +01:00
Will McGugan
fd28e22e53 remove debug print 2023-06-27 11:53:03 +01:00
Dave Pearson
b2602e973a
Merge pull request #2842 from davep/blurred-selection-list/bug/2768
Add missing styles for non-focused and non-highlighted selected selections in a `SelectionList`
2023-06-27 09:57:45 +01:00
Dave Pearson
8e2f81c35a
Update the ChangeLog 2023-06-27 09:14:46 +01:00
Dave Pearson
1a601ef73f
Add missing styles for non-focused "ticked" selections
See #2768.
2023-06-27 09:13:14 +01:00
Will McGugan
25d72feb00
fix for opacity (#2814)
* potential fix for opacity

* add opacity to rich_style

* added can focus

* changelog

* comments

* fix flicker

* test fixes

* docstring [skip ci]
2023-06-26 16:20:16 +01:00
Dave Pearson
cffb9c4806
Merge pull request #2820 from davep/option-list-typo-fix
Fix a typo in the docstring for `OptionList.get_option`
2023-06-21 13:44:23 +01:00
Dave Pearson
3c3ad6c0b2
Fix a typo in the docstring for OptionList.get_option 2023-06-21 13:20:24 +01:00
Dave Pearson
8c105fb373
Fix a broken link to the Worker class (#2816) 2023-06-21 10:44:59 +01:00
Will McGugan
14aeb31cd9
minor bump (#2809)
* minor bump

* changelog
2023-06-20 09:27:17 +01:00
Dave Pearson
4b02d37e8c
TabbedContent remove pane fix (actually Tabs fix) (#2808)
* Add a unit test for https://github.com/Textualize/textual/issues/2807

* Add a test for removing tabs in reverse

* Add a test for the messages sent when removing tabs in reverse

Marked as xfail for the moment, I suspect the root cause of #2807.

* Don't sent Changed when tab removal doesn't result in change

* Update the CHANGELOG

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-06-20 09:15:16 +01:00
Will McGugan
9639449f48
Preserve original sender when using call_after_refresh (#2806)
* Defer sender in call_after_refresh

* docstring

* test

* typing
2023-06-20 09:14:01 +01:00
Dave Pearson
038cdb23d8
Markdown improvements (#2803)
* Initial set of Markdown widget unit tests

Noting too crazy or clever to start with, initially something to just test
the basics and to ensure that the resulting Textual node list is what we'd
expect.

Really just the start of a testing framework for Markdown.

* Allow handling of an unknown token

This allow for a couple of things:

1. First and foremost this will let me test for unhandled tokens in testing.
2. This will also let applications support other token types.

* Update the Markdown testing to get upset about unknown token types

* Treat a code_block markdown token the same as a fence

I believe this should be a fine way to solve this. I don't see anything that
means that a `code_block` is in any way different than a fenced block that
has no syntax specified.

See #2781.

* Add a test for a code_block within Markdown

* Allow for inline fenced code and code blocks

See #2676

Co-authored-by: TomJGooding <101601846+TomJGooding@users.noreply.github.com>

* Update the ChangeLog

* Improve the external Markdown elements are added to the document

* Improve the testing of Markdown

Also add a test for the list inline code block

* Remove the unnecessary pause

* Stop list items in Markdown being added to the focus chain

See #2380

* Remove hint to pyright/pylance/pylint that it's okay to ignore the arg

---------

Co-authored-by: TomJGooding <101601846+TomJGooding@users.noreply.github.com>
2023-06-20 09:13:41 +01:00
Will McGugan
bb9cc6281a
tooltips in compound widgets (#2801)
* tooltips in compound widgets

* snapshot tweak

* test fixes
2023-06-19 14:11:18 +01:00
Will McGugan
e7531f4614 update faq 2023-06-19 11:11:16 +01:00
Will McGugan
d962bbad8d add faq 2023-06-19 11:07:20 +01:00
Will McGugan
c91858d04d
Update why-looks-bad-on-macos.question.md (#2800) 2023-06-19 11:06:58 +01:00
Will McGugan
82411ad337
version bump (#2799)
* version bump

* changelog
2023-06-19 10:26:47 +01:00
Will McGugan
129bef49cf
Alternative scroll to center (#2787)
* remove commented out code

* origin_visible flag

* comments

* docstring

* test fix
2023-06-19 10:09:45 +01:00
Dave Pearson
65fff4f2de
Add a missing word to the Tree label entry in the ChangeLog (#2797) 2023-06-19 09:54:11 +01:00
Will McGugan
5ad64a315c
satisfy pyright (#2793) 2023-06-19 09:53:41 +01:00
Will McGugan
48598a6bb7
fix broken repr in file monitor (#2795)
* fix broken repr in file monitor

* no need for callback

* docstrings and typing
2023-06-18 16:58:38 +01:00
Dave Pearson
c966243b05
Merge pull request #2751 from davep/tabbed-content-redux 2023-06-16 11:14:14 +01:00
Dave Pearson
832208ba83
Add unit testing for TabbedContent adding before/after 2023-06-15 15:43:22 +01:00
Dave Pearson
e4b4aad467
Rename a couple of TabbedContent tests
So they don't get confused with actual "add after".
2023-06-15 14:57:26 +01:00
Dave Pearson
50d93b56c2
Swap to asyncio.gather
See https://github.com/Textualize/textual/pull/2751#discussion_r1230816478
2023-06-15 14:23:33 +01:00
Dave Pearson
282f2c6dd7
Fix a typo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-06-15 12:04:48 +01:00
Dave Pearson
06c2b975ee
Remove unnecessary f-string 2023-06-15 11:55:30 +01:00
Dave Pearson
146b1b8e4c
Update the ChangeLog 2023-06-15 11:26:04 +01:00
Dave Pearson
4dd934a68d
Add a couple of missing pauses to TabbedContent unit tests
These are needed to give messages time to flow.
2023-06-15 10:58:33 +01:00
Dave Pearson
abc0e802d1
Make the rest of the TabbedContent tests lean on async/await 2023-06-15 10:50:57 +01:00
Dave Pearson
f5e516dfd8
Add support for adding a pane before/after another one 2023-06-15 10:41:26 +01:00
Dave Pearson
4af0f8304f
Turn on/off highlighting of the underline depending on tabs 2023-06-15 10:28:50 +01:00
Dave Pearson
6f03566090
Allow completely turning off the highlight
Ideally this would use something like what #2786 intends to add, but
meanwhile this solves the problem of ghost highlights in extreme situations
of adding/removing tabs.
2023-06-15 10:27:52 +01:00
Dave Pearson
ffd6db660a
Remove unused import 2023-06-15 10:05:33 +01:00
Dave Pearson
8e6904b5f2
Merge pull request #2785 from TomJGooding/docs-fix-geometry-typos 2023-06-15 09:55:44 +01:00
Dave Pearson
f21668667d
Be more forgiving when removing tabbed content
It's possible, unlikely but possible, that the content could get removed via
some other route, or out of sync, so allow for that. Don't get upset of the
content has gone away when we're removing the tab that was in charge of it.
2023-06-15 09:51:26 +01:00
TomJGooding
7ea1ed044a docs: fix typos in geometry 2023-06-15 09:37:46 +01:00
Dave Pearson
617244ddd7
Simplify add_pane 2023-06-14 16:31:57 +01:00
Dave Pearson
07c445ceaf
Make the TabbedContent add/remove/clear methods optionally awaitable 2023-06-14 16:14:36 +01:00
Dave Pearson
2c6d09e700
Make attempting to move away from non-existing content a no-op
It's possible that we might be being asked to switch from an item of content
that has actually been removed; there's no harm in making not finding the
old thing a no-op.
2023-06-14 15:36:31 +01:00
Dave Pearson
5f0f353948
Merge branch 'main' into tabbed-content-redux 2023-06-14 15:28:49 +01:00
Dave Pearson
78bfb5a685
Merge pull request #2778 from davep/awaitable-tabs
Awaitable tabs
2023-06-14 14:03:13 +01:00
Dave Pearson
2f72b5f7eb
Merge branch 'main' into awaitable-tabs 2023-06-14 13:41:56 +01:00
Dave Pearson
4fe7bb1d44
Update the ChangeLog 2023-06-14 13:35:09 +01:00
Dave Pearson
be9c1da98d
Correct a docstring 2023-06-14 13:23:15 +01:00
Dave Pearson
9b4317f077
Add before/after options to add_tab
Merging in the core idea of #2762 given that this is an overhaul of Tabs in
general and also adding/removing/clearing tabs in particular.

Co-authored-by: blob42 <contact@blob42.xyz>
2023-06-14 13:09:09 +01:00
Will McGugan
2889a437f2
Style review (#2777)
* further tweaks

* button tweaks

* style tweaks

* style tweaks

* tests

* test fixes

* tidy css
2023-06-14 13:04:24 +01:00
Will McGugan
ad74392c2a
test fix (#2779) 2023-06-14 11:52:18 +01:00
Rodrigo Girão Serrão
118e62de0e
Disabled container (#2776)
* Add regression test for #2772.

* Remove focus on nested disabled widgets.

* Optimisation.

Related comments: https://github.com/Textualize/textual/pull/2776#discussion_r1228327427

* Fix tests.
2023-06-14 11:46:55 +01:00
Dave Pearson
cbbcc65c4e
Add unit tests for Tabs messages 2023-06-14 10:57:02 +01:00
Dave Pearson
d1fe395e6d
Add tests for navigating tabs with the mouse 2023-06-14 10:12:25 +01:00
Dave Pearson
519d32a676
Add a test for accessing a Tab's label 2023-06-14 09:50:22 +01:00
Dave Pearson
56014b1dfb
Add a test for attempting to keyboard-navigate an empty Tabs 2023-06-14 09:45:11 +01:00
Dave Pearson
a97f227d7c
Add a test for navigating tabs with the keyboard 2023-06-14 09:39:18 +01:00
Dave Pearson
9fe8cbbad4
Follow some more tab removal code paths in testing 2023-06-14 09:35:46 +01:00
Dave Pearson
4f8936f4e4
Add a test for changing the active tab from code 2023-06-14 09:21:55 +01:00
Dave Pearson
77c04ad8a2
Add better coverage to the tab removal tests 2023-06-14 09:12:38 +01:00
Dave Pearson
e89186cee8
Add a test for clearing tabs 2023-06-14 09:05:22 +01:00
Dave Pearson
cab0f7429e
Add a test for removing tabs 2023-06-14 09:03:23 +01:00
Dave Pearson
b25f3ddc49
Test making tabs from instances of a Tab 2023-06-14 08:57:33 +01:00
Dave Pearson
9a5d392733
Remove an unneeded type
Recent changes mean this isn't required any more.
2023-06-14 08:54:51 +01:00
Dave Pearson
ca1e99f95d
Make a start on some unit tests for Tabs 2023-06-13 18:32:22 +01:00
Dave Pearson
94561a67c2
Make Tabs.clear awaitable 2023-06-13 15:47:54 +01:00
Dave Pearson
311b17e647
Add a missing new return value to the remove_tab docs 2023-06-13 15:38:26 +01:00
Dave Pearson
145fe13207
Make Tabs.remove_tab optionally awaitable 2023-06-13 15:36:52 +01:00
Dave Pearson
5fc64f2002
Make Tabs.add_tab optionally awaitable 2023-06-13 15:07:12 +01:00
Dave Pearson
82b5b21f82
Make the active Tabs watcher more robust
It's unlikely, but not impossible, that code could end up asking to make a
tab active that doesn't exist any more, so here we make things a wee bit
more robust and turn it into a no-op.
2023-06-13 15:00:10 +01:00
Rodrigo Girão Serrão
436b1184a9
Merge pull request #2744 from Textualize/screen-css
Screen css
2023-06-12 16:56:32 +01:00
darrenburns
b69973322e
Re-raise encountered exceptions in pilot tests (#2754) 2023-06-12 16:42:25 +01:00
darrenburns
231a894941
Fixes suggested by linter (#2769) 2023-06-12 15:00:19 +01:00
Rodrigo Girão Serrão
14269a48f1
Merge pull request #2758 from Textualize/win-sleep-bug
Fix win sleep bug
2023-06-12 11:51:48 +01:00
rodrigogiraoserrao
d47a126847 Merge branch 'win-sleep-bug' of github.com:textualize/textual into win-sleep-bug 2023-06-12 11:38:48 +01:00
Dave Pearson
6deb97af9e
Merge pull request #2767 from davep/tweak-await-remove
Don't return anything from `AwaitMount.__call__`
2023-06-12 11:29:20 +01:00
rodrigogiraoserrao
6a1c470d32 Fix regression test. 2023-06-12 11:26:40 +01:00
Dave Pearson
247895a213
No point in returning something when there's no return value to speak of
Possibly the least-useful PR I've made yet; but once seen it could not be
unseen.
2023-06-12 11:00:19 +01:00
darrenburns
e6bac7a720
Add Deepsource configuration. (#2766) 2023-06-12 10:52:14 +01:00
Rodrigo Girão Serrão
9d5bcc16af
Merge pull request #2759 from Textualize/more-widget-tests
A couple more widget tests.
2023-06-12 10:46:02 +01:00
Rodrigo Girão Serrão
b5fa18f27a
Delete WIP comment 2023-06-12 10:26:13 +01:00
Rodrigo Girão Serrão
38f9bf310f
Longer sleep. 2023-06-12 10:13:48 +01:00
Josh Duncan
1dc02ed5ce
Correct Row Highlighting When Labeled (#2756) 2023-06-12 09:50:48 +01:00
Rodrigo Girão Serrão
e3f9dc1fe8
Use a coroutine that does nothing. 2023-06-09 17:32:12 +01:00
Rodrigo Girão Serrão
0c32c05dfa
Address review feedback. 2023-06-09 15:19:55 +01:00
Rodrigo Girão Serrão
22577b4ce7
A couple more widget tests. 2023-06-09 15:17:12 +01:00
rodrigogiraoserrao
6f31380bd9 Implement cancellable Windows sleep.
Related issues: #2711.
2023-06-09 14:34:39 +01:00
rodrigogiraoserrao
2e71040a71 Add tests. 2023-06-09 14:34:03 +01:00
Dave Pearson
2062ce3853
Pull Tooltip out of the main DOM (#2755)
Fixes #2723
2023-06-08 15:12:41 +01:00
Dave Pearson
ee59817427
Merge branch 'main' into tabbed-content-redux 2023-06-08 10:11:07 +01:00
rodrigogiraoserrao
a7e5822c41 First attempt. 2023-06-07 16:36:04 +01:00
Dave Pearson
83633ad9e0
Try a slightly longer pause to wait for messages 2023-06-07 15:57:36 +01:00
Dave Pearson
a6e016d7e1
Experiment with an actual wait time
The tests touched in this commit are working fine in CI for GNU/Linux and
macOS; but fail on Windows as the message we need to come through doesn't
seem to be coming through.

Testing on Windows (11, in Parallels, on macOS) it seems that setting an
actual time for the pauses does the trick. I'm not sure why, I thought a
pause with no time ensured that all message queues were emptied before
coming out of the pause. Apparently not.

So this is an experiment to see if it'll pass in CI too.
2023-06-07 15:44:09 +01:00
Will McGugan
8947dbe703
on super class (#2746)
* on super class

* simplification

* simplify

* remove whitespace

* changelog

* changelog

* Update tests/test_on.py

Co-authored-by: darrenburns <darrenburns@users.noreply.github.com>

---------

Co-authored-by: darrenburns <darrenburns@users.noreply.github.com>
2023-06-07 13:43:12 +01:00
rodrigogiraoserrao
b3375af8e9 Make black happy. 2023-06-07 13:31:08 +01:00
Dave Pearson
21d7049b2d
Fix a copy/pasteo 2023-06-07 12:47:03 +01:00
Dave Pearson
2bf8fd7905
Add a TabbedContent.Cleared message
Much like Tabs.Cleared, this indicates that all available tabs/panes have
been removed and the widget is now empty. This is especially important here
as the way we remove tabs is such that we can't await their removal and then
make the remove methods async (because Tabs doesn't allow for that).

So the approach taken here is to send a message from TabbedContent, and
delay it as much as possible, ideally once the action that's taking
place *has* taken place.

The reasoning is: a user may clear down all panes, then want to add some
back, possibly with IDs they've used before. The clear down might not have
fully happened, but we can't await it all, so the approach for the user
would be to wait until the Cleared message turns up *then* repopulate.
2023-06-07 12:21:17 +01:00
rodrigogiraoserrao
365d094505 Merge branch 'main' into screen-css 2023-06-07 12:04:55 +01:00
rodrigogiraoserrao
2718a7ade3 Update screen CSS parsing logic.
Do not keep an explicit registry of screens whose CSS has been parsed. Instead, grow methods in the file monitor and in the stylesheet to check if a given path is already being monitored/sourced and add the paths if it isn't.
2023-06-07 12:04:21 +01:00
rodrigogiraoserrao
23fd9cb793 Add test for screen CSS parsing count. 2023-06-07 12:03:12 +01:00
rodrigogiraoserrao
8f2ee8cef2 Tweak docstrings.
Related comments: https://github.com/Textualize/textual/pull/2744#discussion_r1219872393, https://github.com/Textualize/textual/pull/2744#discussion_r1219876738
2023-06-07 10:37:59 +01:00
Dave Pearson
fd243f4973
Add a TabbedContent method to clear all panes 2023-06-07 08:40:25 +01:00
Dave Pearson
0ac613d7fe
Add tests that check the tab count when adding and removing tabs 2023-06-07 08:18:29 +01:00
Dave Pearson
d8aa49b046
Deduplicate the create of tab IDs 2023-06-07 08:18:08 +01:00
Dave Pearson
feb07db435
Document the return value of TabbedContent.add_pane 2023-06-07 07:49:39 +01:00
Dave Pearson
7802970762
Add a tab_count property to TabbedContent
Mimics (and actually simply returns) Tabs.tab_count. The idea being that if
people can now add and remove tabs from TabbedContent, they may want to be
able to keep track of how many tabs there are.
2023-06-07 07:24:18 +01:00
Dave Pearson
c5253f4911
Merge pull request #2748 from davep/one-more-input-test 2023-06-06 19:41:53 +01:00
Dave Pearson
eac8eba761
Test that Input maintains its height
Also... that last elusive line in coverage.
2023-06-06 16:57:46 +01:00
Dave Pearson
8f4b40ef24
Add some tests for adding/removing tabs to TabbedContent 2023-06-06 16:41:43 +01:00
darrenburns
1c3a4bb7bc
Datatable style ordering (#2736)
* Allow customising whether CSS or renderable colors show in datatable

* Simplify

* Add snapshot for style ordering in the DataTable

* Fix layering issue with text colours, add snapshot tests (DataTable)

* Update CHANGELOG.md
2023-06-06 16:32:35 +01:00
Dave Pearson
300401c4b6
Set active to empty if there are no tabs left 2023-06-06 16:31:35 +01:00
Dave Pearson
81edb863fb
Only error out when active is empty and there are tabs available
If, on the other hand, we set active to empty when there is no content to be
tabbed, then we let it slide.
2023-06-06 16:30:45 +01:00
Rodrigo Girão Serrão
51762b140c
Merge pull request #2672 from TomJGooding/docs-button-update-spacing-note
docs(button): update note about button spacing/padding
2023-06-06 16:23:51 +01:00
TomJGooding
ead005d8bc
docs: import message from message not messages (#2747) 2023-06-06 16:13:07 +01:00
Rodrigo Girão Serrão
0d646dd53f
Merge pull request #2708 from Textualize/private-validate-compute
Private validate compute
2023-06-06 15:18:27 +01:00
Rodrigo Girão Serrão
f0871ada74
Merge pull request #2709 from Textualize/delete-reactive-var
Delete Reactive.var.
2023-06-06 15:18:04 +01:00
Dave Pearson
5cf50f7083
Add a remove_pane method to TabbedContent
See #2710.
2023-06-06 14:55:51 +01:00
Dave Pearson
290351db10
Add an add_pane method to TabbedContent
See #2710.
2023-06-06 14:26:40 +01:00
Rodrigo Girão Serrão
845f711ec8
Fix pattern import. 2023-06-06 13:45:13 +01:00
Rodrigo Girão Serrão
b98e004b54
Add CSS and CSS_PATH to screens. 2023-06-06 13:38:13 +01:00
Rodrigo Girão Serrão
34a19f4bff
Add tests for screen CSS. 2023-06-06 13:34:57 +01:00
Dave Pearson
69d86fb764
Make the active tab watcher private 2023-06-06 12:14:24 +01:00
Dave Pearson
2d4183ffaa
Clean up a type warning about tab ID in _on_tabs_tab_activated 2023-06-06 12:02:39 +01:00
Dave Pearson
755da5e969
Merge pull request #2722 from davep/docs-auto-focus-borkage-fix
Fix various screenshots in the docs, broken by the addition of `AUTO_FOCUS`
2023-06-06 11:55:05 +01:00
Dave Pearson
b318d323ca
Merge pull request #2743 from davep/input-tweaks
Assorted tweaks to `Input`
2023-06-06 11:22:35 +01:00
Dave Pearson
235fdc2c48
Remove dead code from Input._on_key
The branch being removed here seems to be trying to handle keyboard bindings
before handling the raw keyboard event. However, in the unit tests, even
when a binding is pressed, this code doesn't get called.

I strongly suspect this is code that predates changes that were made some
time ago in respect to the order in which bindings were processed and their
relationship to keystrokes.

After removing this all tests are passing just fine and hand-testing
`Input` (especially in the demo, for example, both non-password and password
incarnations) shows no problems either.

All evidence suggests that #2737 was incapable of hitting that branch of
code because it just could not be hit these days.
2023-06-06 10:47:16 +01:00
Dave Pearson
552d381c58
Make the value watcher private 2023-06-06 10:42:16 +01:00
Dave Pearson
d4be9ac080
Make cursor position watch private
Also remove the parameter that wasn't being used anyway.
2023-06-06 10:41:20 +01:00
Dave Pearson
b252459d00
Merge pull request #2737 from davep/extend-input-widget-tests
Add more unit testing for the `Input` widget
2023-06-06 10:30:19 +01:00
Dave Pearson
2b67080984
Merge branch 'extend-input-widget-tests' of github.com:davep/textual into extend-input-widget-tests 2023-06-06 10:18:10 +01:00
Dave Pearson
5ca6d54973
Switch clicks_within to use parametrize
TIL.
2023-06-06 10:17:45 +01:00
Dave Pearson
8afe656a01
Fix a function naming typo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-06-06 10:12:09 +01:00
Rodrigo Girão Serrão
0c26f62b82
Mark as breaking change. 2023-06-06 10:05:25 +01:00
Rodrigo Girão Serrão
a26b0fd8e3
Update src/textual/message_pump.py 2023-06-06 10:02:43 +01:00
darrenburns
2158f8ed8d
Fix raise NotImplemented in DataTable (#2705)
* Fix raise NotImplemented in DataTable

* DataTable key return NotImplemented

* Returning NotImplemented in DataTable
2023-06-06 09:49:40 +01:00
Dave Pearson
5c19c72721
Tidy the highlighter test a wee bit 2023-06-06 09:33:18 +01:00
Dave Pearson
fed8ca1121
Add a test for using a highlighter with an Input 2023-06-06 09:19:25 +01:00
Dave Pearson
79fb295cb9
Add a test for deleting left-word inside the first word 2023-06-06 08:13:01 +01:00
Dave Pearson
85cc741aa3
Tidy up the Input mouse tests
Also add a test for clicking outside of the content.
2023-06-06 08:04:33 +01:00
Will McGugan
8b42867bb1 typo 2023-06-05 17:51:19 +01:00
Will McGugan
67ba9aa47a
assets (#2739) 2023-06-05 17:50:34 +01:00
Rodrigo Girão Serrão
48df69ed22
Merge pull request #2738 from Textualize/errors-shown-typo
Fix typo.
2023-06-05 16:31:19 +01:00
Dave Pearson
c08315eb30
Add tests for mouse clicking inside of an Input 2023-06-05 16:16:42 +01:00
Rodrigo Girão Serrão
d35bac429e
Fix typo. 2023-06-05 15:53:25 +01:00
Dave Pearson
71e5644a1f
Add some property testing to the Input widget 2023-06-05 15:25:41 +01:00
Dave Pearson
a082e18238
Add a test for the message impact of a paste event 2023-06-05 15:09:45 +01:00
Dave Pearson
c6e57dec09
Add message-based testing for the Input widget 2023-06-05 14:32:06 +01:00
Dave Pearson
d2bf3b5038
Merge pull request #2735 from davep/extend-radio-set-testing
Extend radio set testing
2023-06-05 13:51:01 +01:00
Dave Pearson
6239731ee2
Add a test for after-the-fact adding of buttons to a RadioSet 2023-06-05 13:30:58 +01:00
Dave Pearson
cb92104f1e
Merge pull request #2732 from davep/content-switcher-more-testing
Finish off `ContentSwitcher` unit testing
2023-06-05 11:37:34 +01:00
Rodrigo Girão Serrão
2057c463a4
Extract prefix (length). 2023-06-05 11:22:06 +01:00
Dave Pearson
ee3aad7e65
Add testing for the control property
Ensure it's always the correct value.
2023-06-05 10:46:11 +01:00
Dave Pearson
29c160eb06
Merge pull request #2728 from davep/main
Fix a typo in the typing example in the SelectionList docs
2023-06-05 10:29:43 +01:00
Dave Pearson
e74941da15
Add more testing for the ContentSwitcher
It looks like "visible_content" might have turned up after the tests were
added; so this adds testing for that to the tests (and gets coverage for
ContentSwitcher to 100%).
2023-06-05 09:05:11 +01:00
Dave Pearson
e79cce676d
Merge branch 'Textualize:main' into main 2023-06-05 08:45:50 +01:00
claws
bfef40a806
Fix typo (#2729) 2023-06-04 12:56:20 +01:00
Dave Pearson
7f1436538e
Fix a typo in the typing example in the SelectionList docs
See #2727.
2023-06-02 22:37:49 +01:00
Dave Pearson
269f2446be
Remove tab presses from compound widgets examples post-AUTO_FOCUS
See #2720.
2023-06-02 07:14:22 +01:00
Dave Pearson
2f1422049f
Remove tab presses from input focus guide post-AUTO_FOCUS
See #2720. I'm not 100% sure about this one; I don't think it's been
modified since the AUTO_FOCUS change was made, so I believe this will be
restoring the example to its intended state.
2023-06-02 07:11:04 +01:00
Dave Pearson
955fb7363a
Remove tab presses from reactivity guide post-AUTO_FOCUS
See #2720. While there wasn't a problem here, there's no point in having
those there any more as the fields will have focus to start with.
2023-06-02 07:00:50 +01:00
Dave Pearson
ef003c7967
Fix ProgressBar gallery entry post-AUTO_FOCUS
See #2720.
2023-06-02 06:49:30 +01:00
Dave Pearson
0555a956aa
Fix Input gallery entry post-AUTO_FOCUS
See #2720.
2023-06-02 06:48:41 +01:00
Dave Pearson
73d08274f1
Fix Input example post-AUTO_FOCUS
See #2720.
2023-06-02 06:47:38 +01:00
Dave Pearson
c86797c8ab
Fix ProgressBar examples post-AUTO_FOCUS
See #2720.
2023-06-02 06:45:03 +01:00
Dave Pearson
4f8a8e1250
Merge pull request #2719 from davep/content-switcher-doc-fix 2023-06-01 21:53:57 +01:00
Dave Pearson
f010dc0a46
Fix the examples for the ContentSwitcher widget
See #2718. The problem is that the work done on #2527 and related PRs has
changed the starting position of focus, which means that any code example
that has key presses in them that start out by tabbing to a control will be
off by one.
2023-06-01 20:53:52 +01:00
Dave Pearson
a8c0c015f8
Merge pull request #2717 from davep/sparkline-examples-non-internal-import
Import `Sparkline` from a non-internal location
2023-06-01 18:41:53 +01:00
Dave Pearson
ec5fe6a33e
Import Sparkline from a non-internal location
Updates the Sparkline examples within the documentation so that the
Sparkline widget is imported in a way that developers working with Textual
should.
2023-06-01 18:31:57 +01:00
Dave Pearson
81ec818639
Merge pull request #2716 from davep/css-good-life-reload-confirmation
In devtools show confirmation of successfully loading CSS after a previous fail
2023-06-01 18:17:46 +01:00
Dave Pearson
bf8b6fe077
Merge branch 'main' into css-good-life-reload-confirmation 2023-06-01 18:09:11 +01:00
Will McGugan
61455db23e changelog 2023-06-01 17:48:09 +01:00
Will McGugan
065effbebd doc fixes 2023-06-01 17:41:08 +01:00
Will McGugan
5f10e4c976 fix blog 2023-06-01 17:36:05 +01:00
Dave Pearson
d0edd99a61
Merge pull request #2713 from davep/tree-node-label-change-should-refresh-the-tree 2023-06-01 17:19:28 +01:00
Rodrigo Girão Serrão
d96884d33c
Merge pull request #2715 from Textualize/fix-modes
Remove duplicated modes.
2023-06-01 16:21:07 +01:00
Dave Pearson
b53eef84d2
Update the ChangeLog with the PR link 2023-06-01 16:16:30 +01:00
Dave Pearson
3e2d1ba52d
In devtools Show confirmation of successfully loading CSS after a previous fail
See #2534
2023-06-01 15:51:49 +01:00
Rodrigo Girão Serrão
3b599d04cd
Remove duplicated modes. 2023-06-01 15:30:26 +01:00
Dave Pearson
3b6f75ce6e
Update the ChangeLog 2023-06-01 11:42:19 +01:00
Dave Pearson
216615e24f
Merge branch 'main' into tree-node-label-change-should-refresh-the-tree 2023-06-01 11:39:57 +01:00
Will McGugan
58a9cb1909
blog post new release (#2712)
* blog post new release

* update words

* Update docs/blog/posts/release0-27-0.md

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-06-01 11:33:54 +01:00
Dave Pearson
e55ee23eae
Defer the repainting of the node in the tree
The previous change actually broke some of the tests in test_disabled.py --
well actually it flat out broke one and caused all the others to run *very*
slowly. No clue why though.

But thinking about this some more, it does feel like delaying the refresh of
the node makes more sense.
2023-06-01 10:49:29 +01:00
Dave Pearson
70f173fae8
Ensure a Tree's node is refreshed when the label is changed
Fixes #2698
2023-06-01 10:37:39 +01:00
Rodrigo Girão Serrão
78db024c01
Add sparkline widget. (#2631)
* Sparkline widget proof of concept.

* Address review comment.

Related comments: https://github.com/Textualize/textual/pull/2631\#discussion_r1202894414

* Blend background colours.

* Add widget sparkline.

* Add snapshot tests.

* Add documentation.

* Update roadmap.

* Address review feedback.

Relevant comments: https://github.com/Textualize/textual/pull/2631\#discussion_r1210394532, https://github.com/Textualize/textual/pull/2631\#discussion_r1210442013

* Improve docs.

Relevant comments: https://github.com/Textualize/textual/pull/2631\#issuecomment-1568529074

* Update snapshot app titles.

* Don't init summary function with None

Related comments: https://github.com/Textualize/textual/pull/2631\#discussion_r1211666076

* Apply suggestions from code review

Co-authored-by: Dave Pearson <davep@davep.org>

* Improve wording.

* Improve wording.

* Simplify example.

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-06-01 09:34:33 +01:00
Rodrigo Girão Serrão
8516ddaf2b
Delete Reactive.var.
Related issues: #2706.
2023-05-31 18:04:53 +01:00
Rodrigo Girão Serrão
e170bbe437
Merge branch 'main' into private-validate-compute 2023-05-31 17:54:52 +01:00
Rodrigo Girão Serrão
b1a6954789
Changelog. 2023-05-31 17:52:11 +01:00
Rodrigo Girão Serrão
73019fa773
Fix name shadowing issue. 2023-05-31 17:50:23 +01:00
Rodrigo Girão Serrão
2293f40416
Use private computes. 2023-05-31 16:17:15 +01:00
Rodrigo Girão Serrão
fdc7ba3f0b
Add tests for private computes. 2023-05-31 16:17:06 +01:00
darrenburns
7049014faa
Option to ensure scroll_to_center doesn't scroll so as to hide the top left corner of the widget (#2682)
* Option to ensure origin of widget is visible when calling scroll to center

* Update CHANGELOG.md

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-05-31 16:13:21 +01:00
Rodrigo Girão Serrão
41af804ca5
Check for private AND public compute methods.
We do this inside _MessagePumpMeta.__new__ because this runs at 'import time', and thus is essentially the earliest we can figure out if this is not going to work.
2023-05-31 16:09:22 +01:00
Dave Pearson
a14e469dd6
Improve OptionList test coverage (#2701)
* Cover the penultimate uncovered line in OptionList

Sort of moot, but worth a test that the control of a message is the option
list.

* Test OptionList hover over disabled option

I *would* have liked to have tested this sort of thing via snapshot tests,
but it seems that pilot.hover isn't quite behaving as desired there. But
this provides a useful test anyway.
2023-05-31 15:23:24 +01:00
Will McGugan
0849e6f410
mount order (#2702)
* mount order

* fix test

* simplify hooks

* changelog

* docstring
2023-05-31 15:16:26 +01:00
Rodrigo Girão Serrão
85722d61db
Test private validate methods. 2023-05-31 14:01:18 +01:00
Rodrigo Girão Serrão
648d5f43ee
Use private validate methods.
Private validate methods are checked before the public ones.
2023-05-31 13:56:35 +01:00
Dave Pearson
4ff1d18cb5
Merge pull request #2700 from davep/split-option-list-snapshits
Split up the OptionList snapshot tests
2023-05-31 11:22:51 +01:00
darrenburns
0dc58bd151
Ensure _options attribute is assigned in Select constructor (#2690)
* Ensure _options attribute is assigned in Select constructor

* Update CHANGELOG.md

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-05-31 09:45:06 +01:00
Dave Pearson
dba14b8a12
Split up the OptionList snapshot tests
Don't run 3 snapshot tests in one test function when it's easier to see what
broke and where if each is in their own function.
2023-05-31 09:17:26 +01:00
Rodrigo Girão Serrão
1c7cb066ae
Activate private validate method test. 2023-05-30 16:38:10 +01:00
Will McGugan
149c39c86c
Tooltips (#2670)
* inflect

* diagram

* tooltip render

* tooltip property

* add guard

* tooltip docs

* docs

* tidy, fix horizontal

* words, removed comment

* fix screenshot render

* simplify

* simfplify

* changelog

* simplify optimize

* inflect tests

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* docstring

* disable auto focus

* should be fraction

* optimization

* snapshot update

* Update tests/snapshot_tests/snapshot_apps/scroll_to_center.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-30 16:14:31 +01:00
Rodrigo Girão Serrão
83c83de78b
Merge pull request #2686 from Textualize/worker-coverage
Increase worker coverage and fix bug.
2023-05-30 16:13:20 +01:00
Aaron Stephens
7c9abea839
fix(_compositor): move hidden_widgets (#2687) 2023-05-30 15:58:14 +01:00
Will McGugan
4930c1615b
Merge branch 'main' into worker-coverage 2023-05-30 15:55:46 +01:00
Rodrigo Girão Serrão
43d39aa061
Merge pull request #2693 from Textualize/stylesbase-typing
Fix typing issues.
2023-05-30 15:09:47 +01:00
Rodrigo Girão Serrão
ee6f1b93a3
Merge pull request #2692 from Textualize/switch-screen
Fix issue with switch screen.
2023-05-30 15:09:19 +01:00
Rodrigo Girão Serrão
0f4f82569c Fix typing issues.
Related issues: #2494, #2680
2023-05-30 14:46:54 +01:00
Rodrigo Girão Serrão
ce771c19f4 Fix issue with switch screen. 2023-05-30 13:55:17 +01:00
darrenburns
3dea4337ac
Add Validator framework note to CHANGELOG (#2685) 2023-05-30 13:02:46 +01:00
Rodrigo Girão Serrão
5126e98b3b Remove weird import. 2023-05-30 10:21:35 +01:00
Rodrigo Girão Serrão
9569a98c77 Increase worker coverage and fix bug. 2023-05-29 19:49:58 +01:00
darrenburns
a40300a6f5
Ensure reflow reflows non-visible widgets, fix scroll_to_center issue (#2684) 2023-05-29 18:23:49 +01:00
Rodrigo Girão Serrão
6cb052a7f2
Fix changelog. (#2683) 2023-05-29 18:17:31 +01:00
darrenburns
3e7b2c53a8
Add Widget.remove_children method (#2657) 2023-05-29 18:03:42 +01:00
darrenburns
ca17d8194e
Add docs for Pretty, fix some reference issues in docs (#2678) 2023-05-29 17:11:39 +01:00
Rodrigo Girão Serrão
73d55725b5
Merge pull request #2604 from Textualize/input-auto-completion
Input completion suggestions
2023-05-29 14:48:40 +01:00
Rodrigo Girão Serrão
baa1f712d8 Change default case sensitivity. 2023-05-29 14:24:49 +01:00
Dave Pearson
ea75fcc5e5
Merge pull request #2679 from davep/fix-dock-type-warning
Fix the dock type warning
2023-05-29 13:55:32 +01:00
Dave Pearson
5a8fe24367
Fix the dock type warning
See #2494.
2023-05-29 13:44:11 +01:00
Dave Pearson
3e462793e4
Merge pull request #2677 from davep/docs-no-insiders-redux
Revisit allowing building the docs without access to "Material for MkDocs Insiders"
2023-05-29 12:57:25 +01:00
Dave Pearson
d4eb0a0c20
Only link Python and Rich types when building full docs
It looks like mkdocstrings will fail out if it can't download the inv files.
Unless there's a setting where you can tell it "try, but if you can't grab
them just don't try and create links" the approach here seems reasonable and
has the same effect.

https://github.com/Textualize/textual/issues/2629#issuecomment-1566672594
for reference.
2023-05-29 08:30:23 +01:00
Dave Pearson
806a6663ad
Remove the privacy plugin from the offline version of the docs
Yes, this does pretty much undo the "offline" part, but without this the
docs can't build if the builder doesn't have access to the insiders' edition
of mkdocs. Doing this as a first step to investigating if there's any
possible way to achieve what we want here:

- Anyone can build
- They can build offline
- They can build for maximum privacy

If not, this step at least hits the first requirement.

See #2629.
2023-05-29 07:40:30 +01:00
Will McGugan
1ea892b062
handler name in classvar (#2675)
* handler name in classvar

* fix for worker handler name

* fix custom templates, event docs

* doc tweak

* doc tweak

* restore signature
2023-05-28 14:56:18 +01:00
Will McGugan
ab10c7c326
fix zero division error (#2674)
* fix zero division error

* push tests
2023-05-28 14:56:05 +01:00
TomJGooding
087a34f6c3 docs(button): update note about button spacing/padding 2023-05-28 08:57:52 +01:00
Dave Pearson
65b0c34f2e
Merge pull request #2660 from davep/dirtree-tweaks 2023-05-26 15:18:58 +01:00
Dave Pearson
ec3334e633
Perform the "is loaded" test in _add_to_load_queue
The test if a node was loaded wasn't being performed when loading the root.
This ensures that will happen. I suspect this is (no pun...) at the root of
the issue with https://github.com/Textualize/frogmouth/issues/50 even though
I can't see the route into how this happens, and can't recreate this at
will.

This feels like a worthwhile change to make anyway as it's a safer approach.
2023-05-25 20:55:22 +01:00
Dave Pearson
32790de26a
Ensure a node has no children before populating it
I'm struggling to recreate https://github.com/Textualize/frogmouth/issues/50
in a controlled way, but reviewing the code here makes me think that this is
a good idea anyway. While DirectoryTree should not end up in _populate_node
if a node has already been populated, it's also the case that it's an
all-or-nothing thing; it makes sense to clear out the children of the node
before populating it; at least in a belt-and-braces way.
2023-05-25 20:49:50 +01:00
Rodrigo Girão Serrão
fd57309ad0 Make validators kwd-only. 2023-05-25 17:57:33 +01:00
Rodrigo Girão Serrão
31e2d1c839 Merge branch 'main' into input-auto-completion 2023-05-25 17:42:37 +01:00
Rodrigo Girão Serrão
ae266551a1 Update suggester implementation. 2023-05-25 17:32:40 +01:00
Rodrigo Girão Serrão
fc86682dfa Add tests for suggester. 2023-05-25 17:32:26 +01:00
Rodrigo Girão Serrão
0488b5ed9c Ignore abstractmethods. 2023-05-25 17:22:21 +01:00
Dave Pearson
ea8c6039a9
Merge pull request #2652 from davep/multiselect 2023-05-25 17:10:20 +01:00
Dave Pearson
c16b32b52f
Merge pull request #2656 from davep/private-validate-and-compute
Add (currently xfailing) tests for private reactive validation and compute methods
2023-05-25 15:53:24 +01:00
Dave Pearson
fa47d0bd41
Mark the public/private validate and compute tests as xfails 2023-05-25 15:27:27 +01:00
Dave Pearson
bd6717f3d5
Add a test for public and private computes
This fails for now.
2023-05-25 15:23:33 +01:00
Dave Pearson
400043dda1
Update snapshit tests 2023-05-25 14:47:11 +01:00
Dave Pearson
93cae8d961
Merge branch 'multiselect' of github.com:davep/textual into multiselect 2023-05-25 14:20:13 +01:00
Dave Pearson
658c1cdf73
Documentation punctuation change 2023-05-25 14:19:47 +01:00
Dave Pearson
4764c100e3
Fix a copy/pasteo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 14:16:15 +01:00
Dave Pearson
aca8ec4833
Merge branch 'multiselect' of github.com:davep/textual into multiselect 2023-05-25 14:12:10 +01:00
Dave Pearson
45e64254e6
Be clear that _apply_to_all sends a SelectedChange message 2023-05-25 14:11:35 +01:00
Dave Pearson
95389ebe76
Fix a typo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 14:05:05 +01:00
Dave Pearson
c69e53f77e
Save a word!
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 14:04:32 +01:00
Dave Pearson
93c3c3652b
Merge branch 'main' into multiselect 2023-05-25 13:59:34 +01:00
Dave Pearson
a944554d0d
Finish a half-finished docstring 2023-05-25 13:58:31 +01:00
Dave Pearson
baa060f9fa
Remove annotation from RHS of the typing example 2023-05-25 13:57:08 +01:00
Aaron Stephens
20d19d977d
Refactor Message.control and Tree Messages (#2602)
* refactor(message): make control a property

* refactor(_tree): remove tree parameter on messages

* refactor(_directory_tree): remove tree parameter on message

* fix: tree message calls

* fix(_select): make Changed.control a property

* refactor(_on): control check

* refactor(_select): rename Changed.widget to select

* docs: changelog entry
2023-05-25 13:48:31 +01:00
Will McGugan
3ab315beb6
Anim screenshot fix (#2655)
* fix screenshots in docs

* fix anim

* added wait for animation switch

* remove comment
2023-05-25 13:46:14 +01:00
Dave Pearson
4c93e63ed6
Fix a copy/pasteo 2023-05-25 13:35:27 +01:00
darrenburns
62fcefbd2d
Validation (#2600)
* A few different types of validation

* Rename

* Fix test

* Updating validation framework

* Update lockfile

* Ensure validators can be None

* Reworking the API a little

* Convert Input.Changed to dataclass

* Add utility for getting failures as strings

* Update an example in Validator docstring

* Remove some redundant `pass`es

* Renaming variables

* Validating Input on submit, attaching result to Submitted event

* Testing various validation features

* Update snapshots and deps

* Styling unfocused -invalid Input differently

* Add snapshot test around input validation and associated styles

* Validation docs

* Tidying validation docs in Input widget reference

* Fix mypy issues

* Remove __bool__ from Failure, make validator field required

* Code review changes

* Improving error messages in Validators
2023-05-25 13:29:33 +01:00
Dave Pearson
6d82d7a1db
Fix a typo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 13:27:31 +01:00
Dave Pearson
ad4c68ba0d
Fix a typo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 13:26:57 +01:00
Dave Pearson
d656fa6a79
Fix a typo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 13:24:01 +01:00
Dave Pearson
51f8d0dc9a
Break up the SelectionList snapshit tests
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 13:20:22 +01:00
Dave Pearson
51133b3a62
Typo fix
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 13:19:18 +01:00
Dave Pearson
34f7136f21
Fix a typo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 13:14:27 +01:00
Dave Pearson
bec362e527
Improve the title for the widget
It's sort moved on from been about check boxen.

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-25 13:04:12 +01:00
Rodrigo Girão Serrão
5cb30b5ecc
Merge pull request #2628 from Textualize/auto-focus-improv
Add auto focus to app.
2023-05-25 11:59:54 +01:00
Rodrigo Girão Serrão
afbf52d8f5
Merge pull request #2654 from Textualize/progressbar-docs
Fix progress bar docs issue.
2023-05-25 11:59:37 +01:00
Dave Pearson
abda34aa13
Add a test for private validation
Currently failing.
2023-05-25 11:48:04 +01:00
Dave Pearson
4472c862be
Anticipate SelectionList making it into 0.27.0 2023-05-25 11:28:52 +01:00
Dave Pearson
3796a849c4
Simplify _make_selection a wee bit 2023-05-25 11:21:50 +01:00
Dave Pearson
939586f5f8
Add snapshot tests for the SelectionList examples 2023-05-25 11:06:21 +01:00
Rodrigo Girão Serrão
08eb1f1fab Remove invalid ref. 2023-05-25 11:01:47 +01:00
Dave Pearson
9a0e82f4c3
Merge branch 'main' into multiselect 2023-05-25 10:04:52 +01:00
Dave Pearson
112f18b94d
Add SelectionList to the widget gallery 2023-05-25 09:58:43 +01:00
Dave Pearson
4ceeefba23
Remove the attempt to link to Pretty
Weirdly Pretty isn't in the docs. Yet.
2023-05-25 09:42:12 +01:00
Dave Pearson
02c4f4d69b
Add an example of using SelectionList.SelectedChanged 2023-05-25 09:35:37 +01:00
Dave Pearson
fe26b89803
Add some more hints about type hinting
Also add a couple more useful links in the area I'm editing.
2023-05-25 09:12:57 +01:00
Dave Pearson
2d544ca697
Rename the tuples selection list example to mention tuples
Making this one look like it was *the* canonical example wasn't a good idea.
2023-05-25 08:58:45 +01:00
Dave Pearson
a9100988b4
Make a start on the SelectionList example apps 2023-05-24 21:36:14 +01:00
Will McGugan
8151946f38
add blur (#2645)
* add blur

* docstring

* blur on disabled

* snapshot test

* Add test
2023-05-24 20:16:11 +01:00
Dave Pearson
a89c199409
Merge pull request #2646 from davep/fix-broken-xrefs
Fix some assorted documentation cross-references
2023-05-24 16:37:01 +01:00
Dave Pearson
bad2a5a064
Merge pull request #2647 from davep/fix-set-classes-docstring
Fix docstring for `DOMNode.set_classes`
2023-05-24 16:24:20 +01:00
Dave Pearson
2c184caa2a
Fix docstring for DOMNode.set_classes
The argument in the Args list was missing its name; also fixes a typo too.
2023-05-24 16:16:15 +01:00
Dave Pearson
718760dcb1
Fix some assorted documentation cross-references
Couple or so things I noticed while working on docs.
2023-05-24 15:53:56 +01:00
Dave Pearson
3e4291cf94
Remove unnecessary inclusion of Selection
It will be included by the nature of selection_list being included.
2023-05-24 15:31:27 +01:00
Dave Pearson
e7876ca001
Merge branch 'main' into multiselect 2023-05-24 15:29:37 +01:00
Dave Pearson
fb82564858
Merge pull request #2643 from davep/include-more-option-stuff-in-docs
Include more missing things from the OptionList
2023-05-24 15:28:52 +01:00
Dave Pearson
09c6ea9911
Include more missing things from the OptionList
While working on the SelectionList documentation I've noticed that even more
things have got lost from the docs relating to OptionList, likely lost when
widgets were removed from the API section of the docs.

This drags more OptionList-related types into the docs, thus providing more
links.
2023-05-24 15:21:41 +01:00
Dave Pearson
49c7b20bc1
Link mention of Strip in a docstring 2023-05-24 15:19:02 +01:00
Dave Pearson
71d7f7dd86
Merge branch 'main' into multiselect 2023-05-24 15:08:04 +01:00
Dave Pearson
910c4782f1
Add the main framework for the OptionList documentation
Lots to flesh out here still, but this gets the core framework in place.
2023-05-24 15:05:10 +01:00
Dave Pearson
113ab41c3b
Some more linking to types within the SelectionList docstrings 2023-05-24 14:58:27 +01:00
Dave Pearson
ac7a892965
Link most(all?) docstring mentions of SelectionList
Putting the hype in hypertext.
2023-05-24 14:41:11 +01:00
Dave Pearson
9c0df44b59
Supply the generic type when creating a Selection
I don't think this is *needed* as such, but it seems like the sensible thing
to do.
2023-05-24 14:35:13 +01:00
Dave Pearson
a32cfdbe40
Better linking for the docstring for MessageSelectionType 2023-05-24 14:32:32 +01:00
Dave Pearson
64dd7d0f17
Better linking for the docstring for SelectionType 2023-05-24 14:31:50 +01:00
Dave Pearson
78980670da
Merge pull request #2640 from davep/include-option-in-docs
Include `widgets.option_list.Option` in the docs
2023-05-24 14:31:27 +01:00
Dave Pearson
2874b24a87
Export genetic types for SelectionList
So these can end up in the docs.
2023-05-24 14:30:15 +01:00
Dave Pearson
7c9b3f4cd6
Include widgets.option_list.Option in the docs
Noticed this in passing; possibly dropped by accident when the widgets were
removed form the API section of the docs?
2023-05-24 14:13:17 +01:00
Dave Pearson
258181d1de
Flesh out the docstring for the selected property 2023-05-24 14:04:53 +01:00
Dave Pearson
a31c3f0774
Correct the Selection.__init__ docstring 2023-05-24 14:03:09 +01:00
Dave Pearson
9742144e8c
Remove a note that isn't relevant any more 2023-05-24 13:00:20 +01:00
Dave Pearson
2e37541d70
Correct the types in a copied docstring 2023-05-24 12:59:20 +01:00
Dave Pearson
64ed982fd4
Make it very clear when SelectedChanged is posted 2023-05-24 12:57:13 +01:00
Dave Pearson
b113663221
Add a note about SelctionToggled vs SelectedChanged 2023-05-24 12:55:31 +01:00
Dave Pearson
65375e88b6
Remove an outdated note 2023-05-24 12:39:33 +01:00
Dave Pearson
9459a4efd7
Merge pull request #2636 from davep/select-reactive-table-fix 2023-05-24 10:52:29 +01:00
Dave Pearson
ed0aa78f22
Merge pull request #2637 from davep/option-list-docs-typo-fix 2023-05-24 10:47:25 +01:00
Dave Pearson
7f3efcf6ed
Fix a typo in the OptionList messages list 2023-05-24 10:41:55 +01:00
Dave Pearson
7d635915fa
Fix Select reactives table layout
The escaped | wasn't being rendered correctly as it was inside back-ticks.
2023-05-24 10:31:34 +01:00
Dave Pearson
cb05cfff53
Test that the control of selection list events is always correct 2023-05-24 10:21:40 +01:00
Dave Pearson
0a63748573
Add a test for later addition of selected selections 2023-05-24 10:16:25 +01:00
Dave Pearson
7110b30b44
Make sure adding a selection later updates selected 2023-05-24 10:16:06 +01:00
Dave Pearson
d3fe23f0bc
Allow passing a Selection into a SelctionList
Up until now I've only been allowing tuples; mostly a hangover from the
initial take on this. Things have drifted a bit now and I feel it makes
sense to allow Selection instances in too.
2023-05-24 10:09:53 +01:00
Dave Pearson
da1faf8fb9
Allow for storing the initial state of a selection 2023-05-24 10:09:21 +01:00
Dave Pearson
2e540548f8
Add a test that removed selected selections are removed from selected 2023-05-24 09:19:56 +01:00
Dave Pearson
9d6e977e0e
Test messages when toggling a selection via user input 2023-05-24 09:15:43 +01:00
Dave Pearson
56103c52e7
Ensure we log any OptionList messages in the messages test
We don't actually want to see them, we don't expect to see them, so here I
make a point of logging them so we can be sure we *don't* see them.
2023-05-24 09:09:40 +01:00
Rodrigo Girão Serrão
2c03956049 Fix type hint. 2023-05-23 17:01:20 +01:00
Dave Pearson
50d77b231f
Add tests for the wrong sized tuple
While type checking picks this up, not everyone uses type checking.
2023-05-23 16:45:53 +01:00
Dave Pearson
9f6d35b871
Start unit tests for the actual selected property 2023-05-23 16:26:28 +01:00
Dave Pearson
c448fa1ea0
Add unit tests for selection list messages 2023-05-23 15:48:34 +01:00
Rodrigo Girão Serrão
3308cdde1c Use FIFOCache.
Related comments: https://github.com/Textualize/textual/pull/2604#discussion_r1202431626
2023-05-23 15:32:53 +01:00
Rodrigo Girão Serrão
239e5eebc6 Use workers to get suggestions. 2023-05-23 15:16:24 +01:00
Dave Pearson
f9780d0346
Add basic selection list creation unit tests 2023-05-23 15:13:46 +01:00
Rodrigo Girão Serrão
e63ec577cd Address review feedback. 2023-05-23 11:46:05 +01:00
Dave Pearson
d38780ba97
Ensure we don't try and post messages before the widget is ready 2023-05-23 11:45:31 +01:00
Rodrigo Girão Serrão
bc92cf57e7 Add auto focus to app.
Related issues: #2594.
2023-05-23 11:32:40 +01:00
Dave Pearson
d5799377a2
Document _selected
It's not for public consumption, but it's useful for anyone reading the code.
2023-05-23 11:31:07 +01:00
Dave Pearson
bee438bc53
Get the selection value tracker in place before calling the superclass 2023-05-23 11:30:04 +01:00
Dave Pearson
fefb33a23b
Add a docstring to the internal copy of the selection value 2023-05-23 11:07:45 +01:00
Rodrigo Girão Serrão
124e62e41b Changelog. 2023-05-23 10:50:00 +01:00
Rodrigo Girão Serrão
297549c7d8 V2 of input suggestions API. 2023-05-23 10:47:22 +01:00
Dave Pearson
81abac1c68
Tidy up some docstrings
Mainly adding missing return values, that sort of thing.
2023-05-23 10:46:00 +01:00
Dave Pearson
23d899935f
Correct a docstring 2023-05-23 10:36:59 +01:00
Dave Pearson
ff404e2bbf
Only refresh on deselect if something was deselected 2023-05-23 10:35:48 +01:00
Dave Pearson
d861cced97
Improve how the _all methods work
Deciding if there was a change when turning all on or off by looking at the
before an after counts was fine, but it's not a sensible way of seeing if
there was a change during a toggle. So this swaps things up a bit and has
the core selection changing methods return a flag to say if they actually
made a change or not.
2023-05-23 10:33:39 +01:00
Dave Pearson
db273ea9ff
Add a method for toggling all options 2023-05-23 10:26:16 +01:00
Dave Pearson
a4148d028b
Add a method for deselecting all options 2023-05-23 10:22:01 +01:00
Dave Pearson
3ce04c814a
Add a method of selecting all selection options 2023-05-23 10:20:00 +01:00
Dave Pearson
a2fc3fad43
Add a method to apply a state change to all selection options 2023-05-23 10:19:20 +01:00
Dave Pearson
4c9afca8fd
Add a docstring for the component classes. 2023-05-23 10:02:07 +01:00
Dave Pearson
195e9b4021
Add the docstring for the bindings 2023-05-23 09:50:44 +01:00
Dave Pearson
ca07d7a58d
Fill in the blanks with docstrings
Adding back docstrings from overriding methods. Initially I was thinking it
made sense to keep them empty, allowing for any inheriting of the
docs (if/when our documentation generation system does that); but in most
cases there's a subtle difference in what's supported in terms of parameters
or return values so it makes sense to tweak the docs a wee bit.
2023-05-23 09:47:45 +01:00
Dave Pearson
607939e41d
Merge pull request #2626 from davep/option-list-typo-fix
Fix a copy/pasteo in an option list docstring
2023-05-23 09:45:37 +01:00
Dave Pearson
10bccfd9ee
Fix a copy/pasteo in an option list docstring 2023-05-23 09:27:40 +01:00
Dave Pearson
9e6bf085b8
Extend add_option so that it accepts selections and selection tuples 2023-05-23 09:24:29 +01:00
Will McGugan
be49aabefe
remove markup, simplify repr (#2623)
* remove markup, simplify repr

* changelog

* remove rendundant repr (thanks Paul)

* changelog
2023-05-22 20:26:37 +01:00
Dave Pearson
f530efda2a
Extend SelectionList.add_options to better support the selection list 2023-05-22 15:58:08 +01:00
Dave Pearson
55f887e66e
Merge pull request #2610 from davep/directory-tree-alt-path
Let child classes of DirectoryTree override Path creation
2023-05-22 15:56:50 +01:00
Dave Pearson
68250e6ce3
Override _remove_option to update the selected values
The developer could remove an option that is selected, so we need to catch
that this has happened and update the collection of selected values.
2023-05-22 15:25:11 +01:00
Dave Pearson
189181ba33
Add support for sending a message when the selection list changes
The developer using this may wish to react to UI changes being made, but
they may also want to just know when the collection of selected values has
changed -- this could happen via code so won't get any UI/IO messages. So
this adds a message that is always sent when a change to the collection of
selected values happens.
2023-05-22 15:23:11 +01:00
Dave Pearson
a25ef78a7f
Fully hint the type of the selection list in mesages 2023-05-22 15:02:32 +01:00
Dave Pearson
13e796bfea
Ensure selections are only one line in length 2023-05-22 14:56:21 +01:00
Rodrigo Girão Serrão
724fedc442
Merge pull request #2621 from Textualize/leave-footer-push-modal-screen
Leave footer when pushing modal screen
2023-05-22 14:43:05 +01:00
Rodrigo Girão Serrão
d48a127ffe
Merge pull request #2540 from Textualize/screen-modes
Implements screen modes
2023-05-22 14:27:35 +01:00
Rodrigo Girão Serrão
c64111bcb5 Add property alias.
Related comment: https://github.com/Textualize/textual/pull/2540\#discussion_r1196634789
2023-05-22 14:21:11 +01:00
Dave Pearson
51d1dade5c
Ensure access to options is actually access to selections 2023-05-22 14:18:20 +01:00
Dave Pearson
07515e22c8
Add an interface for changing selections from code 2023-05-22 14:01:09 +01:00
Rodrigo Girão Serrão
c32d5d3c25 Add regression test for #2606. 2023-05-22 13:53:58 +01:00
Dave Pearson
dae0cd7c02
Raise a widget-specific exception when given a bad option 2023-05-22 13:21:25 +01:00
Dave Pearson
1d925da551
Ensure selection casting works in earlier Pythons 2023-05-22 13:20:49 +01:00
Dave Pearson
127d93a260
Remove a couple of annoying type errors
The code worked and was fine, but pyright was getting upset at the typing.
This clears that up.
2023-05-22 13:13:37 +01:00
Rodrigo Girão Serrão
33a470f569 Fix footer highlight when pushing modal. 2023-05-22 11:45:40 +01:00
Dave Pearson
424c30fcf1
Add a method of getting at the selected values 2023-05-22 11:40:03 +01:00
Dave Pearson
6bc2a6ebd2
Add support for a selection message
In doing so, change up how the toggling happens.
2023-05-22 11:25:56 +01:00
Dave Pearson
41b1c08db5
Docstring tweak 2023-05-22 11:16:17 +01:00
Dave Pearson
4dab6d3b57
Start the SelectionList messages
It would be nice to just inherit form the OptionList messages, but the
naming of the properties wouldn't quite make sense, and there's also the
generic typing issue too. So here I start to spin up my own messages down
here.

Also, as an initial use of this, grab the OptionList highlight message and
turn it onto one of out own.
2023-05-22 11:09:18 +01:00
Rodrigo Girão Serrão
5c1c62edd0
Merge pull request #2607 from Textualize/placeholder-cycle
Placeholder color cycle
2023-05-22 10:50:11 +01:00
Rodrigo Girão Serrão
4e86e655d6
Merge branch 'main' into placeholder-cycle 2023-05-22 10:43:12 +01:00
Rodrigo Girão Serrão
5e04a4d4de
Add description to work decorator. (#2605)
* Add description to work decorator.

* Fix stutter.
2023-05-22 10:32:23 +01:00
Dave Pearson
a570b4403e
Swap the order of the prompt and value for selection items
Mostly I feel it makes sense to have the value first, and the actual prompt
second (based on no reason at all); but given that Select does it prompt
then value, this should conform to the same approach.
2023-05-22 10:30:22 +01:00
Luper Rouch
33da5c1afc
Fix App.BINDINGS type (#2620)
The implicit type was creating mypy errors when defining bindings with
tuples. For example:

    class MyApp(App):
        BINDINGS = [("q", "quit", "Quit")]

Would give the error:

    error: List item 0 has incompatible type "Tuple[str, str, str]"; expected "Binding"  [list-item]
2023-05-22 10:27:31 +01:00
Dave Pearson
8339e8b513
Merge branch 'main' into multiselect 2023-05-22 09:49:39 +01:00
Will McGugan
7d0d1ac5c8
Bump0260 (#2617)
* full map

* docstring changelog

* changelog

* simplify, add comment
2023-05-20 11:30:42 +01:00
Dave Pearson
7dd05e3ec0
Let child classes of DirectoryTree override Path creation
With #1719 in mind, and as an alternative to #2608, this allows for a child
class of DirectoryTree to specify how a fresh `Path` should be created. The
idea here being that whatever is created should be of the `Path` type, but
can have other abilities.
2023-05-19 10:15:04 +01:00
Dave Pearson
c0b5832183
Explain things a wee bit better for the future reader 2023-05-18 16:34:30 +01:00
Rodrigo Girão Serrão
6523fbaff1 Fix tests. 2023-05-18 16:27:09 +01:00
Rodrigo Girão Serrão
c85e428228 Fix placeholder color cycling. 2023-05-18 16:24:07 +01:00
Dave Pearson
6bea9f86d3
Sprinkle bold over all the buttons
At some point I should go through these styles and start to collapse/dedupe
them.
2023-05-18 16:22:47 +01:00
Dave Pearson
bc126ce036
Build the selection list back in __init__ again
Now that I'm no longer having to dodge issues with getting component classes
before the DOM has spun up, I can go back to the simpler method of setting
up the selections.

This also means I can drop Mount handling.
2023-05-18 16:20:32 +01:00
Rodrigo Girão Serrão
75606c8dfd Add explicit sleep. 2023-05-18 16:11:02 +01:00
Dave Pearson
12416d81d1
Remove unused import of Text 2023-05-18 15:42:45 +01:00
Dave Pearson
beb3645aa1
Remove Selection's knowledge of its parent
This isn't needed any more now that I'm doing everything in render_line.
2023-05-18 15:41:14 +01:00
Dave Pearson
b63e85f81c
Remove _make_label
I don't need this any more.
2023-05-18 15:39:59 +01:00
Dave Pearson
8459a8c4f9
Swap to overriding render_line
More experimenting with overriding OptionList, and rather than trying to
swap out and around the prompt under the hood, I got to thinking that it
made more sense to perhaps override render_line.

So far so good...
2023-05-18 15:20:01 +01:00
Rodrigo Girão Serrão
ad986b127d Merge branch 'main' into screen-modes 2023-05-18 15:11:21 +01:00
Rodrigo Girão Serrão
d65daf81c0 Address review comments. 2023-05-18 15:07:52 +01:00
Rodrigo Girão Serrão
97f30a21fb Add tests. 2023-05-18 14:50:28 +01:00
Rodrigo Girão Serrão
bfdaf02f66 Add snapshot test. 2023-05-18 14:26:32 +01:00
Rodrigo Girão Serrão
03a43521dd Fix test. 2023-05-18 14:02:51 +01:00
Rodrigo Girão Serrão
0c520f13ce Change naming. 2023-05-18 13:58:59 +01:00
Rodrigo Girão Serrão
f464241fd6 Implement auto-completion. 2023-05-18 13:41:37 +01:00
Dave Pearson
0c18839c8a
WiP selection list
I think I'm going to give up on basing this off OptionList. It's close
enough that inheriting from it and doing more makes some sense, but it's
also just far enough away that it's starting to feel like it's more work
that is worthwhile and it'll be easier to hand-roll something fresh.
2023-05-18 13:00:23 +01:00
Will McGugan
49e1080279 update howto 2023-05-18 10:03:26 +01:00
Will McGugan
8fd5aec454 fix layout 2023-05-18 09:28:33 +01:00
Dave Pearson
9d0a6d8eac
Merge branch 'main' into multiselect 2023-05-18 08:56:11 +01:00
Will McGugan
ff5665051b
Release0250 (#2598)
* version bump

* changelog
2023-05-17 16:30:36 +01:00
Rodrigo Girão Serrão
a9c8b59df5
Use default string on error inside work. (#2595)
Related issues #2588.
2023-05-17 16:27:32 +01:00
Dave Pearson
84de8a8949
Typo fix (#2596) 2023-05-17 16:26:33 +01:00
darrenburns
e25c6290ba
Add classes to Tab widget (#2589)
* Add classes to Tab widget

* Update CHANGELOG
2023-05-17 16:21:32 +01:00
Dave Pearson
7ff205bc29
Merge pull request #2545 from davep/directory-tree-work-in-worker
Load `DirectoryTree` contents in a worker
2023-05-17 15:42:51 +01:00
Rodrigo Girão Serrão
179a85058e
Merge pull request #2581 from Textualize/auto-focus-improv
AUTO_FOCUS targets first focusable widget.
2023-05-17 15:32:08 +01:00
Will McGugan
f820598846
How to (#2592)
* words

* how to

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-17 15:30:31 +01:00
Dave Pearson
abbffbfa6a
Code tidy
As per https://github.com/Textualize/textual/pull/2545#discussion_r1196591147
2023-05-17 15:30:13 +01:00
Dave Pearson
e381c26165
Create a single method for adding a node to the load queue
In doing so fix an issue where, after the previous change, I wasn't marking
the root of the tree as loaded.
2023-05-17 15:27:01 +01:00
Dave Pearson
522d56c601
Be more optimistic about when the node content is loaded
As per https://github.com/Textualize/textual/pull/2545#discussion_r1196589864
2023-05-17 15:21:38 +01:00
Dave Pearson
86bee6c495
Rename _to_load to _load_queue
As per https://github.com/Textualize/textual/pull/2545#discussion_r1196580316
2023-05-17 15:17:05 +01:00
Dave Pearson
2a91e13ca3
Mark each load task as done when it's done 2023-05-17 14:45:08 +01:00
Dave Pearson
3f6472823e
Merge branch 'main' into directory-tree-work-in-worker 2023-05-17 14:19:59 +01:00
Dave Pearson
dadd7c0a14
Guard against PermissionError
Normally it's not a great idea to eat and hide exceptions within library
code; but I think it makes sense to make an exception here. This is a UI
element that lets the user navigate about a filesystem. If there is
something they don't have permission for, that should not cause an
exception, it should just give up with the best possible outcome.

If actually doing something with the exception is important, the developer
using this could use the filter to do tests and act accordingly.

See #2564.
2023-05-17 14:13:52 +01:00
Dave Pearson
c04bbd1e2e
Ensure the loader kicks off when starting up with . as the directory 2023-05-17 13:41:58 +01:00
Dave Pearson
26e6dbbfa3
Swap to a dual-working approach
Plan C; or is it plan D? Something like that. Anyway... in this approach we
keep a single "forever" async task worker per directory tree, which in turn
looks at the async Queue, and when a new node appears on it it starts a
short-lived thread to load the directory data.

This seems to be working fine on macOS. Next up is testing on Windows.
2023-05-17 13:28:07 +01:00
Dave Pearson
ecde90b1c3
Remove unused import
The code that was using this was removed earlier.
2023-05-17 12:29:36 +01:00
Dave Pearson
a42250daa3
async Queue get blocks when empty, so don't handle empty exception 2023-05-17 12:29:03 +01:00
Rodrigo Girão Serrão
38f9500642 Fix test. 2023-05-17 11:35:10 +01:00
Dave Pearson
82924c2d7c
Make the main load worker into a asyncio task
Turns out, there's a maximum number of threads you can have going in the
underlying pool, that's tied to the number of CPUs. As such, there was a
limit on how many directory trees you could have up and running before it
would start to block all sorts of operations in the surrounding
application (in Parallels on macOS, with the Windows VM appearing to have
just the one CPU, it would give up after 8 directory trees).

So here we move to a slightly different approach: have the main loader still
run "forever", but be an async task; it then in turn farms the loading out
to threads which close once the loading is done.

So far tested on macOS and behaves as expected. Next to test on Windows.
2023-05-17 11:34:05 +01:00
Dave Pearson
64d9c60267
Revert experimental code 2023-05-17 11:26:33 +01:00
Rodrigo Girão Serrão
a058fe53eb Make test clearer. 2023-05-17 11:15:56 +01:00
Dave Pearson
6876a041a4
More Windows thread oddness experimenting 2023-05-17 11:02:04 +01:00
Dave Pearson
80d00ce4bf
Logging and experimenting for Windows 2023-05-17 10:49:46 +01:00
Rodrigo Girão Serrão
dea133d357
Merge branch 'main' into auto-focus-improv 2023-05-17 10:28:54 +01:00
Rodrigo Girão Serrão
45686c8aca Fix tests. 2023-05-17 10:27:57 +01:00
Rodrigo Girão Serrão
8399a31a46 Post ScreenResume to default screen.
When the default screen is first created it was not getting the event ScreenResume. All other screens receive a ScreenResume when first created and _all_ screens (the default one and custom screens) receive this event when they become the active screen again, so this was kind of an edge case that needed the event to be posted by hand.
Related comments: https://github.com/Textualize/textual/pull/2581\#issuecomment-1550231559
2023-05-17 10:09:52 +01:00
Rodrigo Girão Serrão
765c7ce037 Simplify auto focus code.
Related comments: https://github.com/Textualize/textual/pull/2581\#discussion_r1195595104.
2023-05-17 10:01:01 +01:00
Dave Pearson
471ab159ca
Merge branch 'main' into multiselect 2023-05-17 09:21:12 +01:00
Will McGugan
c12fa0e4da
fix for dark switch (#2585) 2023-05-17 07:44:36 +01:00
Glenn McAllister
8753aa5ed0
Update poetry-core requirement (#2572)
Related issues: #2562
2023-05-16 21:36:24 +01:00
Will McGugan
53e765f7d6
Avoid docks when scrolling (#2571)
* handle docked layers

* handle scroll better

* snapshot update

* remove commented out code

* superflous

* dock gutter

* snapshit

* snapshit test

* changelog

* mistake

* docstrings

* changelog

* whitespace

* missing punctuation

* ofx docstring

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-16 21:34:59 +01:00
Will McGugan
3a17a76233
Exit debug (#2554)
* show single error by default

* changelog

* show numbers of errors

* changelog
2023-05-16 21:34:34 +01:00
Will McGugan
abb7705ed0
wait for screen (#2584)
* wait for screen

* comments and changelog

* wait for screen after keys

* extra wait for animation

* comment

* comment

* docstring
2023-05-16 21:06:09 +01:00
Dave Pearson
e69e57d7c0
Remove unused import
Recent changes meant it wasn't needed any more.
2023-05-16 20:53:18 +01:00
Rodrigo Girão Serrão
634789ae93 Add tests to screen modes. 2023-05-16 17:40:09 +01:00
Dave Pearson
58f0d11a93
Change to a single loader thread with a queue 2023-05-16 16:41:36 +01:00
Dave Pearson
926c0a2b4f
Reset all DirectoryTree worker changes
After deciding
https://github.com/Textualize/textual/pull/2545#issuecomment-1547544057 it
makes more sense to roll back to the state of `main` than to try and get to
where I want to be from where we've decided we didn't want to be.

Can't get there from here, so let's go rogue-like on this PR...
2023-05-16 15:29:36 +01:00
Dave Pearson
804d85a2c9
Merge branch 'main' into directory-tree-work-in-worker 2023-05-16 15:16:31 +01:00
Dave Pearson
83e4be77db
Merge pull request #2567 from davep/issue/2557/select-update
Fix clearing an OptionList
2023-05-16 15:11:29 +01:00
Dave Pearson
1ebfe2f418
Update the snapshits 2023-05-16 14:38:11 +01:00
Dave Pearson
3d2e3d9092
Add a snapshot test for a rebuilt Select
This helps test the practical impact of the fix added for #2557.
2023-05-16 14:34:18 +01:00
Will McGugan
faa67a8293
Screen docs (#2579)
* screen docs

* docstrings

* modal example

* docstring

* docstrings

* Apply suggestions from code review

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-05-16 13:44:06 +01:00
Dave Pearson
32fa259c94
Add a TODO comment to the effect that this is a temp fix 2023-05-16 13:38:08 +01:00
Dave Pearson
f12aeb00d2
Remove forced content tracking refresh in clear_options
While the fix for #2557 likely isn't *the* fix (see #2582 for some context
around that), it is a fix that works for now. As such, with the change,
there was a double attempt to refresh the content tracking in the clearing
of options in the OptionList, which shouldn't be necessary.

This removes that.
2023-05-16 13:33:57 +01:00
Rodrigo Girão Serrão
2d9a83e243
Merge pull request #2577 from Textualize/gh-actions
Update workflows.
2023-05-16 13:24:59 +01:00
Dave Pearson
dde3ad397f
Remove duplicated setting of height for Select (#2576) 2023-05-16 12:01:45 +01:00
Rodrigo Girão Serrão
a9a04dc37a Run workflows when they are changed.
Related comments: https://github.com/Textualize/textual/pull/2577\#issuecomment-1549411724
2023-05-16 11:43:31 +01:00
Rodrigo Girão Serrão
4b22234b24
Merge branch 'main' into auto-focus-improv 2023-05-16 11:40:13 +01:00
Rodrigo Girão Serrão
a6ee867ee3 Fix tests. 2023-05-16 11:39:38 +01:00
Rodrigo Girão Serrão
41d11996e8
Merge pull request #2580 from Textualize/dismiss-top
Error when dismissing non-active screen.
2023-05-16 11:38:31 +01:00
Rodrigo Girão Serrão
93f4de918c Fix circular import. 2023-05-16 11:30:14 +01:00
Rodrigo Girão Serrão
b592ac077a AUTO_FOCUS targets first focusable widget.
Related issues: #2578.
2023-05-16 11:27:24 +01:00
Rodrigo Girão Serrão
7a8d6920e8 Error when dismissing non-active screen.
Related issues: #2575.
2023-05-16 11:14:54 +01:00
Rodrigo Girão Serrão
9b09b19e5f Update workflows.
This caches the virtual environment so we don't have to download it every time (the cache can be cleared from the repository > Actions > Caches (on the left).

We also split black formatting into a separate workflow.
This means we can run black ONLY when *.py files are changed.
It also means all other testing jobs don't need to _also_ check formatting.
2023-05-16 10:18:30 +01:00
Will McGugan
6147c28dbf
arrange refactor (#2569)
* arrange refactor

* Apply suggestions from code review

Co-authored-by: Dave Pearson <davep@davep.org>

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Dave Pearson <davep@davep.org>
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-15 14:53:17 +01:00
Rodrigo Girão Serrão
1bba3973bf
Merge pull request #2568 from Textualize/empty-paste
Fix empty paste
2023-05-15 14:31:14 +01:00
Rodrigo Girão Serrão
720bd37bba Consume event. 2023-05-15 14:22:16 +01:00
Rodrigo Girão Serrão
f02e2fcdd9 Short-circuit paste on empty text.
Related comments: https://github.com/Textualize/textual/pull/2568#discussion_r1193790630
2023-05-15 14:12:22 +01:00
Rodrigo Girão Serrão
81289c328a Fix empty paste.
Related issues: #2563.
2023-05-15 13:25:01 +01:00
Rodrigo Girão Serrão
fe7812d94d Add regression test for #2563. 2023-05-15 13:24:48 +01:00
Dave Pearson
aff9bcdf93
Fix clearing an OptionList
See #2557, credit to Will:

  https://github.com/Textualize/textual/issues/2557#issuecomment-1546883815
2023-05-15 11:30:26 +01:00
Dave Pearson
d296fc5f04
Allow for passing in a selection as a tuple 2023-05-15 11:11:04 +01:00
Rodrigo Girão Serrão
83618db642
Merge pull request #2527 from Textualize/auto-focus
Add `auto_focus` to screens
2023-05-15 11:04:15 +01:00
Rodrigo Girão Serrão
0b6e3b3040
Merge branch 'main' into auto-focus 2023-05-15 10:41:15 +01:00
Rodrigo Girão Serrão
4db54eac4b
Merge pull request #2530 from Textualize/move-child-no-op
Moving child before/after self is a no-op.
2023-05-15 10:39:57 +01:00
Rodrigo Girão Serrão
c967661699
Merge branch 'main' into move-child-no-op 2023-05-15 10:31:43 +01:00
Dave Pearson
258180c996
Add a selected flag to the Selection 2023-05-15 10:25:30 +01:00
Dave Pearson
8208388cf9
Allow for type unions under Python 3.7 2023-05-15 10:13:28 +01:00
Will McGugan
d266e3685f
snapshot update (#2555) 2023-05-12 18:57:53 +02:00
Will McGugan
d061065dcc optimization for divide 2023-05-12 18:29:51 +02:00
Will McGugan
c2e7b619f1 Revert "virtual size and docks"
This reverts commit 9a134b4920.
2023-05-12 15:53:47 +02:00
Will McGugan
4e069abd2e Revert "remove total region update"
This reverts commit 47970dd622.
2023-05-12 15:49:39 +02:00
Will McGugan
47970dd622 remove total region update 2023-05-12 15:45:25 +02:00
Will McGugan
9a134b4920 virtual size and docks 2023-05-12 15:36:49 +02:00
Will McGugan
4434b59982 spacing diagram 2023-05-12 14:03:53 +02:00
Dave Pearson
a065ff572e
Correct spelling in a docstring (#2552) 2023-05-12 09:34:27 +02:00
Rodrigo Girão Serrão
4d287837a2 Refactor screen stack modes. 2023-05-11 16:42:49 +01:00
Dave Pearson
e0ac60ce03
Initial framework for the SelectionList
Nothing here actually implements a selection list yet; this just sets out
the very basic framework of the widget, as it inherits form OptionList. The
key things here are:

1. It introduces a Selection class, which is an Option with a typed value.
2. The SelectionList is also typed and expects Selections of that type.
2023-05-11 16:19:13 +01:00
Dave Pearson
5f839da684
Merge branch 'main' into directory-tree-work-in-worker 2023-05-11 15:32:17 +01:00
Dave Pearson
4d225b8ebb
Correct a comment typo 2023-05-11 15:22:19 +01:00
Rodrigo Girão Serrão
4fc56f6db8
Merge pull request #2547 from Textualize/footer-css
Changelog.
2023-05-11 15:12:58 +01:00
Rodrigo Girão Serrão
8dc801fec7 Changelog. 2023-05-11 15:03:21 +01:00
Rodrigo Girão Serrão
a9c38793de
Merge pull request #2546 from Textualize/footer-css
Use footer--description component class.
2023-05-11 15:01:01 +01:00
Rodrigo Girão Serrão
58cf825eb4 Use footer--description component class.
Related issues: #2544.
2023-05-11 12:19:29 +01:00
Dave Pearson
c45126b21c
Update the ChangeLog 2023-05-11 11:19:30 +01:00
Dave Pearson
9b41b743fe
Remove the artificial slowdown 2023-05-11 11:13:19 +01:00
Dave Pearson
05eeaa7679
Tidy up _load_directory
Explain some about the decisions made, and also throw in a bit of
over-cautious worker cancellation checking.
2023-05-11 10:53:07 +01:00
Dave Pearson
82a08177af
Cancel any loads when resetting the tree 2023-05-11 09:59:57 +01:00
Dave Pearson
9ae8e47c6c
Add a method for cancelling all of the load jobs
This marks all current jobs as cancelled and also removes all pending jobs.
2023-05-11 09:59:18 +01:00
Dave Pearson
08246d84ac
Don't post the finished message if we've been cancelled 2023-05-11 09:57:30 +01:00
Dave Pearson
791f2ea189
Ensure we don't create a job for a node that's already being loaded 2023-05-11 09:16:54 +01:00
Dave Pearson
ce7a78db69
Have the reset method take part in background loading
One instance of a call to _load_directory that I missed.
2023-05-11 09:12:10 +01:00
Dave Pearson
4ead43c149
Set up the job tracking before setting the path
Setting the path to anything other than "." is going to result in a reset
happening, so we need the tracking support in place first.
2023-05-11 09:10:55 +01:00
Dave Pearson
df0f73ba3b
Remove debug logging 2023-05-11 08:35:36 +01:00
Dave Pearson
05dc877a24
Check for the worker being cancelled
So far this is working fine, but there was an issue where, if the load of a
very large directory was started, and then the application was cancelled
right away, the application would close down but there would be a long pause
until the shell prompt came back, the cause presumably being that we were
waiting for that particular thread to end.

So here I make sure I check the cancelled state of the worker. This would
also suggest that, while I turned the use of iterdir into a loop so I could
throw the sleep in to emulate a slow directory load, I *actually* want to do
this in a loop so I can test the cancelled state as we stream in the
directory content.
2023-05-11 08:31:01 +01:00
Will McGugan
0dc89dc2a8 wrong axis 2023-05-10 22:25:04 +02:00
Will McGugan
5a02f7335e fix docstrings 2023-05-10 22:21:30 +02:00
Dave Pearson
39971876d0
WiP: Throttle back the number of concurrent loads of a DirectoryTree
Having got the initial version of background loading of nodes in the
directory tree working, this moves to a gentler approach where only so many
loads run at once, and a queue of jobs that need to be completed is kept.

This is an end-of-coding-session WiP commit; there's more to come on this.
But at the moment I'm happy with the way it's going.
2023-05-10 16:26:36 +01:00
Rodrigo Girão Serrão
6e19772563 Add ability to switch between modes. 2023-05-10 16:06:16 +01:00
Rodrigo Girão Serrão
9f3f2033b5 Add default mode. 2023-05-10 14:59:00 +01:00
Dave Pearson
cd05d6cad6
Merge branch 'main' into directory-tree-work-in-worker 2023-05-10 14:22:36 +01:00
Dave Pearson
2d75ca0d77
Merge pull request #2536 from davep/expand-tree-expand-messages
Ensure that `TreeNode` messages are posted when via-API changes are made
2023-05-10 14:18:24 +01:00
Rodrigo Girão Serrão
70e97c6703
Merge pull request #2532 from Textualize/sub-title-str
Allow setting (sub)title of any type.
2023-05-10 13:20:47 +01:00
Rodrigo Girão Serrão
8dd627b0f4
Merge branch 'main' into sub-title-str 2023-05-10 13:10:48 +01:00
Dave Pearson
8b9a8e4174
Simplify _load_directory
Move the node population code into its own method, the idea here being that
the update happens in one call to call_from_thread rather than spawning lots
of calls to it.
2023-05-10 12:06:11 +01:00
Dave Pearson
d673175e62
Experimenting with placing _load_directory in a worker
This isn't the final form, not even close, this is more to help test out the
idea and how well it will work. Note the very deliberate sleep in the code
that's there to emulate loading from a slow blocking source.

This will be removed and tidied up before a final PR, of course. The main
aim here is to emulate a worst-case scenario so that the use of a worker can
be tried out with some confidence.

See #2456.
2023-05-10 11:17:02 +01:00
Dave Pearson
28be54d10d
Merge branch 'main' into expand-tree-expand-messages 2023-05-10 10:12:58 +01:00
Dave Pearson
f19f46bba0
Merge pull request #2519 from davep/cygnus-x-1
Fix for `resolve_fraction_unit` zero division error (#2502)
2023-05-10 10:10:55 +01:00
Dave Pearson
c7fc66fa6c
Ensure that TreeNode messages are posted when via-API changes are made
Until now the Tree.NodeExpanded and Tree.NodeCollapsed messages were only
sent out when changes were made to the tree by user interaction. This meant
that if any changes were made with the TreeNode expand, expand_all,
collapse, collapse_all, toggle or toggle_all API calls no messages would be
sent.

This PR corrects this.

The work here is, in part, required for #2456 (DirectoryTree lazy-loads
directory information on node expansion so if someone is expanding nodes
under code control the DirectoryTree never gets to know that it should load
a directory's content) and will build on #1644, essentially adding a missing
aspect to the latter PR.
2023-05-10 09:24:07 +01:00
Dave Pearson
0eeadf9ae9
Update the CHANGELOG 2023-05-09 21:01:31 +01:00
Rodrigo Girão Serrão
41466be007 Add docstrings. 2023-05-09 17:10:08 +01:00
Rodrigo Girão Serrão
fcf9806f6b Add clarifying comment. 2023-05-09 17:00:07 +01:00
Rodrigo Girão Serrão
17af473558 Annotate no-op. 2023-05-09 16:58:56 +01:00
Rodrigo Girão Serrão
e8baf52bdd Allow setting (sub)title of any type.
Related issues: #2521.
2023-05-09 16:56:56 +01:00
Rodrigo Girão Serrão
3245eb38bb Make auto-focus a class var.
Related comments: https://github.com/Textualize/textual/pull/2527\#discussion_r1188776849
2023-05-09 16:44:37 +01:00
Dave Pearson
30a20ac8da
Break iterdir out into a method of its own for easy testing
As I work on what's to come (loading DirectoryTree with a worker), I'm going
to want to try and construct slow loads so I can test the effectiveness of
the changes. This means a desire to fake a very slow source of directory
information. So let's drop this into its own method so we can then do silly
things like add a sleep to really show stuff down.
2023-05-09 16:41:17 +01:00
Rodrigo Girão Serrão
eafe6b1786 Moving child before/after self is a no-op.
Related issues: #1743.
2023-05-09 15:57:23 +01:00
Dave Pearson
8855471125
Merge pull request #2522 from davep/move-widget-enhanced-testing
Make the widget moving tests more granular and add more tests
2023-05-09 15:07:59 +01:00
Rodrigo Girão Serrão
8d3f69a04d Add auto_focus attribute to screens. 2023-05-09 14:57:50 +01:00
Rodrigo Girão Serrão
ed4d811451 Add tests for Screen auto focus.
Related issues: #2457.
2023-05-09 14:55:18 +01:00
Dave Pearson
a0558e87d8
Merge branch 'main' into cygnus-x-1 2023-05-09 13:38:16 +01:00
Dave Pearson
8d7ae4d1fb
Ensure that remaining fraction is always above zero 2023-05-09 13:36:32 +01:00
Dave Pearson
ee70713002
Simplify the resolver zero division bug unit test 2023-05-09 13:35:55 +01:00
Dave Pearson
d3de6d1587
Make the widget moving tests more granular and add more tests
Adds two (currently xfail) tests to illustrate #1743
2023-05-09 11:19:00 +01:00
Dave Pearson
a77dbf4bee
Tentative fix for resolve_fraction_unit ZeroDivision error
I'll admit to not really following what the code does, so will really need
someone with a better understanding of the aim of this code to look over the
proposed fix; but based on a bunch of runs and hand-debugging, this seems to
do the job.

This passes all existing tests and also removes the reported error.

On the other hand I'm not confident that I'm *not* just masking an
underlying issue with this function.
2023-05-09 10:38:09 +01:00
Dave Pearson
a5cc96cbc7
Make a pass of the #2502 test a fail
If/when I get this actually passing, I want the test to appear to fail so I
know things have changed for the better.

This makes sense, trust me.
2023-05-09 09:44:51 +01:00
Dave Pearson
052ec83b7a
Make the test as small as possible 2023-05-09 09:44:30 +01:00
Dave Pearson
089dce1b41
Add a unit test for #2502
Currently marked as xfail, but this gets it down to the most basic level.
2023-05-09 09:39:12 +01:00
Kim van Wyk
dea21a00ca
minor typo (#2515) 2023-05-08 20:01:45 +01:00
Will McGugan
e3115c50bf
fix for code browser type error (#2514) 2023-05-08 18:42:10 +01:00
Will McGugan
cf7e8a9cb1 update roadmap 2023-05-08 18:10:40 +01:00
Will McGugan
dc102563e9
changelog and release post (#2513)
* changelog and release post

* fix version

* link Select

* remove superfluous css

* Update docs/blog/posts/release2-24-0.md

Co-authored-by: darrenburns <darrenburns@users.noreply.github.com>

* Update docs/blog/posts/release2-24-0.md

Co-authored-by: darrenburns <darrenburns@users.noreply.github.com>

---------

Co-authored-by: darrenburns <darrenburns@users.noreply.github.com>
2023-05-08 17:45:06 +01:00
Rodrigo Girão Serrão
855c90d4f0
Extend @on decorator to filter matchable attributes (#2498)
* Add tests for #2484.

* Implement @on extension.

[skip ci]
Related issues: #2484.

* Changelog.

* Add missing @on test.

* Remove debug prints.

* Document changes.

* Update tests.

Test now fully works, as of #2490.

* Cache parsed selectors.

* Streamline exit condition.

* Fix typing.

* More succint wording.

* Document 'on' kwargs.

* Update src/textual/_on.py

Co-authored-by: Will McGugan <willmcgugan@gmail.com>

* Update docs/guide/events.md

Co-authored-by: Will McGugan <willmcgugan@gmail.com>

* Change 'on' API.

* Remove example code.

* Address feedback.

* Update src/textual/_on.py

Co-authored-by: Will McGugan <willmcgugan@gmail.com>

* Address review feedback.

* Fix #2499.

* don't require control to be manually specified

* update docstring

* deleted words

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-05-08 17:30:07 +01:00
Will McGugan
dd7e768887 merged changelog sections 2023-05-08 12:51:50 +01:00
Rodrigo Girão Serrão
a31e086a2e
Merge pull request #2490 from Textualize/messages-control
Add control to widget messages.
2023-05-08 11:26:31 +01:00
Rodrigo Girão Serrão
8059e5c1a7
Merge branch 'main' into messages-control 2023-05-08 11:18:43 +01:00
Rodrigo Girão Serrão
9c9829eb0f
Add 'control' alias to Tabs messages. (#2483)
* Add 'control' alias to Tabs messages.

Related issues: #2478.

* Changelog.
2023-05-08 11:15:19 +01:00
Will McGugan
7db7139bb8
Select widget (#2501)
* overlay rule

* select WIP

* select control, made binding description optional

* changelog

* style tweak

* Added constrain

* changelog

* test fix

* drop markup, tidy

* tidy

* select namespace

* tests

* docs

* Added changed event

* changelog

* expanded

* tests and snapshits

* examples and docs

* simplify

* update reactive attributes

* type fix

* docstrings

* allow renderables

* superfluous init

* typing fix

* optimization

* revert optimizations

* fixed words

* changelog

* docstrings

* don't need this

* changelog

* comment

* Update docs/widgets/select.md

Co-authored-by: Dave Pearson <davep@davep.org>

* review changes

* review updates

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-05-08 10:55:39 +01:00
Dave Pearson
c2a19bd632
Merge pull request #2510 from davep/chainsaw
Add the ability to remove nodes from a `Tree`
2023-05-08 10:51:44 +01:00
Dave Pearson
0bb0f4d179
Merge pull request #2508 from davep/add-options
Add `add_options` to `OptionList`
2023-05-08 10:51:15 +01:00
Rodrigo Girão Serrão
1e2f632fc6
Fix TabbedContent __init__ signature. (#2497) 2023-05-08 10:47:15 +01:00
Willi Ballenthin
483aa54bd6
Catch OSError when source code is not available (#2469)
* Catch OSError when source code is not available

* update changelog with reference to fixed bug
2023-05-08 10:45:56 +01:00
Rodrigo Girão Serrão
819b2f1eb3
Add DataTable.move_cursor (#2479)
* Add 'DataTable.move_cursor'.

Related issues: #2472.

* Fix #2471.

* Simplify cursor changes.

* Address review feedback.

Related comments: https://github.com/Textualize/textual/pull/2479\#discussion_r1185016002
2023-05-08 10:44:34 +01:00
Dave Pearson
c9d7bb84e2
Update the CHANGELOG 2023-05-08 10:18:34 +01:00
Dave Pearson
6bb2b21091
Update the CHANGELOG 2023-05-08 10:17:36 +01:00
Dave Pearson
745d595d4a
Add unit tests for the new node removal methods
See #2462.
2023-05-08 09:55:32 +01:00
Dave Pearson
64d9455d94
Add support for removing the children of a node
Sometimes the user may wish to delete a given node, other times it might be
a requirement to just remove the children (this will be especially useful
for #2448 where we'll want to keep the directory entry itself, but remove
and recreate its contents).

See #2462.
2023-05-08 09:33:21 +01:00
Dave Pearson
f34e738ddd
Ensure the cursor node is set to None when the tree goes empty
Up until now there wasn't really a way for the tree to go empty, outside of
clear/reset. Now that we can remove nodes on the fly, that is possible. This
takes that into account.

See #2462.
2023-05-08 09:16:58 +01:00
Dave Pearson
2c39f50150
Ensure the Tree's internal tracker gets updated on node delete
See #2462.
2023-05-08 09:15:28 +01:00
Dave Pearson
1d985abf26
Add TreeNode.remove
This is for removing an individual node, via the node. Note that attempting
to remove the root node of a Tree is an error and will case
TreeNode.RemoveRootError to be raised.

See #2462.
2023-05-08 08:44:29 +01:00
Dave Pearson
4c0d3766a8
Add TreeNode.is_root 2023-05-08 08:44:12 +01:00
Dave Pearson
84ddd09223
Add extra snapshit tests
This tests the three main ways of making an option list, and ensures they
all turn out the same.
2023-05-07 20:26:12 +01:00
Dave Pearson
b3b98f1089
Simplify the adding of genuine options
Extending a list with an empty list is petty much a no-op so don't bother to
faff around testing for what Python will be testing for anyway.
2023-05-07 18:11:14 +01:00
Dave Pearson
e526a32220
Update the CHANGELOG 2023-05-07 18:07:31 +01:00
Dave Pearson
8be87d5931
Merge branch 'main' into add-options 2023-05-07 18:06:57 +01:00
Dave Pearson
010356a23e
Allow zero items to be passed to add_options and do zero work 2023-05-07 18:01:56 +01:00
Dave Pearson
b44983e8d4
Add an add_options method to the OptionList
In doing so, pretty much make the add_option code into the add_options code,
and then just have add_option call add_options.

See #2507.
2023-05-07 17:56:02 +01:00
Dave Pearson
630f59dbd4
Remove unnecessary imports from example in docs
Perhaps a hangover from a previous take on this, or just a copy/paste-o.
Either way I just noticed this so thought I'd roll it in here.
2023-05-07 17:52:55 +01:00
Dave Pearson
14850d54a3
Merge pull request #2485 from davep/testing-testing-123-testing 2023-05-05 11:31:40 +01:00
Rodrigo Girão Serrão
73e4d5c6a7 Fix docs link. 2023-05-04 19:09:31 +01:00
Rodrigo Girão Serrão
a30cd159c4 Add control to TabbedContent message. 2023-05-04 19:04:10 +01:00
Rodrigo Girão Serrão
9d1f0283b2 Add control to RadioSet message. 2023-05-04 19:02:01 +01:00
Rodrigo Girão Serrão
8bf5316d65 Added control to markdown messages. 2023-05-04 19:01:31 +01:00
Rodrigo Girão Serrão
a10d2d9f98 Reference container markdown document.
Adding these references to the sub-widgets that make up a markdown document is necessary in order for the blocks to be able to post messages with a reference to the original document, which in turn is needed for the Message.control property to work.
2023-05-04 19:00:11 +01:00
Rodrigo Girão Serrão
2187a1d4a3 Add control to list view messages. 2023-05-04 18:55:51 +01:00
Rodrigo Girão Serrão
55e2e5d7e3 Add control to tree/dir tree messages. 2023-05-04 18:55:12 +01:00
Rodrigo Girão Serrão
14b70b0819 Add control to option list messages. 2023-05-04 18:53:29 +01:00
Dave Pearson
32fbdbd203
Merge pull request #2482 from davep/tree-lines-fix 2023-05-04 18:30:28 +01:00
Dave Pearson
6139c95f3a
Test that the event aliases are actually the same reference
I thought I thought I wanted what I thought but now I think about it I think
I thought wrong and now I think better.
2023-05-04 16:43:20 +01:00
Dave Pearson
8b36d29e74
Add a test for a radio set getting focus when a button gets clicked 2023-05-04 16:22:39 +01:00
Dave Pearson
19f4f64d96
Add tests for selection navigation in a radioset with no buttons pressed 2023-05-04 15:39:33 +01:00
Dave Pearson
e7d3b94334
Test that radioset wraps around when going off the bottom 2023-05-04 15:25:33 +01:00
Dave Pearson
b1443c0162
Test that radioset wraps around when going off the top 2023-05-04 15:22:30 +01:00
Dave Pearson
2113f415a0
Add a test that toggling a pressed radio button has no effect 2023-05-04 15:17:52 +01:00
Dave Pearson
b7cdbb0baa
Test to ensure that Changed.control is Control.checkbox 2023-05-04 15:12:15 +01:00
Dave Pearson
0b4d7fb091
Test to ensure that Changed.control is Control.radio_button 2023-05-04 15:10:45 +01:00
Rodrigo Girão Serrão
c4eda48a0a
Tweaks to DataTable docs. (#2481)
* Tweaks to DataTable docs.

Related PRs: #2479.

* Fix link.
2023-05-04 14:55:14 +01:00
Dave Pearson
bba694e93a
Update the ChangeLog 2023-05-04 14:30:20 +01:00
Dave Pearson
47f52f7692
Merge branch 'main' into tree-lines-fix 2023-05-04 14:27:46 +01:00
Dave Pearson
10e61987e3
Add always_update as a parameter for a var reactive
Redux. I managed to commit the wrong thing last time; although it was using
this and this was done for that.
2023-05-04 14:17:20 +01:00
Dave Pearson
f6da3e9fb2
Add always_update as a parameter for a var reactive 2023-05-04 14:16:34 +01:00
Will McGugan
04083a73f8
exclusive false (#2470)
* exclusive false

* changelog
2023-05-04 11:46:20 +01:00
Rodrigo Girão Serrão
cbd68b20df
Datatable scrolling faq (#2477)
* Add FAQ about DataTable scrolling.

Related issues: #2458

* Write concisely.

* Update questions/datatable-doesnt-scroll.question.md

Co-authored-by: Will McGugan <willmcgugan@gmail.com>

* Remove example.

* Add recommendation.

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-05-04 11:42:19 +01:00
Rodrigo Girão Serrão
38592c34bd
Add FAQ about DataTable scrolling. (#2466)
Related issues: #2458
2023-05-04 10:35:39 +01:00
Dave Pearson
805970193b
Merge branch 'main' into tree-lines-fix 2023-05-04 09:03:59 +01:00
Dave Pearson
71c5a44fdb
Take Tree.show_root into account when drawing guides
Rather than always start at the root, the code should start at the beginning
of the path.

See #2397.
2023-05-04 08:53:24 +01:00
Dave Pearson
ae2a155347
Merge pull request #2473 from davep/fix-dir-tree-eager-path 2023-05-03 22:34:39 +01:00
Dave Pearson
7dfc3e57a1
Fix a crash when DirectoryTree starts out anywhere other than .
A hangover from the previous DirectoryTree, where setting the path didn't
matter. This now sets it *after* calling Tree's __init__, thus ensuring the
line cache and other related things have been created.
2023-05-03 20:54:54 +01:00
Rodrigo Girão Serrão
3728555fbd
Scroll cursor into view. (#2464)
* Scroll cursor into view.

Related issues: #2459.

* Add regression test.

* Update changelog.
2023-05-03 13:57:04 +01:00
Will McGugan
e5c54a3683
blog post (#2465)
* blog posts

* fix typo

* word

* version bump

* changelog

* update words
2023-05-03 13:22:22 +01:00
Dave Pearson
c87a2b1b37
Merge pull request #2463 from davep/directory-tree-redux
Allow changing the "root" of a `DirectoryTree`
2023-05-03 12:15:31 +01:00
Dave Pearson
2e89cd11bb
Add missing type annotation on render_label 2023-05-03 11:52:23 +01:00
Will McGugan
41dbc66b23
optimize focus (#2460)
* optimize focus

* immediate call

* update previews

* snapshot
2023-05-03 11:48:56 +01:00
Dave Pearson
9e15dc45aa
Link the non-issue-related DirectoryTree change back the PR 2023-05-03 11:30:44 +01:00
Dave Pearson
4250912a28
Don't reassign the path when watching the path
Bit of a thinko happening there.
2023-05-03 10:44:45 +01:00
Dave Pearson
af0ed17ebd
Merge branch 'main' into directory-tree-redux 2023-05-03 10:06:30 +01:00
Dave Pearson
c4e2144207
Update the CHANGELOG 2023-05-03 09:59:35 +01:00
Dave Pearson
23d6c3611a
Add DirectoryTree.reload
This is a general reload; reloading the whole tree.
2023-05-03 09:34:55 +01:00
Dave Pearson
3d6fd7ef4c
Add a docstring to _load_directory 2023-05-03 09:13:42 +01:00
Dave Pearson
f509767141
Don't cast a DirEntry.path to a Path any more
It's always a Path now.
2023-05-03 09:13:11 +01:00
Dave Pearson
8311f837b8
Add a docstring to render_label
Well, okay, borrow the same from Tree.
2023-05-03 09:08:21 +01:00
Dave Pearson
d1d435d68b
Flesh out the docstring for validate_path 2023-05-03 09:02:49 +01:00
Dave Pearson
e4c0517cc6
Add the node to the FileSelected message
Until now it wasn't really possible to know *which* DirectoryTree widget had
sent a given message; this makes it available by providing the `node`, which
in turn will provide the `tree`.
2023-05-03 08:58:11 +01:00
Dave Pearson
465f522ef3
Add a reminder to add the node to the FileSelected message 2023-05-02 16:48:06 +01:00
Dave Pearson
5f22cf8e7b
Remove empty rule from DirectoryTree.DEFAULT_CSS 2023-05-02 16:46:07 +01:00
Dave Pearson
40e042d7e3
Make _load_directory private 2023-05-02 16:45:18 +01:00
Will McGugan
90d9693168 typo 2023-05-02 16:36:41 +01:00
Dave Pearson
d4af9d239f
Add a path reactive to DirectoryTree so the path it views can be changed
A couple of things come with this, at least one being a breaking change of
sorts:

- DirectoryTree now has a path attribute
- DirectoryTree.path is a reactive
- When DirectoryTree.path is assigned to it rebuilds the tree content
- DirectoryTree.path can be assigned a str or Path but always evaluates to a Path
- DirEntry.path is now typed as a Path
- DirEntry drops is_dir (Directory.path.is_dir() does that job)
- DirectoryTree.FileSelected.path is now always a Path

This is the first of what might be a few changes here; the main thrust of
this commit being to allow changing a DirectoryTree to view a different
directory, and also to move to a Path-first approach.
2023-05-02 16:33:22 +01:00
Dave Pearson
922934597d
Sort the component classes to match the docs 2023-05-02 16:30:16 +01:00
Will McGugan
a2aef3da0d updated call_from_thread API docs 2023-05-02 16:28:12 +01:00
Will McGugan
aedac6a9b9 update roadmap 2023-05-02 16:20:16 +01:00
Will McGugan
91a9d570a4
On decorator (#2453)
* Add on decorator

* decorator code

* docs for on decorator

* Examples

* test errors

* simplify listing

* words

* changelog

* Update docs/guide/events.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Update docs/guide/events.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Update docs/examples/events/on_decorator.css

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/guide/events.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* rewording

* comment

* clarification

* Added note

---------

Co-authored-by: Dave Pearson <davep@davep.org>
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-05-02 16:17:40 +01:00
Dave Pearson
83c09b3cfd
Add a missing type hint
Looks like this has been missing since DirectoryTree was first written.
2023-05-02 15:51:18 +01:00
Dave Pearson
d0639a0cc1
Correct the type of the TreeExpanded event
This looks to have been a slight typing bug all along.
2023-05-02 15:29:36 +01:00
Rodrigo Girão Serrão
914e50a70f
Export types & doc improvements (#2329)
* Export types used in app.py

* Export more linked types/errors/classes.

* Remove custom template.

* Address review comments.

We need to have explicit 'Returns:' sections in properties if we want to link to the return type while https://github.com/mkdocstrings/python/issues/65 is open.

* Improve docs.
2023-05-02 15:12:53 +01:00
Dave Pearson
911ffdb144
Merge pull request #2455 from davep/snapshit-speedup
Remove the bytewise diffing of failed snapshots
2023-05-02 14:55:47 +01:00
Dave Pearson
d67b516707
Merge pull request #2454 from davep/ci-test-only-code-changes
Attempt to narrow CI/test trigger to just code changes
2023-05-02 14:55:17 +01:00
Dave Pearson
16931a8563
Move DirectoryTree.FileSelected.path's doc to inline style
This brings it in line with the documentation for other widgets and their
messages.
2023-05-02 14:19:55 +01:00
Dave Pearson
2ad3903d43
Remove the bytewise diffing of failed snapshots
In doing so this removes the file similarity value, and as such the key that
the failure report was sorted on. This was done because, given how many
snapshot tests we have now, if lots failed, it would take a long time (often
many minutes) to compile the report.

The report is now sorted on the test name.

Now, no matter how many snapshots fail, the report should be produced pretty
much instantly.
2023-05-02 13:47:18 +01:00
Dave Pearson
9dda90ea75
Extend testing to some more files
In this case the snapshot data, the lock file and the Makefile.
2023-05-02 13:07:47 +01:00
Dave Pearson
7152adfdf5
Remove the test change
That seemed to do the trick!
2023-05-02 13:07:30 +01:00
Dave Pearson
aa9f6392c3
Make a change to a py file to see if CI will kick off tests 2023-05-02 12:57:08 +01:00
Dave Pearson
a8d2724873
Attempt to narrow CI/test trigger to just code changes
Looking at
https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
I *think* this might be the approach to take. Consider this an experimental
change that will very likely get rolled back.

See #2404
2023-05-02 12:52:51 +01:00
Dave Pearson
8a29c7ea2c
Merge pull request #2452 from davep/outline-top-bottom-colour-glitch
Fix outline-top and outline-bottom not handling colour alpha
2023-05-02 11:45:26 +01:00
Dave Pearson
16ca3e10d1
Merge branch 'main' into outline-top-bottom-colour-glitch 2023-05-02 11:34:14 +01:00
Dave Pearson
d34d1b19b2
Merge pull request #2444 from davep/overall-important
Make `!important` apply to rules that have "sub-rules"
2023-05-02 11:33:05 +01:00
Dave Pearson
9c26c6ef32
Merge branch 'main' into outline-top-bottom-colour-glitch 2023-05-02 11:05:52 +01:00
Dave Pearson
7e570df4f4
Fix outline-top and outline-bottom not handling colour alpha
See #2371.
2023-05-02 11:03:54 +01:00
Dave Pearson
87847cea4c
Update the CHANGELOG 2023-05-02 10:16:45 +01:00
Dave Pearson
16d62dfb20
Distribute !important on scrollbar size 2023-05-02 10:13:24 +01:00
Dave Pearson
cbe418de18
Distribute !important on overflow 2023-05-02 10:12:18 +01:00
Will McGugan
e1a8f28f8d
update to log docs (#2451) 2023-05-02 10:09:32 +01:00
Dave Pearson
ad37b6809a
Distribute !important on content-align 2023-05-02 10:08:33 +01:00
Dave Pearson
763f9b012f
Distribute !important on align 2023-05-02 10:06:17 +01:00
Dave Pearson
8fc6e195e1
Change the importance distribution method to be more generic 2023-05-02 09:49:06 +01:00
Dave Pearson
27ca4969a8
Add tests for styles that have "sub-styles" and !important
This is a series of tests for checking styles that have sub-styles, or
sub-parts, or whatever the correct name would be; the testing being that if
!important is applied to the whole, that it works.

Starting with #2420 it became apparent that this didn't work as intended,
and once that work started it became obvious that it affected more than just
border.

So these tests test all of the styles that can be specified as a single
whole, or as a set of parts (sides, directions, etc).
2023-05-02 09:36:08 +01:00
Dave Pearson
4ab9ba9268
Merge branch 'main' into overall-important 2023-05-02 08:46:52 +01:00
Will McGugan
83b1fcc102
raise attribute error (#2443)
* raise attribute error

* fix compute defaults
2023-05-01 16:57:40 +01:00
Will McGugan
ba90657559 update changelog 2023-05-01 16:36:05 +01:00
Will McGugan
20a1612361
Invalid pseudo selectors (#2445)
* token error

* error on bad pseudo selectors
2023-05-01 16:22:35 +01:00
Dave Pearson
60dc38c5cd
Merge branch 'main' into overall-important 2023-05-01 16:22:09 +01:00
Dave Pearson
08de9a0fca
Merge pull request #2442 from davep/private-watcher
Add support for private watch methods
2023-05-01 16:19:24 +01:00
Will McGugan
832d191bd3
bump poetry (#2447) 2023-05-01 15:35:58 +01:00
Dave Pearson
d6eb44bd19
Fix outline-right not being recognised
See #2446.
2023-05-01 15:21:12 +01:00
Dave Pearson
d6f304f5d1
Update the CHANGELOG 2023-05-01 15:19:24 +01:00
Dave Pearson
7a69c037b8
Distribute importance amongst all sides of an outline 2023-05-01 15:00:54 +01:00
Dave Pearson
883e293e1f
Move the important distribution code into its own method
Border isn't the only place we're going to want to do this, so let's now
turn this into a more general body of code and have border use it.
2023-05-01 15:00:07 +01:00
Dave Pearson
5a355da78b
Fixed !important not applying to border 2023-05-01 14:17:29 +01:00
Dave Pearson
54db445dd7
Change private watcher support call public and private if available
See https://github.com/Textualize/textual/pull/2442#issuecomment-1529512891

This changes the original PR so that, rather than calling a private watcher
instead of a public, as originally issued, we now call public and private,
if they're both there.

If they are both there private is called first.
2023-05-01 10:28:55 +01:00
Dave Pearson
847fd6e69e
Add support for private watch methods
This change allows for private watch methods. By convention they start with
an underscore. If a reactive or var has a private watch method, it will be
used in preference to a public watch method.

With this change it becomes easier to have a private reactive/var whose
watcher is also private. For example:

    _counter = var(0)
    """This is a private counter, it won't appear in the docs."

    ...

    def _watch__counter(self) -> None:
        """Watch _counter, but don't appear in the docs either."
        ...

See #2382.
2023-05-01 10:01:50 +01:00
Will McGugan
8fac2c7d2a
Bump0223 (#2424)
* button tweak

* fix for windows

* changelog
2023-04-28 20:56:28 +01:00
Will McGugan
ecee8ef837 fix run on Windows 2023-04-28 20:29:21 -07:00
Will McGugan
c5053eca81
faster focus within (#2423) 2023-04-28 18:08:57 +01:00
Dave Pearson
32c74d9535
Merge pull request #2415 from davep/expose-node-tree
Add `TreeNode.tree`
2023-04-28 14:23:28 +01:00
Dave Pearson
40f7c97500
Merge branch 'main' into expose-node-tree 2023-04-28 13:58:04 +01:00
Will McGugan
e15df80a8c
Version bump (#2418) 2023-04-28 12:38:02 +01:00
Will McGugan
16a1645671
revert timer change (#2417)
* revert timer change

* changelog
2023-04-28 11:47:28 +01:00
Will McGugan
7c696ce378
Updated docs for app.run (#2414)
* fix run app from python

* updated run

* remove function

* update help

* doc update
2023-04-28 10:47:24 +01:00
Dave Pearson
02ed90c633
Add TreeNode.tree
Currently, in the various TreeNode messages, and the handlers you'd write to
handle them, there's no way to easily know *which* tree sent the message and
so which tree the node belongs to.

This commit adds public access to the tree reference to the nodes, so that
in an event handler the developer can check the tree involved in the event.

See #2413.
2023-04-28 10:23:38 +01:00
Dave Pearson
730f78757a
Merge pull request #2409 from TomJGooding/fix-switch-correct-attribute-name-in-changed-docstring
fix(switch): correct attribute in changed docstring
2023-04-27 18:59:19 +01:00
TomJGooding
c063c3ecdf
fix(switch): correct attribute in Changed docstring 2023-04-27 18:42:46 +01:00
Sebastian Pipping
eab1328ccc
Fix demo example CSS (fixes #2389) (#2393)
* demo.py: Stop cutting of demo.css content after 50 lines

* demo.py: Drop unused variable EXAMPLE_CSS

* demo.py: Simplify derivation of example_css
2023-04-27 15:27:43 +01:00
Will McGugan
124c45e68c
Bump0220 (#2405)
* Version bump

* upate version

* fix domain name

* wrong project

* skip on Windows

* disable demo snapshot

* 37 fix
2023-04-27 15:01:46 +01:00
Will McGugan
dd70a7a2dc
fix for min and max with fr unints (#2390)
* fix for min and max with fr unints

* snapshit

* forgot snapshit tests

* fix resolve

* added unit tests

* Windoze fix
2023-04-27 13:35:16 +01:00
Dave Pearson
fe99df95fc
Fix light mode plain text in non-syntax code blocks in Markdown (#2402)
Bit of a workaround at the moment; ideally longer-term we'll go with
something less hard-coded.

See #2400
2023-04-27 12:03:05 +01:00
Will McGugan
55e198767f
Add progress bar to gallery (#2399)
* Add progress bar to gallery

* table fix
2023-04-27 11:37:53 +01:00
Dave Pearson
01df8b0726
Make textual.containers 1fr in meaningful dimensions by default (#2386)
* Make all containers 1fr

An unintended consequence of changes made to containers in v0.21.0 (#2377)
is something like #2385 so this commit sort of rolls that change back, and
solidifies how containers are styled by default in respect to their width
and height. Where appropriate the dimensions will be 1fr.

* Make the DEFAULT_CSS of ProgressBar less greedy

It was attempting to style a Vertical that is uses, but in doing so was
styling all Verticals rather than a Vertical within a ProgressBar.

This fixes that.

* Update the CHANGELOG for the container changes

* Move the ProgressBar CHANGELOG entry into the next release section

* Link the container change entry in the CHANGELOG to its PR

Now that the PR is PRd and we have a PR
2023-04-26 17:07:30 +01:00
Rodrigo Girão Serrão
4148b1d450
Implement a Progress Bar widget. (#2333)
* First prototype of PB.

* Repurpose UnderlineBar.

* Factor out 'Bar' widget.

* Revert "Factor out 'Bar' widget."

This reverts commit 0bb4871adf566416cfe590ac4396e0b79f84165c.

* Add Bar widget.

* Cap progress at 100%.

* Add skeleton for the ETA label.

[skip ci]

* Add ETA display.

* Improve docstrings.

* Directly compute percentage.

* Watch percentage changes directly.

[skip ci]

* Documentation.

* Make reactive percentage private.

Instead, we create a public read-only percentage property.

* Update griffe to fix documentation issue.

Related issues: #1572, https://github.com/mkdocstrings/griffe/issues/128.
Related PRs: https://github.com/mkdocstrings/griffe/pull/135.

* Add example and docs.

* Address review feedback.

[skip ci]

* More documentation.

* Add tests.

* Changelog.

* More tests.

* Fix/fake tests.

* Final tweaks.
2023-04-26 15:25:39 +01:00
Will McGugan
ee0d407067 fix changelog 2023-04-26 14:01:15 +01:00
Will McGugan
f20df9b075
Bump0210 (#2381)
* new version

* docstring
2023-04-26 13:55:41 +01:00
Will McGugan
f53c3cd589
container refactor (#2377)
* container refactor

* Rearrange css

* changelog

* try timer updates

* force update

* sleep idle

* Restore updates
2023-04-26 13:36:08 +01:00
Will McGugan
ff703ad983
pass through unprocessed args (#2374)
* pass through unprocesses args

* omit symbols

* extract args

* posix exception

* timer updates

* another update

* just work on windows damn it

* remove updates
2023-04-26 11:09:04 +01:00
Will McGugan
ec09fb5afc force updates 2023-04-26 10:23:23 +01:00
Dave Pearson
441b98d7a7
Merge pull request #2372 from davep/radioset-redux 2023-04-25 17:21:07 +01:00
Dave Pearson
7a536c790c
Demo snapshot test back up to a 250 wait
Waiting 100 resulted in a fail, so let's bump back up again.
2023-04-25 15:49:43 +01:00
Dave Pearson
db45287646
Lower the wait for the demo snapshot test
250 worked; so let's try it lower.
2023-04-25 15:41:02 +01:00
Dave Pearson
88926a4bb8
Force a wee wait when testing the demo
This keeps randomly failing in Windows in CI; multiple subsequent runs gets
it going in the end, normally one further fail at a time. So let's throw a
wee wait on the end and see if that helps.
2023-04-25 15:27:43 +01:00
Dave Pearson
f2c56e7cd5
Link the RadioSet CHANGELOG entry to the new PR 2023-04-25 15:17:02 +01:00
Dave Pearson
0d5db58692
Update the CHANGELOG 2023-04-25 15:09:35 +01:00
Dave Pearson
c45f9358ee
Change RadioSet so it's less a container of widgets and more a widget
Initially we went with a RadioSet being a simple container of RadioButtons,
with the user navigating the RadioButtons like you would any other set of
widgets. This was fine but it became pretty clear pretty quickly that having
to tab through a non-trivial collection of buttons in a set to get to the
next widget wasn't ideal.

This commit, satisfying #2368, takes over the navigation of the buttons
within the container, makes the container itself a focusable widget, and
sets up some new bindings to allow a more natural and efficient interaction
with the set.
2023-04-25 15:00:44 +01:00
Dave Pearson
a6a373161f
Add some unit testing of the new navigation 2023-04-25 12:06:46 +01:00
Dave Pearson
e16493bf81
Update the snapshot tests
This is necessary now that a focused RadioSet has acquired a border colour
similar to that if a focused Input.
2023-04-25 11:27:23 +01:00
Dave Pearson
59506f3292
Turn a RadioSet into a single focus switching site
With this commit a RadioSet becomes something you can tab into and out of
with just one keypress; navigation of the buttons within moves to being done
with the cursor keys instead.

See #2368.
2023-04-25 11:16:20 +01:00
Dave Pearson
b36afd80a7
Highlight a RadioSet when focus is within it 2023-04-25 10:13:30 +01:00
Dave Pearson
f1d70900cb
Merge pull request #2367 from davep/tidy-builtin-actions
Tidy builtin actions
2023-04-24 16:13:35 +01:00
Dave Pearson
4047c83680
Update the CHANGELOG 2023-04-24 15:22:26 +01:00
Dave Pearson
b14b3b9e39
Expand the builtin action list in the docs 2023-04-24 15:12:51 +01:00
Dave Pearson
fee216132f
Rename action_remove_class_ to action_remove_class 2023-04-24 15:02:22 +01:00
Dave Pearson
4d3cd1295f
Rename action_add_class_ to action_add_class 2023-04-24 15:01:59 +01:00
Dave Pearson
d1ff1b33d6
Expand the docstring for action_back 2023-04-24 15:01:05 +01:00
Dave Pearson
7f4699605e
Add a missing docstring argument for action_check_bindings 2023-04-24 14:59:12 +01:00
Dave Pearson
9371b47b9b
Merge pull request #2365 from davep/no-container-scroll
Have `Container` *not* show scrollbars by default
2023-04-24 14:15:33 +01:00
Dave Pearson
2055a8996f
Move the tutorial over to using ScrollableContainer 2023-04-24 13:13:11 +01:00
Dave Pearson
ca94c5eed0
Merge branch 'main' into no-container-scroll 2023-04-24 11:35:47 +01:00
Rodrigo Girão Serrão
e5033d7d23
Remove hanging lines from docstrings. (#2349)
* Remove hanging lines from docstrings.

Deleted hanging blank lines at the end of docstrings.

Regex pattern:
 - find `\n\n( *)"""`
 - replace with `\n$1"""`
2023-04-24 11:21:38 +01:00
Dave Pearson
a005b81a39
Update the CHANGELOG 2023-04-24 11:18:41 +01:00
Dave Pearson
b896e9d7f9
Update tests to handle scroll changes to Container
See #2361.
2023-04-24 11:10:37 +01:00
Dave Pearson
a91b2c6b35
By default hide the horizontal scrollbar on VerticalScroll
In connection with #2361.
2023-04-24 11:09:52 +01:00
Dave Pearson
d06a4e579d
By default hide the vertical scrollbar on HorizontalScroll
In connection with #2361.
2023-04-24 11:09:09 +01:00
Dave Pearson
38e636921c
Remove default scrollbars from Container
As per #2361 this removes default scrollbars on Container (and so adds them
on ScrollableContainer).
2023-04-24 11:06:31 +01:00
Will McGugan
80f4c12e76
Fix scroll flicker (#2358)
* fix scroll flicker

* fix scroll flicker

* remove event

* do not delay scroll

* remove comment

* test fix

* remove commented code

* comment

* increase pause on click

* changelog [skip ci]

* wait on resume

* remove note [skip ci]
2023-04-24 09:33:15 +01:00
Dave Pearson
8b6d9027e9
Merge pull request #2353 from davep/bug/2352/tabbed-content-active 2023-04-23 16:40:39 +01:00
Will McGugan
24a17ba914
Merge branch 'main' into bug/2352/tabbed-content-active 2023-04-23 16:04:06 +01:00
Rodrigo Girão Serrão
50030b427f
Fix up/down key ansi sequences. (#2280)
* Fix up/down key ansi sequences.

Related issues: #2223.
Related comments: [my reply to OP](https://github.com/Textualize/textual/issues/2223\#issuecomment-1505512300) and [the OP's reply](https://github.com/Textualize/textual/issues/2223\#issuecomment-1506764562).

* Changelog.
2023-04-23 14:14:36 +01:00
Will McGugan
3736807359
fix color system render (#2360)
* fix color system render

* changelog
2023-04-22 17:49:00 +01:00
Dave Pearson
1a84be9fc9
Update the CHANGELOG 2023-04-22 10:29:00 +01:00
Dave Pearson
75543fbd4c
Merge branch 'main' into bug/2352/tabbed-content-active 2023-04-22 10:28:02 +01:00
Will McGugan
a2633ca31e
fix text opacity (#2356) 2023-04-22 08:50:14 +01:00
Dave Pearson
a351d620b2
Add some pauses to the UI-baed tabbed content tests
This particular test seems rather flakey in GitHub's actions. In most cases
passing, with the odd fail here and there (normally when unrelated changed
are made -- I've had this fail when docs have been changed; zero code
changes!)

So, on the off chance that a little extra pause will help...
2023-04-22 08:42:38 +01:00
Dave Pearson
c022d9de2f
Fix TabbedContent.active not changing actual content
Ensures that the actual content gets changed when TabbedContent.active is
updated via code. Also adds more testing for TabbedContent.

See #2352 for details.
2023-04-22 08:28:12 +01:00
Dave Pearson
9e19706b53
Merge pull request #2345 from davep/button-docs-tweakage
Some more Button docs tidying
2023-04-21 09:07:25 +01:00
Dave Pearson
ccf4f06a74
Some more Button docs tidying
While I'm in this file... might as well link the word "variant" to the type
that it's referring to.
2023-04-21 07:57:48 +01:00
Dave Pearson
cd5d9d1e4f
Merge pull request #2344 from davep/type-button-pressed-button-in-docs
Small improvement to the `Button.Pressed` event documentation
2023-04-21 07:47:51 +01:00
Dave Pearson
b34ab0d9a4
Small improvement to the Button.Pressed event documentation
This makes `button` as obvious as `control`, and also ensures it has a type
in the docs too. While here I also add a couple of extra links to make the
docs more inter-linked.
2023-04-21 07:38:42 +01:00
Will McGugan
cab4925eaa
New CLI runner (#2338)
* New CLI runner

* runner functionality

* Add port

* use env for port

* changelog

* test fix

* flush

* remove constant

* comment

* tidy docs

* docstrings

* punctuation

* docstring

* fix test

* snapshot

* Update src/textual/cli/cli.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* guard against bad imports

* guard againsts screenshot

* always print return

* docstrings

* docstrings

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-20 17:09:39 +01:00
Dave Pearson
c8ecd26234
Merge pull request #2340 from davep/assorted-doc-tweaks
Assorted doc tweaks
2023-04-20 16:20:11 +01:00
Dave Pearson
d4f7ef02bb
Merge pull request #2337 from davep/bug/2100/invisible-keys
Move default scroll navigation keys out of `Widget` and into `ScrollableContainer`
2023-04-20 15:37:45 +01:00
Dave Pearson
83da429793
Small collection of docstring tweaks 2023-04-20 14:13:56 +01:00
Dave Pearson
4801b3bc8f
Link the doc for Checkbox.Changed.control to checkbox 2023-04-20 14:01:33 +01:00
Dave Pearson
8ea6658877
Link the doc for RadioButton.Changed.control to radio_button 2023-04-20 13:59:44 +01:00
Dave Pearson
84b5b866d4
Merge branch 'main' into bug/2100/invisible-keys 2023-04-20 13:45:30 +01:00
Dave Pearson
60542c52b3
Merge pull request #2339 from davep/refresh-all-the-screens
Ensure an app's CSS refresh updates all screens in the stack
2023-04-20 13:44:45 +01:00
Dave Pearson
61dc08dd99
Update the CHANGELOG 2023-04-20 11:42:14 +01:00
Dave Pearson
ae656c21c1
Refresh the CSS for all screens in an app's stack, when asked to refresh
Addresses #1999.
2023-04-20 11:39:12 +01:00
Dave Pearson
c507c4a785
Driveby typo fix
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-20 11:14:11 +01:00
Dave Pearson
b6b8fbdb41
Fix typo
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-20 11:13:01 +01:00
Dave Pearson
14f05899b2
Correct the location of the new items in the CHANGELOG
I'd accidentally started adding things under v0.20.1 rather than under a new
unreleased heading.
2023-04-20 10:09:20 +01:00
Dave Pearson
59e325d004
Update the CHANGELOG 2023-04-20 10:08:40 +01:00
Dave Pearson
1c5909eb23
Update the binding inheritance tests for the new moment bindings approach
Now that navigation bindings don't pollute the whole widget hierarchy any
more some of these tests can be tidied up.
2023-04-20 10:04:32 +01:00
Dave Pearson
8a909b0d0a
Change all containers so they don't inherit bindings
This is, to some degree, rendered moot by #2332, but for the moment it still
feels worth doing. The initial intention was to make sure that non-scrolling
containers and their child classes don't have bindings that may mask other
uses for navigation keys. However, it was realised that the "problem"
affected more than just containers (hence #2332).

But... on the off chance we add any more default bindings to
`Widget` (unlikely, but still), this will mean that they don't leak into the
containers unless we intend them to.

See #2331.
2023-04-20 09:51:50 +01:00
Dave Pearson
7d82e30684
Fix demo so that keyboard navigation scrolls the display again
The `Body` class inherited from `Container` rather than one of the scrolling
containers; until now it had worked because `Widget` provided the bindings
to make this happen, now that they've moved into `ScrollableContainer` that
stopped working.
2023-04-20 09:42:29 +01:00
Dave Pearson
fe5f80bdd6
Change ScrollView to inherit from ScrollableContainer rather than Widget
See #2332
2023-04-20 09:40:58 +01:00
Dave Pearson
f4e5f23053
Merge pull request #2336 from davep/tidy-widget
Remove unused import from widget.py
2023-04-20 09:32:01 +01:00
Dave Pearson
ee45356c5c
Update the CHANGELOG 2023-04-20 09:31:28 +01:00
Dave Pearson
49422932c7
Move scroll navigation key bindings out of widget and into own container
The idea here is that not every widget will scroll, and as such not every
widget needs to have default bindings for calling the scrolling methods.
Generally scrolling is something done in a container.

These days we have *Scroll containers. As such it makes sense to introduce
the bindings in a common parent class for those containers.

This commit moves the binding from widget and creates that common parent
class, and then has HorizontalScroll and VerticalScroll inherit from it.

This is, it should be noted, a breaking change. Any code that creates a
scrolling widget that assumes that the bindings are just there, where that
widget doesn't inherit either from HorizontalScroll or VerticalScroll, will
suddenly find that scrolling with the keyboard is no longer possible.

See #2332.
2023-04-20 09:15:05 +01:00
Dave Pearson
88b068fd64
Remove unused import from widget.py 2023-04-20 08:59:38 +01:00
Will McGugan
550cd47123 docstring 2023-04-19 17:13:57 +01:00
Will McGugan
d7f5fb9107
Fix frame rate limiter (#2318)
* simplify

* fix for frame rate limiter

* fix update

* fix update

* update comment

* No need for lock

* remove comment

* fix for glitched test

* force update

* implement dim fix

* docstrings

* foreground fix

* cached filters

* cache default

* fix for filter tests

* docstring

* optimization

* Update src/textual/filter.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/constants.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* fix cache

* remove comment [skip ci]

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-19 16:55:42 +01:00
Dave Pearson
0e8e232a08
Merge pull request #2328 from davep/footer-cleanup
Clean up various warnings in _footer.py
2023-04-19 13:41:07 +01:00
Dave Pearson
f6612490df
Clean up various warnings in _footer.py
While visiting this for other reasons I noticed a number of warnings about
the code that were easy to tidy up. So I tidied them up.
2023-04-19 13:27:10 +01:00
Will McGugan
81882fdf7d
implement dim fix (#2326)
* implement dim fix

* docstrings

* foreground fix

* cached filters

* cache default

* fix for filter tests

* docstring

* optimization

* Update src/textual/filter.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/constants.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-19 13:24:31 +01:00
Dave Pearson
7c5203aa1b
Merge pull request #2321 from davep/screen-results
Add support for "returning" a result value from screens.
2023-04-19 11:47:09 +01:00
Dave Pearson
768a235f3a
Improve a docstring
Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-04-19 11:40:34 +01:00
Dave Pearson
9123a80aa5
Update a screen instance's callback stack when it is switched out
As per the observation here:

  https://github.com/Textualize/textual/pull/2321#pullrequestreview-1391744148
2023-04-19 11:39:19 +01:00
Dave Pearson
5689e62230
Merge pull request #2325 from davep/private-event-handlers
Make textual.widgets.* event handlers private
2023-04-19 11:15:29 +01:00
Dave Pearson
5886c6bd0c
Make DataTable event handlers private
See #2324.
2023-04-19 10:13:23 +01:00
Dave Pearson
36aa3321ff
Make ToggleButton event handlers private
See #2324.
2023-04-19 10:07:36 +01:00
Dave Pearson
d23024141c
Make Tabs event handlers private
See #2324.
2023-04-19 10:05:53 +01:00
Dave Pearson
1063c0f94c
Make Switch event handlers private
See #2324.
2023-04-19 10:04:05 +01:00
Dave Pearson
d2c8206a8e
Make RadioSet event handlers private
See #2324.
2023-04-19 10:02:47 +01:00
Dave Pearson
404d7b8fb8
Make PlaceHolder event handlers private
See #2324.
2023-04-19 09:53:56 +01:00
Dave Pearson
99d3c9fa79
Make OptionList event handlers private
See #2324.
2023-04-19 09:52:43 +01:00
Dave Pearson
da809ec717
Make Markdown event handlers private
See #2324.
2023-04-19 09:44:03 +01:00
Dave Pearson
6b147487bb
Make LoadingIndicator event handlers private
See #2324.
2023-04-19 09:40:45 +01:00
Dave Pearson
489bcf3ad1
Make ListView event handlers private
See #2324.
2023-04-19 09:39:36 +01:00
Dave Pearson
f9071987bd
Make ListItem event handlers private
See #2324.
2023-04-19 09:37:35 +01:00
Will McGugan
db1b784606
dim filter (#2323)
* dim filter

* optimization

* Remove test code

* move functions out of filter

* docstring

* move function to module scope

* docstring

* docstrings
2023-04-19 09:31:59 +01:00
Dave Pearson
18a6428738
Make Input event handlers private
See #2324.
2023-04-19 09:30:44 +01:00
Dave Pearson
c9664f0ff5
Make Header event handlers private
See #2324.
2023-04-19 09:20:10 +01:00
Dave Pearson
69477c2a18
Make DirectoryTree event handlers private
See #2324.
2023-04-19 09:17:01 +01:00
Dave Pearson
590c898213
Make ContentSwitcher.on_mount private
See #2324.
2023-04-19 09:13:28 +01:00
Will McGugan
4981effcba
Revert "Prevent reactive-watcher loop in Tabs / TabbedContent." (#2322)
* Revert "Prevent reactive-watcher loop in Tabs / TabbedContent. (#2305)"

This reverts commit 66a644845b.

* fix stuck tab

* fix for stuck underline

* snpshot
2023-04-18 16:46:10 +01:00
Dave Pearson
c9dd89b944
Merge branch 'main' into screen-results 2023-04-18 14:29:40 +01:00
Will McGugan
cc41a7f81d
Bump0200 (#2320)
* version bump

* changelog
2023-04-18 13:41:15 +01:00
Will McGugan
bbe38f7d30
faq entry on Transparent backgrounds (#2319)
* faq entry

* word

* update to words
2023-04-18 13:29:13 +01:00
Dave Pearson
e3babfd812
Drop dismiss_with
Just go with a single dismiss method.
2023-04-18 13:11:51 +01:00
Dave Pearson
21783fb479
Fix the typing for ResultCallback.__init__ 2023-04-18 12:49:28 +01:00
Dave Pearson
2e7b010301
Allow for a screen being pushed when the stack is empty
Under normal circumstances the code wouldn't encounter this problem as
there's always a default screen; but a handful of tests that were testing
the screen stack broke after the recent additions relating to result
callbacks.

This cleans up that problem.
2023-04-18 11:54:32 +01:00
Rodrigo Girão Serrão
66a644845b
Prevent reactive-watcher loop in Tabs / TabbedContent. (#2305)
* Add regression test for #2229.

* Fix potential reactive-watch loop.

* Simplify regression test.

Labels are cheaper to use and the final visual result of the test won't depend on the directory it runs from.

* Simplify solution.

Turns out I didn't need a descriptor. :(

* Fail on empty tab.
2023-04-18 11:48:33 +01:00
Rodrigo Girão Serrão
3a7cf08ef2
Make scrollable containers focusable. (#2317)
* Make scrollable containers focusable.

Related issues: #2270.
2023-04-18 11:44:32 +01:00
Dave Pearson
77e47f7508
Swap the result callbacks on screens to be a stack of callbacks
It is possible for the same instance of a screen to get pushed onto the
screen stack multiple times; as such we really need to keep track of all the
callback requests.

So here I register a callback for every screen push and clean it up on every
screen pop; with those without callbacks being no-ops.
2023-04-18 11:40:12 +01:00
darrenburns
496f8b4524
Updating styles on demand instead of on_idle (#2304)
* Updating styles on demand instead of on_idle

* Tidy up update_styles

* Fix LRU cache tests

* Remove some debugging code

* Adding test for pseudoclass style update

* Update changelog
2023-04-18 11:36:00 +01:00
Rodrigo Girão Serrão
01d67173e8
Don't expose snippets publically. (#2300) 2023-04-18 10:19:43 +01:00
Dave Pearson
b67f4f89cc
Initial testing of screen result callbacks
This is roughly how it should work. Having got this going and constructed
test code to go with it (outwith of this commit, not unit testing code, just
a test app to try out the ideas), I wanted to get this onto the forge for
further mulling over tomorrow.

The one sneaky/questionable thing here is that I'm sort of dumpster-diving
the screen stack to get the "parent" screen, to make the callback in
context. This both feels right and feels like a cheat. On the other hand
it's public for a reason, right?

Right?
2023-04-17 21:03:49 +01:00
Will McGugan
e930e82526
fix for win driver (#2303) 2023-04-17 17:06:07 +01:00
Dave Pearson
f8b51ea269
Ensure the active message pump is set when app is the sender (#2302)
See https://github.com/Textualize/textual/issues/2301
2023-04-17 16:23:31 +01:00
Will McGugan
0509cf8948
Border style (#2292)
* border styles

* docs for border styles

* fix tests

* tests

* tests and docs

* changelog

* implement auto

* style information fix
2023-04-16 12:31:39 +01:00
Dave Pearson
9fb63f9b53
Merge pull request #2286 from davep/faqup
Update the centring FAQ to reference `Center`
2023-04-15 09:05:07 +01:00
Dave Pearson
52dcca4e8c
Merge pull request #2287 from davep/export-button-variant 2023-04-14 15:59:01 +01:00
Dave Pearson
3c1a311a67
Update the Button docs to mention ButtonVariant
I'm not 100% sure how to get this into the docs as I'd like, and it seems
we've moved the API docs around a lot in respect to widgets, recently (I'm
aware of this but aren't sure what the new layout is yet).

This at least starts to get things into the right place.
2023-04-14 13:08:26 +01:00
Dave Pearson
8fe14e44da
Update the CHANGELOG 2023-04-14 12:19:24 +01:00
Dave Pearson
3ce910f764
Add textual.widgets.button to expose ButtonVariant
See #2264.
2023-04-14 12:17:53 +01:00
Dave Pearson
bec01e99d1
Rebuild the FAQ
Keep forgetting to do this!
2023-04-14 12:11:45 +01:00
Dave Pearson
ee8153c9ed
Update the centring FAQ to reference Center
See #2263.
2023-04-14 12:09:25 +01:00
darrenburns
898de5a69c
Fix for empty ListView bindings not firing (#2281)
* Fix bindings not firing when ListView is empty

* Regression test for empty ListView bindings not working

* Update changelog
2023-04-13 15:32:56 +01:00
Will McGugan
5e50b2e417 optimization 2023-04-13 14:33:01 +01:00
Will McGugan
58b8d22a3c remove bell 2023-04-13 14:23:06 +01:00
Will McGugan
04b994836c
Strips render optimization (#2278)
* WIP optimization

* optimization

* simplify, add comments

* docstring

* Update src/textual/_compositor.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/_compositor.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/strip.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/_compositor.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* driver bell

* optimize render

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-13 14:15:32 +01:00
darrenburns
5246282c22
Improving data table documentation (#2279)
* Improving data table documentation

* More info on DataTable

* Add note on retrieving cursor coordinate

* Add note on DataTable supporting more than just strings

* Add note on cell styling and justifying - common question

* Slight rewording

* Explaining what "row labels" are.

* Update docs/widgets/data_table.md

Co-authored-by: Will McGugan <willmcgugan@gmail.com>

* Update docs/widgets/data_table.md

Co-authored-by: Will McGugan <willmcgugan@gmail.com>

* Update docs/widgets/data_table.md

Co-authored-by: Will McGugan <willmcgugan@gmail.com>

* Update docs/widgets/data_table.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/widgets/data_table.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/widgets/data_table.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/widgets/data_table.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/widgets/data_table.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Improve data table fixed rows/columns docs

* Update some examples

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-13 14:09:19 +01:00
Rodrigo Girão Serrão
bb2c31ba35
Add --port option to textual console. (#2258)
* Add --port option to textual console.

* Changelog.

* Address review feedback.

* Mark unpredictable test as xfail.

This test gets an xfail mark until #2254 is open.

* Make DEVTOOLS_PORT a constant.

Related review: https://github.com/Textualize/textual/pull/2258\#discussion_r1165210395

* Factor logic into function.

Related review: https://github.com/Textualize/textual/pull/2258\#discussion_r1165298259

* Remove dead import.
2023-04-13 11:57:35 +01:00
Rodrigo Girão Serrão
e32cdbb390
Merge pull request #2276 from Textualize/tabs-scroll-to-center
Scroll to center when tab is clicked.
2023-04-13 10:48:15 +01:00
Rodrigo Girão Serrão
5104cbe501 changelog 2023-04-12 22:28:48 +01:00
Rodrigo Girão Serrão
663b09736e Scroll to center when tab is clicked.
Related comment: https://github.com/Textualize/textual/issues/2256#issuecomment-1505551728
2023-04-12 22:25:37 +01:00
Will McGugan
c249548c43
Move responsibility for writing in to driver (#2273)
* Move responsibility for writing in to driver

* remove driver property

* optimization for segments

* force terminal

* Update src/textual/drivers/_writer_thread.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* no safe box

* safe box false

* force null file

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-12 17:10:21 +01:00
darrenburns
6369c37907
Ensure styles applied in correct order in DataTable (#2272)
* Ensure styles applied in correct order in DataTable

* Add snapshot regression test for datatable style ordering

* Update CHANGELOG
2023-04-12 14:45:24 +01:00
Will McGugan
03fa641be7
Simplify driver (#2252)
* Simplify driver

* remove debug flag

* added set_terminal_size to driver

* restore flush

* Restore debug mode

* docstring

* fix parser

* simplify windows driver

* driver update

* annotations

* docstrings
2023-04-12 13:44:22 +01:00
Will McGugan
71becfc090 make Timer.start private 2023-04-12 13:42:57 +01:00
Will McGugan
2aa59f1ff0 changelog 2023-04-12 12:12:47 +01:00
Will McGugan
3c1898edeb don't return task 2023-04-12 12:08:22 +01:00
Will McGugan
f239bc1aa4 docstring 2023-04-12 12:05:24 +01:00
Will McGugan
2852c41597 exception docstring 2023-04-12 11:55:16 +01:00
Will McGugan
f81d76fcf0 docs 2023-04-12 11:43:36 +01:00
Will McGugan
7c25402c5d comment 2023-04-12 11:37:47 +01:00
Will McGugan
4ef070df66 docs 2023-04-12 11:22:19 +01:00
darrenburns
2bfe7df524
Add docstring to action_check_bindings (#2266)
* Add docstring to action_check_bindings

* Use action docstring convention
2023-04-12 11:16:59 +01:00
darrenburns
f95e30870b
Tabbed content activated message (#2260)
* Add a message for the tabbed content activated

* Add a docstring

* Testing tabbed content activated message

* Update changelog

* Add reference to the docs about TabbedContent.TabActivated
2023-04-12 10:55:14 +01:00
darrenburns
6352ceb61b
Datatable remove row (#2253)
* Checking in remove_row progress

* Ensuring structures updated correctly when row deleted

* Clamping index

* Failed attempt

* Removing rows

* Update a type hint in DataTable

* Remove some code that wasnt required

* Use index syntax instead of get

* Add DataTable remove row test

* Snapshot tests for removing rows

* Add a docstring for DataTable.remove_row method

* Update changelog regarding DataTable.remove_row

* Add check_idle call to remove_row
2023-04-11 18:48:58 +01:00
Will McGugan
13939499d9
implement single line comments (#2248) 2023-04-11 15:21:41 +01:00
Rodrigo Girão Serrão
48e8b510ba
Merge pull request #2255 from Textualize/scroll_to_center
Add scroll_to_center method.
2023-04-11 15:20:38 +01:00
Rodrigo Girão Serrão
349f414dac Use Offset operators. 2023-04-11 14:51:59 +01:00
Rodrigo Girão Serrão
8fe9e97fd7 Restore deleted snapshot tests. 2023-04-11 14:23:45 +01:00
Rodrigo Girão Serrão
2588cfdb0d Update snapshot test. 2023-04-11 13:39:24 +01:00
Rodrigo Girão Serrão
454254fab4 Implement scroll_to_center method. 2023-04-11 13:36:34 +01:00
Rodrigo Girão Serrão
e87edd79cb Add test for scroll_to_center method. 2023-04-11 13:29:56 +01:00
Will McGugan
3c8f2ec4e9 map geometry 2023-04-10 21:57:20 +01:00
Will McGugan
af93a82fb1 fix byte example 2023-04-10 17:25:13 +01:00
Will McGugan
3d642e1c71 comments, made update_timer private 2023-04-10 17:10:04 +01:00
Will McGugan
4f7b2d00bc
fix arrangement cache (#2249)
* fix arrangement cache

* changelog
2023-04-10 16:50:34 +01:00
darrenburns
40cc2db3b9
Fix for viewport units, remove DataTable max-height (#2247)
* Add viewport units snapshot test

* Fix snapshot app

* Update snapshots

* Update DataTable max-height to 100%

* Update CHANGELOG.md

* Remove max height from DataTable CSS
2023-04-10 16:13:48 +01:00
Will McGugan
b8468fff98 docstrings 2023-04-10 11:03:24 +01:00
Will McGugan
bd6ec2be48 widget API docs 2023-04-10 09:50:52 +01:00
Will McGugan
9a1e645ccd docstring 2023-04-09 20:23:14 +01:00
Will McGugan
5f7a0beba4 docstrings 2023-04-09 20:20:38 +01:00
Will McGugan
a729ee644c docstring and private 2023-04-09 20:13:53 +01:00
Will McGugan
02452c36bd link actions 2023-04-09 19:04:08 +01:00
Will McGugan
aceee9ff72 docstring 2023-04-09 18:59:36 +01:00
Will McGugan
a4b0c469ba docstrings 2023-04-09 18:39:29 +01:00
Will McGugan
c9de67f7df docstrings, remove unused Color._rich__ 2023-04-09 18:07:42 +01:00
Will McGugan
5fe69b05aa more doc strings 2023-04-09 15:09:20 +01:00
Will McGugan
9d4fd44a3a docstrings 2023-04-09 14:46:05 +01:00
Will McGugan
d7781d1da1 fix doc 2023-04-08 17:51:21 +01:00
Will McGugan
ab74735d14 docstring fix 2023-04-08 15:41:32 +01:00
Will McGugan
2244b1161e
api docs (#2240)
* api docs

* more docstrings

* logs

* docs shakeup

* fix notes, added intro to all apis

* Remove defaults to

* add note to events

* note

* use fira code
2023-04-08 15:35:49 +01:00
Will McGugan
5726a20e8e docstrings 2023-04-07 21:08:08 +01:00
Will McGugan
6c958a1140
docs update (#2239)
* docs update

* class template

* no annotations in sig
2023-04-07 18:57:56 +01:00
Will McGugan
79ebbff933 typo 2023-04-07 12:58:58 +01:00
Will McGugan
074bfd7e2f Headings 2023-04-07 11:56:00 +01:00
Will McGugan
94279ae1f9 docs fix 2023-04-07 11:35:59 +01:00
Will McGugan
c4774155ab changelog 2023-04-07 11:30:15 +01:00
Will McGugan
e9ec627629
version bump (#2236) 2023-04-07 09:52:21 +01:00
Will McGugan
e4b45ba63f
docs on await mount (#2235) 2023-04-07 09:46:27 +01:00
Will McGugan
c3424b0224
CHop fix (#2227) 2023-04-07 08:44:52 +01:00
darrenburns
976bd2f5c2
Move DataTable cursor with page up/down, home, end (#2228)
* Add pageup and pagedown actions to DataTable, with no impls

* Pagedown moves DataTable cursor now

* Account for header height in pagedown action

* Page Up support in the DataTable

* Fix and off-by-1, ensure page up/down works on col cursor

* Add placeholder scroll home/end action handlers to datatable

* Add scroll home and scroll end

* Hide hover cursor when home or end is used

* Ensure home and end work correctly with all curosrs

* Testing home/end/pagedown/pageup cursor movement in DataTable

* Docstrings for new datatable actions

* Fix a broken unit test for the DataTable
2023-04-06 21:22:31 +01:00
Will McGugan
c3e56f1f19 changelog 2023-04-06 21:18:59 +01:00
Will McGugan
4e88bb9b62
flush on exit (#2231) 2023-04-06 21:17:34 +01:00
Will McGugan
2969abf241
optimize horizontal and vertical (#2234)
* optimize horizontal and vertical

* generator to list expressions

* micro op

* another micro-optimization
2023-04-06 21:05:51 +01:00
Will McGugan
44367a7422
Expanding fr (#2221)
* forced fr to expand

* margin size

* remove comment

* missing snapshot

* snapshot tests

* changelog

* optimize

* snapshot fix

* snapshot update

* snapshot and fixes

* docstrings [skip ci]
2023-04-06 17:30:32 +01:00
Jackomatrus
c76667be5f
Fixed a wrong reference (#2226)
The new line referred to in line 177 was added to the StopwatchApp class, not the Stopwatch class.
2023-04-06 11:14:30 +01:00
Will McGugan
5c514b0dab
scroll visible snapshot (#2225)
* scroll visible snapshot

* change text of test
2023-04-06 11:13:09 +01:00
Will McGugan
eadd487584 fix scroll issue 2023-04-06 10:29:50 +01:00
Dave Pearson
a7c0a792cf
Merge pull request #2215 from davep/dirtree-filter 2023-04-05 21:47:56 +01:00
Dave Pearson
688b87b6d1
Update the CHANGELOG 2023-04-05 20:50:16 +01:00
Dave Pearson
7477624507
Merge branch 'main' into dirtree-filter 2023-04-05 20:48:36 +01:00
Dave Pearson
23263c45f1
Document the filtering support of DirectoryTree 2023-04-05 20:47:35 +01:00
Dave Pearson
5c2c5d50b6
Remove hangover argument documentation from initial experiment 2023-04-05 10:13:58 +01:00
Dave Pearson
5f31ecc607
Wee tidy of some docstrings in _markdown.py (#2217) 2023-04-05 10:11:41 +01:00
Alex
f3f065d147
docs: Fix some typo (#2216) 2023-04-05 10:11:27 +01:00
Will McGugan
41af489648
title descriptors (#2213)
* title descriptors

* add extra line around titles

* changelog

* snapshots

* comment

* Fix border refresh

* simplify typing

* test for None case
2023-04-05 10:10:43 +01:00
Dave Pearson
b365e1504b
Swap the directory tree filtering to method-based
This lets developers subclass DirectoryTree and implement their own filter.
2023-04-05 10:08:46 +01:00
Dave Pearson
d93f5c32cc
Keep black happy
Somehow I'd lost my pre-commit hooks.
2023-04-04 22:17:23 +01:00
Dave Pearson
f149828693
Add optional support for filtering path entries to DirectoryTree 2023-04-04 21:40:49 +01:00
Will McGugan
c2f7004fbb changelog 2023-04-04 15:57:55 +01:00
Will McGugan
380114489d docs fix 2023-04-04 15:43:10 +01:00
Will McGugan
b5689b1f69
Worker API (#2182)
* worker class

* worker API tests

* tidy

* Decorator and more tests

* type fix

* error order

* more tests

* remove active message

* move worker manager to app

* cancel nodes

* typing fix

* revert change

* typing fixes and cleanup

* revert typing

* test fix

* cancel group

* Added test for worker

* comment

* workers docs

* Added exit_on_error

* changelog

* svg

* refactor test

* remove debug tweaks

* docstrings

* worker test

* fix typing in run

* fix 3.7 tests

* blog post

* fix deadlock test

* words

* words

* words

* workers docs

* blog post

* Apply suggestions from code review

Co-authored-by: Dave Pearson <davep@davep.org>

* docstring

* fix and docstring

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/widgets/_markdown.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/worker.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Fix black

* docstring

* merge

* changelog

---------

Co-authored-by: Dave Pearson <davep@davep.org>
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-04-04 13:12:51 +01:00
Rodrigo Girão Serrão
c1ef3702fd
Fix border rendering issue. (#2212) 2023-04-04 11:04:14 +01:00
Dave Pearson
c527d168aa
Merge pull request #2205 from davep/bug/2203/radioset
Rework `RadioSet` so it no longer leans on the DOM for state
2023-04-04 09:40:04 +01:00
Rodrigo Girão Serrão
34b926ed3b
Update docstring for visible (#2211)
As per the confusion in #2208
2023-04-04 09:38:36 +01:00
Dave Pearson
c74aaa4112
Add rich.repr.auto to the Changed message 2023-04-03 21:41:48 +01:00
Dave Pearson
52af6064ba
Update the RadioSet tests to not dive into _buttons
It doesn't exist any more.
2023-04-03 21:10:37 +01:00
Dave Pearson
236ceccd30
Do away with _buttons 2023-04-03 20:56:56 +01:00
Dave Pearson
4b23539bee
Merge pull request #2174 from davep/cmd-faqtory 2023-04-03 16:58:42 +01:00
Dave Pearson
3d1d6b1d98
Update the ChangeLog 2023-04-03 11:54:48 +01:00
Dave Pearson
a8beacccc0
Rework RadioSet so that it doesn't lean so heavily on the DOM
Stemming from #2202 and implementing the solution decided in #2203. Pretty
much this change removes all the state change/handling being done on the DOM
and keeps the state internally.
2023-04-03 11:51:28 +01:00
Dave Pearson
815ff86c1f
Merge pull request #2197 from davep/doc-tidy 2023-04-02 15:40:17 +01:00
Dave Pearson
7c1584a812
Remove type information from property docstrings 2023-04-02 10:45:10 +01:00
Dave Pearson
fb56a89862
Remove type information from a property docstring 2023-04-02 10:43:06 +01:00
Will McGugan
eab073e603
Layer scroll fix (#2196)
* fix scroll spacing

* fix and snapshot

* changelog
2023-04-02 09:56:50 +01:00
Will McGugan
e4d158d041 docstring 2023-04-02 08:54:40 +01:00
Will McGugan
eb4c7ef50f
Fix issue with modals (#2195)
* Fix issue with modals

* changelog

* fix binding on button

* binding tweak

* changelog

* snapshots

* version bump
2023-04-02 08:52:35 +01:00
Will McGugan
80d9681caf docstring 2023-04-02 08:47:33 +01:00
Will McGugan
fdb885233f version bump 2023-04-02 08:43:59 +01:00
Will McGugan
2ba48051e6 snapshots 2023-04-02 08:43:02 +01:00
Will McGugan
efa4e9a129 changelog 2023-04-01 18:51:07 +01:00
Will McGugan
11c3790eba binding tweak 2023-04-01 18:48:03 +01:00
Will McGugan
b48178b80d fix binding on button 2023-04-01 18:34:51 +01:00
Will McGugan
241d6c989d changelog 2023-04-01 18:25:39 +01:00
Will McGugan
8273f78c09 Fix issue with modals 2023-04-01 18:21:07 +01:00
Dave Pearson
0b8f044dd3
Remove possible Yorkshireism
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-30 16:56:40 +01:00
Dave Pearson
b5b4623427
Key availability FAQ redux 2023-03-30 15:30:54 +01:00
Dave Pearson
4fcf44c354
Merge pull request #2177 from davep/markdown-number-list
Auto-increment ordered lists within Markdown
2023-03-30 14:24:28 +01:00
Dave Pearson
19a0846068
Merge branch 'main' into markdown-number-list 2023-03-30 14:23:12 +01:00
Will McGugan
0750bc20ea
copy bindings (#2176)
* copy bindings

* changelog

* simplify
2023-03-30 13:53:48 +01:00
Dave Pearson
b9726bb2b1
Auto-increment ordered lists within Markdown
Addresses #2002.
2023-03-30 12:48:05 +01:00
Will McGugan
2094d6b18c titltes on tutorial 2023-03-30 12:15:09 +01:00
Will McGugan
e35a8ade16 fix svg css 2023-03-30 12:07:44 +01:00
Will McGugan
9a30cc2b4d improved error message 2023-03-30 12:05:07 +01:00
Will McGugan
5d1902de86 Better WatchCallbackType 2023-03-30 11:42:37 +01:00
Dave Pearson
01be13d7c6
Add a FAQ about some keys not making it to Textual apps 2023-03-30 11:27:50 +01:00
Dave Pearson
1a42b5024d
Add a Makefile target for building the FAQ
I always have to double-check. Now I can just "make faq".

Or at least I have somewhere else to double-check if I forget the Makefile
target.
2023-03-30 11:26:48 +01:00
Dave Pearson
0a9b9603a0
Extend OptionList testing (#2166)
* Add tests for errors when removing things that don't exist

* Add tests for errors when toggling enabled/disabled on invalid options
2023-03-30 11:20:17 +01:00
Will McGugan
87f96ef8a1
fix for hiding cursor on windows (#2171)
* fix for hiding cursor on windows

* fix freeze

* version bump
2023-03-30 11:04:04 +01:00
darrenburns
b0656fd606
Some docstrings for actions (#2172) 2023-03-30 10:18:19 +01:00
Will McGugan
2cd8295325
Release0170 (#2165)
* blog post

* blog post

* options list

* snapshot

* words

* fix flicker
2023-03-29 16:29:28 +01:00
Dave Pearson
0be094cf4a
Add OptionList widget (#2154)
* Menu skeleton

The vaguest of starts. Near the end of the day and I want to pick this up
later/tomorrow, so making sure it's on the forge before I go AFK.

* Initial design for populating the menu

One of the driving forces in the design here is that a menu option can have
a prompt that is more than one line in height; and different options can
have different height prompts. This has meant that I've had to finally get
to grips with Rich renderable types and related things.

The menu is going to lean heavily on the line API, and aims to be as
efficient as possible when it comes to having a very large menu. Large menus
are a bad idea! Nobody should be using large menus. On the other hand,
people will do it so let's allow for it.

Work in progress commit. Lots more to come.

* Add a reminder about width

* Make mypy and friend happy with OptionLineSpan.__contains__

* Fix typo

* Add a debug message

I'll remove this later, but I'd like to bubble up some debug stuff into my
own test app.

* Get scrolling working

After battling for ages to try and figure out why scrolling just wasn't
working at all, two things turned out to be at play:

1. If `overflow: hidden` you need force=True. Doh!
   - I should know that too as I added force. O_o
2. Even if you do the above, it doesn't work as you'd expect *if* animation
   is turned on. Turning that off made things work.

I've raised #2077 as a reminder to myself that I need to look into '2' some
more. The menus feel very snappy with animation off, but I suspect there
will be a call to allow animation during menu navigation so that'll need
sorting at some point I guess.

* Add support for home and end keys

Which, shockingly, go to the first and last items in the menu.

* Remind myself I need to remove the Debug message

Once I'm done with it.

* Make the MenuOption class a NamedTuple

There's no obvious benefit to it being a full class, but some benefits to it
being a NamedTuple.

* Add a Menu.OptionHighlighted message

* Add a missing argument to a docstring

* Fully type the option line segments list

I forgot to ensure that it was fully typed.

* Add a method for getting an option at a given position

* Better name for the location of the option

* Include the highlighted index in the OptionHighlighted message

* Add home and end to the binding docstring

* Add support for page up/down in a menu

* Rename OptionLineSegments to OptionLine

It's the details for a line of an option that hold the segments, amongst
other things. No point in repeating information here.

* Add support for a Menu.OptionSelected message

* Remove a TODO comment

It's not that it doesn't need doing yet; it's just that I've moved some TODO
stuff to a WIP document.

* Document the enter binding

* Add a reminder to myself about why animate is off

For a menu I feel that animate *should* be off, but if anyone is reading
this bit of code and feels it should be on, this will explain why it isn't.

* Explain OptionLineSpan a wee bit more

* Import Literal from typing_extensions rather than typing

This is needed for older Pythons.

* Move the prompt shapes calculation code into its own method

* Add a property for getting the option count of the menu

* Add a method of adding an option to the menu

* Highlight first option if no highlight and then movement

* Ensure the virtual height is recalculated on addition

* Remove the method for getting a specific option

There's little point in letting the user treat the menu as if it's an array;
they should know what they put into it and anything that happens *on* the
menu will result in a message which will point to the option anyway.

* Add a menu separator

This isn't the complete version of this; aside from the obvious fact that at
the moment it's just treated line an ordinary menu option (which we don't
want), the presence of a separator means the index of options will be thrown
off, from the user's point of view. The point being, a menu with 4 options
and a separator might look like this:

    Option 1
    Option 2
    --------
    Option 3
    Option 4

I think the index of "Option 3" above should likely be 2 (starting from 0,
of course), not 3. This means I need to tweak the internals of the menu code
to take this into account while also keeping things efficient.

That's next up; but I wanted to get the core of this change in first so I
can noodle away and get the best approach to this.

* Finish off support for menu separators

Here I sort of add support for a menu having both content *and* prompts.
Content is anything that goes in the menu and results in lines being
rendered. Prompts are things that the end user actually gets to select from.
A menu option will have a prompt that has one or more lines. A menu
separator isn't an option but takes up one line.

* Add (back) a method for getting a particular option

Now that the menu content and the menu options are different lists, it's
possible to allow this again. While it still follows that menus shouldn't
really be treated like lists, there's no harm in providing this facility.

* Allow styling separators

* Fix how we tell the Rule to have no style

* Add a documentation line for the separator component class

* Apply default styling to the non-special options

* Set the default color to $text

This isn't actually working, but if I set it to an actual colour, it does
work. Need to dig into this more.

* Remove a TODO warning that isn't valid any more

* Have the menu option messages get the option via Menu.option

It did, and still could, pull directly from the _option property but one
step of indirection means that I can be sure anything "external" is going
via the public interface (yes, I know the message isn't really "external"
but it feels correct to treat it as such because it's for public
consumption).

* Make OptionLine just a Line and drop magic numbers for separators

Rather than overload the option index of the option line class with a magic
number to say that something isn't really an option, here I make the class
just about being a line, I keep the option_index but make it optional (no
pun intended); so that if it's `None` that means "this isn't related to a
menu option".

* Drop the assert that non-option content is a separator

I can't see much benefit in doing this in what should be a fairly tight
loop. This code relates to data that's all under the hood so we shouldn't
need to be quite so defensive.

* Remove unused import of Final

* Add a clear method

* Add support for disabled menu options

At the moment this is done in a way that, as the user navigates, the
disabled options *aren't* skipped. I'm still undecided about this. Your
traditional dropdown menus sometimes do that, sometimes don't do that. And
to make things even more interesting this menu can really be used as a
large-data-friendly listbox and I'm not sure we'd want that there.

This may change.

Also, at this point, I'm also working to keep the MenuOption class a
NamedTuple, which means it's read-only (I don't want the user messing with
things outside of the menu), which means there's interface methods for
changing the disabled state that copy the option and change the disabled
state.

Again, I'll see if I carry on liking this or not. So far I'm okay with this.

* Dial in the styles some more

* Rename some methods that use index to say index in the name

I'm going to be adding support for an id for options too, and want the user
to be able to either access an option via index or via ID. This is the first
step to allowing that.

* Remove an unnecessary inherit

Looks like this was a hangover from an early version of the message classes
and I didn't clean up.

* Fix copy/paste-o

Now there is forever evidence as to where I stole my homework from.

* Add support for menu option IDs

The idea here is that they're purely from, and purely for, the developer who
is creating the menu. Internally I don't care about them and don't
personally use them. However, there is without a doubt a good case for
allowing the developer to specify IDs for options so here's optional support
for that.

* Add a method to get a menu option via an ID

* Reduce property access and list access calls

* Have the content-tracker code do a little less work

* Drop the menu option data attribute

It wasn't going to work well, was going to cause a bunch of problems with
typing, and really it's easier to do by the dev by having them inherit from
MenuOption. So let's do that.

* Remove unused imports

* Add a TODO reminder about subclasses menu optons

* Add an initial bit of unit testing

Just the most basic test so far; it's the end of the day but I want to start
here.

* Allow the caller to use None as an alias for MenuSeparator

In doing so, overhaul how I type candidate menu content vs actual menu
content, setting up a couple of type aliases and making it easier to
maintain.

* Rename the parameter for Menu.add to better match other changes

* Swap MenuOption over to being a standard class

It would have been nice to keep it as a named tuple, but I want the
developer to be able to subclass and add their own properties to the
option (think attaching some random data to a menu option). The problem is
you can't subclass a named tuple.

So... standard class it is, with some reasonably defensive work to
discourage the developer from changing the prompt and the ID on the fly.

For obvious reasons I need to let them change the disabled state on the fly,
and this is where things end up being a little iffy. The only way (right
now) the menu will refresh when the disabled state changes is if the
developer does so via one of the methods on Menu. If they go toggling the
state on the option itself and hope that the menu will reflect this... no,
that's not going to happen.

I *could* make it happen by somehow capturing a reference to the parent menu
inside the menu option, but then things get circular and I don't like that.

* Test using None as an alternative to MenuSeparator

* Flesh out the initial menu unit tests

* Add a module docstring to the core menu unit test

* Add some testing for using subclassed menu options

* Add a property for getting an iterator of the options

* Add unit tests for option enabled/disabled

* Rename Menu -> OptionList (and friends)

The great renaming! We sort of had decided this was coming, but kept going
back and forth on if we should, what it should be, etc. Decision made today.
While this is mostly everything you want from a menu, it is foundational
enough that it needs to really be something else so it's a list of options.
Options; in a list. An OptionList.

* Add a test for adding more items to an option list later on

* Remove the debug message

I think I'm at a stage where I don't need to use it any more.

* Start of OptionList movement tests

End of day commit; more to come.

* Update the pyi for the Menu -> OptionList rename

Missed this during the grand rename.

* Tidy up a test

* Export the DuplicateID exception

* Add a test for creating a duplicate ID

* Add some more OptionList movement tests

* Allow scrollbars by default

Until the great renaming, this code was all about being menus, which
normally don't have scrollbars, and so I made a point of not having them on.
Now that this code is more about it being a list of stuff, which can be the
foundation for a menu, we want the bars there by default and any derived
menu widget can turn them off.

So here we go.

This introduces some issues that now need to be addressed. For one thing no
thought has been given to horizontal scrolling in this code (easy enough to
solve).

Also, weirdly though, the vertical scrollbars aren't quite reaching the
bottom when we highlight the last item. Wasn't expecting that, although I'm
sure there's a simple cause for that.

* Remove hover component class

I do want this, but not yet, so don't have it kicking around until I'm
actually doing something with it.

* Add missing items to the component classes docstring.

* Crop the lines that we draw

This in turn adds support for horizontal scrolling. We're not actually going
to support horizontal scrolling; in conversation with Will we've decided
that it will be *only* a vertical scrolling list, so options will be
rendered within the confines of the width.

* Allow for scrollbars by default

* Make scrolling to a non-highlight a nop rather than an error

Being able to call scroll_to_highlight even if nothing is highlighted is
useful; throwing an error when something isn't, isn't helpful. So let's make
that a no-op.

* Make a note that option ID tracking could be changed

* Ensure highlight is pulled into view on resize

It's possible that a resize might cause a highlight to partially, or even
totally, go out of view. This commit ensures that after such an event this
will be handled.

* Save an attribute access

* Microoptimise _refresh_content_tracking some more

* Reintroduce animation

But only if the vertical scrollbar is visible (see #2077 for context).

* Force a refresh when doing a specific add

* Add support for a mouse hover effect

* Highlighted a clicked option (where appropriate)

* Improve the style of a focused highlighted hovered option

* Reduce the number of attribute lookups in the line drawing method

* Simplify the way we handle page up/down at the margins

Rather than wrap around when doing page up/down, have them work as home/end
when at the margins.

* Remove unnecessary import

* Add some more option list movement tests

* Add tests for moving around an empty list

* Remove the debug message (again)

* Test moving when there are items but no highlight

* Ensure the mouse over gets cleared on clear

* Remove mouse hover logging code

It was useful while adding mouse hover support, but it's not needed now.

* Force a refresh of content tracking when doing a clear

* Rename some methods to talk about options

I want to add a `remove` for options, but widgets already have a `remove`.
So I could call it `remove_option` but then that's an imbalance with `add`.
So this renames `add` to `add_option`, and also renames `clear` to
`clear_options`.

* Add support for removing an option

* Add highlight wrapping back

I made some recent changes to highlight validation where more sensible in
the general sense, but broke the wrapping when using cursor keys to move
around. This takes that into account.

* Add tests for removing options

* Reduce the number of attribute lookups for spans

* Swap to watching highlighted to handle movement

I'd started out with an explicit refresh of the highlighted option, while
working on other things, and forgot to swap over to using a watch method.
This commit fixes that.

* Make a mouse-clicked option select that option too

* Add unit tests for option list messages

* Add unit tests for mouse hover events

* Clarify the point of the mouse click test

* Add an option list message test for highlighting a disabled option

* Add tests for interacting with disabled OptionList options

* Typo fixing

Try and make the docstring sound something approaching English.

* Fix the OptionMessage.__init__ docstring

* Add the API documentation for the OptionList

* Update the OptionTest message tests for initial highlight

Having changed things around a little regarding initial highlight, the unit
tests needed updating.

* Start the reference for the OptionList

I feel this needs a bit more work, but this feels like the core of what we
want to be emphasising.

* Add the OptionList to the gallary

* Try some extra pauses in OptionList tests

While the tests are all passing just fine locally, I'm getting the whole
whack-a-mole thing in CI that is mostly down to subtle timing issues. This
is a test to see if these extra pauses let the test apps settle down before
starting the meat of the testing.

* Try pausing in tests without setting a time

* Add snapshot tests for the OptionList examples

* Sort the bindings

* Add a docstring to the default CSS

* Explain that mouse_hovering_over can be None

* Turn mouse_hovering_over into an internal property

There was a reason that I had it as a reactive, at one point, but looking at
the final form of this code I can't see a use for it any more. So bring it
internal and make it cheaper to update.

* Update the CHANGELOG

* Update the mouse hover test after the changes to the tracking variable

* Tweak the descriptions of the hover tests

Now that I've changed this away from being a reactive.

* Tweak the OptionList hover tests some more

* Rename the up/down actions to cursor_up/down

Re: https://github.com/Textualize/textual/pull/2154#discussion_r1151587080

* Don't kick off an idle check if the widget isn't running

Added at Will's suggestion. :-P

* Simplify how we watch the vertical scrollbar status

Re: https://github.com/Textualize/textual/pull/2154#discussion_r1151593625

* Change the hover highlight to $boost

Re: https://github.com/Textualize/textual/pull/2154#discussion_r1151628190

* Add a custom exception for when an option can't be found

Re:
74a2d079b3 (r1151632957)
and 74a2d079b3 (r1151631495)

* Update tests for the new option list exceptions

* Remove the options property

We've decided it has little utility given the rest of the interface of the
widget.

Re: https://github.com/Textualize/textual/pull/2154#discussion_r1151630437

* Remove import of iterator

It's no longer required.

* Fix some option list unit tests after removing options property

* Crate Line.segments as a strip

Rather than recreate the strip every time around, just create it as a Strip
to start with. Also, in doing so, add the option meta up front rather than
every time we draw the line.

Re: https://github.com/Textualize/textual/pull/2154#discussion_r1151600239

* Correct a comment typo

* Simplify the Separator docstring

* Docstring wording tweak

* Remove the import of Segment

It's not needed any more

* Flesh out the OptionList reference some more

Things like the component classes, bindings and messages had been left out.

* Update snapshot tests

Nothing of consequence has changed but it looked like the change to how the
lines are originally constructed has resulted in an under-the-hood change to
the data that goes into a snapshot.

* Add a missing word to a docstring

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Fix a typo

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Fix a typo

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Document some raises that were missing

* Turn off animation

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-29 14:27:56 +01:00
Will McGugan
a75b7cd088 verbosity doc paragraph 2023-03-29 10:22:38 +01:00
Dave Tapley
1dc24222ff
Document log groups and console -x (#2161) (#2162)
https://github.com/Textualize/textual/discussions/2161

Groups as of:
ab0de0139c/src/textual/_log.py (L4-L15)
2023-03-29 10:20:21 +01:00
Will McGugan
ab0de0139c
Update README.md
Move Discord button
2023-03-28 17:43:48 +01:00
Will McGugan
8596fbf4e8
Update README.md
Link Discord button
2023-03-28 17:43:22 +01:00
Will McGugan
3c60683aa8
Update README.md
Added Discord button
2023-03-28 17:40:47 +01:00
Will McGugan
45e944b65d
Update README.md
Added discord link
2023-03-28 17:24:39 +01:00
Rodrigo Girão Serrão
01899189d8
Merge pull request #2128 from Textualize/fix-2063
Fix issues with watching CSS reloading
2023-03-28 16:01:46 +01:00
Rodrigo Girão Serrão
a06b59f951
Merge branch 'main' into fix-2063 2023-03-28 15:49:07 +01:00
Will McGugan
eaca92bd37
Set classes (#2160)
* Setting classes

* changelog

* docstrings

* test bad identifiers

* Update CHANGELOG.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Add return of self

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-03-28 15:45:40 +01:00
Will McGugan
85a6f8343e change Any import 2023-03-28 15:29:33 +01:00
Will McGugan
b005c13956
remove arrangement spacing (#2157)
* remove arrangement spacing

* snapshot test

* comment

* changelog
2023-03-28 15:27:01 +01:00
Rodrigo Girão Serrão
b9c6aec2e6 Add clarifications. 2023-03-28 15:07:39 +01:00
Rodrigo Girão Serrão
3a6967341c Remove dead import. 2023-03-28 15:03:30 +01:00
Rodrigo Girão Serrão
e2a16b5696 Add snapshot test for hot reloading. 2023-03-28 15:01:51 +01:00
Rodrigo Girão Serrão
474d5bc784 Add mechanism to run arbitrary code before screenshot. 2023-03-28 14:59:43 +01:00
darrenburns
17c6f3fc2a
Fix for interaction between pseudoclasses and widget-level render caches (#2155)
* Using pseudoclass state in DataTable cache keys

* Use full pseudo-class state on tree cache key

* Adding tests for Widget.get_pseudo_class_state

* Test hiding hover cursor when mouse cursor leaves DataTable

* Update CHANGELOG.md
2023-03-28 14:26:24 +01:00
Will McGugan
73f065bbbd
Logging handler (#2151)
* logging handler

* changelog

* remove logging experiment

* handler

* fix

* docs for logging handler
2023-03-28 11:50:28 +01:00
Will McGugan
c7103faae4
Merge branch 'main' into fix-2063 2023-03-28 10:35:06 +01:00
Rodrigo Girão Serrão
d787f61090
State version of widget addition in docs. (#2144)
* State version of widget addition in docs.

Related issues: #2133

* Fix ListX version info.

* Retroactively update changelog.
2023-03-27 22:32:18 +01:00
Will McGugan
a69b863005
fix for active message pump (#2148)
* fix for active message pump

* Add log file

* changelog
2023-03-27 22:31:30 +01:00
Rodrigo Girão Serrão
977698c99d
Merge pull request #2145 from Textualize/drop-uvloop
Drop implicit uvloop support.
2023-03-27 18:45:25 +01:00
Rodrigo Girão Serrão
11971446de Drop implicit uvloop support.
Related issues: #2051.
2023-03-27 18:37:21 +01:00
Rodrigo Girão Serrão
054c2f34d6
Merge pull request #2142 from Textualize/update-border-docs
Update docs with new border type.
2023-03-27 17:42:42 +01:00
Rodrigo Girão Serrão
f6f80249ee Snapshot update. 2023-03-27 17:31:47 +01:00
Will McGugan
e8c40410ee
check full map first (#2143) 2023-03-27 17:31:11 +01:00
Rodrigo Girão Serrão
9fa7de13dc Update docs with new border type.
Related PRs: #2139.
Related comments: https://github.com/Textualize/textual/pull/2139\#discussion_r1149249378
2023-03-27 16:55:26 +01:00
Will McGugan
0940546aab
compositor refactor and transparent screens (#2139)
* compositor refactor and trasparent screens

* multuple layers

* catch screen stack error

* refinement

* error messages

* capture screen stack

* new border type

* Background screen

* borders and bindings

* snapshot

* screen docs

* fix for missing screens

* screens docs

* fix for non updating transparent screens

* fix background resize

* changelog

* copy

* superfluous function

* update diagram

* inline code

* Update CHANGELOG.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/guide/screens.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* superfluous file

* Explicit None

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* docstring

* update docstring

* docstring make property private

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* docstring

* update docstring

* Apply suggestions from code review

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* docstrings

* remove comment, add docstring

* Apply suggestions from code review

Co-authored-by: Dave Pearson <davep@davep.org>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
Co-authored-by: Dave Pearson <davep@davep.org>
2023-03-27 16:44:58 +01:00
Roy Attias
d0035b4d4b
examples: json_tree: Use public attributes (#2138) 2023-03-27 14:26:55 +01:00
darrenburns
5cbc9277da
Loosen importlib-metadata dependency specifier (#2140) 2023-03-27 11:14:45 +01:00
Will McGugan
844c6a006e fix post message 2023-03-24 21:33:40 +00:00
Will McGugan
32dc14e484
Fix scrollbar thumb (#2134)
* scrollbar tweak

* scrolbar rounding

* snapshot
2023-03-24 21:15:02 +00:00
Will McGugan
472b5cd946 snapshot test 2023-03-23 21:00:26 +00:00
Will McGugan
1e4dd1cee4 fix scrollbar thumb height 2023-03-23 20:59:44 +00:00
Will McGugan
11cf1f1d28
Fix map invalidation (#2129)
* Invalidation logic

* comment and docstring

* changelog

* snapshot
2023-03-23 18:36:46 +00:00
Rodrigo Girão Serrão
ac826e56bd Update changelog. 2023-03-23 17:39:42 +00:00
Rodrigo Girão Serrão
dce49cbefe Merge branch 'main' into fix-2063 2023-03-23 17:39:18 +00:00
Rodrigo Girão Serrão
676d93c80c Fix #2063.
Related issues: #2063. [skip ci]
2023-03-23 17:34:15 +00:00
Will McGugan
3fe04f7b2d
Text log scroll end (#2127)
* added switches

* snapshot

* changelog

* tweak docstrings

* Update src/textual/widgets/_text_log.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-23 17:21:13 +00:00
Rodrigo Girão Serrão
8fd3ccb32c
Add tests for action parsing. (#2112)
* Add tests for action parsing.

[skip ci]

* Fix action parsing issues.

Related issues: #2088.

* Simplify action parsing.

Turns out that we can just wrap the string that we want to parse as the arguments in '({string_here},)', as per @willmcgugan's comment in the PR review.

Related review comments: https://github.com/Textualize/textual/pull/2112\#issuecomment-1481015988

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-03-23 15:54:06 +00:00
Will McGugan
a4252a5760
auto table (#2123)
* auto table

* ws

* debug
2023-03-23 15:47:14 +00:00
Rodrigo Girão Serrão
700481129e
Merge pull request #2124 from Textualize/rodrigogiraoserrao-patch-1
Update CHANGELOG.md
2023-03-23 15:44:01 +00:00
Rodrigo Girão Serrão
8708f7b8bb
Update CHANGELOG.md 2023-03-23 15:01:50 +00:00
Rodrigo Girão Serrão
139896260b
Merge pull request #2102 from Textualize/verb-methods-return-self
Return 'self' in some widget verb methods.
2023-03-23 15:00:18 +00:00
Will McGugan
461db5dcd6
enable console markup (#2122)
* enable console markup

* changelog

* snapshot
2023-03-23 14:56:35 +00:00
Will McGugan
5a00dcdeff comment in diagnose 2023-03-23 13:34:23 +00:00
Rodrigo Girão Serrão
b3e6f7a9a6
Merge pull request #2119 from Textualize/fix-2107
Use consistent phrasing in styles reference
2023-03-23 12:05:12 +00:00
Rodrigo Girão Serrão
48d0547d86 Merge branch 'main' into fix-2107 2023-03-23 11:04:21 +00:00
Rodrigo Girão Serrão
559f976f78 Add more consistent phrasing.
Related issues: #2107
2023-03-23 11:04:17 +00:00
Rodrigo Girão Serrão
65e005cffe Return 'self' explicitly.
Related review comment: https://github.com/Textualize/textual/pull/2102\#pullrequestreview-1354201387
2023-03-23 10:07:33 +00:00
Rodrigo Girão Serrão
e15805b93b
Fix #1540. (#2097) 2023-03-23 09:38:50 +00:00
Rodrigo Girão Serrão
7316b5b6b0
Merge pull request #2113 from Textualize/fix-border-example
Improve subsection titles.
2023-03-23 09:13:51 +00:00
Rodrigo Girão Serrão
f9922ebe29 Improve subsection titles.
Related issues: #2108
Related PRs: #2110, #2064
2023-03-22 23:00:13 +00:00
Rodrigo Girão Serrão
a935a632fa
Merge pull request #2110 from Textualize/fix-2108
Fix missing border example.
2023-03-22 22:48:37 +00:00
Rodrigo Girão Serrão
9c672e69f0 Fix missing border example.
Related issues: #2108
Related PRs: #2064
2023-03-22 21:05:10 +00:00
Will McGugan
e758514ff3 word 2023-03-22 13:52:31 +00:00
Will McGugan
9529cac352
Version 0.16.0 (#2106)
* snapshot

* words

* word update
2023-03-22 13:38:23 +00:00
Rodrigo Girão Serrão
2a810f8c87
Implement border (sub)title. (#2064)
* Add Widget.border_title and border_subtitle.

Related issues: #1864

* Test setting border_(sub)title.

* Add border (sub)title references to StylesCache.

These internal references will make it easier for the instance of 'StylesCache' to know which border (sub)title to use, if/when needed.

* Add method to render border label.

* Add styles to align border (sub)title.

* Render border labels.

* Update styles template.

* Make new 'render_row' parameters optional.

* Add (sub)title border snapshot tests.

* Document border (sub)title and styles.

* Pass (sub)title directly as arguments.

Get rid of the watchers to make data flow easier to follow.
Related comment: https://github.com/Textualize/textual/pull/2064/files\#r1137746697

* Tweak example.

* Fix render_border_label.

This was wrong because border labels can be composed of multiple segments if they contain multiple styles. Additionally, we want to render a single blank space of padding around the title.

* Ensure we get no label when there's no space.

* Add tests for border label rendering.

* 'render_border_label' now returns iterable of segments.

* Add label to render_row.

* Fix calling signature in tests.

* Add padding to snapshot tests.

* Fix changelog.

* Update snapshot tests.

* Update snapshot tests.

* Border labels expand if there's no corners.

* Update CHANGELOG.md

* Fix docs.

* Remove irrelevant line.

* Fix snapshot tests.

* Don't share Console among tests.

* Simplify example in styles guide.

* Avoid expensive function call when possible.

* rewording

* positive branch first

* remove wasteful indirection

* fix changelog

---------

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
2023-03-22 11:07:38 +00:00
Rodrigo Girão Serrão
b4c2afe789 Remove fat-finger deletion. 2023-03-22 09:53:54 +00:00
Rodrigo Girão Serrão
d32694f176 Update docstrings. 2023-03-22 09:39:40 +00:00
Rodrigo Girão Serrão
16bdcf8f1d Return 'self' in some widget verb methods.
I compiled a list of all widget methods that return 'None' and for which it _could_ make sense to make this change.
(I filtered out some methods, like watch and action methods.)

I tried choosing a subset of those methods, trying to only pick methods for which there weren't two things that could be returned (e.g., 'Widget.move_child' _could_ return either the widget or the child that was moved) and I also tried to only pick methods that have little or no parameters (e.g., 'Widget.animate' has many parameters and is typically called with quite a few.

These are all the 'Widget' methods for which this could make sense:
- 'move_child' (either return 'self' or the actual 'child' that was moved…)
- 'animate'
- 'scroll_to' / 'scroll_relate' / 'scroll_home' / 'scroll_end' / 'scroll_left' / 'scroll_right' / 'scroll_down' / 'scroll_up' / 'scroll_page_up' / 'scroll_page_down' / 'scroll_page_left' / 'scroll_page_right' / 'scroll_visible'
- 'refresh'
- 'focus' / 'reset_focus'
- 'capture_mouse' / 'release_mouse'

Additionally, I looked at each widget, and found these methods:
- 'Tree'
    - 'TreeNode'
        - 'expand' / 'expand_all' / 'collapse' / 'collapse_all' / 'toggle' / 'toggle_all'
        - 'set_label'
    - 'clear' / 'reset'
    - 'select_node' (either return 'self' or the actual 'node' that was selected)
    - 'scroll_to_line' / 'scroll_to_node'
    - 'refresh_line'
- 'ToggleButton'
    - 'toggle' (and 'action_toggle'?)
- 'TextLog'
    - 'write'
    - 'clear'
- 'Tabs'
    - 'add_tab' / 'remove_tab'
    - 'clear'
- 'Switch'
    - 'toggle' (and 'action_toggle'?)
- 'Static'
    - 'update'
- 'Pretty'
    - 'update'
- 'Placeholder'
    - 'cycle_variant'
- '_markdown.py'
    - 'MarkdownBlock'
        - 'set_content'
    - 'MarkdownTableOfContents'
        - 'set_table_of_contents'
- 'Input'
    - 'insert_text_at_cursor'
- 'DirectoryTree'
    - 'load_directory'
- 'DataTable'
    - 'update_cell' / 'update_cell_at'
    - 'clear'
    - 'refresh_coordinate' / 'refresh_row' / 'refresh_column'
    - 'sort'
- 'Button'
    - 'press'

Related issues: #1908
Related discussions: #1817
2023-03-22 08:17:00 +00:00
Rodrigo Girão Serrão
29692736d0
Merge pull request #2095 from Textualize/fix-1438
Allow paths when creating 'DirectoryTree'.
2023-03-21 14:35:28 +00:00
Rodrigo Girão Serrão
f92c939511 Rename variable. 2023-03-21 14:27:03 +00:00
Rodrigo Girão Serrão
2d70172b8e Allow paths when creating 'DirectoryTree'.
Related issues: #1438.
2023-03-21 14:18:49 +00:00
Will McGugan
5cd1263875
Simplify driver (#2091)
* simplify driver

* fix headless driver

* docstrings and simplify

* tidy

* docstrings

* docstring

* docstring

* more docstrings

* import

* Update src/textual/app.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/driver.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* docstring

* Update src/textual/drivers/linux_driver.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/drivers/linux_driver.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update src/textual/drivers/linux_driver.py

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* docstring

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-21 10:17:51 +00:00
Will McGugan
a08d8e417b
full map optimization fix (#2092) 2023-03-20 15:30:52 +00:00
Will McGugan
7185e2930d
Driver class environ (#2036)
* Driver class environment variable

* comments
2023-03-20 11:21:56 +00:00
Will McGugan
2a6368754a fix screenshot 2023-03-18 17:02:46 +00:00
Will McGugan
50f4bd5f46 remove fonts 2023-03-18 16:47:51 +00:00
Will McGugan
8fca0852d4
fix for scrollbar issue (#2086)
* fix for scrollbar issue

* pause between mouse messages
2023-03-18 13:55:24 +00:00
d999c69261
Allow customizing the markdown parser (#2075)
* Allow customizing the markdown parser

For instance, code using Markdown might wish to create a markdown
parser that does not parse embedded HTML:
```py
def parser_factory():
    parser = MarkdownIt("gfm-like")
    parser.options["html"] = False
    return parser
```

* blacken

* Implement requested changes

* fix AttributeError
2023-03-18 11:19:05 +00:00
Will McGugan
f5e779c4c4
tabbed content widget (#2059)
* tabbed content widget

* TabbedContent widget and docs

* missing docs

* fix active

* doc fix

* test fix

* additional test

* test for render_str

* docstring

* changelog

* doc update

* changelog

* fix bad optimization

* Update docs/widgets/tabbed_content.md

Co-authored-by: Dave Pearson <davep@davep.org>

* fix for empty initial

* docstrings

* Update src/textual/widgets/_content_switcher.py

Co-authored-by: Dave Pearson <davep@davep.org>

* docstring

* remove log

* permit nested tabs

* renamed TabsCleared to Cleared

* added tests, fix types on click

* tests

* fix broken test

* fix for nested tabs

---------

Co-authored-by: Dave Pearson <davep@davep.org>
2023-03-18 10:38:41 +00:00
Will McGugan
2c120c0983
Replace markdown table (#2055)
* Replace markdown table

* snapshots

* fix markdown snapshot

* snapshot update

* imports and docstrings

* remove reference to DataTable

* typing fix
2023-03-18 10:38:26 +00:00
Will McGugan
45520f2da1
color tests to 100% (#2078)
* color tests to 100%

* tweak

* remove overly complex code
2023-03-16 11:42:51 +00:00
Will McGugan
de692aaf07
fix for remove nodes (#2080)
* fix for remove nodes

* added test
2023-03-16 11:36:10 +00:00
Will McGugan
a404ee5e01
add app to active message pump (#2071)
* add app to active message pump

* made sender private

* changelog
2023-03-16 11:26:08 +00:00
Will McGugan
43253f5d80
fix border issue (#2074)
* fix border issue

* add PR to changelog
2023-03-16 09:03:02 +00:00
Will McGugan
9b191914cb copy change 2023-03-15 20:28:02 +00:00
TomJGooding
111233f1b4
fix(markdown): handle hard line breaks (#2060) 2023-03-15 20:24:15 +00:00
Will McGugan
04340bd0ba
new post (#2069)
* new post

* Update docs/blog/posts/await-me-maybe.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/blog/posts/await-me-maybe.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* Update docs/blog/posts/await-me-maybe.md

Co-authored-by: Dave Pearson <davep@davep.org>

* Update docs/blog/posts/await-me-maybe.md

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>

* words

---------

Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
Co-authored-by: Dave Pearson <davep@davep.org>
2023-03-15 16:49:12 +00:00
Will McGugan
8d17ad39fd copy edit 2023-03-15 16:39:05 +00:00
Will McGugan
c889b4bfe9 words 2023-03-15 16:35:18 +00:00
Will McGugan
d64e9a7e67
Update docs/blog/posts/await-me-maybe.md
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-15 16:15:47 +00:00
Will McGugan
66535e9c07
Update docs/blog/posts/await-me-maybe.md
Co-authored-by: Dave Pearson <davep@davep.org>
2023-03-15 16:01:11 +00:00
Will McGugan
01045e6b7f
Update docs/blog/posts/await-me-maybe.md
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-15 16:00:55 +00:00
Will McGugan
dab39c719b
Update docs/blog/posts/await-me-maybe.md
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-15 15:51:30 +00:00
Will McGugan
31be9e059e new post 2023-03-15 15:34:39 +00:00
Rodrigo Girão Serrão
1246934643
Merge pull request #2030 from Textualize/add-containers
Add containers
2023-03-15 10:37:01 +00:00
Rodrigo Girão Serrão
10a5d171eb
Get rid of _Clock and move utility time-related functions to _time.py. (#2042)
* Remove _clock.py::sleep.

* Move _clock.py::get_time_no_wait to _time.py.

* Move _clock.py::get_time to _time.py.

* Remove async version of _time.py::get_time.

We started by removing '_time.py::get_time' because that was the async one and then I renamed 'get_time_no_wait' to 'get_time'.

* Make 'get_time' just an alias.
2023-03-15 08:56:10 +00:00
Rodrigo Girão Serrão
285de4b0fa Merge branch 'main' into add-containers 2023-03-14 14:35:23 +00:00
Rodrigo Girão Serrão
d775a90fa2 Address review comments. 2023-03-14 14:33:10 +00:00
Rodrigo Girão Serrão
f9a1e27c6f Merge branch 'main' into add-containers
[skip ci]
2023-03-13 16:21:46 +00:00
Rodrigo Girão Serrão
3518d38d85 Update snapshot tests. 2023-03-13 12:02:36 +00:00
Rodrigo Girão Serrão
cc8f65259e Merge branch 'main' into add-containers 2023-03-13 12:00:08 +00:00
Rodrigo Girão Serrão
429c8a3649 Tweak default Center/Middle dimensions.
We set dimensions to 1fr instead of 100% (original request) or blank (previous change) for consistency with the other containers.
2023-03-13 11:48:49 +00:00
Rodrigo Girão Serrão
0e51520a2c Make docs comply with new containers. 2023-03-13 11:44:47 +00:00
Rodrigo Girão Serrão
48ce1a149d Add snapshot test for Center/Middle. 2023-03-13 11:18:33 +00:00
Rodrigo Girão Serrão
bdeea9fb86 Tweak Center/Middle default dimensions. 2023-03-13 11:10:50 +00:00
Rodrigo Girão Serrão
c13308a360 Add tests for Horizontal/Vertical(Scroll) containers. 2023-03-09 17:39:05 +00:00
Rodrigo Girão Serrão
5674b4b628 Add 'Vertical'.
Related issues: #1957.
2023-03-09 15:38:31 +00:00
Rodrigo Girão Serrão
38c7cc1849 Fix default CSS for 'VerticalScroll'. 2023-03-09 15:36:38 +00:00
Rodrigo Girão Serrão
639d8f0250 Change default 'overflow' style for 'Horizontal'.
Related issues: #1957.
2023-03-09 15:30:44 +00:00
Rodrigo Girão Serrão
58ad5dfdd9 Tweak docstrings. 2023-03-09 15:26:51 +00:00
Rodrigo Girão Serrão
e111449856 Add container 'Middle'.
Related issues: #1957.
2023-03-09 15:24:13 +00:00
Rodrigo Girão Serrão
f91750ed3d Add container 'Center'.
This container will centre children horizontally.

Related issues: #1957.
2023-03-09 15:21:20 +00:00
Rodrigo Girão Serrão
be41797a8d Merge branch 'main' into add-containers 2023-03-09 15:19:43 +00:00
Rodrigo Girão Serrão
90dce06eae Add 'HorizontalScroll'.
Related issues: #1957.
2023-03-09 14:35:49 +00:00
Rodrigo Girão Serrão
4ca62eee60 Update docstring. 2023-03-09 12:21:53 +00:00
Rodrigo Girão Serrão
8565d3cef6 Renamed 'Vertical' to 'VerticalScroll'.
Related issues: #1957.
2023-03-08 18:31:24 +00:00
1080 changed files with 79522 additions and 13505 deletions

View file

@ -8,3 +8,4 @@ exclude_lines =
if __name__ == "__main__":
@overload
__rich_repr__
@abstractmethod

7
.deepsource.toml Normal file
View file

@ -0,0 +1,7 @@
version = 1
[[analyzers]]
name = "python"
[analyzers.meta]
runtime_version = "3.x.x"

View file

@ -1,12 +1,17 @@
---
hide:
- navigation
---
<!-- Auto-generated by FAQtory -->
<!-- Do not edit by hand! -->
# Frequently Asked Questions
{%- for question in questions %}
- [{{ question.title }}](#{{ question.slug }})
{%- endfor %}
Welcome to the Textual FAQ.
Here we try and answer any question that comes up frequently.
If you can't find what you are looking for here, see our other [help](./help.md) channels.
{%- for question in questions %}
@ -15,8 +20,8 @@
{{ question.body }}
---
{%- endfor %}
<hr>
Generated by [FAQtory](https://github.com/willmcgugan/faqtory)

22
.github/workflows/black_format.yml vendored Normal file
View file

@ -0,0 +1,22 @@
name: Black format check
on:
pull_request:
paths:
- '.github/workflows/black_format.yml'
- '**.py'
jobs:
black-format-check:
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@v3.5.2
- name: Set up Python 3.11
uses: actions/setup-python@v4.6.0
with:
python-version: 3.11
- name: Install black
run: python -m pip install black
- name: Run black
run: black --check src

73
.github/workflows/codeql.yml vendored Normal file
View file

@ -0,0 +1,73 @@
name: "CodeQL"
on:
push:
branches: [ 'main' ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ 'main' ]
paths:
- '.github/workflows/codeql.yml'
- '**.py'
- '**.pyi'
- '**.lock'
- '**.js'
- '**.ts'
schedule:
- cron: '10 20 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

View file

@ -1,7 +1,8 @@
name: issues
name: Closed issue comment
on:
issues:
types: [closed]
jobs:
add-comment:
runs-on: ubuntu-latest
@ -14,5 +15,5 @@ jobs:
issue-number: ${{ github.event.issue.number }}
body: |
Don't forget to [star](https://github.com/Textualize/textual) the repository!
Follow [@textualizeio](https://twitter.com/textualizeio) for Textual updates.

View file

@ -1,7 +1,8 @@
name: issues
name: FAQ issue comment
on:
issues:
types: [opened]
jobs:
add-comment:
if: ${{ !contains( 'willmcgugan,darrenburns,davep,rodrigogiraoserrao', github.actor ) }}

View file

@ -1,40 +1,51 @@
name: Test Textual module
on: [pull_request]
on:
pull_request:
paths:
- ".github/workflows/pythonpackage.yml"
- "**.py"
- "**.pyi"
- "**.css"
- "**.ambr"
- "**.lock"
- "Makefile"
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
os: [ubuntu-latest, windows-latest]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3.5.2
- name: Install and configure Poetry # This could be cached, too...
uses: snok/install-poetry@v1.3.3
with:
version: 1.4.2
virtualenvs-in-project: true
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4.7.1
with:
python-version: ${{ matrix.python-version }}
architecture: x64
- name: Install and configure Poetry
uses: snok/install-poetry@v1.3.3
allow-prereleases: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
version: 1.2.2
virtualenvs-in-project: true
path: .venv
key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
run: poetry install --extras "dev"
run: poetry install --extras syntax
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
- name: Format check with black
run: |
source $VENV
make format-check
# - name: Typecheck with mypy
# run: |
# source $VENV
# make typecheck
# - name: Typecheck with mypy
# run: |
# make typecheck
- name: Test with pytest
run: |
source $VENV
@ -44,4 +55,4 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: snapshot-report-textual
path: tests/snapshot_tests/output/snapshot_report.html
path: snapshot_report.html

4
.gitignore vendored
View file

@ -117,8 +117,8 @@ venv.bak/
# mypy
.mypy_cache/
# Snapshot testing report output directory
tests/snapshot_tests/output
# Snapshot testing report output (default location)
snapshot_report.html
# Sandbox folder - convenient place for us to develop small test apps without leaving the repo
sandbox/

View file

@ -4,10 +4,18 @@ repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
args: [ '--unsafe' ]
- id: check-ast # simply checks whether the files parse as valid python
- id: check-builtin-literals # requires literal syntax when initializing empty or zero python builtin types
- id: check-case-conflict # checks for files that would conflict in case-insensitive filesystems
- id: check-merge-conflict # checks for files that contain merge conflict strings
- id: check-json # checks json files for parseable syntax
- id: check-toml # checks toml files for parseable syntax
- id: check-yaml # checks yaml files for parseable syntax
args: [ '--unsafe' ] # Instead of loading the files, simply parse them for syntax.
- id: check-shebang-scripts-are-executable # ensures that (non-binary) files with a shebang are executable
- id: check-vcs-permalinks # ensures that links to vcs websites are permalinks
- id: end-of-file-fixer # ensures that a file is either empty, or ends with one newline
- id: mixed-line-ending # replaces or checks mixed line ending
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
@ -19,4 +27,10 @@ repos:
rev: 23.1.0
hooks:
- id: black
- repo: https://github.com/hadialqattan/pycln # removes unused imports
rev: v2.3.0
hooks:
- id: pycln
language_version: "3.11"
args: [--all]
exclude: ^tests/snapshot_tests

View file

@ -5,11 +5,828 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
### Fixed
- Duplicate CSS errors when parsing CSS from a screen https://github.com/Textualize/textual/issues/3581
- Added missing `blur` pseudo class https://github.com/Textualize/textual/issues/3439
- Fixed visual glitched characters on Windows due to Python limitation https://github.com/Textualize/textual/issues/2548
- Fixed outline not rendering correctly in some scenarios (e.g. on Button widgets) https://github.com/Textualize/textual/issues/3628
- Fixed live-reloading of screen CSS https://github.com/Textualize/textual/issues/3454
- `Select.value` could be in an invalid state https://github.com/Textualize/textual/issues/3612
- Off-by-one in CSS error reporting https://github.com/Textualize/textual/issues/3625
### Added
- Exceptions to `textual.widgets.select` https://github.com/Textualize/textual/pull/3614
- `InvalidSelectValueError` for when setting a `Select` to an invalid value
- `EmptySelectError` when creating/setting a `Select` to have no options when `allow_blank` is `False`
- `Select` methods https://github.com/Textualize/textual/pull/3614
- `clear`
- `is_blank`
- Constant `Select.BLANK` to flag an empty selection https://github.com/Textualize/textual/pull/3614
- Added `restrict`, `type`, `max_length`, and `valid_empty` to Input https://github.com/Textualize/textual/pull/3657
### Changed
- 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
- Breaking change: Setting `Select.value` to `None` no longer clears the selection (See `Select.BLANK` and `Select.clear`) https://github.com/Textualize/textual/pull/3614
## [0.41.0] - 2023-10-31
### Fixed
- Fixed `Input.cursor_blink` reactive not changing blink state after `Input` was mounted https://github.com/Textualize/textual/pull/3498
- Fixed `Tabs.active` attribute value not being re-assigned after removing a tab or clearing https://github.com/Textualize/textual/pull/3498
- Fixed `DirectoryTree` race-condition crash when changing path https://github.com/Textualize/textual/pull/3498
- Fixed issue with `LRUCache.discard` https://github.com/Textualize/textual/issues/3537
- Fixed `DataTable` not scrolling to rows that were just added https://github.com/Textualize/textual/pull/3552
- Fixed cache bug with `DataTable.update_cell` https://github.com/Textualize/textual/pull/3551
- Fixed CSS errors being repeated https://github.com/Textualize/textual/pull/3566
- Fix issue with chunky highlights on buttons https://github.com/Textualize/textual/pull/3571
- Fixed `OptionList` event leakage from `CommandPalette` to `App`.
- Fixed crash in `LoadingIndicator` https://github.com/Textualize/textual/pull/3498
- Fixed crash when `Tabs` appeared as a descendant of `TabbedContent` in the DOM https://github.com/Textualize/textual/pull/3602
- Fixed the command palette cancelling other workers https://github.com/Textualize/textual/issues/3615
### Added
- Add Document `get_index_from_location` / `get_location_from_index` https://github.com/Textualize/textual/pull/3410
- Add setter for `TextArea.text` https://github.com/Textualize/textual/discussions/3525
- Added `key` argument to the `DataTable.sort()` method, allowing the table to be sorted using a custom function (or other callable) https://github.com/Textualize/textual/pull/3090
- Added `initial` to all css rules, which restores default (i.e. value from DEFAULT_CSS) https://github.com/Textualize/textual/pull/3566
- 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
- Breaking change: `Input.blink_timer` made private (renamed to `Input._blink_timer`) https://github.com/Textualize/textual/pull/3498
- Breaking change: `Input.cursor_blink` reactive updated to not run on mount (now `init=False`) https://github.com/Textualize/textual/pull/3498
- Breaking change: `AwaitTabbedContent` class removed https://github.com/Textualize/textual/pull/3498
- Breaking change: `Tabs.remove_tab` now returns an `AwaitComplete` instead of an `AwaitRemove` https://github.com/Textualize/textual/pull/3498
- Breaking change: `Tabs.clear` now returns an `AwaitComplete` instead of an `AwaitRemove` https://github.com/Textualize/textual/pull/3498
- `TabbedContent.add_pane` now returns an `AwaitComplete` instead of an `AwaitTabbedContent` https://github.com/Textualize/textual/pull/3498
- `TabbedContent.remove_pane` now returns an `AwaitComplete` instead of an `AwaitTabbedContent` https://github.com/Textualize/textual/pull/3498
- `TabbedContent.clear_pane` now returns an `AwaitComplete` instead of an `AwaitTabbedContent` https://github.com/Textualize/textual/pull/3498
- `Tabs.add_tab` now returns an `AwaitComplete` instead of an `AwaitMount` https://github.com/Textualize/textual/pull/3498
- `DirectoryTree.reload` now returns an `AwaitComplete`, which may be awaited to ensure the node has finished being processed by the internal queue https://github.com/Textualize/textual/pull/3498
- `Tabs.remove_tab` now returns an `AwaitComplete`, which may be awaited to ensure the tab is unmounted and internal state is updated https://github.com/Textualize/textual/pull/3498
- `App.switch_mode` now returns an `AwaitMount`, which may be awaited to ensure the screen is mounted https://github.com/Textualize/textual/pull/3498
- Buttons will now display multiple lines, and have auto height https://github.com/Textualize/textual/pull/3539
- DataTable now has a max-height of 100vh rather than 100%, which doesn't work with auto
- Breaking change: empty rules now result in an error https://github.com/Textualize/textual/pull/3566
- Improved startup time by caching CSS parsing https://github.com/Textualize/textual/pull/3575
- Workers are now created/run in a thread-safe way https://github.com/Textualize/textual/pull/3586
## [0.40.0] - 2023-10-11
### Added
- Added `loading` reactive property to widgets https://github.com/Textualize/textual/pull/3509
## [0.39.0] - 2023-10-10
### Fixed
- `Pilot.click`/`Pilot.hover` can't use `Screen` as a selector https://github.com/Textualize/textual/issues/3395
- App exception when a `Tree` is initialized/mounted with `disabled=True` https://github.com/Textualize/textual/issues/3407
- Fixed `print` locations not being correctly reported in `textual console` https://github.com/Textualize/textual/issues/3237
- Fix location of IME and emoji popups https://github.com/Textualize/textual/pull/3408
- Fixed application freeze when pasting an emoji into an application on Windows https://github.com/Textualize/textual/issues/3178
- Fixed duplicate option ID handling in the `OptionList` https://github.com/Textualize/textual/issues/3455
- Fix crash when removing and updating DataTable cell at same time https://github.com/Textualize/textual/pull/3487
- Fixed fractional styles to allow integer values https://github.com/Textualize/textual/issues/3414
- Stop eating stdout/stderr in headless mode - print works again in tests https://github.com/Textualize/textual/pull/3486
### Added
- `OutOfBounds` exception to be raised by `Pilot` https://github.com/Textualize/textual/pull/3360
- `TextArea.cursor_screen_offset` property for getting the screen-relative position of the cursor https://github.com/Textualize/textual/pull/3408
- `Input.cursor_screen_offset` property for getting the screen-relative position of the cursor https://github.com/Textualize/textual/pull/3408
- Reactive `cell_padding` (and respective parameter) to define horizontal cell padding in data table columns https://github.com/Textualize/textual/issues/3435
- Added `Input.clear` method https://github.com/Textualize/textual/pull/3430
- Added `TextArea.SelectionChanged` and `TextArea.Changed` messages https://github.com/Textualize/textual/pull/3442
- Added `wait_for_dismiss` parameter to `App.push_screen` https://github.com/Textualize/textual/pull/3477
- Allow scrollbar-size to be set to 0 to achieve scrollable containers with no visible scrollbars https://github.com/Textualize/textual/pull/3488
### Changed
- Breaking change: tree-sitter and tree-sitter-languages dependencies moved to `syntax` extra https://github.com/Textualize/textual/pull/3398
- `Pilot.click`/`Pilot.hover` now raises `OutOfBounds` when clicking outside visible screen https://github.com/Textualize/textual/pull/3360
- `Pilot.click`/`Pilot.hover` now return a Boolean indicating whether the click/hover landed on the widget that matches the selector https://github.com/Textualize/textual/pull/3360
- Added a delay to when the `No Matches` message appears in the command palette, thus removing a flicker https://github.com/Textualize/textual/pull/3399
- Timer callbacks are now typed more loosely https://github.com/Textualize/textual/issues/3434
## [0.38.1] - 2023-09-21
### Fixed
- Hotfix - added missing highlight files in build distribution https://github.com/Textualize/textual/pull/3370
## [0.38.0] - 2023-09-21
### Added
- Added a TextArea https://github.com/Textualize/textual/pull/2931
- Added :dark and :light pseudo classes
### Fixed
- Fixed `DataTable` not updating component styles on hot-reloading https://github.com/Textualize/textual/issues/3312
### Changed
- Breaking change: CSS in DEFAULT_CSS is now automatically scoped to the widget (set SCOPED_CSS=False) to disable
- Breaking change: Changed `Markdown.goto_anchor` to return a boolean (if the anchor was found) instead of `None` https://github.com/Textualize/textual/pull/3334
## [0.37.1] - 2023-09-16
### Fixed
- Fixed the command palette crashing with a `TimeoutError` in any Python before 3.11 https://github.com/Textualize/textual/issues/3320
- Fixed `Input` event leakage from `CommandPalette` to `App`.
## [0.37.0] - 2023-09-15
### Added
- Added the command palette https://github.com/Textualize/textual/pull/3058
- `Input` is now validated when focus moves out of it https://github.com/Textualize/textual/pull/3193
- Attribute `Input.validate_on` (and `__init__` parameter of the same name) to customise when validation occurs https://github.com/Textualize/textual/pull/3193
- Screen-specific (sub-)title attributes https://github.com/Textualize/textual/pull/3199:
- `Screen.TITLE`
- `Screen.SUB_TITLE`
- `Screen.title`
- `Screen.sub_title`
- Properties `Header.screen_title` and `Header.screen_sub_title` https://github.com/Textualize/textual/pull/3199
- Added `DirectoryTree.DirectorySelected` message https://github.com/Textualize/textual/issues/3200
- Added `widgets.Collapsible` contributed by Sunyoung Yoo https://github.com/Textualize/textual/pull/2989
### Fixed
- Fixed a crash when removing an option from an `OptionList` while the mouse is hovering over the last option https://github.com/Textualize/textual/issues/3270
- Fixed a crash in `MarkdownViewer` when clicking on a link that contains an anchor https://github.com/Textualize/textual/issues/3094
- Fixed wrong message pump in pop_screen https://github.com/Textualize/textual/pull/3315
### Changed
- Widget.notify and App.notify are now thread-safe https://github.com/Textualize/textual/pull/3275
- Breaking change: Widget.notify and App.notify now return None https://github.com/Textualize/textual/pull/3275
- App.unnotify is now private (renamed to App._unnotify) https://github.com/Textualize/textual/pull/3275
- `Markdown.load` will now attempt to scroll to a related heading if an anchor is provided https://github.com/Textualize/textual/pull/3244
- `ProgressBar` explicitly supports being set back to its indeterminate state https://github.com/Textualize/textual/pull/3286
## [0.36.0] - 2023-09-05
### Added
- TCSS styles `layer` and `layers` can be strings https://github.com/Textualize/textual/pull/3169
- `App.return_code` for the app return code https://github.com/Textualize/textual/pull/3202
- Added `animate` switch to `Tree.scroll_to_line` and `Tree.scroll_to_node` https://github.com/Textualize/textual/pull/3210
- Added `Rule` widget https://github.com/Textualize/textual/pull/3209
- Added App.current_mode to get the current mode https://github.com/Textualize/textual/pull/3233
### Changed
- Reactive callbacks are now scheduled on the message pump of the reactable that is watching instead of the owner of reactive attribute https://github.com/Textualize/textual/pull/3065
- Callbacks scheduled with `call_next` will now have the same prevented messages as when the callback was scheduled https://github.com/Textualize/textual/pull/3065
- Added `cursor_type` to the `DataTable` constructor.
- Fixed `push_screen` not updating Screen.CSS styles https://github.com/Textualize/textual/issues/3217
- `DataTable.add_row` accepts `height=None` to automatically compute optimal height for a row https://github.com/Textualize/textual/pull/3213
### Fixed
- Fixed flicker when calling pop_screen multiple times https://github.com/Textualize/textual/issues/3126
- Fixed setting styles.layout not updating https://github.com/Textualize/textual/issues/3047
- Fixed flicker when scrolling tree up or down a line https://github.com/Textualize/textual/issues/3206
## [0.35.1]
### Fixed
- Fixed flash of 80x24 interface in textual-web
## [0.35.0]
### Added
- Ability to enable/disable tabs via the reactive `disabled` in tab panes https://github.com/Textualize/textual/pull/3152
- Textual-web driver support for Windows
### Fixed
- Could not hide/show/disable/enable tabs in nested `TabbedContent` https://github.com/Textualize/textual/pull/3150
## [0.34.0] - 2023-08-22
### Added
- Methods `TabbedContent.disable_tab` and `TabbedContent.enable_tab` https://github.com/Textualize/textual/pull/3112
- Methods `Tabs.disable` and `Tabs.enable` https://github.com/Textualize/textual/pull/3112
- Messages `Tab.Disabled`, `Tab.Enabled`, `Tabs.TabDisabled` and `Tabs.Enabled` https://github.com/Textualize/textual/pull/3112
- Methods `TabbedContent.hide_tab` and `TabbedContent.show_tab` https://github.com/Textualize/textual/pull/3112
- Methods `Tabs.hide` and `Tabs.show` https://github.com/Textualize/textual/pull/3112
- Messages `Tabs.TabHidden` and `Tabs.TabShown` https://github.com/Textualize/textual/pull/3112
- Added `ListView.extend` method to append multiple items https://github.com/Textualize/textual/pull/3012
### Changed
- grid-columns and grid-rows now accept an `auto` token to detect the optimal size https://github.com/Textualize/textual/pull/3107
- LoadingIndicator now has a minimum height of 1 line.
### Fixed
- Fixed auto height container with default grid-rows https://github.com/Textualize/textual/issues/1597
- Fixed `page_up` and `page_down` bug in `DataTable` when `show_header = False` https://github.com/Textualize/textual/pull/3093
- Fixed issue with visible children inside invisible container when moving focus https://github.com/Textualize/textual/issues/3053
## [0.33.0] - 2023-08-15
### Fixed
- Fixed unintuitive sizing behaviour of TabbedContent https://github.com/Textualize/textual/issues/2411
- Fixed relative units not always expanding auto containers https://github.com/Textualize/textual/pull/3059
- Fixed background refresh https://github.com/Textualize/textual/issues/3055
- Fixed `SelectionList.clear_options` https://github.com/Textualize/textual/pull/3075
- `MouseMove` events bubble up from widgets. `App` and `Screen` receive `MouseMove` events even if there's no Widget under the cursor. https://github.com/Textualize/textual/issues/2905
- Fixed click on double-width char https://github.com/Textualize/textual/issues/2968
### Changed
- Breaking change: `DOMNode.visible` now takes into account full DOM to report whether a node is visible or not.
### Removed
- Property `Widget.focusable_children` https://github.com/Textualize/textual/pull/3070
### Added
- Added an interface for replacing prompt of an individual option in an `OptionList` https://github.com/Textualize/textual/issues/2603
- Added `DirectoryTree.reload_node` method https://github.com/Textualize/textual/issues/2757
- Added widgets.Digit https://github.com/Textualize/textual/pull/3073
- Added `BORDER_TITLE` and `BORDER_SUBTITLE` classvars to Widget https://github.com/Textualize/textual/pull/3097
### Changed
- DescendantBlur and DescendantFocus can now be used with @on decorator
## [0.32.0] - 2023-08-03
### Added
- Added widgets.Log
- Added Widget.is_vertical_scroll_end, Widget.is_horizontal_scroll_end, Widget.is_vertical_scrollbar_grabbed, Widget.is_horizontal_scrollbar_grabbed
### Changed
- Breaking change: Renamed TextLog to RichLog
## [0.31.0] - 2023-08-01
### Added
- Added App.begin_capture_print, App.end_capture_print, Widget.begin_capture_print, Widget.end_capture_print https://github.com/Textualize/textual/issues/2952
- Added the ability to run async methods as thread workers https://github.com/Textualize/textual/pull/2938
- Added `App.stop_animation` https://github.com/Textualize/textual/issues/2786
- Added `Widget.stop_animation` https://github.com/Textualize/textual/issues/2786
### Changed
- Breaking change: Creating a thread worker now requires that a `thread=True` keyword argument is passed https://github.com/Textualize/textual/pull/2938
- Breaking change: `Markdown.load` no longer captures all errors and returns a `bool`, errors now propagate https://github.com/Textualize/textual/issues/2956
- Breaking change: the default style of a `DataTable` now has `max-height: 100%` https://github.com/Textualize/textual/issues/2959
### Fixed
- Fixed a crash when a `SelectionList` had a prompt wider than itself https://github.com/Textualize/textual/issues/2900
- Fixed a bug where `Click` events were bubbling up from `Switch` widgets https://github.com/Textualize/textual/issues/2366
- Fixed a crash when using empty CSS variables https://github.com/Textualize/textual/issues/1849
- Fixed issue with tabs in TextLog https://github.com/Textualize/textual/issues/3007
- Fixed a bug with `DataTable` hover highlighting https://github.com/Textualize/textual/issues/2909
## [0.30.0] - 2023-07-17
### Added
- Added `DataTable.remove_column` method https://github.com/Textualize/textual/pull/2899
- Added notifications https://github.com/Textualize/textual/pull/2866
- Added `on_complete` callback to scroll methods https://github.com/Textualize/textual/pull/2903
### Fixed
- Fixed CancelledError issue with timer https://github.com/Textualize/textual/issues/2854
- Fixed Toggle Buttons issue with not being clickable/hoverable https://github.com/Textualize/textual/pull/2930
## [0.29.0] - 2023-07-03
### Changed
- Factored dev tools (`textual` command) in to external lib (`textual-dev`).
### Added
- Updated `DataTable.get_cell` type hints to accept string keys https://github.com/Textualize/textual/issues/2586
- Added `DataTable.get_cell_coordinate` method
- Added `DataTable.get_row_index` method https://github.com/Textualize/textual/issues/2587
- Added `DataTable.get_column_index` method
- Added can-focus pseudo-class to target widgets that may receive focus
- Make `Markdown.update` optionally awaitable https://github.com/Textualize/textual/pull/2838
- Added `default` parameter to `DataTable.add_column` for populating existing rows https://github.com/Textualize/textual/pull/2836
- Added can-focus pseudo-class to target widgets that may receive focus
### Fixed
- Fixed crash when columns were added to populated `DataTable` https://github.com/Textualize/textual/pull/2836
- Fixed issues with opacity on Screens https://github.com/Textualize/textual/issues/2616
- Fixed style problem with selected selections in a non-focused selection list https://github.com/Textualize/textual/issues/2768
- Fixed sys.stdout and sys.stderr being None https://github.com/Textualize/textual/issues/2879
## [0.28.1] - 2023-06-20
### Fixed
- Fixed indented code blocks not showing up in `Markdown` https://github.com/Textualize/textual/issues/2781
- Fixed inline code blocks in lists showing out of order in `Markdown` https://github.com/Textualize/textual/issues/2676
- Fixed list items in a `Markdown` being added to the focus chain https://github.com/Textualize/textual/issues/2380
- Fixed `Tabs` posting unnecessary messages when removing non-active tabs https://github.com/Textualize/textual/issues/2807
- call_after_refresh will preserve the sender within the callback https://github.com/Textualize/textual/pull/2806
### Added
- Added a method of allowing third party code to handle unhandled tokens in `Markdown` https://github.com/Textualize/textual/pull/2803
- Added `MarkdownBlock` as an exported symbol in `textual.widgets.markdown` https://github.com/Textualize/textual/pull/2803
### Changed
- Tooltips are now inherited, so will work with compound widgets
## [0.28.0] - 2023-06-19
### Added
- The devtools console now confirms when CSS files have been successfully loaded after a previous error https://github.com/Textualize/textual/pull/2716
- Class variable `CSS` to screens https://github.com/Textualize/textual/issues/2137
- Class variable `CSS_PATH` to screens https://github.com/Textualize/textual/issues/2137
- Added `cursor_foreground_priority` and `cursor_background_priority` to `DataTable` https://github.com/Textualize/textual/pull/2736
- Added Region.center
- Added `center` parameter to `Widget.scroll_to_region`
- Added `origin_visible` parameter to `Widget.scroll_to_region`
- Added `origin_visible` parameter to `Widget.scroll_to_center`
- Added `TabbedContent.tab_count` https://github.com/Textualize/textual/pull/2751
- Added `TabbedContent.add_pane` https://github.com/Textualize/textual/pull/2751
- Added `TabbedContent.remove_pane` https://github.com/Textualize/textual/pull/2751
- Added `TabbedContent.clear_panes` https://github.com/Textualize/textual/pull/2751
- Added `TabbedContent.Cleared` https://github.com/Textualize/textual/pull/2751
### Fixed
- Fixed setting `TreeNode.label` on an existing `Tree` node not immediately refreshing https://github.com/Textualize/textual/pull/2713
- Correctly implement `__eq__` protocol in DataTable https://github.com/Textualize/textual/pull/2705
- Fixed exceptions in Pilot tests being silently ignored https://github.com/Textualize/textual/pull/2754
- Fixed issue where internal data of `OptionList` could be invalid for short window after `clear_options` https://github.com/Textualize/textual/pull/2754
- Fixed `Tooltip` causing a `query_one` on a lone `Static` to fail https://github.com/Textualize/textual/issues/2723
- Nested widgets wouldn't lose focus when parent is disabled https://github.com/Textualize/textual/issues/2772
- Fixed the `Tabs` `Underline` highlight getting "lost" in some extreme situations https://github.com/Textualize/textual/pull/2751
### Changed
- Breaking change: The `@on` decorator will now match a message class and any child classes https://github.com/Textualize/textual/pull/2746
- Breaking change: Styles update to checkbox, radiobutton, OptionList, Select, SelectionList, Switch https://github.com/Textualize/textual/pull/2777
- `Tabs.add_tab` is now optionally awaitable https://github.com/Textualize/textual/pull/2778
- `Tabs.add_tab` now takes `before` and `after` arguments to position a new tab https://github.com/Textualize/textual/pull/2778
- `Tabs.remove_tab` is now optionally awaitable https://github.com/Textualize/textual/pull/2778
- Breaking change: `Tabs.clear` has been changed from returning `self` to being optionally awaitable https://github.com/Textualize/textual/pull/2778
## [0.27.0] - 2023-06-01
### Fixed
- Fixed zero division error https://github.com/Textualize/textual/issues/2673
- Fix `scroll_to_center` when there were nested layers out of view (Compositor full_map not populated fully) https://github.com/Textualize/textual/pull/2684
- Fix crash when `Select` widget value attribute was set in `compose` https://github.com/Textualize/textual/pull/2690
- Issue with computing progress in workers https://github.com/Textualize/textual/pull/2686
- Issues with `switch_screen` not updating the results callback appropriately https://github.com/Textualize/textual/issues/2650
- Fixed incorrect mount order https://github.com/Textualize/textual/pull/2702
### Added
- `work` decorator accepts `description` parameter to add debug string https://github.com/Textualize/textual/issues/2597
- Added `SelectionList` widget https://github.com/Textualize/textual/pull/2652
- `App.AUTO_FOCUS` to set auto focus on all screens https://github.com/Textualize/textual/issues/2594
- Option to `scroll_to_center` to ensure we don't scroll such that the top left corner of the widget is not visible https://github.com/Textualize/textual/pull/2682
- Added `Widget.tooltip` property https://github.com/Textualize/textual/pull/2670
- Added `Region.inflect` https://github.com/Textualize/textual/pull/2670
- `Suggester` API to compose with widgets for automatic suggestions https://github.com/Textualize/textual/issues/2330
- `SuggestFromList` class to let widgets get completions from a fixed set of options https://github.com/Textualize/textual/pull/2604
- `Input` has a new component class `input--suggestion` https://github.com/Textualize/textual/pull/2604
- Added `Widget.remove_children` https://github.com/Textualize/textual/pull/2657
- Added `Validator` framework and validation for `Input` https://github.com/Textualize/textual/pull/2600
- Ability to have private and public validate methods https://github.com/Textualize/textual/pull/2708
- Ability to have private compute methods https://github.com/Textualize/textual/pull/2708
- Added `message_hook` to App.run_test https://github.com/Textualize/textual/pull/2702
- Added `Sparkline` widget https://github.com/Textualize/textual/pull/2631
### Changed
- `Placeholder` now sets its color cycle per app https://github.com/Textualize/textual/issues/2590
- Footer now clears key highlight regardless of whether it's in the active screen or not https://github.com/Textualize/textual/issues/2606
- The default Widget repr no longer displays classes and pseudo-classes (to reduce noise in logs). Add them to your `__rich_repr__` method if needed. https://github.com/Textualize/textual/pull/2623
- Setting `Screen.AUTO_FOCUS` to `None` will inherit `AUTO_FOCUS` from the app instead of disabling it https://github.com/Textualize/textual/issues/2594
- Setting `Screen.AUTO_FOCUS` to `""` will disable it on the screen https://github.com/Textualize/textual/issues/2594
- Messages now have a `handler_name` class var which contains the name of the default handler method.
- `Message.control` is now a property instead of a class variable. https://github.com/Textualize/textual/issues/2528
- `Tree` and `DirectoryTree` Messages no longer accept a `tree` parameter, using `self.node.tree` instead. https://github.com/Textualize/textual/issues/2529
- Keybinding <kbd>right</kbd> in `Input` is also used to accept a suggestion if the cursor is at the end of the input https://github.com/Textualize/textual/pull/2604
- `Input.__init__` now accepts a `suggester` attribute for completion suggestions https://github.com/Textualize/textual/pull/2604
- Using `switch_screen` to switch to the currently active screen is now a no-op https://github.com/Textualize/textual/pull/2692
- Breaking change: removed `reactive.py::Reactive.var` in favor of `reactive.py::var` https://github.com/Textualize/textual/pull/2709/
### Removed
- `Placeholder.reset_color_cycle`
- Removed `Widget.reset_focus` (now called `Widget.blur`) https://github.com/Textualize/textual/issues/2642
## [0.26.0] - 2023-05-20
### Added
- Added `Widget.can_view`
### Changed
- Textual will now scroll focused widgets to center if not in view
## [0.25.0] - 2023-05-17
### Changed
- App `title` and `sub_title` attributes can be set to any type https://github.com/Textualize/textual/issues/2521
- `DirectoryTree` now loads directory contents in a worker https://github.com/Textualize/textual/issues/2456
- Only a single error will be written by default, unless in dev mode ("debug" in App.features) https://github.com/Textualize/textual/issues/2480
- Using `Widget.move_child` where the target and the child being moved are the same is now a no-op https://github.com/Textualize/textual/issues/1743
- Calling `dismiss` on a screen that is not at the top of the stack now raises an exception https://github.com/Textualize/textual/issues/2575
- `MessagePump.call_after_refresh` and `MessagePump.call_later` will now return `False` if the callback could not be scheduled. https://github.com/Textualize/textual/pull/2584
### Fixed
- Fixed `ZeroDivisionError` in `resolve_fraction_unit` https://github.com/Textualize/textual/issues/2502
- Fixed `TreeNode.expand` and `TreeNode.expand_all` not posting a `Tree.NodeExpanded` message https://github.com/Textualize/textual/issues/2535
- Fixed `TreeNode.collapse` and `TreeNode.collapse_all` not posting a `Tree.NodeCollapsed` message https://github.com/Textualize/textual/issues/2535
- Fixed `TreeNode.toggle` and `TreeNode.toggle_all` not posting a `Tree.NodeExpanded` or `Tree.NodeCollapsed` message https://github.com/Textualize/textual/issues/2535
- `footer--description` component class was being ignored https://github.com/Textualize/textual/issues/2544
- Pasting empty selection in `Input` would raise an exception https://github.com/Textualize/textual/issues/2563
- `Screen.AUTO_FOCUS` now focuses the first _focusable_ widget that matches the selector https://github.com/Textualize/textual/issues/2578
- `Screen.AUTO_FOCUS` now works on the default screen on startup https://github.com/Textualize/textual/pull/2581
- Fix for setting dark in App `__init__` https://github.com/Textualize/textual/issues/2583
- Fix issue with scrolling and docks https://github.com/Textualize/textual/issues/2525
- Fix not being able to use CSS classes with `Tab` https://github.com/Textualize/textual/pull/2589
### Added
- Class variable `AUTO_FOCUS` to screens https://github.com/Textualize/textual/issues/2457
- Added `NULL_SPACING` and `NULL_REGION` to geometry.py
## [0.24.1] - 2023-05-08
### Fixed
- Fix TypeError in code browser
## [0.24.0] - 2023-05-08
### Fixed
- Fixed crash when creating a `DirectoryTree` starting anywhere other than `.`
- Fixed line drawing in `Tree` when `Tree.show_root` is `True` https://github.com/Textualize/textual/issues/2397
- Fixed line drawing in `Tree` not marking branches as selected when first getting focus https://github.com/Textualize/textual/issues/2397
### Changed
- The DataTable cursor is now scrolled into view when the cursor coordinate is changed programmatically https://github.com/Textualize/textual/issues/2459
- run_worker exclusive parameter is now `False` by default https://github.com/Textualize/textual/pull/2470
- Added `always_update` as an optional argument for `reactive.var`
- Made Binding description default to empty string, which is equivalent to show=False https://github.com/Textualize/textual/pull/2501
- Modified Message to allow it to be used as a dataclass https://github.com/Textualize/textual/pull/2501
- Decorator `@on` accepts arbitrary `**kwargs` to apply selectors to attributes of the message https://github.com/Textualize/textual/pull/2498
### Added
- Property `control` as alias for attribute `tabs` in `Tabs` messages https://github.com/Textualize/textual/pull/2483
- Experimental: Added "overlay" rule https://github.com/Textualize/textual/pull/2501
- Experimental: Added "constrain" rule https://github.com/Textualize/textual/pull/2501
- Added textual.widgets.Select https://github.com/Textualize/textual/pull/2501
- Added Region.translate_inside https://github.com/Textualize/textual/pull/2501
- `TabbedContent` now takes kwargs `id`, `name`, `classes`, and `disabled`, upon initialization, like other widgets https://github.com/Textualize/textual/pull/2497
- Method `DataTable.move_cursor` https://github.com/Textualize/textual/issues/2472
- Added `OptionList.add_options` https://github.com/Textualize/textual/pull/2508
- Added `TreeNode.is_root` https://github.com/Textualize/textual/pull/2510
- Added `TreeNode.remove_children` https://github.com/Textualize/textual/pull/2510
- Added `TreeNode.remove` https://github.com/Textualize/textual/pull/2510
- Added classvar `Message.ALLOW_SELECTOR_MATCH` https://github.com/Textualize/textual/pull/2498
- Added `ALLOW_SELECTOR_MATCH` to all built-in messages associated with widgets https://github.com/Textualize/textual/pull/2498
- Markdown document sub-widgets now reference the container document
- Table of contents of a markdown document now references the document
- Added the `control` property to messages
- `DirectoryTree.FileSelected`
- `ListView`
- `Highlighted`
- `Selected`
- `Markdown`
- `TableOfContentsUpdated`
- `TableOfContentsSelected`
- `LinkClicked`
- `OptionList`
- `OptionHighlighted`
- `OptionSelected`
- `RadioSet.Changed`
- `TabContent.TabActivated`
- `Tree`
- `NodeSelected`
- `NodeHighlighted`
- `NodeExpanded`
- `NodeCollapsed`
## [0.23.0] - 2023-05-03
### Fixed
- Fixed `outline` top and bottom not handling alpha - https://github.com/Textualize/textual/issues/2371
- Fixed `!important` not applying to `align` https://github.com/Textualize/textual/issues/2420
- Fixed `!important` not applying to `border` https://github.com/Textualize/textual/issues/2420
- Fixed `!important` not applying to `content-align` https://github.com/Textualize/textual/issues/2420
- Fixed `!important` not applying to `outline` https://github.com/Textualize/textual/issues/2420
- Fixed `!important` not applying to `overflow` https://github.com/Textualize/textual/issues/2420
- Fixed `!important` not applying to `scrollbar-size` https://github.com/Textualize/textual/issues/2420
- Fixed `outline-right` not being recognised https://github.com/Textualize/textual/issues/2446
- Fixed OSError when a file system is not available https://github.com/Textualize/textual/issues/2468
### Changed
- Setting attributes with a `compute_` method will now raise an `AttributeError` https://github.com/Textualize/textual/issues/2383
- Unknown psuedo-selectors will now raise a tokenizer error (previously they were silently ignored) https://github.com/Textualize/textual/pull/2445
- Breaking change: `DirectoryTree.FileSelected.path` is now always a `Path` https://github.com/Textualize/textual/issues/2448
- Breaking change: `Directorytree.load_directory` renamed to `Directorytree._load_directory` https://github.com/Textualize/textual/issues/2448
- Unknown pseudo-selectors will now raise a tokenizer error (previously they were silently ignored) https://github.com/Textualize/textual/pull/2445
### Added
- Watch methods can now optionally be private https://github.com/Textualize/textual/issues/2382
- Added `DirectoryTree.path` reactive attribute https://github.com/Textualize/textual/issues/2448
- Added `DirectoryTree.FileSelected.node` https://github.com/Textualize/textual/pull/2463
- Added `DirectoryTree.reload` https://github.com/Textualize/textual/issues/2448
- Added textual.on decorator https://github.com/Textualize/textual/issues/2398
## [0.22.3] - 2023-04-29
### Fixed
- Fixed `textual run` on Windows https://github.com/Textualize/textual/issues/2406
- Fixed top border of button hover state
## [0.22.2] - 2023-04-29
### Added
- Added `TreeNode.tree` as a read-only public attribute https://github.com/Textualize/textual/issues/2413
### Fixed
- Fixed superfluous style updates for focus-within pseudo-selector
## [0.22.1] - 2023-04-28
### Fixed
- Fixed timer issue https://github.com/Textualize/textual/issues/2416
- Fixed `textual run` issue https://github.com/Textualize/textual/issues/2391
## [0.22.0] - 2023-04-27
### Fixed
- Fixed broken fr units when there is a min or max dimension https://github.com/Textualize/textual/issues/2378
- Fixed plain text in Markdown code blocks with no syntax being difficult to read https://github.com/Textualize/textual/issues/2400
### Added
- Added `ProgressBar` widget https://github.com/Textualize/textual/pull/2333
### Changed
- All `textual.containers` are now `1fr` in relevant dimensions by default https://github.com/Textualize/textual/pull/2386
## [0.21.0] - 2023-04-26
### Changed
- `textual run` execs apps in a new context.
- Textual console no longer parses console markup.
- Breaking change: `Container` no longer shows required scrollbars by default https://github.com/Textualize/textual/issues/2361
- Breaking change: `VerticalScroll` no longer shows a required horizontal scrollbar by default
- Breaking change: `HorizontalScroll` no longer shows a required vertical scrollbar by default
- Breaking change: Renamed `App.action_add_class_` to `App.action_add_class`
- Breaking change: Renamed `App.action_remove_class_` to `App.action_remove_class`
- Breaking change: `RadioSet` is now a single focusable widget https://github.com/Textualize/textual/pull/2372
- Breaking change: Removed `containers.Content` (use `containers.VerticalScroll` now)
### Added
- Added `-c` switch to `textual run` which runs commands in a Textual dev environment.
- Breaking change: standard keyboard scrollable navigation bindings have been moved off `Widget` and onto a new base class for scrollable containers (see also below addition) https://github.com/Textualize/textual/issues/2332
- `ScrollView` now inherits from `ScrollableContainer` rather than `Widget` https://github.com/Textualize/textual/issues/2332
- Containers no longer inherit any bindings from `Widget` https://github.com/Textualize/textual/issues/2331
- Added `ScrollableContainer`; a container class that binds the common navigation keys to scroll actions (see also above breaking change) https://github.com/Textualize/textual/issues/2332
### Fixed
- Fixed dark mode toggles in a "child" screen not updating a "parent" screen https://github.com/Textualize/textual/issues/1999
- Fixed "panel" border not exposed via CSS
- Fixed `TabbedContent.active` changes not changing the actual content https://github.com/Textualize/textual/issues/2352
- Fixed broken color on macOS Terminal https://github.com/Textualize/textual/issues/2359
## [0.20.1] - 2023-04-18
### Fix
- New fix for stuck tabs underline https://github.com/Textualize/textual/issues/2229
## [0.20.0] - 2023-04-18
### Changed
- Changed signature of Driver. Technically a breaking change, but unlikely to affect anyone.
- Breaking change: Timer.start is now private, and returns None. There was no reason to call this manually, so unlikely to affect anyone.
- A clicked tab will now be scrolled to the center of its tab container https://github.com/Textualize/textual/pull/2276
- Style updates are now done immediately rather than on_idle https://github.com/Textualize/textual/pull/2304
- `ButtonVariant` is now exported from `textual.widgets.button` https://github.com/Textualize/textual/issues/2264
- `HorizontalScroll` and `VerticalScroll` are now focusable by default https://github.com/Textualize/textual/pull/2317
### Added
- Added `DataTable.remove_row` method https://github.com/Textualize/textual/pull/2253
- option `--port` to the command `textual console` to specify which port the console should connect to https://github.com/Textualize/textual/pull/2258
- `Widget.scroll_to_center` method to scroll children to the center of container widget https://github.com/Textualize/textual/pull/2255 and https://github.com/Textualize/textual/pull/2276
- Added `TabActivated` message to `TabbedContent` https://github.com/Textualize/textual/pull/2260
- Added "panel" border style https://github.com/Textualize/textual/pull/2292
- Added `border-title-color`, `border-title-background`, `border-title-style` rules https://github.com/Textualize/textual/issues/2289
- Added `border-subtitle-color`, `border-subtitle-background`, `border-subtitle-style` rules https://github.com/Textualize/textual/issues/2289
### Fixed
- Fixed order styles are applied in DataTable - allows combining of renderable styles and component classes https://github.com/Textualize/textual/pull/2272
- Fixed key combos with up/down keys in some terminals https://github.com/Textualize/textual/pull/2280
- Fix empty ListView preventing bindings from firing https://github.com/Textualize/textual/pull/2281
- Fix `get_component_styles` returning incorrect values on first call when combined with pseudoclasses https://github.com/Textualize/textual/pull/2304
- Fixed `active_message_pump.get` sometimes resulting in a `LookupError` https://github.com/Textualize/textual/issues/2301
## [0.19.1] - 2023-04-10
### Fixed
- Fix viewport units using wrong viewport size https://github.com/Textualize/textual/pull/2247
- Fixed layout not clearing arrangement cache https://github.com/Textualize/textual/pull/2249
## [0.19.0] - 2023-04-07
### Added
- Added support for filtering a `DirectoryTree` https://github.com/Textualize/textual/pull/2215
### Changed
- Allowed border_title and border_subtitle to accept Text objects
- Added additional line around titles
- When a container is auto, relative dimensions in children stretch the container. https://github.com/Textualize/textual/pull/2221
- DataTable page up / down now move cursor
### Fixed
- Fixed margin not being respected when width or height is "auto" https://github.com/Textualize/textual/issues/2220
- Fixed issue which prevent scroll_visible from working https://github.com/Textualize/textual/issues/2181
- Fixed missing tracebacks on Windows https://github.com/Textualize/textual/issues/2027
## [0.18.0] - 2023-04-04
### Added
- Added Worker API https://github.com/Textualize/textual/pull/2182
### Changed
- Breaking change: Markdown.update is no longer a coroutine https://github.com/Textualize/textual/pull/2182
### Fixed
- `RadioSet` is now far less likely to report `pressed_button` as `None` https://github.com/Textualize/textual/issues/2203
## [0.17.3] - 2023-04-02
### [Fixed]
- Fixed scrollable area not taking in to account dock https://github.com/Textualize/textual/issues/2188
## [0.17.2] - 2023-04-02
### [Fixed]
- Fixed bindings persistance https://github.com/Textualize/textual/issues/1613
- The `Markdown` widget now auto-increments ordered lists https://github.com/Textualize/textual/issues/2002
- Fixed modal bindings https://github.com/Textualize/textual/issues/2194
- Fix binding enter to active button https://github.com/Textualize/textual/issues/2194
### [Changed]
- tab and shift+tab are now defined on Screen.
## [0.17.1] - 2023-03-30
### Fixed
- Fix cursor not hiding on Windows https://github.com/Textualize/textual/issues/2170
- Fixed freeze when ctrl-clicking links https://github.com/Textualize/textual/issues/2167 https://github.com/Textualize/textual/issues/2073
## [0.17.0] - 2023-03-29
### Fixed
- Issue with parsing action strings whose arguments contained quoted closing parenthesis https://github.com/Textualize/textual/pull/2112
- Issues with parsing action strings with tuple arguments https://github.com/Textualize/textual/pull/2112
- Issue with watching for CSS file changes https://github.com/Textualize/textual/pull/2128
- Fix for tabs not invalidating https://github.com/Textualize/textual/issues/2125
- Fixed scrollbar layers issue https://github.com/Textualize/textual/issues/1358
- Fix for interaction between pseudo-classes and widget-level render caches https://github.com/Textualize/textual/pull/2155
### Changed
- DataTable now has height: auto by default. https://github.com/Textualize/textual/issues/2117
- Textual will now render strings within renderables (such as tables) as Console Markup by default. You can wrap your text with rich.Text() if you want the original behavior. https://github.com/Textualize/textual/issues/2120
- Some widget methods now return `self` instead of `None` https://github.com/Textualize/textual/pull/2102:
- `Widget`: `refresh`, `focus`, `reset_focus`
- `Button.press`
- `DataTable`: `clear`, `refresh_coordinate`, `refresh_row`, `refresh_column`, `sort`
- `Placehoder.cycle_variant`
- `Switch.toggle`
- `Tabs.clear`
- `TextLog`: `write`, `clear`
- `TreeNode`: `expand`, `expand_all`, `collapse`, `collapse_all`, `toggle`, `toggle_all`
- `Tree`: `clear`, `reset`
- Screens with alpha in their background color will now blend with the background. https://github.com/Textualize/textual/pull/2139
- Added "thick" border style. https://github.com/Textualize/textual/pull/2139
- message_pump.app will now set the active app if it is not already set.
- DataTable now has max height set to 100vh
### Added
- Added auto_scroll attribute to TextLog https://github.com/Textualize/textual/pull/2127
- Added scroll_end switch to TextLog.write https://github.com/Textualize/textual/pull/2127
- Added `Widget.get_pseudo_class_state` https://github.com/Textualize/textual/pull/2155
- Added Screen.ModalScreen which prevents App from handling bindings. https://github.com/Textualize/textual/pull/2139
- Added TEXTUAL_LOG env var which should be a path that Textual will write verbose logs to (textual devtools is generally preferred) https://github.com/Textualize/textual/pull/2148
- Added textual.logging.TextualHandler logging handler
- Added Query.set_classes, DOMNode.set_classes, and `classes` setter for Widget https://github.com/Textualize/textual/issues/1081
- Added `OptionList` https://github.com/Textualize/textual/pull/2154
## [0.16.0] - 2023-03-22
### Added
- Added `parser_factory` argument to `Markdown` and `MarkdownViewer` constructors https://github.com/Textualize/textual/pull/2075
- Added `HorizontalScroll` https://github.com/Textualize/textual/issues/1957
- Added `Center` https://github.com/Textualize/textual/issues/1957
- Added `Middle` https://github.com/Textualize/textual/issues/1957
- Added `VerticalScroll` (mimicking the old behaviour of `Vertical`) https://github.com/Textualize/textual/issues/1957
- Added `Widget.border_title` and `Widget.border_subtitle` to set border (sub)title for a widget https://github.com/Textualize/textual/issues/1864
- Added CSS styles `border_title_align` and `border_subtitle_align`.
- Added `TabbedContent` widget https://github.com/Textualize/textual/pull/2059
- Added `get_child_by_type` method to widgets / app https://github.com/Textualize/textual/pull/2059
- Added `Widget.render_str` method https://github.com/Textualize/textual/pull/2059
- Added TEXTUAL_DRIVER environment variable
### Changed
- Dropped "loading-indicator--dot" component style from LoadingIndicator https://github.com/Textualize/textual/pull/2050
- Tabs widget now sends Tabs.Cleared when there is no active tab.
- Breaking change: changed default behaviour of `Vertical` (see `VerticalScroll`) https://github.com/Textualize/textual/issues/1957
- The default `overflow` style for `Horizontal` was changed to `hidden hidden` https://github.com/Textualize/textual/issues/1957
- `DirectoryTree` also accepts `pathlib.Path` objects as the path to list https://github.com/Textualize/textual/issues/1438
### Removed
- Removed `sender` attribute from messages. It's now just private (`_sender`). https://github.com/Textualize/textual/pull/2071
### Fixed
- Fixed borders not rendering correctly. https://github.com/Textualize/textual/pull/2074
- Fix for error when removing nodes. https://github.com/Textualize/textual/issues/2079
## [0.15.1] - 2023-03-14
@ -22,6 +839,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Fixed container not resizing when a widget is removed https://github.com/Textualize/textual/issues/2007
- Fixes issue where the horizontal scrollbar would be incorrectly enabled https://github.com/Textualize/textual/pull/2024
## [0.15.0] - 2023-03-13
### Changed
- Fixed container not resizing when a widget is removed https://github.com/Textualize/textual/issues/2007
- Fixed issue where the horizontal scrollbar would be incorrectly enabled https://github.com/Textualize/textual/pull/2024
- Fixed `Pilot.click` not correctly creating the mouse events https://github.com/Textualize/textual/issues/2022
@ -356,11 +1180,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.6.0] - 2022-12-11
https://textual.textualize.io/blog/2022/12/11/version-060
### Added
- Added "inherited bindings" -- BINDINGS classvar will be merged with base classes, unless inherit_bindings is set to False
- Added `Tree` widget which replaces `TreeControl`.
- Added widget `Placeholder` https://github.com/Textualize/textual/issues/1200.
- Added `ListView` and `ListItem` widgets https://github.com/Textualize/textual/pull/1143
### Changed
@ -596,6 +1423,45 @@ https://textual.textualize.io/blog/2022/11/08/version-040/#version-040
- New handler system for messages that doesn't require inheritance
- Improved traceback handling
[0.41.0]: https://github.com/Textualize/textual/compare/v0.40.0...v0.41.0
[0.40.0]: https://github.com/Textualize/textual/compare/v0.39.0...v0.40.0
[0.39.0]: https://github.com/Textualize/textual/compare/v0.38.1...v0.39.0
[0.38.1]: https://github.com/Textualize/textual/compare/v0.38.0...v0.38.1
[0.38.0]: https://github.com/Textualize/textual/compare/v0.37.1...v0.38.0
[0.37.1]: https://github.com/Textualize/textual/compare/v0.37.0...v0.37.1
[0.37.0]: https://github.com/Textualize/textual/compare/v0.36.0...v0.37.0
[0.36.0]: https://github.com/Textualize/textual/compare/v0.35.1...v0.36.0
[0.35.1]: https://github.com/Textualize/textual/compare/v0.35.0...v0.35.1
[0.35.0]: https://github.com/Textualize/textual/compare/v0.34.0...v0.35.0
[0.34.0]: https://github.com/Textualize/textual/compare/v0.33.0...v0.34.0
[0.33.0]: https://github.com/Textualize/textual/compare/v0.32.0...v0.33.0
[0.32.0]: https://github.com/Textualize/textual/compare/v0.31.0...v0.32.0
[0.31.0]: https://github.com/Textualize/textual/compare/v0.30.0...v0.31.0
[0.30.0]: https://github.com/Textualize/textual/compare/v0.29.0...v0.30.0
[0.29.0]: https://github.com/Textualize/textual/compare/v0.28.1...v0.29.0
[0.28.1]: https://github.com/Textualize/textual/compare/v0.28.0...v0.28.1
[0.28.0]: https://github.com/Textualize/textual/compare/v0.27.0...v0.28.0
[0.27.0]: https://github.com/Textualize/textual/compare/v0.26.0...v0.27.0
[0.26.0]: https://github.com/Textualize/textual/compare/v0.25.0...v0.26.0
[0.25.0]: https://github.com/Textualize/textual/compare/v0.24.1...v0.25.0
[0.24.1]: https://github.com/Textualize/textual/compare/v0.24.0...v0.24.1
[0.24.0]: https://github.com/Textualize/textual/compare/v0.23.0...v0.24.0
[0.23.0]: https://github.com/Textualize/textual/compare/v0.22.3...v0.23.0
[0.22.3]: https://github.com/Textualize/textual/compare/v0.22.2...v0.22.3
[0.22.2]: https://github.com/Textualize/textual/compare/v0.22.1...v0.22.2
[0.22.1]: https://github.com/Textualize/textual/compare/v0.22.0...v0.22.1
[0.22.0]: https://github.com/Textualize/textual/compare/v0.21.0...v0.22.0
[0.21.0]: https://github.com/Textualize/textual/compare/v0.20.1...v0.21.0
[0.20.1]: https://github.com/Textualize/textual/compare/v0.20.0...v0.20.1
[0.20.0]: https://github.com/Textualize/textual/compare/v0.19.1...v0.20.0
[0.19.1]: https://github.com/Textualize/textual/compare/v0.19.0...v0.19.1
[0.19.0]: https://github.com/Textualize/textual/compare/v0.18.0...v0.19.0
[0.18.0]: https://github.com/Textualize/textual/compare/v0.17.4...v0.18.0
[0.17.3]: https://github.com/Textualize/textual/compare/v0.17.2...v0.17.3
[0.17.2]: https://github.com/Textualize/textual/compare/v0.17.1...v0.17.2
[0.17.1]: https://github.com/Textualize/textual/compare/v0.17.0...v0.17.1
[0.17.0]: https://github.com/Textualize/textual/compare/v0.16.0...v0.17.0
[0.16.0]: https://github.com/Textualize/textual/compare/v0.15.1...v0.16.0
[0.15.1]: https://github.com/Textualize/textual/compare/v0.15.0...v0.15.1
[0.15.0]: https://github.com/Textualize/textual/compare/v0.14.0...v0.15.0
[0.14.0]: https://github.com/Textualize/textual/compare/v0.13.0...v0.14.0

110
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,110 @@
# Contributing to Textual
First of all, thanks for taking the time to contribute to Textual!
## How can I contribute?
You can contribute to Textual in many ways:
1. [Report a bug](https://github.com/textualize/textual/issues/new?title=%5BBUG%5D%20short%20bug%20description&template=bug_report.md)
2. Add a new feature
3. Fix a bug
4. Improve the documentation
## Setup
To make a code or documentation contribution you will need to set up Textual locally.
You can follow these steps:
1. Make sure you have Poetry installed ([see instructions here](https://python-poetry.org))
2. Clone the Textual repository
3. Run `poetry shell` to create a virtual environment for the dependencies
4. Run `poetry install` to install all dependencies
5. Make sure the latest version of Textual was installed by running the command `textual --version`
6. Install the pre-commit hooks with the command `pre-commit install`
## Demo
Once you have Textual installed, run the Textual demo to get an impression of what Textual can do and to double check that everything was installed correctly:
```bash
python -m textual
```
## Guidelines
- Read any issue instructions carefully. Feel free to ask for clarification if any details are missing.
- Add docstrings to all of your code (functions, methods, classes, ...). The codebase should have enough examples for you to copy from.
- Write tests for your code.
- If you are fixing a bug, make sure to add regression tests that link to the original issue.
- If you are implementing a visual element, make sure to add _snapshot tests_. [See below](#snapshot-testing) for more details.
## Before opening a PR
Before you open your PR, please go through this checklist and make sure you've checked all the items that apply:
- [ ] Update the `CHANGELOG.md`
- [ ] Format your code with black (`make format`)
- [ ] All your code has docstrings in the style of the rest of the codebase
- [ ] Your code passes all tests (`make test`)
([Read this](#makefile-commands) if the command `make` doesn't work for you.)
## Updating and building the documentation
If you change the documentation, you will want to build the documentation to make sure everything looks like it should.
The command `make docs-serve-offline` should start a server that will let you preview the documentation locally and that should reload whenever you save changes to the documentation or the code files.
([Read this](#makefile-commands) if the command `make` doesn't work for you.)
We strive to write our documentation in a clear and accessible way so, if you find any issues with the documentation, we encourage you to open an issue where you can enumerate the things you think should be changed or added.
Opening an issue or a discussion is typically better than opening a PR directly.
That's because there are many subjective considerations that go into writing documentation and we cannot expect you, a well-intentioned external contributor, to be aware of those subjective considerations that we take into account when writing our documentation.
Of course, this does not apply to objective/technical issues with the documentation like bugs or broken links.
## After opening a PR
When you open a PR, your code will be reviewed by one of the Textual maintainers.
In that review process,
- We will take a look at all of the changes you are making
- We might ask for clarifications (why did you do X or Y?)
- We might ask for more tests/more documentation
- We might ask for some code changes
The sole purpose of those interactions is to make sure that, in the long run, everyone has the best experience possible with Textual and with the feature you are implementing/fixing.
Don't be discouraged if a reviewer asks for code changes.
If you go through our history of pull requests, you will see that every single one of the maintainers has had to make changes following a review.
## Snapshot testing
Snapshot tests ensure that visual things (like widgets) look like they are supposed to.
PR [#1969](https://github.com/Textualize/textual/pull/1969) is a good example of what adding snapshot tests looks like: it amounts to a change in the file `tests/snapshot_tests/test_snapshots.py` that should run an app that you write and compare it against a historic snapshot of what that app should look like.
When you create a new snapshot test, run it with `pytest -vv tests/snapshot_tests/test_snapshots.py`.
Because you just created this snapshot test, there is no history to compare against and the test will fail.
After running the snapshot tests, you should see a link that opens an interface in your browser.
This interface should show all failing snapshot tests and a side-by-side diff between what the app looked like when the test ran versus the historic snapshot.
Make sure your snapshot app looks like it is supposed to and that you didn't break any other snapshot tests.
If everything looks fine, you can run `make test-snapshot-update` to update the snapshot history with your new snapshot.
This will write to the file `tests/snapshot_tests/__snapshots__/test_snapshots.ambr`, which you should NOT modify by hand.
([Read this](#makefile-commands) if the command `make` doesn't work for you.)
## Join the community
Seems a little overwhelming?
Join our community on [Discord](https://discord.gg/Enf6Z3qhVr) to get help!
## Makefile commands
Textual has a `Makefile` file that contains the most common commands used when developing Textual.
([Read about Make and makefiles on Wikipedia.](https://en.wikipedia.org/wiki/Make_(software)))
If you don't have Make and you're on Windows, you may want to [install Make](https://stackoverflow.com/q/32127524/2828287).

202
FAQ.md
View file

@ -1,202 +0,0 @@
<!-- Auto-generated by FAQtory -->
<!-- Do not edit by hand! -->
# Frequently Asked Questions
- [Does Textual support images?](#does-textual-support-images)
- [How can I fix ImportError cannot import name ComposeResult from textual.app ?](#how-can-i-fix-importerror-cannot-import-name-composeresult-from-textualapp-)
- [How can I select and copy text in a Textual app?](#how-can-i-select-and-copy-text-in-a-textual-app)
- [How do I center a widget in a screen?](#how-do-i-center-a-widget-in-a-screen)
- [How do I pass arguments to an app?](#how-do-i-pass-arguments-to-an-app)
- [Why doesn't Textual look good on macOS?](#why-doesn't-textual-look-good-on-macos)
- [Why doesn't Textual support ANSI themes?](#why-doesn't-textual-support-ansi-themes)
<a name="does-textual-support-images"></a>
## Does Textual support images?
Textual doesn't have built in support for images yet, but it is on the [Roadmap](https://textual.textualize.io/roadmap/).
See also the [rich-pixels](https://github.com/darrenburns/rich-pixels) project for a Rich renderable for images that works with Textual.
<a name="how-can-i-fix-importerror-cannot-import-name-composeresult-from-textualapp-"></a>
## How can I fix ImportError cannot import name ComposeResult from textual.app ?
You likely have an older version of Textual. You can install the latest version by adding the `-U` switch which will force pip to upgrade.
The following should do it:
```
pip install "textual[dev]" -U
```
<a name="how-can-i-select-and-copy-text-in-a-textual-app"></a>
## How can I select and copy text in a Textual app?
Running a Textual app puts your terminal in to *application mode* which disables clicking and dragging to select text.
Most terminal emulators offer a modifier key which you can hold while you click and drag to restore the behavior you
may expect from the command line. The exact modifier key depends on the terminal and platform you are running on.
- **iTerm** Hold the OPTION key.
- **Gnome Terminal** Hold the SHIFT key.
- **Windows Terminal** Hold the SHIFT key.
Refer to the documentation for your terminal emulator, if it is not listed above.
<a name="how-do-i-center-a-widget-in-a-screen"></a>
## How do I center a widget in a screen?
To center a widget within a container use
[`align`](https://textual.textualize.io/styles/align/). But remember that
`align` works on the *children* of a container, it isn't something you use
on the child you want centered.
For example, here's an app that shows a `Button` in the middle of a
`Screen`:
```python
from textual.app import App, ComposeResult
from textual.widgets import Button
class ButtonApp(App):
CSS = """
Screen {
align: center middle;
}
"""
def compose(self) -> ComposeResult:
yield Button("PUSH ME!")
if __name__ == "__main__":
ButtonApp().run()
```
If you use the above on multiple widgets, you'll find they appear to
"left-align" in the center of the screen, like this:
```
+-----+
| |
+-----+
+---------+
| |
+---------+
+---------------+
| |
+---------------+
```
If you want them more like this:
```
+-----+
| |
+-----+
+---------+
| |
+---------+
+---------------+
| |
+---------------+
```
the best approach is to wrap each widget in a container that individually
centers it. For example:
```python
from textual.app import App, ComposeResult
from textual.containers import Container
from textual.widgets import Button
class Center( Container ):
DEFAULT_CSS = """
Center {
height: auto;
width: 100%;
align: center middle;
}
"""
class ButtonApp(App):
CSS = """
Screen {
align: center middle;
}
"""
def compose(self) -> ComposeResult:
yield Center(Button("PUSH ME!"))
yield Center(Button("AND ME!"))
yield Center(Button("ALSO PLEASE PUSH ME!"))
yield Center(Button("HEY ME ALSO!!"))
if __name__ == "__main__":
ButtonApp().run()
```
<a name="how-do-i-pass-arguments-to-an-app"></a>
## How do I pass arguments to an app?
When creating your `App` class, override `__init__` as you would when
inheriting normally. For example:
```python
from textual.app import App, ComposeResult
from textual.widgets import Static
class Greetings(App[None]):
def __init__(self, greeting: str="Hello", to_greet: str="World") -> None:
self.greeting = greeting
self.to_greet = to_greet
super().__init__()
def compose(self) -> ComposeResult:
yield Static(f"{self.greeting}, {self.to_greet}")
```
Then the app can be run, passing in various arguments; for example:
```python
# Running with default arguments.
Greetings().run()
# Running with a keyword arguyment.
Greetings(to_greet="davep").run()
# Running with both positional arguments.
Greetings("Well hello", "there").run()
```
<a name="why-doesn't-textual-look-good-on-macos"></a>
## Why doesn't Textual look good on macOS?
The default macOS `Terminal.app` is getting rather old now; it has problems
such as being limited to just 256 colors, being slow to draw and not all
box-drawing characters are fully-supported. We recommend installing a newer
terminal such as [iTerm2](https://iterm2.com/),
[Kitty](https://sw.kovidgoyal.net/kitty/) or
[WezTerm](https://wezfurlong.org/wezterm/).
<a name="why-doesn't-textual-support-ansi-themes"></a>
## Why doesn't Textual support ANSI themes?
Textual will not generate escape sequences for the 16 themeable *ANSI* colors.
This is an intentional design decision we took for for the following reasons:
- Not everyone has a carefully chosen ANSI color theme. Color combinations which may look fine on your system, may be unreadable on another machine. There is very little an app author or Textual can do to resolve this. Asking users to simply pick a better theme is not a good solution, since not all users will know how.
- ANSI colors can't be manipulated in the way Textual can do with other colors. Textual can blend colors and produce light and dark shades from an original color, which is used to create more readable text and user interfaces. Color blending will also be used to power future accessibility features.
Textual has a design system which guarantees apps will be readable on all platforms and terminals, and produces better results than ANSI colors.
There is currently a light and dark version of the design system, but more are planned. It will also be possible for users to customize the source colors on a per-app or per-system basis. This means that in the future you will be able to modify the core colors to blend in with your chosen terminal theme.
<hr>
Generated by [FAQtory](https://github.com/willmcgugan/faqtory)

View file

@ -12,6 +12,10 @@ unit-test:
test-snapshot-update:
$(run) pytest --cov-report term-missing --cov=textual tests/ -vv --snapshot-update
.PHONY: coverage
coverage:
$(run) coverage html
.PHONY: typecheck
typecheck:
$(run) mypy src/textual
@ -28,6 +32,10 @@ format-check:
clean-screenshot-cache:
rm -rf .screenshot_cache
.PHONY: faq
faq:
$(run) faqtory build
.PHONY: docs-offline-nav
docs-offline-nav:
echo "INHERIT: mkdocs-offline.yml" > mkdocs-nav-offline.yml
@ -43,6 +51,11 @@ docs-serve: clean-screenshot-cache docs-online-nav
$(run) mkdocs serve --config-file mkdocs-nav-online.yml
rm -f mkdocs-nav-online.yml
.PHONY: docs-serve-offline
docs-serve-offline: clean-screenshot-cache docs-offline-nav
$(run) mkdocs serve --config-file mkdocs-nav-offline.yml
rm -f mkdocs-nav-offline.yml
.PHONY: docs-build
docs-build: docs-online-nav
$(run) mkdocs build --config-file mkdocs-nav-online.yml
@ -71,7 +84,8 @@ clean: clean-screenshot-cache clean-offline-docs
.PHONY: setup
setup:
poetry install --extras dev
poetry install
poetry install --extras syntax
.PHONY: update
update:
@ -80,3 +94,11 @@ update:
.PHONY: install-pre-commit
install-pre-commit:
$(run) pre-commit install
.PHONY: demo
demo:
$(run) python -m textual
.PHONY: repl
repl:
$(run) python

View file

@ -1,17 +1,24 @@
# Textual
![Textual splash image](https://raw.githubusercontent.com/Textualize/textual/main/imgs/textual.png)
[![Discord](https://img.shields.io/discord/1026214085173461072)](https://discord.gg/Enf6Z3qhVr)
# Textual
Textual is a *Rapid Application Development* framework for Python.
Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and (coming soon) a web browser!
<details>
<details>
<summary> 🎬 Demonstration </summary>
<hr>
A quick run through of some Textual features.
https://user-images.githubusercontent.com/554369/197355913-65d3c125-493d-4c05-a590-5311f16c40ff.mov
@ -21,12 +28,11 @@ https://user-images.githubusercontent.com/554369/197355913-65d3c125-493d-4c05-a5
</details>
## About
Textual adds interactivity to [Rich](https://github.com/Textualize/rich) with an API inspired by modern web development.
On modern terminal software (installed by default on most systems), Textual apps can use **16.7 million** colors with mouse support and smooth flicker-free animation. A powerful layout engine and re-usable components makes it possible to build apps that rival the desktop and web experience.
On modern terminal software (installed by default on most systems), Textual apps can use **16.7 million** colors with mouse support and smooth flicker-free animation. A powerful layout engine and re-usable components makes it possible to build apps that rival the desktop and web experience.
## Compatibility
@ -37,10 +43,16 @@ Textual runs on Linux, macOS, and Windows. Textual requires Python 3.7 or above.
Install Textual via pip:
```
pip install "textual[dev]"
pip install textual
```
The addition of `[dev]` installs Textual development tools. See the [docs](https://textual.textualize.io/getting_started/) if you need help getting started.
If you plan on developing Textual apps, you should also install the development tools with the following command:
```
pip install textual-dev
```
See the [docs](https://textual.textualize.io/getting_started/) if you need help getting started.
## Demo
@ -56,6 +68,10 @@ python -m textual
Head over to the [Textual documentation](http://textual.textualize.io/) to start building!
## Join us on Discord
Join the Textual developers and community on our [Discord Server](https://discord.gg/Enf6Z3qhVr).
## Examples
The Textual repository comes with a number of examples you can experiment with or use as a template for your own projects.
@ -72,12 +88,12 @@ https://user-images.githubusercontent.com/554369/197188237-88d3f7e4-4e5f-40b5-b9
</details>
<details>
<details>
<summary> 📷 Calculator </summary>
<hr>
This is [calculator.py](https://github.com/Textualize/textual/blob/main/examples/calculator.py) which demonstrates Textual grid layouts.
![calculator screenshot](https://raw.githubusercontent.com/Textualize/textual/main/imgs/calculator.png)
</details>
@ -87,7 +103,7 @@ This is [calculator.py](https://github.com/Textualize/textual/blob/main/examples
<hr>
This is the Stopwatch example from the [tutorial](https://textual.textualize.io/tutorial/).
https://user-images.githubusercontent.com/554369/197360718-0c834ef5-6285-4d37-85cf-23eed4aa56c5.mov
@ -102,12 +118,12 @@ https://user-images.githubusercontent.com/554369/197360718-0c834ef5-6285-4d37-85
The `textual` command has a few sub-commands to preview Textual styles.
<details>
<details>
<summary> 🎬 Easing reference </summary>
<hr>
This is the *easing* reference which demonstrates the easing parameter on animation, with both movement and opacity. You can run it with the following command:
```bash
textual easing
```
@ -118,12 +134,12 @@ https://user-images.githubusercontent.com/554369/196157100-352852a6-2b09-4dc8-a8
</details>
<details>
<details>
<summary> 🎬 Borders reference </summary>
<hr>
This is the borders reference which demonstrates some of the borders styles in Textual. You can run it with the following command:
```bash
textual borders
```
@ -131,16 +147,16 @@ textual borders
https://user-images.githubusercontent.com/554369/196158235-4b45fb78-053d-4fd5-b285-e09b4f1c67a8.mov
</details>
<details>
<details>
<summary> 🎬 Colors reference </summary>
<hr>
This is a reference for Textual's color design system.
```bash
textual colors
```
@ -151,6 +167,5 @@ https://user-images.githubusercontent.com/554369/197357417-2d407aac-8969-44d3-82
</details>
</details>

335
docs/FAQ.md Normal file
View file

@ -0,0 +1,335 @@
---
hide:
- navigation
---
<!-- Auto-generated by FAQtory -->
<!-- Do not edit by hand! -->
# Frequently Asked Questions
Welcome to the Textual FAQ.
Here we try and answer any question that comes up frequently.
If you can't find what you are looking for here, see our other [help](./help.md) channels.
<a name="does-textual-support-images"></a>
## Does Textual support images?
Textual doesn't have built-in support for images yet, but it is on the [Roadmap](https://textual.textualize.io/roadmap/).
See also the [rich-pixels](https://github.com/darrenburns/rich-pixels) project for a Rich renderable for images that works with Textual.
---
<a name="how-can-i-fix-importerror-cannot-import-name-composeresult-from-textualapp-"></a>
## How can I fix ImportError cannot import name ComposeResult from textual.app ?
You likely have an older version of Textual. You can install the latest version by adding the `-U` switch which will force pip to upgrade.
The following should do it:
```
pip install textual-dev -U
```
---
<a name="how-can-i-select-and-copy-text-in-a-textual-app"></a>
## How can I select and copy text in a Textual app?
Running a Textual app puts your terminal in to *application mode* which disables clicking and dragging to select text.
Most terminal emulators offer a modifier key which you can hold while you click and drag to restore the behavior you
may expect from the command line. The exact modifier key depends on the terminal and platform you are running on.
- **iTerm** Hold the OPTION key.
- **Gnome Terminal** Hold the SHIFT key.
- **Windows Terminal** Hold the SHIFT key.
Refer to the documentation for your terminal emulator, if it is not listed above.
---
<a name="how-can-i-set-a-translucent-app-background"></a>
## How can I set a translucent app background?
Some terminal emulators have a translucent background feature which allows the desktop underneath to be partially visible.
This feature is unlikely to work with Textual, as the translucency effect requires the use of ANSI background colors, which Textual doesn't use.
Textual uses 16.7 million colors where available which enables consistent colors across all platforms and additional effects which aren't possible with ANSI colors.
For more information on ANSI colors in Textual, see [Why no Ansi Themes?](#why-doesnt-textual-support-ansi-themes).
---
<a name="how-do-i-center-a-widget-in-a-screen"></a>
## How do I center a widget in a screen?
!!! tip
See [*How To Center Things*](https://textual.textualize.io/how-to/center-things/) in the
Textual documentation for a more comprensive answer to this question.
To center a widget within a container use
[`align`](https://textual.textualize.io/styles/align/). But remember that
`align` works on the *children* of a container, it isn't something you use
on the child you want centered.
For example, here's an app that shows a `Button` in the middle of a
`Screen`:
```python
from textual.app import App, ComposeResult
from textual.widgets import Button
class ButtonApp(App):
CSS = """
Screen {
align: center middle;
}
"""
def compose(self) -> ComposeResult:
yield Button("PUSH ME!")
if __name__ == "__main__":
ButtonApp().run()
```
If you use the above on multiple widgets, you'll find they appear to
"left-align" in the center of the screen, like this:
```
+-----+
| |
+-----+
+---------+
| |
+---------+
+---------------+
| |
+---------------+
```
If you want them more like this:
```
+-----+
| |
+-----+
+---------+
| |
+---------+
+---------------+
| |
+---------------+
```
the best approach is to wrap each widget in a [`Center`
container](https://textual.textualize.io/api/containers/#textual.containers.Center)
that individually centers it. For example:
```python
from textual.app import App, ComposeResult
from textual.containers import Center
from textual.widgets import Button
class ButtonApp(App):
CSS = """
Screen {
align: center middle;
}
"""
def compose(self) -> ComposeResult:
yield Center(Button("PUSH ME!"))
yield Center(Button("AND ME!"))
yield Center(Button("ALSO PLEASE PUSH ME!"))
yield Center(Button("HEY ME ALSO!!"))
if __name__ == "__main__":
ButtonApp().run()
```
---
<a name="how-do-i-fix-workerdeclarationerror"></a>
## How do I fix WorkerDeclarationError?
Textual version 0.31.0 requires that you set `thread=True` on the `@work` decorator if you want to run a threaded worker.
If you want a threaded worker, you would declare it in the following way:
```python
@work(thread=True)
def run_in_background():
...
```
If you *don't* want a threaded worker, you should make your work function `async`:
```python
@work()
async def run_in_background():
...
```
This change was made because it was too easy to accidentally create a threaded worker, which may produce unexpected results.
---
<a name="how-do-i-pass-arguments-to-an-app"></a>
## How do I pass arguments to an app?
When creating your `App` class, override `__init__` as you would when
inheriting normally. For example:
```python
from textual.app import App, ComposeResult
from textual.widgets import Static
class Greetings(App[None]):
def __init__(self, greeting: str="Hello", to_greet: str="World") -> None:
self.greeting = greeting
self.to_greet = to_greet
super().__init__()
def compose(self) -> ComposeResult:
yield Static(f"{self.greeting}, {self.to_greet}")
```
Then the app can be run, passing in various arguments; for example:
```python
# Running with default arguments.
Greetings().run()
# Running with a keyword argument.
Greetings(to_greet="davep").run()
# Running with both positional arguments.
Greetings("Well hello", "there").run()
```
---
<a name="no-widget-called-textlog"></a>
## No widget called TextLog
The `TextLog` widget was renamed to `RichLog` in Textual 0.32.0.
You will need to replace all references to `TextLog` in your code, with `RichLog`.
Most IDEs will have a search and replace function which will help you do this.
Here's how you should import RichLog:
```python
from textual.widgets import RichLog
```
---
<a name="why-do-some-key-combinations-never-make-it-to-my-app"></a>
## Why do some key combinations never make it to my app?
Textual can only ever support key combinations that are passed on by your
terminal application. Which keys get passed on can differ from terminal to
terminal, and from operating system to operating system.
Because of this it's best to stick to key combinations that are known to be
universally-supported; these include the likes of:
- Letters
- Numbers
- Numbered function keys (especially F1 through F10)
- Space
- Return
- Arrow, home, end and page keys
- Control
- Shift
When [creating bindings for your
application](https://textual.textualize.io/guide/input/#bindings) we
recommend picking keys and key combinations from the above.
Keys that aren't normally passed through by terminals include Cmd and Option
on macOS, and the Windows key on Windows.
If you need to test what [key
combinations](https://textual.textualize.io/guide/input/#keyboard-input)
work in different environments you can try them out with `textual keys`.
---
<a name="why-doesn't-textual-look-good-on-macos"></a>
## Why doesn't Textual look good on macOS?
You may find that the default macOS Terminal.app doesn't render Textual apps (and likely other TUIs) very well, particuarily when it comes to box characters.
For instance, you may find it displays misaligned blocks and lines like this:
<img width="1042" alt="Screenshot 2023-06-19 at 10 43 02" src="https://github.com/Textualize/textual/assets/554369/e61f3876-3dd1-4ac8-b380-22922c89c7d6">
You can (mostly) fix this by opening settings -> profiles > Text tab, and changing the font settings.
We have found that Menlo Regular font, with a character spacing of 1 and line spacing of 0.805 produces reasonable results.
If you want to use another font, you may have to tweak the line spacing until you get good results.
<img width="737" alt="Screenshot 2023-06-19 at 10 44 00" src="https://github.com/Textualize/textual/assets/554369/0a052a93-b1fd-4327-9d33-d954b51a9ad2">
With these changes, Textual apps render more as intended:
<img width="1042" alt="Screenshot 2023-06-19 at 10 43 23" src="https://github.com/Textualize/textual/assets/554369/a0c4aa05-c509-4ac1-b0b8-e68ce4433f70">
Even with this *fix*, Terminal.app has a few limitations.
It is limited to 256 colors, and can be a little slow compared to more modern alternatives.
Fortunately there are a number of free terminal emulators for macOS which produces high quality results.
We recommend any of the following terminals:
- [iTerm2](https://iterm2.com/)
- [Kitty](https://sw.kovidgoyal.net/kitty/)
- [WezTerm](https://wezfurlong.org/wezterm/)
### Terminal.app colors
<img width="762" alt="Screenshot 2023-06-19 at 11 00 12" src="https://github.com/Textualize/textual/assets/554369/e0555d23-e141-4069-b318-f3965c880208">
### iTerm2 colors
<img width="1002" alt="Screenshot 2023-06-19 at 11 00 25" src="https://github.com/Textualize/textual/assets/554369/9a8cde57-5121-49a7-a2e0-5f6fc871b7a6">
---
<a name="why-doesn't-textual-support-ansi-themes"></a>
## Why doesn't Textual support ANSI themes?
Textual will not generate escape sequences for the 16 themeable *ANSI* colors.
This is an intentional design decision we took for for the following reasons:
- Not everyone has a carefully chosen ANSI color theme. Color combinations which may look fine on your system, may be unreadable on another machine. There is very little an app author or Textual can do to resolve this. Asking users to simply pick a better theme is not a good solution, since not all users will know how.
- ANSI colors can't be manipulated in the way Textual can do with other colors. Textual can blend colors and produce light and dark shades from an original color, which is used to create more readable text and user interfaces. Color blending will also be used to power future accessibility features.
Textual has a design system which guarantees apps will be readable on all platforms and terminals, and produces better results than ANSI colors.
There is currently a light and dark version of the design system, but more are planned. It will also be possible for users to customize the source colors on a per-app or per-system basis. This means that in the future you will be able to modify the core colors to blend in with your chosen terminal theme.
---
<a name="why-doesn't-the-`datatable`-scroll-programmatically"></a>
## Why doesn't the `DataTable` scroll programmatically?
If scrolling in your `DataTable` is _apparently_ broken, it may be because your `DataTable` is using the default value of `height: auto`.
This means that the table will be sized to fit its rows without scrolling, which may cause the *container* (typically the screen) to scroll.
If you would like the table itself to scroll, set the height to something other than `auto`, like `100%`.
**NOTE:** As of Textual v0.31.0 the `max-height` of a `DataTable` is set to `100%`, this will mean that the above is no longer the default experience.
---
Generated by [FAQtory](https://github.com/willmcgugan/faqtory)

View file

@ -0,0 +1,114 @@
{{ log.debug("Rendering " + class.path) }}
<div class="doc doc-object doc-class">
{% with html_id = class.path %}
{% if root %}
{% set show_full_path = config.show_root_full_path %}
{% set root_members = True %}
{% elif root_members %}
{% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %}
{% set root_members = False %}
{% else %}
{% set show_full_path = config.show_object_full_path %}
{% endif %}
{% if 1 %}
{% filter heading(heading_level,
role="class",
id=html_id,
class="doc doc-heading",
toc_label=class.name) %}
{% if config.separate_signature %}
<span class="doc doc-object-name doc-class-name">{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}</span>
{% elif config.merge_init_into_class and "__init__" in class.members -%}
{%- with function = class.members["__init__"] -%}
{%- filter highlight(language="python", inline=True) -%}
{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}
{%- include "signature.html" with context -%}
{%- endfilter -%}
{%- endwith -%}
{% else %}
<code>{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}</code>
{% endif %}
{% with labels = ['class'] %}
{% include "labels.html" with context %}
{% endwith %}
{% endfilter %}
{% if config.separate_signature and config.merge_init_into_class %}
{% if "__init__" in class.members %}
{% with function = class.members["__init__"] %}
{% filter highlight(language="python", inline=False) -%}
def {% filter format_signature(config.line_length) %}
__init__{% include "signature.html" with context %}
{% endfilter %}:
{% endfilter %}
{% endwith %}
{% endif %}
{% endif %}
{% else %}
{% if config.show_root_toc_entry %}
{% filter heading(heading_level,
role="class",
id=html_id,
toc_label=class.path if config.show_root_full_path else class.name,
hidden=True) %}
{% endfilter %}
{% endif %}
{% set heading_level = heading_level - 1 %}
{% endif %}
<div class="doc doc-contents {% if root %}first{% endif %}">
{% if config.show_bases and class.bases %}
<p class="doc doc-class-bases">
Bases: {% for expression in class.bases -%}
<code>{% include "expression.html" with context %}</code>{% if not loop.last %}, {% endif %}
{% endfor -%}
</p>
{% endif %}
{% with docstring_sections = class.docstring.parsed %}
{% include "docstring.html" with context %}
{% endwith %}
{% if config.merge_init_into_class %}
{% if "__init__" in class.members and class.members["__init__"].has_docstring %}
{% with docstring_sections = class.members["__init__"].docstring.parsed %}
{% include "docstring.html" with context %}
{% endwith %}
{% endif %}
{% endif %}
{% if config.show_source %}
{% if config.merge_init_into_class %}
{% if "__init__" in class.members and class.members["__init__"].source %}
<details class="quote">
<summary>Source code in <code>{{ class.relative_filepath }}</code></summary>
{{ class.members["__init__"].source|highlight(language="python", linestart=class.members["__init__"].lineno, linenums=True) }}
</details>
{% endif %}
{% elif class.source %}
<details class="quote">
<summary>Source code in <code>{{ class.relative_filepath }}</code></summary>
{{ class.source|highlight(language="python", linestart=class.lineno, linenums=True) }}
</details>
{% endif %}
{% endif %}
{% with obj = class %}
{% set root = False %}
{% set heading_level = heading_level + 1 %}
{% include "children.html" with context %}
{% endwith %}
</div>
{% endwith %}
</div>

View file

@ -0,0 +1,5 @@
{{ log.debug("Rendering admonition") }}
<details class="{{ section.value.kind }}" open>
<summary>{{ section.title|convert_markdown(heading_level, html_id, strip_paragraph=True) }}</summary>
{{ section.value.contents|convert_markdown(heading_level, html_id) }}
</details>

View file

@ -0,0 +1,78 @@
{{ log.debug("Rendering attributes section") }}
{% if config.docstring_section_style == "table" %}
{% block table_style %}
<h5>{{ section.title or "Attributes" }}</h5>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for attribute in section.value %}
<tr>
<td><code>{{ attribute.name }}</code></td>
<td>
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
{% endif %}
</td>
<td>{{ attribute.description|convert_markdown(heading_level, html_id) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock table_style %}
{% elif config.docstring_section_style == "list" %}
{% block list_style %}
<p>{{ section.title or "Attributes:" }}</p>
<ul>
{% for attribute in section.value %}
<li class="field-body">
<b>{{ attribute.name }}</b>
{% if attribute.annotation %}
{% with expression = attribute.annotation %}
(<code>{% include "expression.html" with context %}</code>)
{% endwith %}
{% endif %}
{{ attribute.description|convert_markdown(heading_level, html_id) }}
</li>
{% endfor %}
</ul>
{% endblock list_style %}
{% elif config.docstring_section_style == "spacy" %}
{% block spacy_style %}
<table>
<thead>
<tr>
<th><b>{{ (section.title or "ATTRIBUTE").rstrip(":").upper() }}</b></th>
<th><b>DESCRIPTION</b></th>
</tr>
</thead>
<tbody>
{% for attribute in section.value %}
<tr>
<td><code>{{ attribute.name }}</code></td>
<td class="doc-attribute-details">
{{ attribute.description|convert_markdown(heading_level, html_id) }}
<p>
{% if attribute.annotation %}
<span class="doc-attribute-annotation">
<b>TYPE:</b>
{% with expression = attribute.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
</span>
{% endif %}
</p>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock spacy_style %}
{% endif %}

View file

@ -0,0 +1,96 @@
{{ log.debug("Rendering parameters section") }}
{% if config.docstring_section_style == "table" %}
{% block table_style %}
<h5>{{ section.title or "Parameters" }}</h5>
<table>
<thead>
<tr>
<th>Parameter</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for parameter in section.value %}
<tr>
<td>
<strong><code>{{ parameter.name }}</code></strong>
<br>
{% if parameter.annotation %}
{% with expression = parameter.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
{% endif %}
</td>
<td>
{% if parameter.default %}
{% with expression = parameter.default %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
{% else %}
<em>required</em>
{% endif %}
</td>
<td>{{ parameter.description|convert_markdown(heading_level, html_id) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock table_style %}
{% elif config.docstring_section_style == "list" %}
{% block list_style %}
<p>{{ section.title or "Parameters:" }}</p>
<ul>
{% for parameter in section.value %}
<li class="field-body">
<b>{{ parameter.name }}</b>
{% if parameter.annotation %}
{% with expression = parameter.annotation %}
(<code>{% include "expression.html" with context %}</code>)
{% endwith %}
{% endif %}
{{ parameter.description|convert_markdown(heading_level, html_id) }}
</li>
{% endfor %}
</ul>
{% endblock list_style %}
{% elif config.docstring_section_style == "spacy" %}
{% block spacy_style %}
<table>
<thead>
<tr>
<th><b>{{ (section.title or "PARAMETER").rstrip(":").upper() }}</b></th>
<th><b>DESCRIPTION</b></th>
</tr>
</thead>
<tbody>
{% for parameter in section.value %}
<tr>
<td><code>{{ parameter.name }}</code></td>
<td class="doc-param-details">
{{ parameter.description|convert_markdown(heading_level, html_id) }}
<p>
{% if parameter.annotation %}
<span class="doc-param-annotation">
<b>TYPE:</b>
{% with expression = parameter.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
</span>
{% endif %}
{% if parameter.default %}
<span class="doc-param-default">
<b>DEFAULT:</b>
{% with expression = parameter.default %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
</span>
{% endif %}
</p>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock spacy_style %}
{% endif %}

View file

@ -0,0 +1,72 @@
{{ log.debug("Rendering raises section") }}
{% if config.docstring_section_style == "table" %}
{% block table_style %}
<h5>{{ section.title or "Raises" }}</h5>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for raises in section.value %}
<tr>
<td>
{% if raises.annotation %}
{% with expression = raises.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
{% endif %}
</td>
<td>{{ raises.description|convert_markdown(heading_level, html_id) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock table_style %}
{% elif config.docstring_section_style == "list" %}
{% block list_style %}
<p>{{ section.title or "Raises:" }}</p>
<ul>
{% for raises in section.value %}
<li class="field-body">
{% if raises.annotation %}
{% with expression = raises.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
{% endif %}
{{ raises.description|convert_markdown(heading_level, html_id) }}
</li>
{% endfor %}
</ul>
{% endblock list_style %}
{% elif config.docstring_section_style == "spacy" %}
{% block spacy_style %}
<table>
<thead>
<tr>
<th><b>{{ (section.title or "RAISES").rstrip(":").upper() }}</b></th>
<th><b>DESCRIPTION</b></th>
</tr>
</thead>
<tbody>
{% for raises in section.value %}
<tr>
<td>
<span class="doc-raises-annotation">
{% with expression = raises.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
</span>
</td>
<td class="doc-raises-details">
{{ raises.description|convert_markdown(heading_level, html_id) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock spacy_style %}
{% endif %}

View file

@ -0,0 +1,91 @@
{{ log.debug("Rendering returns section") }}
{% if config.docstring_section_style == "table" %}
{% block table_style %}
{% set name_column = section.value|selectattr("name")|any %}
<h5>{{ section.title or "Returns" }}</h5>
<table>
<thead>
<tr>
{% if name_column %}<th>Name</th>{% endif %}
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for returns in section.value %}
<tr>
{% if name_column %}<td>{% if returns.name %}<code>{{ returns.name }}</code>{% endif %}</td>{% endif %}
<td>
{% if returns.annotation %}
{% with expression = returns.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
{% endif %}
</td>
<td>{{ returns.description|convert_markdown(heading_level, html_id) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock table_style %}
{% elif config.docstring_section_style == "list" %}
{% block list_style %}
<p>{{ section.title or "Returns:" }}</p>
<ul>
{% for returns in section.value %}
<li class="field-body">
{% if returns.name %}<b>{{ returns.name }}</b>{% endif %}
{% if returns.annotation %}
{% with expression = returns.annotation %}
{% if returns.name %}({% endif %}
<code>{% include "expression.html" with context %}</code>
{% if returns.name %}){% endif %}
{% endwith %}
{% endif %}
{{ returns.description|convert_markdown(heading_level, html_id) }}
</li>
{% endfor %}
</ul>
{% endblock list_style %}
{% elif config.docstring_section_style == "spacy" %}
{% block spacy_style %}
<table>
<thead>
<tr>
<th><b>{{ (section.title or "RETURNS").rstrip(":").upper() }}</b></th>
<th><b>DESCRIPTION</b></th>
</tr>
</thead>
<tbody>
{% for returns in section.value %}
<tr>
<td>
{% if returns.name %}
<code>{{ returns.name }}</code>
{% elif returns.annotation %}
<span class="doc-returns-annotation">
{% with expression = returns.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
</span>
{% endif %}
</td>
<td class="doc-returns-details">
{{ returns.description|convert_markdown(heading_level, html_id) }}
{% if returns.name and returns.annotation %}
<p>
<span class="doc-returns-annotation">
<b>TYPE:</b>
{% with expression = returns.annotation %}
<code>{% include "expression.html" with context %}</code>
{% endwith %}
</span>
</p>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock spacy_style %}
{% endif %}

View file

@ -0,0 +1,73 @@
{{ log.debug("Rendering " + function.path) }}
<div class="doc doc-object doc-function">
{% with html_id = function.path %}
{% if root %}
{% set show_full_path = config.show_root_full_path %}
{% set root_members = True %}
{% elif root_members %}
{% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %}
{% set root_members = False %}
{% else %}
{% set show_full_path = config.show_object_full_path %}
{% endif %}
{% if not root or config.show_root_heading %}
{% filter heading(heading_level,
role="function",
id=html_id,
class="doc doc-heading",
toc_label=function.name ~ "()") %}
{% if config.separate_signature %}
<span class="doc doc-object-name doc-function-name">{% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %}</span>
{% else %}
{% filter highlight(language="python", inline=True) %}
{% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %}
{% include "signature.html" with context %}
{% endfilter %}
{% endif %}
{% with labels = function.labels or [(function.parameters._parameters_list and function.parameters._parameters_list[0].name == 'self') and 'method' or 'function'] %}
{% include "labels.html" with context %}
{% endwith %}
{% endfilter %}
{% if config.separate_signature %}
{% filter highlight(language="python", inline=False) %}
def {% filter format_signature(config.line_length) %}
{% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %}
{% include "signature.html" with context %}
{% endfilter %}:
{% endfilter %}
{% endif %}
{% else %}
{% if config.show_root_toc_entry %}
{% filter heading(heading_level,
role="function",
id=html_id,
toc_label=function.path if config.show_root_full_path else function.name,
hidden=True) %}
{% endfilter %}
{% endif %}
{% set heading_level = heading_level - 1 %}
{% endif %}
<div class="doc doc-contents {% if root %}first{% endif %}">
{% with docstring_sections = function.docstring.parsed %}
{% include "docstring.html" with context %}
{% endwith %}
{% if config.show_source and function.source %}
<details class="quote">
<summary>Source code in <code>{{ function.relative_filepath }}</code></summary>
{{ function.source|highlight(language="python", linestart=function.lineno, linenums=True) }}
</details>
{% endif %}
</div>
{% endwith %}
</div>

View file

@ -0,0 +1,48 @@
{%- if config.show_signature -%}
{{ log.debug("Rendering signature") }}
{%- with -%}
{%- set ns = namespace(has_pos_only=False, render_pos_only_separator=True, render_kw_only_separator=True, equal="=") -%}
{%- if config.show_signature_annotations -%}
{%- set ns.equal = " = " -%}
{%- endif -%}
(
{%- for parameter in function.parameters -%}
{%- if 1 -%}
{%- if parameter.kind.value == "positional-only" -%}
{%- set ns.has_pos_only = True -%}
{%- else -%}
{%- if ns.has_pos_only and ns.render_pos_only_separator -%}
{%- set ns.render_pos_only_separator = False %}/, {% endif -%}
{%- if parameter.kind.value == "keyword-only" -%}
{%- if ns.render_kw_only_separator -%}
{%- set ns.render_kw_only_separator = False %}*, {% endif -%}
{%- endif -%}
{%- endif -%}
{%- if config.show_signature_annotations and parameter.annotation is not none -%}
{%- set annotation = ": " + parameter.annotation|safe -%}
{%- endif -%}
{%- if parameter.default is not none and parameter.kind.value != "variadic positional" and parameter.kind.value != "variadic keyword" -%}
{%- set default = ns.equal + parameter.default|safe -%}
{%- endif -%}
{%- if parameter.kind.value == "variadic positional" -%}
{%- set ns.render_kw_only_separator = False -%}
{%- endif -%}
{% if parameter.kind.value == "variadic positional" %}*{% elif parameter.kind.value == "variadic keyword" %}**{% endif -%}
{{ parameter.name }}{{ annotation }}{{ default }}
{%- if not loop.last %}, {% endif -%}
{%- endif -%}
{%- endfor -%}
)
{%- if config.show_signature_annotations and function.annotation %} -> {{ function.annotation|safe }}{%- endif -%}
{%- endwith -%}
{%- endif -%}

View file

@ -1,67 +0,0 @@
{{ log.debug("Rendering " + attribute.path) }}
<div class="doc doc-object doc-attribute">
{% with html_id = attribute.path %}
{% if root %}
{% set show_full_path = config.show_root_full_path %}
{% set root_members = True %}
{% elif root_members %}
{% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %}
{% set root_members = False %}
{% else %}
{% set show_full_path = config.show_object_full_path %}
{% endif %}
{% if not root or config.show_root_heading %}
{% filter heading(heading_level,
role="data" if attribute.parent.kind.value == "module" else "attr",
id=html_id,
class="doc doc-heading",
toc_label=attribute.name) %}
{% if config.separate_signature %}
<span class="doc doc-object-name doc-attribute-name">{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}</span>
{% else %}
{% filter highlight(language="python", inline=True) %}
{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}
{% if attribute.annotation %}: {{ attribute.annotation }}{% endif %}
{% endfilter %}
{% endif %}
{% with labels = attribute.labels %}
{% include "labels.html" with context %}
{% endwith %}
{% endfilter %}
{% if config.separate_signature %}
{% filter highlight(language="python", inline=False) %}
{% filter format_code(config.line_length) %}
{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}
{% if attribute.annotation %}: {{ attribute.annotation|safe }}{% endif %}
{% endfilter %}
{% endfilter %}
{% endif %}
{% else %}
{% if config.show_root_toc_entry %}
{% filter heading(heading_level,
role="data" if attribute.parent.kind.value == "module" else "attr",
id=html_id,
toc_label=attribute.path if config.show_root_full_path else attribute.name,
hidden=True) %}
{% endfilter %}
{% endif %}
{% set heading_level = heading_level - 1 %}
{% endif %}
<div class="doc doc-contents {% if root %}first{% endif %}">
{% with docstring_sections = attribute.docstring.parsed %}
{% include "docstring.html" with context %}
{% endwith %}
</div>
{% endwith %}
</div>

View file

@ -1 +1,5 @@
::: textual.app
options:
filters:
- "!^_"
- "^__init__$"

View file

@ -1,3 +0,0 @@
::: textual.widgets.Button
::: textual.widgets._button.ButtonVariant
::: textual.widgets._button.InvalidButtonVariant

View file

@ -1 +0,0 @@
::: textual.widgets.Checkbox

1
docs/api/command.md Normal file
View file

@ -0,0 +1 @@
::: textual.command

View file

@ -1 +0,0 @@
::: textual.widgets.DataTable

View file

@ -1 +0,0 @@
::: textual.widgets.DirectoryTree

1
docs/api/errors.md Normal file
View file

@ -0,0 +1 @@
::: textual.errors

1
docs/api/filter.md Normal file
View file

@ -0,0 +1 @@
::: textual.filter

View file

@ -1 +0,0 @@
::: textual.widgets.Footer

View file

@ -0,0 +1 @@
::: textual.fuzzy

View file

@ -1 +0,0 @@
::: textual.widgets.Header

View file

@ -1 +0,0 @@
::: textual.widgets.Input

View file

@ -1 +0,0 @@
::: textual.widgets.Label

View file

@ -1 +0,0 @@
::: textual.widgets.ListItem

View file

@ -1 +0,0 @@
::: textual.widgets.ListView

View file

@ -1 +0,0 @@
::: textual.widgets.LoadingIndicator

5
docs/api/logger.md Normal file
View file

@ -0,0 +1,5 @@
# Logger
A [logger class](/guide/devtools/#logging-handler) that logs to the Textual [console](/guide/devtools#console).
::: textual.Logger

1
docs/api/logging.md Normal file
View file

@ -0,0 +1 @@
::: textual.logging

3
docs/api/map_geometry.md Normal file
View file

@ -0,0 +1,3 @@
A data structure returned by [screen.find_widget][textual.screen.Screen.find_widget].
::: textual._compositor.MapGeometry

View file

@ -1 +0,0 @@
::: textual.widgets.Markdown

View file

@ -1 +0,0 @@
::: textual.widgets.MarkdownViewer

View file

@ -1,5 +1 @@
A message pump is a class that processes messages.
It is a base class for the `App`, `Screen`, and `Widget` classes.
::: textual.message_pump

3
docs/api/on.md Normal file
View file

@ -0,0 +1,3 @@
# On
::: textual.on

View file

@ -1,2 +0,0 @@
::: textual.widgets.Placeholder
::: textual.widgets._placeholder.PlaceholderVariant

View file

@ -1 +0,0 @@
::: textual.widgets.RadioButton

View file

@ -1 +0,0 @@
::: textual.widgets.RadioSet

1
docs/api/scrollbar.md Normal file
View file

@ -0,0 +1 @@
::: textual.scrollbar

View file

@ -1 +0,0 @@
::: textual.widgets.Static

1
docs/api/suggester.md Normal file
View file

@ -0,0 +1 @@
::: textual.suggester

View file

@ -1 +0,0 @@
::: textual.widgets.Switch

View file

@ -0,0 +1 @@
::: textual._system_commands

View file

@ -1,2 +0,0 @@
::: textual.widgets.Tab
::: textual.widgets.Tabs

View file

@ -1 +0,0 @@
::: textual.widgets.TextLog

View file

@ -1 +0,0 @@
::: textual.widgets._toggle_button.ToggleButton

View file

@ -1,4 +0,0 @@
::: textual.widgets.Tree
::: textual.widgets._tree.TreeNode
::: textual.widgets._tree.NodeID
::: textual.widgets._tree.TreeDataType

1
docs/api/types.md Normal file
View file

@ -0,0 +1 @@
::: textual.types

1
docs/api/validation.md Normal file
View file

@ -0,0 +1 @@
::: textual.validation

View file

@ -1 +0,0 @@
::: textual.widgets.Welcome

View file

@ -1 +1,5 @@
::: textual.widget
options:
filters:
- "!^_"
- "^__init__$"

2
docs/api/work.md Normal file
View file

@ -0,0 +1,2 @@
::: textual.work

1
docs/api/worker.md Normal file
View file

@ -0,0 +1 @@
::: textual.worker

View file

@ -0,0 +1 @@
::: textual._worker_manager

View file

@ -1,16 +1,17 @@
willmcgugan:
name: Will McGugan
description: CEO / code-monkey
avatar: https://github.com/willmcgugan.png
darrenburns:
name: Darren Burns
description: Code-monkey
avatar: https://github.com/darrenburns.png
davep:
name: Dave Pearson
description: Code-monkey
avatar: https://github.com/davep.png
rodrigo:
name: Rodrigo Girão Serrão
description: Code-monkey
avatar: https://github.com/rodrigogiraoserrao.png
authors:
willmcgugan:
name: Will McGugan
description: CEO / code-monkey
avatar: https://github.com/willmcgugan.png
darrenburns:
name: Darren Burns
description: Code-monkey
avatar: https://github.com/darrenburns.png
davep:
name: Dave Pearson
description: Code-monkey
avatar: https://github.com/davep.png
rodrigo:
name: Rodrigo Girão Serrão
description: Code-monkey
avatar: https://github.com/rodrigogiraoserrao.png

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 40 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 128 KiB

View file

@ -0,0 +1,17 @@
from rich import inspect
from rich.console import Console
c = Console(record=True, width=110)
f = open("foo.txt", "w")
inspect(f, console=c)
c.save_svg("inspect1.svg")
inspect(f, console=c, methods=True)
c.save_svg("inspect2.svg")
inspect(f, console=c, methods=True, help=True)
c.save_svg("inspect3.svg")

View file

@ -0,0 +1,132 @@
<svg class="rich-terminal" viewBox="0 0 1360 464.79999999999995" 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-861812764-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-861812764-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-861812764-r1 { fill: #608ab1 }
.terminal-861812764-r2 { fill: #608ab1;font-weight: bold }
.terminal-861812764-r3 { fill: #ff2c7a;font-weight: bold }
.terminal-861812764-r4 { fill: #c5c8c6 }
.terminal-861812764-r5 { fill: #98a84b }
.terminal-861812764-r6 { fill: #68a0b3 }
.terminal-861812764-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-861812764-r8 { fill: #d0b344 }
.terminal-861812764-r9 { fill: #d0b344;font-style: italic; }
.terminal-861812764-r10 { fill: #ff2627;font-style: italic; }
.terminal-861812764-r11 { fill: #98729f;font-style: italic; }
</style>
<defs>
<clipPath id="terminal-861812764-clip-terminal">
<rect x="0" y="0" width="1341.0" height="413.79999999999995" />
</clipPath>
<clipPath id="terminal-861812764-line-0">
<rect x="0" y="1.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-1">
<rect x="0" y="25.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-2">
<rect x="0" y="50.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-3">
<rect x="0" y="74.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-4">
<rect x="0" y="99.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-5">
<rect x="0" y="123.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-6">
<rect x="0" y="147.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-7">
<rect x="0" y="172.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-8">
<rect x="0" y="196.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-9">
<rect x="0" y="221.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-10">
<rect x="0" y="245.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-11">
<rect x="0" y="269.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-12">
<rect x="0" y="294.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-13">
<rect x="0" y="318.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-14">
<rect x="0" y="343.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-861812764-line-15">
<rect x="0" y="367.5" width="1342" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1358" height="462.8" rx="8"/><text class="terminal-861812764-title" fill="#c5c8c6" text-anchor="middle" x="679" y="27">Rich</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-861812764-clip-terminal)">
<g class="terminal-861812764-matrix">
<text class="terminal-861812764-r1" x="0" y="20" textLength="24.4" clip-path="url(#terminal-861812764-line-0)">╭─</text><text class="terminal-861812764-r1" x="24.4" y="20" textLength="231.8" clip-path="url(#terminal-861812764-line-0)">───────────────────</text><text class="terminal-861812764-r2" x="268.4" y="20" textLength="12.2" clip-path="url(#terminal-861812764-line-0)">&lt;</text><text class="terminal-861812764-r3" x="280.6" y="20" textLength="61" clip-path="url(#terminal-861812764-line-0)">class</text><text class="terminal-861812764-r5" x="353.8" y="20" textLength="231.8" clip-path="url(#terminal-861812764-line-0)">&#x27;_io.TextIOWrapper&#x27;</text><text class="terminal-861812764-r2" x="585.6" y="20" textLength="12.2" clip-path="url(#terminal-861812764-line-0)">&gt;</text><text class="terminal-861812764-r1" x="610" y="20" textLength="244" clip-path="url(#terminal-861812764-line-0)">────────────────────</text><text class="terminal-861812764-r1" x="854" y="20" textLength="24.4" clip-path="url(#terminal-861812764-line-0)">─╮</text><text class="terminal-861812764-r4" x="1342" y="20" textLength="12.2" clip-path="url(#terminal-861812764-line-0)">
</text><text class="terminal-861812764-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-861812764-line-1)"></text><text class="terminal-861812764-r6" x="24.4" y="44.4" textLength="829.6" clip-path="url(#terminal-861812764-line-1)">Character&#160;and&#160;line&#160;based&#160;layer&#160;over&#160;a&#160;BufferedIOBase&#160;object,&#160;buffer.</text><text class="terminal-861812764-r1" x="866.2" y="44.4" textLength="12.2" clip-path="url(#terminal-861812764-line-1)"></text><text class="terminal-861812764-r4" x="1342" y="44.4" textLength="12.2" clip-path="url(#terminal-861812764-line-1)">
</text><text class="terminal-861812764-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-861812764-line-2)"></text><text class="terminal-861812764-r1" x="866.2" y="68.8" textLength="12.2" clip-path="url(#terminal-861812764-line-2)"></text><text class="terminal-861812764-r4" x="1342" y="68.8" textLength="12.2" clip-path="url(#terminal-861812764-line-2)">
</text><text class="terminal-861812764-r1" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-861812764-line-3)"></text><text class="terminal-861812764-r5" x="24.4" y="93.2" textLength="829.6" clip-path="url(#terminal-861812764-line-3)">╭──────────────────────────────────────────────────────────────────╮</text><text class="terminal-861812764-r1" x="866.2" y="93.2" textLength="12.2" clip-path="url(#terminal-861812764-line-3)"></text><text class="terminal-861812764-r4" x="1342" y="93.2" textLength="12.2" clip-path="url(#terminal-861812764-line-3)">
</text><text class="terminal-861812764-r1" x="0" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)"></text><text class="terminal-861812764-r5" x="24.4" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)"></text><text class="terminal-861812764-r7" x="48.8" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)">&lt;</text><text class="terminal-861812764-r3" x="61" y="117.6" textLength="207.4" clip-path="url(#terminal-861812764-line-4)">_io.TextIOWrapper</text><text class="terminal-861812764-r8" x="280.6" y="117.6" textLength="48.8" clip-path="url(#terminal-861812764-line-4)">name</text><text class="terminal-861812764-r4" x="329.4" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)">=</text><text class="terminal-861812764-r5" x="341.6" y="117.6" textLength="109.8" clip-path="url(#terminal-861812764-line-4)">&#x27;foo.txt&#x27;</text><text class="terminal-861812764-r8" x="463.6" y="117.6" textLength="48.8" clip-path="url(#terminal-861812764-line-4)">mode</text><text class="terminal-861812764-r4" x="512.4" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)">=</text><text class="terminal-861812764-r5" x="524.6" y="117.6" textLength="36.6" clip-path="url(#terminal-861812764-line-4)">&#x27;w&#x27;</text><text class="terminal-861812764-r8" x="573.4" y="117.6" textLength="97.6" clip-path="url(#terminal-861812764-line-4)">encoding</text><text class="terminal-861812764-r4" x="671" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)">=</text><text class="terminal-861812764-r5" x="683.2" y="117.6" textLength="85.4" clip-path="url(#terminal-861812764-line-4)">&#x27;UTF-8&#x27;</text><text class="terminal-861812764-r7" x="768.6" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)">&gt;</text><text class="terminal-861812764-r5" x="841.8" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)"></text><text class="terminal-861812764-r1" x="866.2" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)"></text><text class="terminal-861812764-r4" x="1342" y="117.6" textLength="12.2" clip-path="url(#terminal-861812764-line-4)">
</text><text class="terminal-861812764-r1" x="0" y="142" textLength="12.2" clip-path="url(#terminal-861812764-line-5)"></text><text class="terminal-861812764-r5" x="24.4" y="142" textLength="829.6" clip-path="url(#terminal-861812764-line-5)">╰──────────────────────────────────────────────────────────────────╯</text><text class="terminal-861812764-r1" x="866.2" y="142" textLength="12.2" clip-path="url(#terminal-861812764-line-5)"></text><text class="terminal-861812764-r4" x="1342" y="142" textLength="12.2" clip-path="url(#terminal-861812764-line-5)">
</text><text class="terminal-861812764-r1" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-861812764-line-6)"></text><text class="terminal-861812764-r1" x="866.2" y="166.4" textLength="12.2" clip-path="url(#terminal-861812764-line-6)"></text><text class="terminal-861812764-r4" x="1342" y="166.4" textLength="12.2" clip-path="url(#terminal-861812764-line-6)">
</text><text class="terminal-861812764-r1" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-861812764-line-7)"></text><text class="terminal-861812764-r9" x="122" y="190.8" textLength="73.2" clip-path="url(#terminal-861812764-line-7)">buffer</text><text class="terminal-861812764-r4" x="195.2" y="190.8" textLength="24.4" clip-path="url(#terminal-861812764-line-7)">&#160;=</text><text class="terminal-861812764-r7" x="231.8" y="190.8" textLength="12.2" clip-path="url(#terminal-861812764-line-7)">&lt;</text><text class="terminal-861812764-r3" x="244" y="190.8" textLength="219.6" clip-path="url(#terminal-861812764-line-7)">_io.BufferedWriter</text><text class="terminal-861812764-r8" x="475.8" y="190.8" textLength="48.8" clip-path="url(#terminal-861812764-line-7)">name</text><text class="terminal-861812764-r4" x="524.6" y="190.8" textLength="12.2" clip-path="url(#terminal-861812764-line-7)">=</text><text class="terminal-861812764-r5" x="536.8" y="190.8" textLength="109.8" clip-path="url(#terminal-861812764-line-7)">&#x27;foo.txt&#x27;</text><text class="terminal-861812764-r7" x="646.6" y="190.8" textLength="12.2" clip-path="url(#terminal-861812764-line-7)">&gt;</text><text class="terminal-861812764-r1" x="866.2" y="190.8" textLength="12.2" clip-path="url(#terminal-861812764-line-7)"></text><text class="terminal-861812764-r4" x="1342" y="190.8" textLength="12.2" clip-path="url(#terminal-861812764-line-7)">
</text><text class="terminal-861812764-r1" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-861812764-line-8)"></text><text class="terminal-861812764-r9" x="122" y="215.2" textLength="73.2" clip-path="url(#terminal-861812764-line-8)">closed</text><text class="terminal-861812764-r4" x="195.2" y="215.2" textLength="24.4" clip-path="url(#terminal-861812764-line-8)">&#160;=</text><text class="terminal-861812764-r10" x="231.8" y="215.2" textLength="61" clip-path="url(#terminal-861812764-line-8)">False</text><text class="terminal-861812764-r1" x="866.2" y="215.2" textLength="12.2" clip-path="url(#terminal-861812764-line-8)"></text><text class="terminal-861812764-r4" x="1342" y="215.2" textLength="12.2" clip-path="url(#terminal-861812764-line-8)">
</text><text class="terminal-861812764-r1" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-861812764-line-9)"></text><text class="terminal-861812764-r9" x="97.6" y="239.6" textLength="97.6" clip-path="url(#terminal-861812764-line-9)">encoding</text><text class="terminal-861812764-r4" x="195.2" y="239.6" textLength="24.4" clip-path="url(#terminal-861812764-line-9)">&#160;=</text><text class="terminal-861812764-r5" x="231.8" y="239.6" textLength="85.4" clip-path="url(#terminal-861812764-line-9)">&#x27;UTF-8&#x27;</text><text class="terminal-861812764-r1" x="866.2" y="239.6" textLength="12.2" clip-path="url(#terminal-861812764-line-9)"></text><text class="terminal-861812764-r4" x="1342" y="239.6" textLength="12.2" clip-path="url(#terminal-861812764-line-9)">
</text><text class="terminal-861812764-r1" x="0" y="264" textLength="12.2" clip-path="url(#terminal-861812764-line-10)"></text><text class="terminal-861812764-r9" x="122" y="264" textLength="73.2" clip-path="url(#terminal-861812764-line-10)">errors</text><text class="terminal-861812764-r4" x="195.2" y="264" textLength="24.4" clip-path="url(#terminal-861812764-line-10)">&#160;=</text><text class="terminal-861812764-r5" x="231.8" y="264" textLength="97.6" clip-path="url(#terminal-861812764-line-10)">&#x27;strict&#x27;</text><text class="terminal-861812764-r1" x="866.2" y="264" textLength="12.2" clip-path="url(#terminal-861812764-line-10)"></text><text class="terminal-861812764-r4" x="1342" y="264" textLength="12.2" clip-path="url(#terminal-861812764-line-10)">
</text><text class="terminal-861812764-r1" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-861812764-line-11)"></text><text class="terminal-861812764-r9" x="24.4" y="288.4" textLength="170.8" clip-path="url(#terminal-861812764-line-11)">line_buffering</text><text class="terminal-861812764-r4" x="195.2" y="288.4" textLength="24.4" clip-path="url(#terminal-861812764-line-11)">&#160;=</text><text class="terminal-861812764-r10" x="231.8" y="288.4" textLength="61" clip-path="url(#terminal-861812764-line-11)">False</text><text class="terminal-861812764-r1" x="866.2" y="288.4" textLength="12.2" clip-path="url(#terminal-861812764-line-11)"></text><text class="terminal-861812764-r4" x="1342" y="288.4" textLength="12.2" clip-path="url(#terminal-861812764-line-11)">
</text><text class="terminal-861812764-r1" x="0" y="312.8" textLength="12.2" clip-path="url(#terminal-861812764-line-12)"></text><text class="terminal-861812764-r9" x="146.4" y="312.8" textLength="48.8" clip-path="url(#terminal-861812764-line-12)">mode</text><text class="terminal-861812764-r4" x="195.2" y="312.8" textLength="24.4" clip-path="url(#terminal-861812764-line-12)">&#160;=</text><text class="terminal-861812764-r5" x="231.8" y="312.8" textLength="36.6" clip-path="url(#terminal-861812764-line-12)">&#x27;w&#x27;</text><text class="terminal-861812764-r1" x="866.2" y="312.8" textLength="12.2" clip-path="url(#terminal-861812764-line-12)"></text><text class="terminal-861812764-r4" x="1342" y="312.8" textLength="12.2" clip-path="url(#terminal-861812764-line-12)">
</text><text class="terminal-861812764-r1" x="0" y="337.2" textLength="12.2" clip-path="url(#terminal-861812764-line-13)"></text><text class="terminal-861812764-r9" x="146.4" y="337.2" textLength="48.8" clip-path="url(#terminal-861812764-line-13)">name</text><text class="terminal-861812764-r4" x="195.2" y="337.2" textLength="24.4" clip-path="url(#terminal-861812764-line-13)">&#160;=</text><text class="terminal-861812764-r5" x="231.8" y="337.2" textLength="109.8" clip-path="url(#terminal-861812764-line-13)">&#x27;foo.txt&#x27;</text><text class="terminal-861812764-r1" x="866.2" y="337.2" textLength="12.2" clip-path="url(#terminal-861812764-line-13)"></text><text class="terminal-861812764-r4" x="1342" y="337.2" textLength="12.2" clip-path="url(#terminal-861812764-line-13)">
</text><text class="terminal-861812764-r1" x="0" y="361.6" textLength="12.2" clip-path="url(#terminal-861812764-line-14)"></text><text class="terminal-861812764-r9" x="97.6" y="361.6" textLength="97.6" clip-path="url(#terminal-861812764-line-14)">newlines</text><text class="terminal-861812764-r4" x="195.2" y="361.6" textLength="24.4" clip-path="url(#terminal-861812764-line-14)">&#160;=</text><text class="terminal-861812764-r11" x="231.8" y="361.6" textLength="48.8" clip-path="url(#terminal-861812764-line-14)">None</text><text class="terminal-861812764-r1" x="866.2" y="361.6" textLength="12.2" clip-path="url(#terminal-861812764-line-14)"></text><text class="terminal-861812764-r4" x="1342" y="361.6" textLength="12.2" clip-path="url(#terminal-861812764-line-14)">
</text><text class="terminal-861812764-r1" x="0" y="386" textLength="12.2" clip-path="url(#terminal-861812764-line-15)"></text><text class="terminal-861812764-r9" x="36.6" y="386" textLength="158.6" clip-path="url(#terminal-861812764-line-15)">write_through</text><text class="terminal-861812764-r4" x="195.2" y="386" textLength="24.4" clip-path="url(#terminal-861812764-line-15)">&#160;=</text><text class="terminal-861812764-r10" x="231.8" y="386" textLength="61" clip-path="url(#terminal-861812764-line-15)">False</text><text class="terminal-861812764-r1" x="866.2" y="386" textLength="12.2" clip-path="url(#terminal-861812764-line-15)"></text><text class="terminal-861812764-r4" x="1342" y="386" textLength="12.2" clip-path="url(#terminal-861812764-line-15)">
</text><text class="terminal-861812764-r1" x="0" y="410.4" textLength="878.4" clip-path="url(#terminal-861812764-line-16)">╰──────────────────────────────────────────────────────────────────────╯</text><text class="terminal-861812764-r4" x="1342" y="410.4" textLength="12.2" clip-path="url(#terminal-861812764-line-16)">
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,223 @@
<svg class="rich-terminal" viewBox="0 0 1360 977.1999999999999" 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-1452477714-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-1452477714-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-1452477714-r1 { fill: #608ab1 }
.terminal-1452477714-r2 { fill: #608ab1;font-weight: bold }
.terminal-1452477714-r3 { fill: #ff2c7a;font-weight: bold }
.terminal-1452477714-r4 { fill: #c5c8c6 }
.terminal-1452477714-r5 { fill: #98a84b }
.terminal-1452477714-r6 { fill: #68a0b3 }
.terminal-1452477714-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-1452477714-r8 { fill: #d0b344 }
.terminal-1452477714-r9 { fill: #d0b344;font-style: italic; }
.terminal-1452477714-r10 { fill: #ff2627;font-style: italic; }
.terminal-1452477714-r11 { fill: #98729f;font-style: italic; }
.terminal-1452477714-r12 { fill: #398280;font-style: italic; }
.terminal-1452477714-r13 { fill: #cc555a;font-weight: bold }
.terminal-1452477714-r14 { fill: #868887 }
.terminal-1452477714-r15 { fill: #6b753d }
.terminal-1452477714-r16 { fill: #68a0b3;font-weight: bold }
.terminal-1452477714-r17 { fill: #98729f }
.terminal-1452477714-r18 { fill: #868887;font-weight: bold }
</style>
<defs>
<clipPath id="terminal-1452477714-clip-terminal">
<rect x="0" y="0" width="1341.0" height="926.1999999999999" />
</clipPath>
<clipPath id="terminal-1452477714-line-0">
<rect x="0" y="1.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-1">
<rect x="0" y="25.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-2">
<rect x="0" y="50.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-3">
<rect x="0" y="74.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-4">
<rect x="0" y="99.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-5">
<rect x="0" y="123.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-6">
<rect x="0" y="147.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-7">
<rect x="0" y="172.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-8">
<rect x="0" y="196.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-9">
<rect x="0" y="221.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-10">
<rect x="0" y="245.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-11">
<rect x="0" y="269.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-12">
<rect x="0" y="294.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-13">
<rect x="0" y="318.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-14">
<rect x="0" y="343.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-15">
<rect x="0" y="367.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-16">
<rect x="0" y="391.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-17">
<rect x="0" y="416.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-18">
<rect x="0" y="440.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-19">
<rect x="0" y="465.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-20">
<rect x="0" y="489.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-21">
<rect x="0" y="513.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-22">
<rect x="0" y="538.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-23">
<rect x="0" y="562.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-24">
<rect x="0" y="587.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-25">
<rect x="0" y="611.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-26">
<rect x="0" y="635.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-27">
<rect x="0" y="660.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-28">
<rect x="0" y="684.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-29">
<rect x="0" y="709.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-30">
<rect x="0" y="733.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-31">
<rect x="0" y="757.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-32">
<rect x="0" y="782.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-33">
<rect x="0" y="806.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-34">
<rect x="0" y="831.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-35">
<rect x="0" y="855.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1452477714-line-36">
<rect x="0" y="879.9" width="1342" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1358" height="975.2" rx="8"/><text class="terminal-1452477714-title" fill="#c5c8c6" text-anchor="middle" x="679" y="27">Rich</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-1452477714-clip-terminal)">
<g class="terminal-1452477714-matrix">
<text class="terminal-1452477714-r1" x="0" y="20" textLength="24.4" clip-path="url(#terminal-1452477714-line-0)">╭─</text><text class="terminal-1452477714-r1" x="24.4" y="20" textLength="463.6" clip-path="url(#terminal-1452477714-line-0)">──────────────────────────────────────</text><text class="terminal-1452477714-r2" x="500.2" y="20" textLength="12.2" clip-path="url(#terminal-1452477714-line-0)">&lt;</text><text class="terminal-1452477714-r3" x="512.4" y="20" textLength="61" clip-path="url(#terminal-1452477714-line-0)">class</text><text class="terminal-1452477714-r5" x="585.6" y="20" textLength="231.8" clip-path="url(#terminal-1452477714-line-0)">&#x27;_io.TextIOWrapper&#x27;</text><text class="terminal-1452477714-r2" x="817.4" y="20" textLength="12.2" clip-path="url(#terminal-1452477714-line-0)">&gt;</text><text class="terminal-1452477714-r1" x="841.8" y="20" textLength="475.8" clip-path="url(#terminal-1452477714-line-0)">───────────────────────────────────────</text><text class="terminal-1452477714-r1" x="1317.6" y="20" textLength="24.4" clip-path="url(#terminal-1452477714-line-0)">─╮</text><text class="terminal-1452477714-r4" x="1342" y="20" textLength="12.2" clip-path="url(#terminal-1452477714-line-0)">
</text><text class="terminal-1452477714-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-1)"></text><text class="terminal-1452477714-r6" x="24.4" y="44.4" textLength="829.6" clip-path="url(#terminal-1452477714-line-1)">Character&#160;and&#160;line&#160;based&#160;layer&#160;over&#160;a&#160;BufferedIOBase&#160;object,&#160;buffer.</text><text class="terminal-1452477714-r1" x="1329.8" y="44.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-1)"></text><text class="terminal-1452477714-r4" x="1342" y="44.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-1)">
</text><text class="terminal-1452477714-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-2)"></text><text class="terminal-1452477714-r1" x="1329.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-2)"></text><text class="terminal-1452477714-r4" x="1342" y="68.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-2)">
</text><text class="terminal-1452477714-r1" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-3)"></text><text class="terminal-1452477714-r5" x="24.4" y="93.2" textLength="1293.2" clip-path="url(#terminal-1452477714-line-3)">╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮</text><text class="terminal-1452477714-r1" x="1329.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-3)"></text><text class="terminal-1452477714-r4" x="1342" y="93.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-3)">
</text><text class="terminal-1452477714-r1" x="0" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)"></text><text class="terminal-1452477714-r5" x="24.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)"></text><text class="terminal-1452477714-r7" x="48.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)">&lt;</text><text class="terminal-1452477714-r3" x="61" y="117.6" textLength="207.4" clip-path="url(#terminal-1452477714-line-4)">_io.TextIOWrapper</text><text class="terminal-1452477714-r8" x="280.6" y="117.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-4)">name</text><text class="terminal-1452477714-r4" x="329.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)">=</text><text class="terminal-1452477714-r5" x="341.6" y="117.6" textLength="109.8" clip-path="url(#terminal-1452477714-line-4)">&#x27;foo.txt&#x27;</text><text class="terminal-1452477714-r8" x="463.6" y="117.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-4)">mode</text><text class="terminal-1452477714-r4" x="512.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)">=</text><text class="terminal-1452477714-r5" x="524.6" y="117.6" textLength="36.6" clip-path="url(#terminal-1452477714-line-4)">&#x27;w&#x27;</text><text class="terminal-1452477714-r8" x="573.4" y="117.6" textLength="97.6" clip-path="url(#terminal-1452477714-line-4)">encoding</text><text class="terminal-1452477714-r4" x="671" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)">=</text><text class="terminal-1452477714-r5" x="683.2" y="117.6" textLength="85.4" clip-path="url(#terminal-1452477714-line-4)">&#x27;UTF-8&#x27;</text><text class="terminal-1452477714-r7" x="768.6" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)">&gt;</text><text class="terminal-1452477714-r5" x="1305.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)"></text><text class="terminal-1452477714-r1" x="1329.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)"></text><text class="terminal-1452477714-r4" x="1342" y="117.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-4)">
</text><text class="terminal-1452477714-r1" x="0" y="142" textLength="12.2" clip-path="url(#terminal-1452477714-line-5)"></text><text class="terminal-1452477714-r5" x="24.4" y="142" textLength="1293.2" clip-path="url(#terminal-1452477714-line-5)">╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-1452477714-r1" x="1329.8" y="142" textLength="12.2" clip-path="url(#terminal-1452477714-line-5)"></text><text class="terminal-1452477714-r4" x="1342" y="142" textLength="12.2" clip-path="url(#terminal-1452477714-line-5)">
</text><text class="terminal-1452477714-r1" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-6)"></text><text class="terminal-1452477714-r1" x="1329.8" y="166.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-6)"></text><text class="terminal-1452477714-r4" x="1342" y="166.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-6)">
</text><text class="terminal-1452477714-r1" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-7)"></text><text class="terminal-1452477714-r9" x="122" y="190.8" textLength="73.2" clip-path="url(#terminal-1452477714-line-7)">buffer</text><text class="terminal-1452477714-r4" x="195.2" y="190.8" textLength="24.4" clip-path="url(#terminal-1452477714-line-7)">&#160;=</text><text class="terminal-1452477714-r7" x="231.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-7)">&lt;</text><text class="terminal-1452477714-r3" x="244" y="190.8" textLength="219.6" clip-path="url(#terminal-1452477714-line-7)">_io.BufferedWriter</text><text class="terminal-1452477714-r8" x="475.8" y="190.8" textLength="48.8" clip-path="url(#terminal-1452477714-line-7)">name</text><text class="terminal-1452477714-r4" x="524.6" y="190.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-7)">=</text><text class="terminal-1452477714-r5" x="536.8" y="190.8" textLength="109.8" clip-path="url(#terminal-1452477714-line-7)">&#x27;foo.txt&#x27;</text><text class="terminal-1452477714-r7" x="646.6" y="190.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-7)">&gt;</text><text class="terminal-1452477714-r1" x="1329.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-7)"></text><text class="terminal-1452477714-r4" x="1342" y="190.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-7)">
</text><text class="terminal-1452477714-r1" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-8)"></text><text class="terminal-1452477714-r9" x="122" y="215.2" textLength="73.2" clip-path="url(#terminal-1452477714-line-8)">closed</text><text class="terminal-1452477714-r4" x="195.2" y="215.2" textLength="24.4" clip-path="url(#terminal-1452477714-line-8)">&#160;=</text><text class="terminal-1452477714-r10" x="231.8" y="215.2" textLength="61" clip-path="url(#terminal-1452477714-line-8)">False</text><text class="terminal-1452477714-r1" x="1329.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-8)"></text><text class="terminal-1452477714-r4" x="1342" y="215.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-8)">
</text><text class="terminal-1452477714-r1" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-9)"></text><text class="terminal-1452477714-r9" x="97.6" y="239.6" textLength="97.6" clip-path="url(#terminal-1452477714-line-9)">encoding</text><text class="terminal-1452477714-r4" x="195.2" y="239.6" textLength="24.4" clip-path="url(#terminal-1452477714-line-9)">&#160;=</text><text class="terminal-1452477714-r5" x="231.8" y="239.6" textLength="85.4" clip-path="url(#terminal-1452477714-line-9)">&#x27;UTF-8&#x27;</text><text class="terminal-1452477714-r1" x="1329.8" y="239.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-9)"></text><text class="terminal-1452477714-r4" x="1342" y="239.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-9)">
</text><text class="terminal-1452477714-r1" x="0" y="264" textLength="12.2" clip-path="url(#terminal-1452477714-line-10)"></text><text class="terminal-1452477714-r9" x="122" y="264" textLength="73.2" clip-path="url(#terminal-1452477714-line-10)">errors</text><text class="terminal-1452477714-r4" x="195.2" y="264" textLength="24.4" clip-path="url(#terminal-1452477714-line-10)">&#160;=</text><text class="terminal-1452477714-r5" x="231.8" y="264" textLength="97.6" clip-path="url(#terminal-1452477714-line-10)">&#x27;strict&#x27;</text><text class="terminal-1452477714-r1" x="1329.8" y="264" textLength="12.2" clip-path="url(#terminal-1452477714-line-10)"></text><text class="terminal-1452477714-r4" x="1342" y="264" textLength="12.2" clip-path="url(#terminal-1452477714-line-10)">
</text><text class="terminal-1452477714-r1" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-11)"></text><text class="terminal-1452477714-r9" x="24.4" y="288.4" textLength="170.8" clip-path="url(#terminal-1452477714-line-11)">line_buffering</text><text class="terminal-1452477714-r4" x="195.2" y="288.4" textLength="24.4" clip-path="url(#terminal-1452477714-line-11)">&#160;=</text><text class="terminal-1452477714-r10" x="231.8" y="288.4" textLength="61" clip-path="url(#terminal-1452477714-line-11)">False</text><text class="terminal-1452477714-r1" x="1329.8" y="288.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-11)"></text><text class="terminal-1452477714-r4" x="1342" y="288.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-11)">
</text><text class="terminal-1452477714-r1" x="0" y="312.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-12)"></text><text class="terminal-1452477714-r9" x="146.4" y="312.8" textLength="48.8" clip-path="url(#terminal-1452477714-line-12)">mode</text><text class="terminal-1452477714-r4" x="195.2" y="312.8" textLength="24.4" clip-path="url(#terminal-1452477714-line-12)">&#160;=</text><text class="terminal-1452477714-r5" x="231.8" y="312.8" textLength="36.6" clip-path="url(#terminal-1452477714-line-12)">&#x27;w&#x27;</text><text class="terminal-1452477714-r1" x="1329.8" y="312.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-12)"></text><text class="terminal-1452477714-r4" x="1342" y="312.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-12)">
</text><text class="terminal-1452477714-r1" x="0" y="337.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-13)"></text><text class="terminal-1452477714-r9" x="146.4" y="337.2" textLength="48.8" clip-path="url(#terminal-1452477714-line-13)">name</text><text class="terminal-1452477714-r4" x="195.2" y="337.2" textLength="24.4" clip-path="url(#terminal-1452477714-line-13)">&#160;=</text><text class="terminal-1452477714-r5" x="231.8" y="337.2" textLength="109.8" clip-path="url(#terminal-1452477714-line-13)">&#x27;foo.txt&#x27;</text><text class="terminal-1452477714-r1" x="1329.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-13)"></text><text class="terminal-1452477714-r4" x="1342" y="337.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-13)">
</text><text class="terminal-1452477714-r1" x="0" y="361.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-14)"></text><text class="terminal-1452477714-r9" x="97.6" y="361.6" textLength="97.6" clip-path="url(#terminal-1452477714-line-14)">newlines</text><text class="terminal-1452477714-r4" x="195.2" y="361.6" textLength="24.4" clip-path="url(#terminal-1452477714-line-14)">&#160;=</text><text class="terminal-1452477714-r11" x="231.8" y="361.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-14)">None</text><text class="terminal-1452477714-r1" x="1329.8" y="361.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-14)"></text><text class="terminal-1452477714-r4" x="1342" y="361.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-14)">
</text><text class="terminal-1452477714-r1" x="0" y="386" textLength="12.2" clip-path="url(#terminal-1452477714-line-15)"></text><text class="terminal-1452477714-r9" x="36.6" y="386" textLength="158.6" clip-path="url(#terminal-1452477714-line-15)">write_through</text><text class="terminal-1452477714-r4" x="195.2" y="386" textLength="24.4" clip-path="url(#terminal-1452477714-line-15)">&#160;=</text><text class="terminal-1452477714-r10" x="231.8" y="386" textLength="61" clip-path="url(#terminal-1452477714-line-15)">False</text><text class="terminal-1452477714-r1" x="1329.8" y="386" textLength="12.2" clip-path="url(#terminal-1452477714-line-15)"></text><text class="terminal-1452477714-r4" x="1342" y="386" textLength="12.2" clip-path="url(#terminal-1452477714-line-15)">
</text><text class="terminal-1452477714-r1" x="0" y="410.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-16)"></text><text class="terminal-1452477714-r9" x="134.2" y="410.4" textLength="61" clip-path="url(#terminal-1452477714-line-16)">close</text><text class="terminal-1452477714-r4" x="195.2" y="410.4" textLength="24.4" clip-path="url(#terminal-1452477714-line-16)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="410.4" textLength="48.8" clip-path="url(#terminal-1452477714-line-16)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="410.4" textLength="61" clip-path="url(#terminal-1452477714-line-16)">close</text><text class="terminal-1452477714-r7" x="341.6" y="410.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-16)">(</text><text class="terminal-1452477714-r7" x="353.8" y="410.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-16)">)</text><text class="terminal-1452477714-r4" x="366" y="410.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-16)">:</text><text class="terminal-1452477714-r14" x="390.4" y="410.4" textLength="366" clip-path="url(#terminal-1452477714-line-16)">Flush&#160;and&#160;close&#160;the&#160;IO&#160;object.</text><text class="terminal-1452477714-r1" x="1329.8" y="410.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-16)"></text><text class="terminal-1452477714-r4" x="1342" y="410.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-16)">
</text><text class="terminal-1452477714-r1" x="0" y="434.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-17)"></text><text class="terminal-1452477714-r9" x="122" y="434.8" textLength="73.2" clip-path="url(#terminal-1452477714-line-17)">detach</text><text class="terminal-1452477714-r4" x="195.2" y="434.8" textLength="24.4" clip-path="url(#terminal-1452477714-line-17)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="434.8" textLength="48.8" clip-path="url(#terminal-1452477714-line-17)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="434.8" textLength="73.2" clip-path="url(#terminal-1452477714-line-17)">detach</text><text class="terminal-1452477714-r7" x="353.8" y="434.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-17)">(</text><text class="terminal-1452477714-r7" x="366" y="434.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-17)">)</text><text class="terminal-1452477714-r4" x="378.2" y="434.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-17)">:</text><text class="terminal-1452477714-r14" x="402.6" y="434.8" textLength="793" clip-path="url(#terminal-1452477714-line-17)">Separate&#160;the&#160;underlying&#160;buffer&#160;from&#160;the&#160;TextIOBase&#160;and&#160;return&#160;it.</text><text class="terminal-1452477714-r1" x="1329.8" y="434.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-17)"></text><text class="terminal-1452477714-r4" x="1342" y="434.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-17)">
</text><text class="terminal-1452477714-r1" x="0" y="459.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-18)"></text><text class="terminal-1452477714-r9" x="122" y="459.2" textLength="73.2" clip-path="url(#terminal-1452477714-line-18)">fileno</text><text class="terminal-1452477714-r4" x="195.2" y="459.2" textLength="24.4" clip-path="url(#terminal-1452477714-line-18)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="459.2" textLength="48.8" clip-path="url(#terminal-1452477714-line-18)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="459.2" textLength="73.2" clip-path="url(#terminal-1452477714-line-18)">fileno</text><text class="terminal-1452477714-r7" x="353.8" y="459.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-18)">(</text><text class="terminal-1452477714-r7" x="366" y="459.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-18)">)</text><text class="terminal-1452477714-r4" x="378.2" y="459.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-18)">:</text><text class="terminal-1452477714-r14" x="402.6" y="459.2" textLength="597.8" clip-path="url(#terminal-1452477714-line-18)">Returns&#160;underlying&#160;file&#160;descriptor&#160;if&#160;one&#160;exists.</text><text class="terminal-1452477714-r1" x="1329.8" y="459.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-18)"></text><text class="terminal-1452477714-r4" x="1342" y="459.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-18)">
</text><text class="terminal-1452477714-r1" x="0" y="483.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-19)"></text><text class="terminal-1452477714-r9" x="134.2" y="483.6" textLength="61" clip-path="url(#terminal-1452477714-line-19)">flush</text><text class="terminal-1452477714-r4" x="195.2" y="483.6" textLength="24.4" clip-path="url(#terminal-1452477714-line-19)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="483.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-19)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="483.6" textLength="61" clip-path="url(#terminal-1452477714-line-19)">flush</text><text class="terminal-1452477714-r7" x="341.6" y="483.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-19)">(</text><text class="terminal-1452477714-r7" x="353.8" y="483.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-19)">)</text><text class="terminal-1452477714-r4" x="366" y="483.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-19)">:</text><text class="terminal-1452477714-r14" x="390.4" y="483.6" textLength="427" clip-path="url(#terminal-1452477714-line-19)">Flush&#160;write&#160;buffers,&#160;if&#160;applicable.</text><text class="terminal-1452477714-r1" x="1329.8" y="483.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-19)"></text><text class="terminal-1452477714-r4" x="1342" y="483.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-19)">
</text><text class="terminal-1452477714-r1" x="0" y="508" textLength="12.2" clip-path="url(#terminal-1452477714-line-20)"></text><text class="terminal-1452477714-r9" x="122" y="508" textLength="73.2" clip-path="url(#terminal-1452477714-line-20)">isatty</text><text class="terminal-1452477714-r4" x="195.2" y="508" textLength="24.4" clip-path="url(#terminal-1452477714-line-20)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="508" textLength="48.8" clip-path="url(#terminal-1452477714-line-20)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="508" textLength="73.2" clip-path="url(#terminal-1452477714-line-20)">isatty</text><text class="terminal-1452477714-r7" x="353.8" y="508" textLength="12.2" clip-path="url(#terminal-1452477714-line-20)">(</text><text class="terminal-1452477714-r7" x="366" y="508" textLength="12.2" clip-path="url(#terminal-1452477714-line-20)">)</text><text class="terminal-1452477714-r4" x="378.2" y="508" textLength="12.2" clip-path="url(#terminal-1452477714-line-20)">:</text><text class="terminal-1452477714-r14" x="402.6" y="508" textLength="317.2" clip-path="url(#terminal-1452477714-line-20)">Return&#160;whether&#160;this&#160;is&#160;an&#160;</text><text class="terminal-1452477714-r15" x="719.8" y="508" textLength="158.6" clip-path="url(#terminal-1452477714-line-20)">&#x27;interactive&#x27;</text><text class="terminal-1452477714-r14" x="878.4" y="508" textLength="97.6" clip-path="url(#terminal-1452477714-line-20)">&#160;stream.</text><text class="terminal-1452477714-r1" x="1329.8" y="508" textLength="12.2" clip-path="url(#terminal-1452477714-line-20)"></text><text class="terminal-1452477714-r4" x="1342" y="508" textLength="12.2" clip-path="url(#terminal-1452477714-line-20)">
</text><text class="terminal-1452477714-r1" x="0" y="532.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-21)"></text><text class="terminal-1452477714-r9" x="146.4" y="532.4" textLength="48.8" clip-path="url(#terminal-1452477714-line-21)">read</text><text class="terminal-1452477714-r4" x="195.2" y="532.4" textLength="24.4" clip-path="url(#terminal-1452477714-line-21)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="532.4" textLength="48.8" clip-path="url(#terminal-1452477714-line-21)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="532.4" textLength="48.8" clip-path="url(#terminal-1452477714-line-21)">read</text><text class="terminal-1452477714-r7" x="329.4" y="532.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-21)">(</text><text class="terminal-1452477714-r8" x="341.6" y="532.4" textLength="48.8" clip-path="url(#terminal-1452477714-line-21)">size</text><text class="terminal-1452477714-r4" x="390.4" y="532.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-21)">=</text><text class="terminal-1452477714-r16" x="402.6" y="532.4" textLength="24.4" clip-path="url(#terminal-1452477714-line-21)">-1</text><text class="terminal-1452477714-r4" x="427" y="532.4" textLength="24.4" clip-path="url(#terminal-1452477714-line-21)">,&#160;</text><text class="terminal-1452477714-r17" x="451.4" y="532.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-21)">/</text><text class="terminal-1452477714-r7" x="463.6" y="532.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-21)">)</text><text class="terminal-1452477714-r4" x="475.8" y="532.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-21)">:</text><text class="terminal-1452477714-r14" x="500.2" y="532.4" textLength="463.6" clip-path="url(#terminal-1452477714-line-21)">Read&#160;at&#160;most&#160;n&#160;characters&#160;from&#160;stream.</text><text class="terminal-1452477714-r1" x="1329.8" y="532.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-21)"></text><text class="terminal-1452477714-r4" x="1342" y="532.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-21)">
</text><text class="terminal-1452477714-r1" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-22)"></text><text class="terminal-1452477714-r9" x="97.6" y="556.8" textLength="97.6" clip-path="url(#terminal-1452477714-line-22)">readable</text><text class="terminal-1452477714-r4" x="195.2" y="556.8" textLength="24.4" clip-path="url(#terminal-1452477714-line-22)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="556.8" textLength="48.8" clip-path="url(#terminal-1452477714-line-22)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="556.8" textLength="97.6" clip-path="url(#terminal-1452477714-line-22)">readable</text><text class="terminal-1452477714-r7" x="378.2" y="556.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-22)">(</text><text class="terminal-1452477714-r7" x="390.4" y="556.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-22)">)</text><text class="terminal-1452477714-r4" x="402.6" y="556.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-22)">:</text><text class="terminal-1452477714-r14" x="427" y="556.8" textLength="549" clip-path="url(#terminal-1452477714-line-22)">Return&#160;whether&#160;object&#160;was&#160;opened&#160;for&#160;reading.</text><text class="terminal-1452477714-r1" x="1329.8" y="556.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-22)"></text><text class="terminal-1452477714-r4" x="1342" y="556.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-22)">
</text><text class="terminal-1452477714-r1" x="0" y="581.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-23)"></text><text class="terminal-1452477714-r9" x="97.6" y="581.2" textLength="97.6" clip-path="url(#terminal-1452477714-line-23)">readline</text><text class="terminal-1452477714-r4" x="195.2" y="581.2" textLength="24.4" clip-path="url(#terminal-1452477714-line-23)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="581.2" textLength="48.8" clip-path="url(#terminal-1452477714-line-23)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="581.2" textLength="97.6" clip-path="url(#terminal-1452477714-line-23)">readline</text><text class="terminal-1452477714-r7" x="378.2" y="581.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-23)">(</text><text class="terminal-1452477714-r8" x="390.4" y="581.2" textLength="48.8" clip-path="url(#terminal-1452477714-line-23)">size</text><text class="terminal-1452477714-r4" x="439.2" y="581.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-23)">=</text><text class="terminal-1452477714-r16" x="451.4" y="581.2" textLength="24.4" clip-path="url(#terminal-1452477714-line-23)">-1</text><text class="terminal-1452477714-r4" x="475.8" y="581.2" textLength="24.4" clip-path="url(#terminal-1452477714-line-23)">,&#160;</text><text class="terminal-1452477714-r17" x="500.2" y="581.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-23)">/</text><text class="terminal-1452477714-r7" x="512.4" y="581.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-23)">)</text><text class="terminal-1452477714-r4" x="524.6" y="581.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-23)">:</text><text class="terminal-1452477714-r14" x="549" y="581.2" textLength="317.2" clip-path="url(#terminal-1452477714-line-23)">Read&#160;until&#160;newline&#160;or&#160;EOF.</text><text class="terminal-1452477714-r1" x="1329.8" y="581.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-23)"></text><text class="terminal-1452477714-r4" x="1342" y="581.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-23)">
</text><text class="terminal-1452477714-r1" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-24)"></text><text class="terminal-1452477714-r9" x="85.4" y="605.6" textLength="109.8" clip-path="url(#terminal-1452477714-line-24)">readlines</text><text class="terminal-1452477714-r4" x="195.2" y="605.6" textLength="24.4" clip-path="url(#terminal-1452477714-line-24)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="605.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-24)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="605.6" textLength="109.8" clip-path="url(#terminal-1452477714-line-24)">readlines</text><text class="terminal-1452477714-r7" x="390.4" y="605.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-24)">(</text><text class="terminal-1452477714-r8" x="402.6" y="605.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-24)">hint</text><text class="terminal-1452477714-r4" x="451.4" y="605.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-24)">=</text><text class="terminal-1452477714-r16" x="463.6" y="605.6" textLength="24.4" clip-path="url(#terminal-1452477714-line-24)">-1</text><text class="terminal-1452477714-r4" x="488" y="605.6" textLength="24.4" clip-path="url(#terminal-1452477714-line-24)">,&#160;</text><text class="terminal-1452477714-r17" x="512.4" y="605.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-24)">/</text><text class="terminal-1452477714-r7" x="524.6" y="605.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-24)">)</text><text class="terminal-1452477714-r4" x="536.8" y="605.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-24)">:</text><text class="terminal-1452477714-r14" x="561.2" y="605.6" textLength="475.8" clip-path="url(#terminal-1452477714-line-24)">Return&#160;a&#160;list&#160;of&#160;lines&#160;from&#160;the&#160;stream.</text><text class="terminal-1452477714-r1" x="1329.8" y="605.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-24)"></text><text class="terminal-1452477714-r4" x="1342" y="605.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-24)">
</text><text class="terminal-1452477714-r1" x="0" y="630" textLength="12.2" clip-path="url(#terminal-1452477714-line-25)"></text><text class="terminal-1452477714-r9" x="61" y="630" textLength="134.2" clip-path="url(#terminal-1452477714-line-25)">reconfigure</text><text class="terminal-1452477714-r4" x="195.2" y="630" textLength="24.4" clip-path="url(#terminal-1452477714-line-25)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="630" textLength="48.8" clip-path="url(#terminal-1452477714-line-25)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="630" textLength="134.2" clip-path="url(#terminal-1452477714-line-25)">reconfigure</text><text class="terminal-1452477714-r7" x="414.8" y="630" textLength="12.2" clip-path="url(#terminal-1452477714-line-25)">(</text><text class="terminal-1452477714-r4" x="427" y="630" textLength="36.6" clip-path="url(#terminal-1452477714-line-25)">*,&#160;</text><text class="terminal-1452477714-r8" x="463.6" y="630" textLength="97.6" clip-path="url(#terminal-1452477714-line-25)">encoding</text><text class="terminal-1452477714-r4" x="561.2" y="630" textLength="12.2" clip-path="url(#terminal-1452477714-line-25)">=</text><text class="terminal-1452477714-r11" x="573.4" y="630" textLength="48.8" clip-path="url(#terminal-1452477714-line-25)">None</text><text class="terminal-1452477714-r4" x="622.2" y="630" textLength="24.4" clip-path="url(#terminal-1452477714-line-25)">,&#160;</text><text class="terminal-1452477714-r8" x="646.6" y="630" textLength="73.2" clip-path="url(#terminal-1452477714-line-25)">errors</text><text class="terminal-1452477714-r4" x="719.8" y="630" textLength="12.2" clip-path="url(#terminal-1452477714-line-25)">=</text><text class="terminal-1452477714-r11" x="732" y="630" textLength="48.8" clip-path="url(#terminal-1452477714-line-25)">None</text><text class="terminal-1452477714-r4" x="780.8" y="630" textLength="24.4" clip-path="url(#terminal-1452477714-line-25)">,&#160;</text><text class="terminal-1452477714-r8" x="805.2" y="630" textLength="85.4" clip-path="url(#terminal-1452477714-line-25)">newline</text><text class="terminal-1452477714-r4" x="890.6" y="630" textLength="12.2" clip-path="url(#terminal-1452477714-line-25)">=</text><text class="terminal-1452477714-r11" x="902.8" y="630" textLength="48.8" clip-path="url(#terminal-1452477714-line-25)">None</text><text class="terminal-1452477714-r4" x="951.6" y="630" textLength="24.4" clip-path="url(#terminal-1452477714-line-25)">,&#160;</text><text class="terminal-1452477714-r8" x="976" y="630" textLength="170.8" clip-path="url(#terminal-1452477714-line-25)">line_buffering</text><text class="terminal-1452477714-r4" x="1146.8" y="630" textLength="12.2" clip-path="url(#terminal-1452477714-line-25)">=</text><text class="terminal-1452477714-r11" x="1159" y="630" textLength="48.8" clip-path="url(#terminal-1452477714-line-25)">None</text><text class="terminal-1452477714-r4" x="1207.8" y="630" textLength="24.4" clip-path="url(#terminal-1452477714-line-25)">,&#160;</text><text class="terminal-1452477714-r1" x="1329.8" y="630" textLength="12.2" clip-path="url(#terminal-1452477714-line-25)"></text><text class="terminal-1452477714-r4" x="1342" y="630" textLength="12.2" clip-path="url(#terminal-1452477714-line-25)">
</text><text class="terminal-1452477714-r1" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-26)"></text><text class="terminal-1452477714-r8" x="231.8" y="654.4" textLength="158.6" clip-path="url(#terminal-1452477714-line-26)">write_through</text><text class="terminal-1452477714-r4" x="390.4" y="654.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-26)">=</text><text class="terminal-1452477714-r11" x="402.6" y="654.4" textLength="48.8" clip-path="url(#terminal-1452477714-line-26)">None</text><text class="terminal-1452477714-r7" x="451.4" y="654.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-26)">)</text><text class="terminal-1452477714-r4" x="463.6" y="654.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-26)">:</text><text class="terminal-1452477714-r14" x="488" y="654.4" textLength="585.6" clip-path="url(#terminal-1452477714-line-26)">Reconfigure&#160;the&#160;text&#160;stream&#160;with&#160;new&#160;parameters.</text><text class="terminal-1452477714-r1" x="1329.8" y="654.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-26)"></text><text class="terminal-1452477714-r4" x="1342" y="654.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-26)">
</text><text class="terminal-1452477714-r1" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)"></text><text class="terminal-1452477714-r9" x="146.4" y="678.8" textLength="48.8" clip-path="url(#terminal-1452477714-line-27)">seek</text><text class="terminal-1452477714-r4" x="195.2" y="678.8" textLength="24.4" clip-path="url(#terminal-1452477714-line-27)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="678.8" textLength="48.8" clip-path="url(#terminal-1452477714-line-27)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="678.8" textLength="48.8" clip-path="url(#terminal-1452477714-line-27)">seek</text><text class="terminal-1452477714-r7" x="329.4" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)">(</text><text class="terminal-1452477714-r4" x="341.6" y="678.8" textLength="97.6" clip-path="url(#terminal-1452477714-line-27)">cookie,&#160;</text><text class="terminal-1452477714-r8" x="439.2" y="678.8" textLength="73.2" clip-path="url(#terminal-1452477714-line-27)">whence</text><text class="terminal-1452477714-r4" x="512.4" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)">=</text><text class="terminal-1452477714-r16" x="524.6" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)">0</text><text class="terminal-1452477714-r4" x="536.8" y="678.8" textLength="24.4" clip-path="url(#terminal-1452477714-line-27)">,&#160;</text><text class="terminal-1452477714-r17" x="561.2" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)">/</text><text class="terminal-1452477714-r7" x="573.4" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)">)</text><text class="terminal-1452477714-r4" x="585.6" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)">:</text><text class="terminal-1452477714-r14" x="610" y="678.8" textLength="280.6" clip-path="url(#terminal-1452477714-line-27)">Change&#160;stream&#160;position.</text><text class="terminal-1452477714-r1" x="1329.8" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)"></text><text class="terminal-1452477714-r4" x="1342" y="678.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-27)">
</text><text class="terminal-1452477714-r1" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-28)"></text><text class="terminal-1452477714-r9" x="97.6" y="703.2" textLength="97.6" clip-path="url(#terminal-1452477714-line-28)">seekable</text><text class="terminal-1452477714-r4" x="195.2" y="703.2" textLength="24.4" clip-path="url(#terminal-1452477714-line-28)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="703.2" textLength="48.8" clip-path="url(#terminal-1452477714-line-28)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="703.2" textLength="97.6" clip-path="url(#terminal-1452477714-line-28)">seekable</text><text class="terminal-1452477714-r7" x="378.2" y="703.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-28)">(</text><text class="terminal-1452477714-r7" x="390.4" y="703.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-28)">)</text><text class="terminal-1452477714-r4" x="402.6" y="703.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-28)">:</text><text class="terminal-1452477714-r14" x="427" y="703.2" textLength="549" clip-path="url(#terminal-1452477714-line-28)">Return&#160;whether&#160;object&#160;supports&#160;random&#160;access.</text><text class="terminal-1452477714-r1" x="1329.8" y="703.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-28)"></text><text class="terminal-1452477714-r4" x="1342" y="703.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-28)">
</text><text class="terminal-1452477714-r1" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-29)"></text><text class="terminal-1452477714-r9" x="146.4" y="727.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-29)">tell</text><text class="terminal-1452477714-r4" x="195.2" y="727.6" textLength="24.4" clip-path="url(#terminal-1452477714-line-29)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="727.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-29)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="727.6" textLength="48.8" clip-path="url(#terminal-1452477714-line-29)">tell</text><text class="terminal-1452477714-r7" x="329.4" y="727.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-29)">(</text><text class="terminal-1452477714-r7" x="341.6" y="727.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-29)">)</text><text class="terminal-1452477714-r4" x="353.8" y="727.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-29)">:</text><text class="terminal-1452477714-r14" x="378.2" y="727.6" textLength="378.2" clip-path="url(#terminal-1452477714-line-29)">Return&#160;current&#160;stream&#160;position.</text><text class="terminal-1452477714-r1" x="1329.8" y="727.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-29)"></text><text class="terminal-1452477714-r4" x="1342" y="727.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-29)">
</text><text class="terminal-1452477714-r1" x="0" y="752" textLength="12.2" clip-path="url(#terminal-1452477714-line-30)"></text><text class="terminal-1452477714-r9" x="97.6" y="752" textLength="97.6" clip-path="url(#terminal-1452477714-line-30)">truncate</text><text class="terminal-1452477714-r4" x="195.2" y="752" textLength="24.4" clip-path="url(#terminal-1452477714-line-30)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="752" textLength="48.8" clip-path="url(#terminal-1452477714-line-30)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="752" textLength="97.6" clip-path="url(#terminal-1452477714-line-30)">truncate</text><text class="terminal-1452477714-r7" x="378.2" y="752" textLength="12.2" clip-path="url(#terminal-1452477714-line-30)">(</text><text class="terminal-1452477714-r8" x="390.4" y="752" textLength="36.6" clip-path="url(#terminal-1452477714-line-30)">pos</text><text class="terminal-1452477714-r4" x="427" y="752" textLength="12.2" clip-path="url(#terminal-1452477714-line-30)">=</text><text class="terminal-1452477714-r11" x="439.2" y="752" textLength="48.8" clip-path="url(#terminal-1452477714-line-30)">None</text><text class="terminal-1452477714-r4" x="488" y="752" textLength="24.4" clip-path="url(#terminal-1452477714-line-30)">,&#160;</text><text class="terminal-1452477714-r17" x="512.4" y="752" textLength="12.2" clip-path="url(#terminal-1452477714-line-30)">/</text><text class="terminal-1452477714-r7" x="524.6" y="752" textLength="12.2" clip-path="url(#terminal-1452477714-line-30)">)</text><text class="terminal-1452477714-r4" x="536.8" y="752" textLength="12.2" clip-path="url(#terminal-1452477714-line-30)">:</text><text class="terminal-1452477714-r14" x="561.2" y="752" textLength="341.6" clip-path="url(#terminal-1452477714-line-30)">Truncate&#160;file&#160;to&#160;size&#160;bytes.</text><text class="terminal-1452477714-r1" x="1329.8" y="752" textLength="12.2" clip-path="url(#terminal-1452477714-line-30)"></text><text class="terminal-1452477714-r4" x="1342" y="752" textLength="12.2" clip-path="url(#terminal-1452477714-line-30)">
</text><text class="terminal-1452477714-r1" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-31)"></text><text class="terminal-1452477714-r9" x="97.6" y="776.4" textLength="97.6" clip-path="url(#terminal-1452477714-line-31)">writable</text><text class="terminal-1452477714-r4" x="195.2" y="776.4" textLength="24.4" clip-path="url(#terminal-1452477714-line-31)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="776.4" textLength="48.8" clip-path="url(#terminal-1452477714-line-31)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="776.4" textLength="97.6" clip-path="url(#terminal-1452477714-line-31)">writable</text><text class="terminal-1452477714-r7" x="378.2" y="776.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-31)">(</text><text class="terminal-1452477714-r7" x="390.4" y="776.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-31)">)</text><text class="terminal-1452477714-r4" x="402.6" y="776.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-31)">:</text><text class="terminal-1452477714-r14" x="427" y="776.4" textLength="549" clip-path="url(#terminal-1452477714-line-31)">Return&#160;whether&#160;object&#160;was&#160;opened&#160;for&#160;writing.</text><text class="terminal-1452477714-r1" x="1329.8" y="776.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-31)"></text><text class="terminal-1452477714-r4" x="1342" y="776.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-31)">
</text><text class="terminal-1452477714-r1" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-32)"></text><text class="terminal-1452477714-r9" x="134.2" y="800.8" textLength="61" clip-path="url(#terminal-1452477714-line-32)">write</text><text class="terminal-1452477714-r4" x="195.2" y="800.8" textLength="24.4" clip-path="url(#terminal-1452477714-line-32)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="800.8" textLength="48.8" clip-path="url(#terminal-1452477714-line-32)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="800.8" textLength="61" clip-path="url(#terminal-1452477714-line-32)">write</text><text class="terminal-1452477714-r7" x="341.6" y="800.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-32)">(</text><text class="terminal-1452477714-r4" x="353.8" y="800.8" textLength="73.2" clip-path="url(#terminal-1452477714-line-32)">text,&#160;</text><text class="terminal-1452477714-r17" x="427" y="800.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-32)">/</text><text class="terminal-1452477714-r7" x="439.2" y="800.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-32)">)</text><text class="terminal-1452477714-r4" x="451.4" y="800.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-32)">:</text><text class="terminal-1452477714-r1" x="1329.8" y="800.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-32)"></text><text class="terminal-1452477714-r4" x="1342" y="800.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-32)">
</text><text class="terminal-1452477714-r1" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-33)"></text><text class="terminal-1452477714-r14" x="231.8" y="825.2" textLength="280.6" clip-path="url(#terminal-1452477714-line-33)">Write&#160;string&#160;to&#160;stream.</text><text class="terminal-1452477714-r1" x="1329.8" y="825.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-33)"></text><text class="terminal-1452477714-r4" x="1342" y="825.2" textLength="12.2" clip-path="url(#terminal-1452477714-line-33)">
</text><text class="terminal-1452477714-r1" x="0" y="849.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-34)"></text><text class="terminal-1452477714-r14" x="231.8" y="849.6" textLength="500.2" clip-path="url(#terminal-1452477714-line-34)">Returns&#160;the&#160;number&#160;of&#160;characters&#160;written&#160;</text><text class="terminal-1452477714-r18" x="732" y="849.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-34)">(</text><text class="terminal-1452477714-r14" x="744.2" y="849.6" textLength="292.8" clip-path="url(#terminal-1452477714-line-34)">which&#160;is&#160;always&#160;equal&#160;to</text><text class="terminal-1452477714-r1" x="1329.8" y="849.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-34)"></text><text class="terminal-1452477714-r4" x="1342" y="849.6" textLength="12.2" clip-path="url(#terminal-1452477714-line-34)">
</text><text class="terminal-1452477714-r1" x="0" y="874" textLength="12.2" clip-path="url(#terminal-1452477714-line-35)"></text><text class="terminal-1452477714-r14" x="231.8" y="874" textLength="292.8" clip-path="url(#terminal-1452477714-line-35)">the&#160;length&#160;of&#160;the&#160;string</text><text class="terminal-1452477714-r18" x="524.6" y="874" textLength="12.2" clip-path="url(#terminal-1452477714-line-35)">)</text><text class="terminal-1452477714-r14" x="536.8" y="874" textLength="12.2" clip-path="url(#terminal-1452477714-line-35)">.</text><text class="terminal-1452477714-r1" x="1329.8" y="874" textLength="12.2" clip-path="url(#terminal-1452477714-line-35)"></text><text class="terminal-1452477714-r4" x="1342" y="874" textLength="12.2" clip-path="url(#terminal-1452477714-line-35)">
</text><text class="terminal-1452477714-r1" x="0" y="898.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-36)"></text><text class="terminal-1452477714-r9" x="73.2" y="898.4" textLength="122" clip-path="url(#terminal-1452477714-line-36)">writelines</text><text class="terminal-1452477714-r4" x="195.2" y="898.4" textLength="24.4" clip-path="url(#terminal-1452477714-line-36)">&#160;=</text><text class="terminal-1452477714-r12" x="231.8" y="898.4" textLength="48.8" clip-path="url(#terminal-1452477714-line-36)">def&#160;</text><text class="terminal-1452477714-r13" x="280.6" y="898.4" textLength="122" clip-path="url(#terminal-1452477714-line-36)">writelines</text><text class="terminal-1452477714-r7" x="402.6" y="898.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-36)">(</text><text class="terminal-1452477714-r4" x="414.8" y="898.4" textLength="85.4" clip-path="url(#terminal-1452477714-line-36)">lines,&#160;</text><text class="terminal-1452477714-r17" x="500.2" y="898.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-36)">/</text><text class="terminal-1452477714-r7" x="512.4" y="898.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-36)">)</text><text class="terminal-1452477714-r4" x="524.6" y="898.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-36)">:</text><text class="terminal-1452477714-r14" x="549" y="898.4" textLength="390.4" clip-path="url(#terminal-1452477714-line-36)">Write&#160;a&#160;list&#160;of&#160;lines&#160;to&#160;stream.</text><text class="terminal-1452477714-r1" x="1329.8" y="898.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-36)"></text><text class="terminal-1452477714-r4" x="1342" y="898.4" textLength="12.2" clip-path="url(#terminal-1452477714-line-36)">
</text><text class="terminal-1452477714-r1" x="0" y="922.8" textLength="1342" clip-path="url(#terminal-1452477714-line-37)">╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-1452477714-r4" x="1342" y="922.8" textLength="12.2" clip-path="url(#terminal-1452477714-line-37)">
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 56 KiB

View file

@ -0,0 +1,576 @@
<svg class="rich-terminal" viewBox="0 0 1360 3100.0" 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-1636594121-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-1636594121-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-1636594121-r1 { fill: #608ab1 }
.terminal-1636594121-r2 { fill: #608ab1;font-weight: bold }
.terminal-1636594121-r3 { fill: #ff2c7a;font-weight: bold }
.terminal-1636594121-r4 { fill: #c5c8c6 }
.terminal-1636594121-r5 { fill: #98a84b }
.terminal-1636594121-r6 { fill: #68a0b3 }
.terminal-1636594121-r7 { fill: #98729f;font-weight: bold }
.terminal-1636594121-r8 { fill: #68a0b3;font-weight: bold }
.terminal-1636594121-r9 { fill: #98729f;font-style: italic; }
.terminal-1636594121-r10 { fill: #00823d;font-style: italic; }
.terminal-1636594121-r11 { fill: #c5c8c6;font-weight: bold }
.terminal-1636594121-r12 { fill: #d0b344 }
.terminal-1636594121-r13 { fill: #d0b344;font-style: italic; }
.terminal-1636594121-r14 { fill: #ff2627;font-style: italic; }
.terminal-1636594121-r15 { fill: #398280;font-style: italic; }
.terminal-1636594121-r16 { fill: #cc555a;font-weight: bold }
.terminal-1636594121-r17 { fill: #868887 }
.terminal-1636594121-r18 { fill: #6b753d }
.terminal-1636594121-r19 { fill: #a92727;font-style: italic; }
.terminal-1636594121-r20 { fill: #98729f }
.terminal-1636594121-r21 { fill: #6b546f;font-weight: bold }
.terminal-1636594121-r22 { fill: #868887;font-weight: bold }
.terminal-1636594121-r23 { fill: #4e707b;font-weight: bold }
</style>
<defs>
<clipPath id="terminal-1636594121-clip-terminal">
<rect x="0" y="0" width="1341.0" height="3049.0" />
</clipPath>
<clipPath id="terminal-1636594121-line-0">
<rect x="0" y="1.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-1">
<rect x="0" y="25.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-2">
<rect x="0" y="50.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-3">
<rect x="0" y="74.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-4">
<rect x="0" y="99.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-5">
<rect x="0" y="123.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-6">
<rect x="0" y="147.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-7">
<rect x="0" y="172.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-8">
<rect x="0" y="196.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-9">
<rect x="0" y="221.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-10">
<rect x="0" y="245.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-11">
<rect x="0" y="269.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-12">
<rect x="0" y="294.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-13">
<rect x="0" y="318.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-14">
<rect x="0" y="343.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-15">
<rect x="0" y="367.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-16">
<rect x="0" y="391.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-17">
<rect x="0" y="416.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-18">
<rect x="0" y="440.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-19">
<rect x="0" y="465.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-20">
<rect x="0" y="489.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-21">
<rect x="0" y="513.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-22">
<rect x="0" y="538.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-23">
<rect x="0" y="562.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-24">
<rect x="0" y="587.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-25">
<rect x="0" y="611.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-26">
<rect x="0" y="635.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-27">
<rect x="0" y="660.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-28">
<rect x="0" y="684.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-29">
<rect x="0" y="709.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-30">
<rect x="0" y="733.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-31">
<rect x="0" y="757.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-32">
<rect x="0" y="782.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-33">
<rect x="0" y="806.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-34">
<rect x="0" y="831.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-35">
<rect x="0" y="855.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-36">
<rect x="0" y="879.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-37">
<rect x="0" y="904.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-38">
<rect x="0" y="928.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-39">
<rect x="0" y="953.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-40">
<rect x="0" y="977.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-41">
<rect x="0" y="1001.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-42">
<rect x="0" y="1026.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-43">
<rect x="0" y="1050.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-44">
<rect x="0" y="1075.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-45">
<rect x="0" y="1099.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-46">
<rect x="0" y="1123.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-47">
<rect x="0" y="1148.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-48">
<rect x="0" y="1172.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-49">
<rect x="0" y="1197.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-50">
<rect x="0" y="1221.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-51">
<rect x="0" y="1245.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-52">
<rect x="0" y="1270.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-53">
<rect x="0" y="1294.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-54">
<rect x="0" y="1319.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-55">
<rect x="0" y="1343.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-56">
<rect x="0" y="1367.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-57">
<rect x="0" y="1392.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-58">
<rect x="0" y="1416.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-59">
<rect x="0" y="1441.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-60">
<rect x="0" y="1465.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-61">
<rect x="0" y="1489.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-62">
<rect x="0" y="1514.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-63">
<rect x="0" y="1538.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-64">
<rect x="0" y="1563.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-65">
<rect x="0" y="1587.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-66">
<rect x="0" y="1611.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-67">
<rect x="0" y="1636.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-68">
<rect x="0" y="1660.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-69">
<rect x="0" y="1685.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-70">
<rect x="0" y="1709.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-71">
<rect x="0" y="1733.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-72">
<rect x="0" y="1758.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-73">
<rect x="0" y="1782.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-74">
<rect x="0" y="1807.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-75">
<rect x="0" y="1831.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-76">
<rect x="0" y="1855.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-77">
<rect x="0" y="1880.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-78">
<rect x="0" y="1904.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-79">
<rect x="0" y="1929.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-80">
<rect x="0" y="1953.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-81">
<rect x="0" y="1977.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-82">
<rect x="0" y="2002.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-83">
<rect x="0" y="2026.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-84">
<rect x="0" y="2051.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-85">
<rect x="0" y="2075.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-86">
<rect x="0" y="2099.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-87">
<rect x="0" y="2124.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-88">
<rect x="0" y="2148.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-89">
<rect x="0" y="2173.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-90">
<rect x="0" y="2197.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-91">
<rect x="0" y="2221.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-92">
<rect x="0" y="2246.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-93">
<rect x="0" y="2270.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-94">
<rect x="0" y="2295.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-95">
<rect x="0" y="2319.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-96">
<rect x="0" y="2343.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-97">
<rect x="0" y="2368.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-98">
<rect x="0" y="2392.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-99">
<rect x="0" y="2417.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-100">
<rect x="0" y="2441.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-101">
<rect x="0" y="2465.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-102">
<rect x="0" y="2490.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-103">
<rect x="0" y="2514.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-104">
<rect x="0" y="2539.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-105">
<rect x="0" y="2563.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-106">
<rect x="0" y="2587.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-107">
<rect x="0" y="2612.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-108">
<rect x="0" y="2636.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-109">
<rect x="0" y="2661.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-110">
<rect x="0" y="2685.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-111">
<rect x="0" y="2709.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-112">
<rect x="0" y="2734.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-113">
<rect x="0" y="2758.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-114">
<rect x="0" y="2783.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-115">
<rect x="0" y="2807.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-116">
<rect x="0" y="2831.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-117">
<rect x="0" y="2856.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-118">
<rect x="0" y="2880.7" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-119">
<rect x="0" y="2905.1" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-120">
<rect x="0" y="2929.5" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-121">
<rect x="0" y="2953.9" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-122">
<rect x="0" y="2978.3" width="1342" height="24.65"/>
</clipPath>
<clipPath id="terminal-1636594121-line-123">
<rect x="0" y="3002.7" width="1342" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1358" height="3098" rx="8"/><text class="terminal-1636594121-title" fill="#c5c8c6" text-anchor="middle" x="679" y="27">Rich</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-1636594121-clip-terminal)">
<g class="terminal-1636594121-matrix">
<text class="terminal-1636594121-r1" x="0" y="20" textLength="24.4" clip-path="url(#terminal-1636594121-line-0)">╭─</text><text class="terminal-1636594121-r1" x="24.4" y="20" textLength="463.6" clip-path="url(#terminal-1636594121-line-0)">──────────────────────────────────────</text><text class="terminal-1636594121-r2" x="500.2" y="20" textLength="12.2" clip-path="url(#terminal-1636594121-line-0)">&lt;</text><text class="terminal-1636594121-r3" x="512.4" y="20" textLength="61" clip-path="url(#terminal-1636594121-line-0)">class</text><text class="terminal-1636594121-r5" x="585.6" y="20" textLength="231.8" clip-path="url(#terminal-1636594121-line-0)">&#x27;_io.TextIOWrapper&#x27;</text><text class="terminal-1636594121-r2" x="817.4" y="20" textLength="12.2" clip-path="url(#terminal-1636594121-line-0)">&gt;</text><text class="terminal-1636594121-r1" x="841.8" y="20" textLength="475.8" clip-path="url(#terminal-1636594121-line-0)">───────────────────────────────────────</text><text class="terminal-1636594121-r1" x="1317.6" y="20" textLength="24.4" clip-path="url(#terminal-1636594121-line-0)">─╮</text><text class="terminal-1636594121-r4" x="1342" y="20" textLength="12.2" clip-path="url(#terminal-1636594121-line-0)">
</text><text class="terminal-1636594121-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-1)"></text><text class="terminal-1636594121-r6" x="24.4" y="44.4" textLength="829.6" clip-path="url(#terminal-1636594121-line-1)">Character&#160;and&#160;line&#160;based&#160;layer&#160;over&#160;a&#160;BufferedIOBase&#160;object,&#160;buffer.</text><text class="terminal-1636594121-r1" x="1329.8" y="44.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-1)"></text><text class="terminal-1636594121-r4" x="1342" y="44.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-1)">
</text><text class="terminal-1636594121-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-2)"></text><text class="terminal-1636594121-r1" x="1329.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-2)"></text><text class="terminal-1636594121-r4" x="1342" y="68.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-2)">
</text><text class="terminal-1636594121-r1" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-3)"></text><text class="terminal-1636594121-r6" x="24.4" y="93.2" textLength="768.6" clip-path="url(#terminal-1636594121-line-3)">encoding&#160;gives&#160;the&#160;name&#160;of&#160;the&#160;encoding&#160;that&#160;the&#160;stream&#160;will&#160;be</text><text class="terminal-1636594121-r1" x="1329.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-3)"></text><text class="terminal-1636594121-r4" x="1342" y="93.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-3)">
</text><text class="terminal-1636594121-r1" x="0" y="117.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-4)"></text><text class="terminal-1636594121-r6" x="24.4" y="117.6" textLength="488" clip-path="url(#terminal-1636594121-line-4)">decoded&#160;or&#160;encoded&#160;with.&#160;It&#160;defaults&#160;to&#160;</text><text class="terminal-1636594121-r7" x="512.4" y="117.6" textLength="219.6" clip-path="url(#terminal-1636594121-line-4)">locale.getencoding</text><text class="terminal-1636594121-r8" x="732" y="117.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-4)">(</text><text class="terminal-1636594121-r8" x="744.2" y="117.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-4)">)</text><text class="terminal-1636594121-r6" x="756.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-4)">.</text><text class="terminal-1636594121-r1" x="1329.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-4)"></text><text class="terminal-1636594121-r4" x="1342" y="117.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-4)">
</text><text class="terminal-1636594121-r1" x="0" y="142" textLength="12.2" clip-path="url(#terminal-1636594121-line-5)"></text><text class="terminal-1636594121-r1" x="1329.8" y="142" textLength="12.2" clip-path="url(#terminal-1636594121-line-5)"></text><text class="terminal-1636594121-r4" x="1342" y="142" textLength="12.2" clip-path="url(#terminal-1636594121-line-5)">
</text><text class="terminal-1636594121-r1" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-6)"></text><text class="terminal-1636594121-r6" x="24.4" y="166.4" textLength="707.6" clip-path="url(#terminal-1636594121-line-6)">errors&#160;determines&#160;the&#160;strictness&#160;of&#160;encoding&#160;and&#160;decoding&#160;</text><text class="terminal-1636594121-r8" x="732" y="166.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-6)">(</text><text class="terminal-1636594121-r6" x="744.2" y="166.4" textLength="36.6" clip-path="url(#terminal-1636594121-line-6)">see</text><text class="terminal-1636594121-r1" x="1329.8" y="166.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-6)"></text><text class="terminal-1636594121-r4" x="1342" y="166.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-6)">
</text><text class="terminal-1636594121-r1" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-7)"></text><text class="terminal-1636594121-r7" x="24.4" y="190.8" textLength="48.8" clip-path="url(#terminal-1636594121-line-7)">help</text><text class="terminal-1636594121-r8" x="73.2" y="190.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-7)">(</text><text class="terminal-1636594121-r6" x="85.4" y="190.8" textLength="146.4" clip-path="url(#terminal-1636594121-line-7)">codecs.Codec</text><text class="terminal-1636594121-r8" x="231.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-7)">)</text><text class="terminal-1636594121-r6" x="244" y="190.8" textLength="500.2" clip-path="url(#terminal-1636594121-line-7)">&#160;or&#160;the&#160;documentation&#160;for&#160;codecs.register</text><text class="terminal-1636594121-r8" x="744.2" y="190.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-7)">)</text><text class="terminal-1636594121-r6" x="756.4" y="190.8" textLength="48.8" clip-path="url(#terminal-1636594121-line-7)">&#160;and</text><text class="terminal-1636594121-r1" x="1329.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-7)"></text><text class="terminal-1636594121-r4" x="1342" y="190.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-7)">
</text><text class="terminal-1636594121-r1" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-8)"></text><text class="terminal-1636594121-r6" x="24.4" y="215.2" textLength="146.4" clip-path="url(#terminal-1636594121-line-8)">defaults&#160;to&#160;</text><text class="terminal-1636594121-r5" x="170.8" y="215.2" textLength="97.6" clip-path="url(#terminal-1636594121-line-8)">&quot;strict&quot;</text><text class="terminal-1636594121-r6" x="268.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-8)">.</text><text class="terminal-1636594121-r1" x="1329.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-8)"></text><text class="terminal-1636594121-r4" x="1342" y="215.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-8)">
</text><text class="terminal-1636594121-r1" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-9)"></text><text class="terminal-1636594121-r1" x="1329.8" y="239.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-9)"></text><text class="terminal-1636594121-r4" x="1342" y="239.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-9)">
</text><text class="terminal-1636594121-r1" x="0" y="264" textLength="12.2" clip-path="url(#terminal-1636594121-line-10)"></text><text class="terminal-1636594121-r6" x="24.4" y="264" textLength="695.4" clip-path="url(#terminal-1636594121-line-10)">newline&#160;controls&#160;how&#160;line&#160;endings&#160;are&#160;handled.&#160;It&#160;can&#160;be&#160;</text><text class="terminal-1636594121-r9" x="719.8" y="264" textLength="48.8" clip-path="url(#terminal-1636594121-line-10)">None</text><text class="terminal-1636594121-r6" x="768.6" y="264" textLength="24.4" clip-path="url(#terminal-1636594121-line-10)">,&#160;</text><text class="terminal-1636594121-r5" x="793" y="264" textLength="24.4" clip-path="url(#terminal-1636594121-line-10)">&#x27;&#x27;</text><text class="terminal-1636594121-r6" x="817.4" y="264" textLength="12.2" clip-path="url(#terminal-1636594121-line-10)">,</text><text class="terminal-1636594121-r1" x="1329.8" y="264" textLength="12.2" clip-path="url(#terminal-1636594121-line-10)"></text><text class="terminal-1636594121-r4" x="1342" y="264" textLength="12.2" clip-path="url(#terminal-1636594121-line-10)">
</text><text class="terminal-1636594121-r1" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-11)"></text><text class="terminal-1636594121-r5" x="24.4" y="288.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-11)">&#x27;\n&#x27;</text><text class="terminal-1636594121-r6" x="73.2" y="288.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-11)">,&#160;</text><text class="terminal-1636594121-r5" x="97.6" y="288.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-11)">&#x27;\r&#x27;</text><text class="terminal-1636594121-r6" x="146.4" y="288.4" textLength="73.2" clip-path="url(#terminal-1636594121-line-11)">,&#160;and&#160;</text><text class="terminal-1636594121-r5" x="219.6" y="288.4" textLength="73.2" clip-path="url(#terminal-1636594121-line-11)">&#x27;\r\n&#x27;</text><text class="terminal-1636594121-r6" x="292.8" y="288.4" textLength="280.6" clip-path="url(#terminal-1636594121-line-11)">.&#160;&#160;It&#160;works&#160;as&#160;follows:</text><text class="terminal-1636594121-r1" x="1329.8" y="288.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-11)"></text><text class="terminal-1636594121-r4" x="1342" y="288.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-11)">
</text><text class="terminal-1636594121-r1" x="0" y="312.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-12)"></text><text class="terminal-1636594121-r1" x="1329.8" y="312.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-12)"></text><text class="terminal-1636594121-r4" x="1342" y="312.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-12)">
</text><text class="terminal-1636594121-r1" x="0" y="337.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-13)"></text><text class="terminal-1636594121-r6" x="24.4" y="337.2" textLength="317.2" clip-path="url(#terminal-1636594121-line-13)">*&#160;On&#160;input,&#160;if&#160;newline&#160;is&#160;</text><text class="terminal-1636594121-r9" x="341.6" y="337.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-13)">None</text><text class="terminal-1636594121-r6" x="390.4" y="337.2" textLength="341.6" clip-path="url(#terminal-1636594121-line-13)">,&#160;universal&#160;newlines&#160;mode&#160;is</text><text class="terminal-1636594121-r1" x="1329.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-13)"></text><text class="terminal-1636594121-r4" x="1342" y="337.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-13)">
</text><text class="terminal-1636594121-r1" x="0" y="361.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-14)"></text><text class="terminal-1636594121-r6" x="24.4" y="361.6" textLength="500.2" clip-path="url(#terminal-1636594121-line-14)">&#160;&#160;enabled.&#160;Lines&#160;in&#160;the&#160;input&#160;can&#160;end&#160;in&#160;</text><text class="terminal-1636594121-r5" x="524.6" y="361.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-14)">&#x27;\n&#x27;</text><text class="terminal-1636594121-r6" x="573.4" y="361.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-14)">,&#160;</text><text class="terminal-1636594121-r5" x="597.8" y="361.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-14)">&#x27;\r&#x27;</text><text class="terminal-1636594121-r6" x="646.6" y="361.6" textLength="61" clip-path="url(#terminal-1636594121-line-14)">,&#160;or&#160;</text><text class="terminal-1636594121-r5" x="707.6" y="361.6" textLength="73.2" clip-path="url(#terminal-1636594121-line-14)">&#x27;\r\n&#x27;</text><text class="terminal-1636594121-r6" x="780.8" y="361.6" textLength="61" clip-path="url(#terminal-1636594121-line-14)">,&#160;and</text><text class="terminal-1636594121-r1" x="1329.8" y="361.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-14)"></text><text class="terminal-1636594121-r4" x="1342" y="361.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-14)">
</text><text class="terminal-1636594121-r1" x="0" y="386" textLength="12.2" clip-path="url(#terminal-1636594121-line-15)"></text><text class="terminal-1636594121-r6" x="24.4" y="386" textLength="341.6" clip-path="url(#terminal-1636594121-line-15)">&#160;&#160;these&#160;are&#160;translated&#160;into&#160;</text><text class="terminal-1636594121-r5" x="366" y="386" textLength="48.8" clip-path="url(#terminal-1636594121-line-15)">&#x27;\n&#x27;</text><text class="terminal-1636594121-r6" x="414.8" y="386" textLength="353.8" clip-path="url(#terminal-1636594121-line-15)">&#160;before&#160;being&#160;returned&#160;to&#160;the</text><text class="terminal-1636594121-r1" x="1329.8" y="386" textLength="12.2" clip-path="url(#terminal-1636594121-line-15)"></text><text class="terminal-1636594121-r4" x="1342" y="386" textLength="12.2" clip-path="url(#terminal-1636594121-line-15)">
</text><text class="terminal-1636594121-r1" x="0" y="410.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-16)"></text><text class="terminal-1636594121-r6" x="24.4" y="410.4" textLength="231.8" clip-path="url(#terminal-1636594121-line-16)">&#160;&#160;caller.&#160;If&#160;it&#160;is&#160;</text><text class="terminal-1636594121-r5" x="256.2" y="410.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-16)">&#x27;&#x27;</text><text class="terminal-1636594121-r6" x="280.6" y="410.4" textLength="549" clip-path="url(#terminal-1636594121-line-16)">,&#160;universal&#160;newline&#160;mode&#160;is&#160;enabled,&#160;but&#160;line</text><text class="terminal-1636594121-r1" x="1329.8" y="410.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-16)"></text><text class="terminal-1636594121-r4" x="1342" y="410.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-16)">
</text><text class="terminal-1636594121-r1" x="0" y="434.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-17)"></text><text class="terminal-1636594121-r6" x="24.4" y="434.8" textLength="817.4" clip-path="url(#terminal-1636594121-line-17)">&#160;&#160;endings&#160;are&#160;returned&#160;to&#160;the&#160;caller&#160;untranslated.&#160;If&#160;it&#160;has&#160;any&#160;of</text><text class="terminal-1636594121-r1" x="1329.8" y="434.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-17)"></text><text class="terminal-1636594121-r4" x="1342" y="434.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-17)">
</text><text class="terminal-1636594121-r1" x="0" y="459.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-18)"></text><text class="terminal-1636594121-r6" x="24.4" y="459.2" textLength="854" clip-path="url(#terminal-1636594121-line-18)">&#160;&#160;the&#160;other&#160;legal&#160;values,&#160;input&#160;lines&#160;are&#160;only&#160;terminated&#160;by&#160;the&#160;given</text><text class="terminal-1636594121-r1" x="1329.8" y="459.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-18)"></text><text class="terminal-1636594121-r4" x="1342" y="459.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-18)">
</text><text class="terminal-1636594121-r1" x="0" y="483.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-19)"></text><text class="terminal-1636594121-r6" x="24.4" y="483.6" textLength="841.8" clip-path="url(#terminal-1636594121-line-19)">&#160;&#160;string,&#160;and&#160;the&#160;line&#160;ending&#160;is&#160;returned&#160;to&#160;the&#160;caller&#160;untranslated.</text><text class="terminal-1636594121-r1" x="1329.8" y="483.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-19)"></text><text class="terminal-1636594121-r4" x="1342" y="483.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-19)">
</text><text class="terminal-1636594121-r1" x="0" y="508" textLength="12.2" clip-path="url(#terminal-1636594121-line-20)"></text><text class="terminal-1636594121-r1" x="1329.8" y="508" textLength="12.2" clip-path="url(#terminal-1636594121-line-20)"></text><text class="terminal-1636594121-r4" x="1342" y="508" textLength="12.2" clip-path="url(#terminal-1636594121-line-20)">
</text><text class="terminal-1636594121-r1" x="0" y="532.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-21)"></text><text class="terminal-1636594121-r6" x="24.4" y="532.4" textLength="329.4" clip-path="url(#terminal-1636594121-line-21)">*&#160;On&#160;output,&#160;if&#160;newline&#160;is&#160;</text><text class="terminal-1636594121-r9" x="353.8" y="532.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-21)">None</text><text class="terminal-1636594121-r6" x="402.6" y="532.4" textLength="73.2" clip-path="url(#terminal-1636594121-line-21)">,&#160;any&#160;</text><text class="terminal-1636594121-r5" x="475.8" y="532.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-21)">&#x27;\n&#x27;</text><text class="terminal-1636594121-r6" x="524.6" y="532.4" textLength="280.6" clip-path="url(#terminal-1636594121-line-21)">&#160;characters&#160;written&#160;are</text><text class="terminal-1636594121-r1" x="1329.8" y="532.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-21)"></text><text class="terminal-1636594121-r4" x="1342" y="532.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-21)">
</text><text class="terminal-1636594121-r1" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-22)"></text><text class="terminal-1636594121-r6" x="24.4" y="556.8" textLength="793" clip-path="url(#terminal-1636594121-line-22)">&#160;&#160;translated&#160;to&#160;the&#160;system&#160;default&#160;line&#160;separator,&#160;os.linesep.&#160;If</text><text class="terminal-1636594121-r1" x="1329.8" y="556.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-22)"></text><text class="terminal-1636594121-r4" x="1342" y="556.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-22)">
</text><text class="terminal-1636594121-r1" x="0" y="581.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-23)"></text><text class="terminal-1636594121-r6" x="24.4" y="581.2" textLength="158.6" clip-path="url(#terminal-1636594121-line-23)">&#160;&#160;newline&#160;is&#160;</text><text class="terminal-1636594121-r5" x="183" y="581.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-23)">&#x27;&#x27;</text><text class="terminal-1636594121-r6" x="207.4" y="581.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-23)">&#160;or&#160;</text><text class="terminal-1636594121-r5" x="256.2" y="581.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-23)">&#x27;\n&#x27;</text><text class="terminal-1636594121-r6" x="305" y="581.2" textLength="573.4" clip-path="url(#terminal-1636594121-line-23)">,&#160;no&#160;translation&#160;takes&#160;place.&#160;If&#160;newline&#160;is&#160;any</text><text class="terminal-1636594121-r1" x="1329.8" y="581.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-23)"></text><text class="terminal-1636594121-r4" x="1342" y="581.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-23)">
</text><text class="terminal-1636594121-r1" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-24)"></text><text class="terminal-1636594121-r6" x="24.4" y="605.6" textLength="402.6" clip-path="url(#terminal-1636594121-line-24)">&#160;&#160;of&#160;the&#160;other&#160;legal&#160;values,&#160;any&#160;</text><text class="terminal-1636594121-r5" x="427" y="605.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-24)">&#x27;\n&#x27;</text><text class="terminal-1636594121-r6" x="475.8" y="605.6" textLength="414.8" clip-path="url(#terminal-1636594121-line-24)">&#160;characters&#160;written&#160;are&#160;translated</text><text class="terminal-1636594121-r1" x="1329.8" y="605.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-24)"></text><text class="terminal-1636594121-r4" x="1342" y="605.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-24)">
</text><text class="terminal-1636594121-r1" x="0" y="630" textLength="12.2" clip-path="url(#terminal-1636594121-line-25)"></text><text class="terminal-1636594121-r6" x="24.4" y="630" textLength="268.4" clip-path="url(#terminal-1636594121-line-25)">&#160;&#160;to&#160;the&#160;given&#160;string.</text><text class="terminal-1636594121-r1" x="1329.8" y="630" textLength="12.2" clip-path="url(#terminal-1636594121-line-25)"></text><text class="terminal-1636594121-r4" x="1342" y="630" textLength="12.2" clip-path="url(#terminal-1636594121-line-25)">
</text><text class="terminal-1636594121-r1" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-26)"></text><text class="terminal-1636594121-r1" x="1329.8" y="654.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-26)"></text><text class="terminal-1636594121-r4" x="1342" y="654.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-26)">
</text><text class="terminal-1636594121-r1" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-27)"></text><text class="terminal-1636594121-r6" x="24.4" y="678.8" textLength="256.2" clip-path="url(#terminal-1636594121-line-27)">If&#160;line_buffering&#160;is&#160;</text><text class="terminal-1636594121-r10" x="280.6" y="678.8" textLength="48.8" clip-path="url(#terminal-1636594121-line-27)">True</text><text class="terminal-1636594121-r6" x="329.4" y="678.8" textLength="524.6" clip-path="url(#terminal-1636594121-line-27)">,&#160;a&#160;call&#160;to&#160;flush&#160;is&#160;implied&#160;when&#160;a&#160;call&#160;to</text><text class="terminal-1636594121-r1" x="1329.8" y="678.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-27)"></text><text class="terminal-1636594121-r4" x="1342" y="678.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-27)">
</text><text class="terminal-1636594121-r1" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-28)"></text><text class="terminal-1636594121-r6" x="24.4" y="703.2" textLength="427" clip-path="url(#terminal-1636594121-line-28)">write&#160;contains&#160;a&#160;newline&#160;character.</text><text class="terminal-1636594121-r1" x="1329.8" y="703.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-28)"></text><text class="terminal-1636594121-r4" x="1342" y="703.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-28)">
</text><text class="terminal-1636594121-r1" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-29)"></text><text class="terminal-1636594121-r1" x="1329.8" y="727.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-29)"></text><text class="terminal-1636594121-r4" x="1342" y="727.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-29)">
</text><text class="terminal-1636594121-r1" x="0" y="752" textLength="12.2" clip-path="url(#terminal-1636594121-line-30)"></text><text class="terminal-1636594121-r5" x="24.4" y="752" textLength="1293.2" clip-path="url(#terminal-1636594121-line-30)">╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮</text><text class="terminal-1636594121-r1" x="1329.8" y="752" textLength="12.2" clip-path="url(#terminal-1636594121-line-30)"></text><text class="terminal-1636594121-r4" x="1342" y="752" textLength="12.2" clip-path="url(#terminal-1636594121-line-30)">
</text><text class="terminal-1636594121-r1" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)"></text><text class="terminal-1636594121-r5" x="24.4" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)"></text><text class="terminal-1636594121-r11" x="48.8" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)">&lt;</text><text class="terminal-1636594121-r3" x="61" y="776.4" textLength="207.4" clip-path="url(#terminal-1636594121-line-31)">_io.TextIOWrapper</text><text class="terminal-1636594121-r12" x="280.6" y="776.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-31)">name</text><text class="terminal-1636594121-r4" x="329.4" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)">=</text><text class="terminal-1636594121-r5" x="341.6" y="776.4" textLength="109.8" clip-path="url(#terminal-1636594121-line-31)">&#x27;foo.txt&#x27;</text><text class="terminal-1636594121-r12" x="463.6" y="776.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-31)">mode</text><text class="terminal-1636594121-r4" x="512.4" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)">=</text><text class="terminal-1636594121-r5" x="524.6" y="776.4" textLength="36.6" clip-path="url(#terminal-1636594121-line-31)">&#x27;w&#x27;</text><text class="terminal-1636594121-r12" x="573.4" y="776.4" textLength="97.6" clip-path="url(#terminal-1636594121-line-31)">encoding</text><text class="terminal-1636594121-r4" x="671" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)">=</text><text class="terminal-1636594121-r5" x="683.2" y="776.4" textLength="85.4" clip-path="url(#terminal-1636594121-line-31)">&#x27;UTF-8&#x27;</text><text class="terminal-1636594121-r11" x="768.6" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)">&gt;</text><text class="terminal-1636594121-r5" x="1305.4" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)"></text><text class="terminal-1636594121-r1" x="1329.8" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)"></text><text class="terminal-1636594121-r4" x="1342" y="776.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-31)">
</text><text class="terminal-1636594121-r1" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-32)"></text><text class="terminal-1636594121-r5" x="24.4" y="800.8" textLength="1293.2" clip-path="url(#terminal-1636594121-line-32)">╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-1636594121-r1" x="1329.8" y="800.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-32)"></text><text class="terminal-1636594121-r4" x="1342" y="800.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-32)">
</text><text class="terminal-1636594121-r1" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-33)"></text><text class="terminal-1636594121-r1" x="1329.8" y="825.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-33)"></text><text class="terminal-1636594121-r4" x="1342" y="825.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-33)">
</text><text class="terminal-1636594121-r1" x="0" y="849.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-34)"></text><text class="terminal-1636594121-r13" x="122" y="849.6" textLength="73.2" clip-path="url(#terminal-1636594121-line-34)">buffer</text><text class="terminal-1636594121-r4" x="195.2" y="849.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-34)">&#160;=</text><text class="terminal-1636594121-r11" x="231.8" y="849.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-34)">&lt;</text><text class="terminal-1636594121-r3" x="244" y="849.6" textLength="219.6" clip-path="url(#terminal-1636594121-line-34)">_io.BufferedWriter</text><text class="terminal-1636594121-r12" x="475.8" y="849.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-34)">name</text><text class="terminal-1636594121-r4" x="524.6" y="849.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-34)">=</text><text class="terminal-1636594121-r5" x="536.8" y="849.6" textLength="109.8" clip-path="url(#terminal-1636594121-line-34)">&#x27;foo.txt&#x27;</text><text class="terminal-1636594121-r11" x="646.6" y="849.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-34)">&gt;</text><text class="terminal-1636594121-r1" x="1329.8" y="849.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-34)"></text><text class="terminal-1636594121-r4" x="1342" y="849.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-34)">
</text><text class="terminal-1636594121-r1" x="0" y="874" textLength="12.2" clip-path="url(#terminal-1636594121-line-35)"></text><text class="terminal-1636594121-r13" x="122" y="874" textLength="73.2" clip-path="url(#terminal-1636594121-line-35)">closed</text><text class="terminal-1636594121-r4" x="195.2" y="874" textLength="24.4" clip-path="url(#terminal-1636594121-line-35)">&#160;=</text><text class="terminal-1636594121-r14" x="231.8" y="874" textLength="61" clip-path="url(#terminal-1636594121-line-35)">False</text><text class="terminal-1636594121-r1" x="1329.8" y="874" textLength="12.2" clip-path="url(#terminal-1636594121-line-35)"></text><text class="terminal-1636594121-r4" x="1342" y="874" textLength="12.2" clip-path="url(#terminal-1636594121-line-35)">
</text><text class="terminal-1636594121-r1" x="0" y="898.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-36)"></text><text class="terminal-1636594121-r13" x="97.6" y="898.4" textLength="97.6" clip-path="url(#terminal-1636594121-line-36)">encoding</text><text class="terminal-1636594121-r4" x="195.2" y="898.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-36)">&#160;=</text><text class="terminal-1636594121-r5" x="231.8" y="898.4" textLength="85.4" clip-path="url(#terminal-1636594121-line-36)">&#x27;UTF-8&#x27;</text><text class="terminal-1636594121-r1" x="1329.8" y="898.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-36)"></text><text class="terminal-1636594121-r4" x="1342" y="898.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-36)">
</text><text class="terminal-1636594121-r1" x="0" y="922.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-37)"></text><text class="terminal-1636594121-r13" x="122" y="922.8" textLength="73.2" clip-path="url(#terminal-1636594121-line-37)">errors</text><text class="terminal-1636594121-r4" x="195.2" y="922.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-37)">&#160;=</text><text class="terminal-1636594121-r5" x="231.8" y="922.8" textLength="97.6" clip-path="url(#terminal-1636594121-line-37)">&#x27;strict&#x27;</text><text class="terminal-1636594121-r1" x="1329.8" y="922.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-37)"></text><text class="terminal-1636594121-r4" x="1342" y="922.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-37)">
</text><text class="terminal-1636594121-r1" x="0" y="947.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-38)"></text><text class="terminal-1636594121-r13" x="24.4" y="947.2" textLength="170.8" clip-path="url(#terminal-1636594121-line-38)">line_buffering</text><text class="terminal-1636594121-r4" x="195.2" y="947.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-38)">&#160;=</text><text class="terminal-1636594121-r14" x="231.8" y="947.2" textLength="61" clip-path="url(#terminal-1636594121-line-38)">False</text><text class="terminal-1636594121-r1" x="1329.8" y="947.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-38)"></text><text class="terminal-1636594121-r4" x="1342" y="947.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-38)">
</text><text class="terminal-1636594121-r1" x="0" y="971.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-39)"></text><text class="terminal-1636594121-r13" x="146.4" y="971.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-39)">mode</text><text class="terminal-1636594121-r4" x="195.2" y="971.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-39)">&#160;=</text><text class="terminal-1636594121-r5" x="231.8" y="971.6" textLength="36.6" clip-path="url(#terminal-1636594121-line-39)">&#x27;w&#x27;</text><text class="terminal-1636594121-r1" x="1329.8" y="971.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-39)"></text><text class="terminal-1636594121-r4" x="1342" y="971.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-39)">
</text><text class="terminal-1636594121-r1" x="0" y="996" textLength="12.2" clip-path="url(#terminal-1636594121-line-40)"></text><text class="terminal-1636594121-r13" x="146.4" y="996" textLength="48.8" clip-path="url(#terminal-1636594121-line-40)">name</text><text class="terminal-1636594121-r4" x="195.2" y="996" textLength="24.4" clip-path="url(#terminal-1636594121-line-40)">&#160;=</text><text class="terminal-1636594121-r5" x="231.8" y="996" textLength="109.8" clip-path="url(#terminal-1636594121-line-40)">&#x27;foo.txt&#x27;</text><text class="terminal-1636594121-r1" x="1329.8" y="996" textLength="12.2" clip-path="url(#terminal-1636594121-line-40)"></text><text class="terminal-1636594121-r4" x="1342" y="996" textLength="12.2" clip-path="url(#terminal-1636594121-line-40)">
</text><text class="terminal-1636594121-r1" x="0" y="1020.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-41)"></text><text class="terminal-1636594121-r13" x="97.6" y="1020.4" textLength="97.6" clip-path="url(#terminal-1636594121-line-41)">newlines</text><text class="terminal-1636594121-r4" x="195.2" y="1020.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-41)">&#160;=</text><text class="terminal-1636594121-r9" x="231.8" y="1020.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-41)">None</text><text class="terminal-1636594121-r1" x="1329.8" y="1020.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-41)"></text><text class="terminal-1636594121-r4" x="1342" y="1020.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-41)">
</text><text class="terminal-1636594121-r1" x="0" y="1044.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-42)"></text><text class="terminal-1636594121-r13" x="36.6" y="1044.8" textLength="158.6" clip-path="url(#terminal-1636594121-line-42)">write_through</text><text class="terminal-1636594121-r4" x="195.2" y="1044.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-42)">&#160;=</text><text class="terminal-1636594121-r14" x="231.8" y="1044.8" textLength="61" clip-path="url(#terminal-1636594121-line-42)">False</text><text class="terminal-1636594121-r1" x="1329.8" y="1044.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-42)"></text><text class="terminal-1636594121-r4" x="1342" y="1044.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-42)">
</text><text class="terminal-1636594121-r1" x="0" y="1069.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-43)"></text><text class="terminal-1636594121-r13" x="134.2" y="1069.2" textLength="61" clip-path="url(#terminal-1636594121-line-43)">close</text><text class="terminal-1636594121-r4" x="195.2" y="1069.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-43)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1069.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-43)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1069.2" textLength="61" clip-path="url(#terminal-1636594121-line-43)">close</text><text class="terminal-1636594121-r11" x="341.6" y="1069.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-43)">(</text><text class="terminal-1636594121-r11" x="353.8" y="1069.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-43)">)</text><text class="terminal-1636594121-r4" x="366" y="1069.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-43)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1069.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-43)"></text><text class="terminal-1636594121-r4" x="1342" y="1069.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-43)">
</text><text class="terminal-1636594121-r1" x="0" y="1093.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-44)"></text><text class="terminal-1636594121-r17" x="231.8" y="1093.6" textLength="366" clip-path="url(#terminal-1636594121-line-44)">Flush&#160;and&#160;close&#160;the&#160;IO&#160;object.</text><text class="terminal-1636594121-r1" x="1329.8" y="1093.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-44)"></text><text class="terminal-1636594121-r4" x="1342" y="1093.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-44)">
</text><text class="terminal-1636594121-r1" x="0" y="1118" textLength="12.2" clip-path="url(#terminal-1636594121-line-45)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1118" textLength="12.2" clip-path="url(#terminal-1636594121-line-45)"></text><text class="terminal-1636594121-r4" x="1342" y="1118" textLength="12.2" clip-path="url(#terminal-1636594121-line-45)">
</text><text class="terminal-1636594121-r1" x="0" y="1142.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-46)"></text><text class="terminal-1636594121-r17" x="231.8" y="1142.4" textLength="683.2" clip-path="url(#terminal-1636594121-line-46)">This&#160;method&#160;has&#160;no&#160;effect&#160;if&#160;the&#160;file&#160;is&#160;already&#160;closed.</text><text class="terminal-1636594121-r1" x="1329.8" y="1142.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-46)"></text><text class="terminal-1636594121-r4" x="1342" y="1142.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-46)">
</text><text class="terminal-1636594121-r1" x="0" y="1166.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-47)"></text><text class="terminal-1636594121-r13" x="122" y="1166.8" textLength="73.2" clip-path="url(#terminal-1636594121-line-47)">detach</text><text class="terminal-1636594121-r4" x="195.2" y="1166.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-47)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1166.8" textLength="48.8" clip-path="url(#terminal-1636594121-line-47)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1166.8" textLength="73.2" clip-path="url(#terminal-1636594121-line-47)">detach</text><text class="terminal-1636594121-r11" x="353.8" y="1166.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-47)">(</text><text class="terminal-1636594121-r11" x="366" y="1166.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-47)">)</text><text class="terminal-1636594121-r4" x="378.2" y="1166.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-47)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1166.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-47)"></text><text class="terminal-1636594121-r4" x="1342" y="1166.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-47)">
</text><text class="terminal-1636594121-r1" x="0" y="1191.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-48)"></text><text class="terminal-1636594121-r17" x="231.8" y="1191.2" textLength="793" clip-path="url(#terminal-1636594121-line-48)">Separate&#160;the&#160;underlying&#160;buffer&#160;from&#160;the&#160;TextIOBase&#160;and&#160;return&#160;it.</text><text class="terminal-1636594121-r1" x="1329.8" y="1191.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-48)"></text><text class="terminal-1636594121-r4" x="1342" y="1191.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-48)">
</text><text class="terminal-1636594121-r1" x="0" y="1215.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-49)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1215.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-49)"></text><text class="terminal-1636594121-r4" x="1342" y="1215.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-49)">
</text><text class="terminal-1636594121-r1" x="0" y="1240" textLength="12.2" clip-path="url(#terminal-1636594121-line-50)"></text><text class="terminal-1636594121-r17" x="231.8" y="1240" textLength="805.2" clip-path="url(#terminal-1636594121-line-50)">After&#160;the&#160;underlying&#160;buffer&#160;has&#160;been&#160;detached,&#160;the&#160;TextIO&#160;is&#160;in&#160;an</text><text class="terminal-1636594121-r1" x="1329.8" y="1240" textLength="12.2" clip-path="url(#terminal-1636594121-line-50)"></text><text class="terminal-1636594121-r4" x="1342" y="1240" textLength="12.2" clip-path="url(#terminal-1636594121-line-50)">
</text><text class="terminal-1636594121-r1" x="0" y="1264.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-51)"></text><text class="terminal-1636594121-r17" x="231.8" y="1264.4" textLength="183" clip-path="url(#terminal-1636594121-line-51)">unusable&#160;state.</text><text class="terminal-1636594121-r1" x="1329.8" y="1264.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-51)"></text><text class="terminal-1636594121-r4" x="1342" y="1264.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-51)">
</text><text class="terminal-1636594121-r1" x="0" y="1288.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-52)"></text><text class="terminal-1636594121-r13" x="122" y="1288.8" textLength="73.2" clip-path="url(#terminal-1636594121-line-52)">fileno</text><text class="terminal-1636594121-r4" x="195.2" y="1288.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-52)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1288.8" textLength="48.8" clip-path="url(#terminal-1636594121-line-52)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1288.8" textLength="73.2" clip-path="url(#terminal-1636594121-line-52)">fileno</text><text class="terminal-1636594121-r11" x="353.8" y="1288.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-52)">(</text><text class="terminal-1636594121-r11" x="366" y="1288.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-52)">)</text><text class="terminal-1636594121-r4" x="378.2" y="1288.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-52)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1288.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-52)"></text><text class="terminal-1636594121-r4" x="1342" y="1288.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-52)">
</text><text class="terminal-1636594121-r1" x="0" y="1313.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-53)"></text><text class="terminal-1636594121-r17" x="231.8" y="1313.2" textLength="597.8" clip-path="url(#terminal-1636594121-line-53)">Returns&#160;underlying&#160;file&#160;descriptor&#160;if&#160;one&#160;exists.</text><text class="terminal-1636594121-r1" x="1329.8" y="1313.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-53)"></text><text class="terminal-1636594121-r4" x="1342" y="1313.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-53)">
</text><text class="terminal-1636594121-r1" x="0" y="1337.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-54)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1337.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-54)"></text><text class="terminal-1636594121-r4" x="1342" y="1337.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-54)">
</text><text class="terminal-1636594121-r1" x="0" y="1362" textLength="12.2" clip-path="url(#terminal-1636594121-line-55)"></text><text class="terminal-1636594121-r17" x="231.8" y="1362" textLength="805.2" clip-path="url(#terminal-1636594121-line-55)">OSError&#160;is&#160;raised&#160;if&#160;the&#160;IO&#160;object&#160;does&#160;not&#160;use&#160;a&#160;file&#160;descriptor.</text><text class="terminal-1636594121-r1" x="1329.8" y="1362" textLength="12.2" clip-path="url(#terminal-1636594121-line-55)"></text><text class="terminal-1636594121-r4" x="1342" y="1362" textLength="12.2" clip-path="url(#terminal-1636594121-line-55)">
</text><text class="terminal-1636594121-r1" x="0" y="1386.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-56)"></text><text class="terminal-1636594121-r13" x="134.2" y="1386.4" textLength="61" clip-path="url(#terminal-1636594121-line-56)">flush</text><text class="terminal-1636594121-r4" x="195.2" y="1386.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-56)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1386.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-56)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1386.4" textLength="61" clip-path="url(#terminal-1636594121-line-56)">flush</text><text class="terminal-1636594121-r11" x="341.6" y="1386.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-56)">(</text><text class="terminal-1636594121-r11" x="353.8" y="1386.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-56)">)</text><text class="terminal-1636594121-r4" x="366" y="1386.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-56)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1386.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-56)"></text><text class="terminal-1636594121-r4" x="1342" y="1386.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-56)">
</text><text class="terminal-1636594121-r1" x="0" y="1410.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-57)"></text><text class="terminal-1636594121-r17" x="231.8" y="1410.8" textLength="427" clip-path="url(#terminal-1636594121-line-57)">Flush&#160;write&#160;buffers,&#160;if&#160;applicable.</text><text class="terminal-1636594121-r1" x="1329.8" y="1410.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-57)"></text><text class="terminal-1636594121-r4" x="1342" y="1410.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-57)">
</text><text class="terminal-1636594121-r1" x="0" y="1435.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-58)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1435.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-58)"></text><text class="terminal-1636594121-r4" x="1342" y="1435.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-58)">
</text><text class="terminal-1636594121-r1" x="0" y="1459.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-59)"></text><text class="terminal-1636594121-r17" x="231.8" y="1459.6" textLength="768.6" clip-path="url(#terminal-1636594121-line-59)">This&#160;is&#160;not&#160;implemented&#160;for&#160;read-only&#160;and&#160;non-blocking&#160;streams.</text><text class="terminal-1636594121-r1" x="1329.8" y="1459.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-59)"></text><text class="terminal-1636594121-r4" x="1342" y="1459.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-59)">
</text><text class="terminal-1636594121-r1" x="0" y="1484" textLength="12.2" clip-path="url(#terminal-1636594121-line-60)"></text><text class="terminal-1636594121-r13" x="122" y="1484" textLength="73.2" clip-path="url(#terminal-1636594121-line-60)">isatty</text><text class="terminal-1636594121-r4" x="195.2" y="1484" textLength="24.4" clip-path="url(#terminal-1636594121-line-60)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1484" textLength="48.8" clip-path="url(#terminal-1636594121-line-60)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1484" textLength="73.2" clip-path="url(#terminal-1636594121-line-60)">isatty</text><text class="terminal-1636594121-r11" x="353.8" y="1484" textLength="12.2" clip-path="url(#terminal-1636594121-line-60)">(</text><text class="terminal-1636594121-r11" x="366" y="1484" textLength="12.2" clip-path="url(#terminal-1636594121-line-60)">)</text><text class="terminal-1636594121-r4" x="378.2" y="1484" textLength="12.2" clip-path="url(#terminal-1636594121-line-60)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1484" textLength="12.2" clip-path="url(#terminal-1636594121-line-60)"></text><text class="terminal-1636594121-r4" x="1342" y="1484" textLength="12.2" clip-path="url(#terminal-1636594121-line-60)">
</text><text class="terminal-1636594121-r1" x="0" y="1508.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-61)"></text><text class="terminal-1636594121-r17" x="231.8" y="1508.4" textLength="317.2" clip-path="url(#terminal-1636594121-line-61)">Return&#160;whether&#160;this&#160;is&#160;an&#160;</text><text class="terminal-1636594121-r18" x="549" y="1508.4" textLength="158.6" clip-path="url(#terminal-1636594121-line-61)">&#x27;interactive&#x27;</text><text class="terminal-1636594121-r17" x="707.6" y="1508.4" textLength="97.6" clip-path="url(#terminal-1636594121-line-61)">&#160;stream.</text><text class="terminal-1636594121-r1" x="1329.8" y="1508.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-61)"></text><text class="terminal-1636594121-r4" x="1342" y="1508.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-61)">
</text><text class="terminal-1636594121-r1" x="0" y="1532.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-62)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1532.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-62)"></text><text class="terminal-1636594121-r4" x="1342" y="1532.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-62)">
</text><text class="terminal-1636594121-r1" x="0" y="1557.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-63)"></text><text class="terminal-1636594121-r17" x="231.8" y="1557.2" textLength="85.4" clip-path="url(#terminal-1636594121-line-63)">Return&#160;</text><text class="terminal-1636594121-r19" x="317.2" y="1557.2" textLength="61" clip-path="url(#terminal-1636594121-line-63)">False</text><text class="terminal-1636594121-r17" x="378.2" y="1557.2" textLength="329.4" clip-path="url(#terminal-1636594121-line-63)">&#160;if&#160;it&#160;can&#x27;t&#160;be&#160;determined.</text><text class="terminal-1636594121-r1" x="1329.8" y="1557.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-63)"></text><text class="terminal-1636594121-r4" x="1342" y="1557.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-63)">
</text><text class="terminal-1636594121-r1" x="0" y="1581.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-64)"></text><text class="terminal-1636594121-r13" x="146.4" y="1581.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-64)">read</text><text class="terminal-1636594121-r4" x="195.2" y="1581.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-64)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1581.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-64)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1581.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-64)">read</text><text class="terminal-1636594121-r11" x="329.4" y="1581.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-64)">(</text><text class="terminal-1636594121-r12" x="341.6" y="1581.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-64)">size</text><text class="terminal-1636594121-r4" x="390.4" y="1581.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-64)">=</text><text class="terminal-1636594121-r8" x="402.6" y="1581.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-64)">-1</text><text class="terminal-1636594121-r4" x="427" y="1581.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-64)">,&#160;</text><text class="terminal-1636594121-r20" x="451.4" y="1581.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-64)">/</text><text class="terminal-1636594121-r11" x="463.6" y="1581.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-64)">)</text><text class="terminal-1636594121-r4" x="475.8" y="1581.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-64)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1581.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-64)"></text><text class="terminal-1636594121-r4" x="1342" y="1581.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-64)">
</text><text class="terminal-1636594121-r1" x="0" y="1606" textLength="12.2" clip-path="url(#terminal-1636594121-line-65)"></text><text class="terminal-1636594121-r17" x="231.8" y="1606" textLength="463.6" clip-path="url(#terminal-1636594121-line-65)">Read&#160;at&#160;most&#160;n&#160;characters&#160;from&#160;stream.</text><text class="terminal-1636594121-r1" x="1329.8" y="1606" textLength="12.2" clip-path="url(#terminal-1636594121-line-65)"></text><text class="terminal-1636594121-r4" x="1342" y="1606" textLength="12.2" clip-path="url(#terminal-1636594121-line-65)">
</text><text class="terminal-1636594121-r1" x="0" y="1630.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-66)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1630.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-66)"></text><text class="terminal-1636594121-r4" x="1342" y="1630.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-66)">
</text><text class="terminal-1636594121-r1" x="0" y="1654.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-67)"></text><text class="terminal-1636594121-r17" x="231.8" y="1654.8" textLength="841.8" clip-path="url(#terminal-1636594121-line-67)">Read&#160;from&#160;underlying&#160;buffer&#160;until&#160;we&#160;have&#160;n&#160;characters&#160;or&#160;we&#160;hit&#160;EOF.</text><text class="terminal-1636594121-r1" x="1329.8" y="1654.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-67)"></text><text class="terminal-1636594121-r4" x="1342" y="1654.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-67)">
</text><text class="terminal-1636594121-r1" x="0" y="1679.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-68)"></text><text class="terminal-1636594121-r17" x="231.8" y="1679.2" textLength="536.8" clip-path="url(#terminal-1636594121-line-68)">If&#160;n&#160;is&#160;negative&#160;or&#160;omitted,&#160;read&#160;until&#160;EOF.</text><text class="terminal-1636594121-r1" x="1329.8" y="1679.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-68)"></text><text class="terminal-1636594121-r4" x="1342" y="1679.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-68)">
</text><text class="terminal-1636594121-r1" x="0" y="1703.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-69)"></text><text class="terminal-1636594121-r13" x="97.6" y="1703.6" textLength="97.6" clip-path="url(#terminal-1636594121-line-69)">readable</text><text class="terminal-1636594121-r4" x="195.2" y="1703.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-69)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1703.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-69)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1703.6" textLength="97.6" clip-path="url(#terminal-1636594121-line-69)">readable</text><text class="terminal-1636594121-r11" x="378.2" y="1703.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-69)">(</text><text class="terminal-1636594121-r11" x="390.4" y="1703.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-69)">)</text><text class="terminal-1636594121-r4" x="402.6" y="1703.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-69)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1703.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-69)"></text><text class="terminal-1636594121-r4" x="1342" y="1703.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-69)">
</text><text class="terminal-1636594121-r1" x="0" y="1728" textLength="12.2" clip-path="url(#terminal-1636594121-line-70)"></text><text class="terminal-1636594121-r17" x="231.8" y="1728" textLength="549" clip-path="url(#terminal-1636594121-line-70)">Return&#160;whether&#160;object&#160;was&#160;opened&#160;for&#160;reading.</text><text class="terminal-1636594121-r1" x="1329.8" y="1728" textLength="12.2" clip-path="url(#terminal-1636594121-line-70)"></text><text class="terminal-1636594121-r4" x="1342" y="1728" textLength="12.2" clip-path="url(#terminal-1636594121-line-70)">
</text><text class="terminal-1636594121-r1" x="0" y="1752.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-71)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1752.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-71)"></text><text class="terminal-1636594121-r4" x="1342" y="1752.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-71)">
</text><text class="terminal-1636594121-r1" x="0" y="1776.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-72)"></text><text class="terminal-1636594121-r17" x="231.8" y="1776.8" textLength="36.6" clip-path="url(#terminal-1636594121-line-72)">If&#160;</text><text class="terminal-1636594121-r19" x="268.4" y="1776.8" textLength="61" clip-path="url(#terminal-1636594121-line-72)">False</text><text class="terminal-1636594121-r17" x="329.4" y="1776.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-72)">,&#160;</text><text class="terminal-1636594121-r21" x="353.8" y="1776.8" textLength="48.8" clip-path="url(#terminal-1636594121-line-72)">read</text><text class="terminal-1636594121-r22" x="402.6" y="1776.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-72)">(</text><text class="terminal-1636594121-r22" x="414.8" y="1776.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-72)">)</text><text class="terminal-1636594121-r17" x="427" y="1776.8" textLength="244" clip-path="url(#terminal-1636594121-line-72)">&#160;will&#160;raise&#160;OSError.</text><text class="terminal-1636594121-r1" x="1329.8" y="1776.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-72)"></text><text class="terminal-1636594121-r4" x="1342" y="1776.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-72)">
</text><text class="terminal-1636594121-r1" x="0" y="1801.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-73)"></text><text class="terminal-1636594121-r13" x="97.6" y="1801.2" textLength="97.6" clip-path="url(#terminal-1636594121-line-73)">readline</text><text class="terminal-1636594121-r4" x="195.2" y="1801.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-73)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1801.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-73)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1801.2" textLength="97.6" clip-path="url(#terminal-1636594121-line-73)">readline</text><text class="terminal-1636594121-r11" x="378.2" y="1801.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-73)">(</text><text class="terminal-1636594121-r12" x="390.4" y="1801.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-73)">size</text><text class="terminal-1636594121-r4" x="439.2" y="1801.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-73)">=</text><text class="terminal-1636594121-r8" x="451.4" y="1801.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-73)">-1</text><text class="terminal-1636594121-r4" x="475.8" y="1801.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-73)">,&#160;</text><text class="terminal-1636594121-r20" x="500.2" y="1801.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-73)">/</text><text class="terminal-1636594121-r11" x="512.4" y="1801.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-73)">)</text><text class="terminal-1636594121-r4" x="524.6" y="1801.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-73)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1801.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-73)"></text><text class="terminal-1636594121-r4" x="1342" y="1801.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-73)">
</text><text class="terminal-1636594121-r1" x="0" y="1825.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-74)"></text><text class="terminal-1636594121-r17" x="231.8" y="1825.6" textLength="317.2" clip-path="url(#terminal-1636594121-line-74)">Read&#160;until&#160;newline&#160;or&#160;EOF.</text><text class="terminal-1636594121-r1" x="1329.8" y="1825.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-74)"></text><text class="terminal-1636594121-r4" x="1342" y="1825.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-74)">
</text><text class="terminal-1636594121-r1" x="0" y="1850" textLength="12.2" clip-path="url(#terminal-1636594121-line-75)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1850" textLength="12.2" clip-path="url(#terminal-1636594121-line-75)"></text><text class="terminal-1636594121-r4" x="1342" y="1850" textLength="12.2" clip-path="url(#terminal-1636594121-line-75)">
</text><text class="terminal-1636594121-r1" x="0" y="1874.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-76)"></text><text class="terminal-1636594121-r17" x="231.8" y="1874.4" textLength="610" clip-path="url(#terminal-1636594121-line-76)">Returns&#160;an&#160;empty&#160;string&#160;if&#160;EOF&#160;is&#160;hit&#160;immediately.</text><text class="terminal-1636594121-r1" x="1329.8" y="1874.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-76)"></text><text class="terminal-1636594121-r4" x="1342" y="1874.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-76)">
</text><text class="terminal-1636594121-r1" x="0" y="1898.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-77)"></text><text class="terminal-1636594121-r13" x="85.4" y="1898.8" textLength="109.8" clip-path="url(#terminal-1636594121-line-77)">readlines</text><text class="terminal-1636594121-r4" x="195.2" y="1898.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-77)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="1898.8" textLength="48.8" clip-path="url(#terminal-1636594121-line-77)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="1898.8" textLength="109.8" clip-path="url(#terminal-1636594121-line-77)">readlines</text><text class="terminal-1636594121-r11" x="390.4" y="1898.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-77)">(</text><text class="terminal-1636594121-r12" x="402.6" y="1898.8" textLength="48.8" clip-path="url(#terminal-1636594121-line-77)">hint</text><text class="terminal-1636594121-r4" x="451.4" y="1898.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-77)">=</text><text class="terminal-1636594121-r8" x="463.6" y="1898.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-77)">-1</text><text class="terminal-1636594121-r4" x="488" y="1898.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-77)">,&#160;</text><text class="terminal-1636594121-r20" x="512.4" y="1898.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-77)">/</text><text class="terminal-1636594121-r11" x="524.6" y="1898.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-77)">)</text><text class="terminal-1636594121-r4" x="536.8" y="1898.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-77)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="1898.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-77)"></text><text class="terminal-1636594121-r4" x="1342" y="1898.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-77)">
</text><text class="terminal-1636594121-r1" x="0" y="1923.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-78)"></text><text class="terminal-1636594121-r17" x="231.8" y="1923.2" textLength="475.8" clip-path="url(#terminal-1636594121-line-78)">Return&#160;a&#160;list&#160;of&#160;lines&#160;from&#160;the&#160;stream.</text><text class="terminal-1636594121-r1" x="1329.8" y="1923.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-78)"></text><text class="terminal-1636594121-r4" x="1342" y="1923.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-78)">
</text><text class="terminal-1636594121-r1" x="0" y="1947.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-79)"></text><text class="terminal-1636594121-r1" x="1329.8" y="1947.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-79)"></text><text class="terminal-1636594121-r4" x="1342" y="1947.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-79)">
</text><text class="terminal-1636594121-r1" x="0" y="1972" textLength="12.2" clip-path="url(#terminal-1636594121-line-80)"></text><text class="terminal-1636594121-r17" x="231.8" y="1972" textLength="805.2" clip-path="url(#terminal-1636594121-line-80)">hint&#160;can&#160;be&#160;specified&#160;to&#160;control&#160;the&#160;number&#160;of&#160;lines&#160;read:&#160;no&#160;more</text><text class="terminal-1636594121-r1" x="1329.8" y="1972" textLength="12.2" clip-path="url(#terminal-1636594121-line-80)"></text><text class="terminal-1636594121-r4" x="1342" y="1972" textLength="12.2" clip-path="url(#terminal-1636594121-line-80)">
</text><text class="terminal-1636594121-r1" x="0" y="1996.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-81)"></text><text class="terminal-1636594121-r17" x="231.8" y="1996.4" textLength="451.4" clip-path="url(#terminal-1636594121-line-81)">lines&#160;will&#160;be&#160;read&#160;if&#160;the&#160;total&#160;size&#160;</text><text class="terminal-1636594121-r22" x="683.2" y="1996.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-81)">(</text><text class="terminal-1636594121-r17" x="695.4" y="1996.4" textLength="231.8" clip-path="url(#terminal-1636594121-line-81)">in&#160;bytes/characters</text><text class="terminal-1636594121-r22" x="927.2" y="1996.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-81)">)</text><text class="terminal-1636594121-r17" x="939.4" y="1996.4" textLength="85.4" clip-path="url(#terminal-1636594121-line-81)">&#160;of&#160;all</text><text class="terminal-1636594121-r1" x="1329.8" y="1996.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-81)"></text><text class="terminal-1636594121-r4" x="1342" y="1996.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-81)">
</text><text class="terminal-1636594121-r1" x="0" y="2020.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-82)"></text><text class="terminal-1636594121-r17" x="231.8" y="2020.8" textLength="317.2" clip-path="url(#terminal-1636594121-line-82)">lines&#160;so&#160;far&#160;exceeds&#160;hint.</text><text class="terminal-1636594121-r1" x="1329.8" y="2020.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-82)"></text><text class="terminal-1636594121-r4" x="1342" y="2020.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-82)">
</text><text class="terminal-1636594121-r1" x="0" y="2045.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-83)"></text><text class="terminal-1636594121-r13" x="61" y="2045.2" textLength="134.2" clip-path="url(#terminal-1636594121-line-83)">reconfigure</text><text class="terminal-1636594121-r4" x="195.2" y="2045.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-83)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="2045.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-83)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="2045.2" textLength="134.2" clip-path="url(#terminal-1636594121-line-83)">reconfigure</text><text class="terminal-1636594121-r11" x="414.8" y="2045.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-83)">(</text><text class="terminal-1636594121-r4" x="427" y="2045.2" textLength="36.6" clip-path="url(#terminal-1636594121-line-83)">*,&#160;</text><text class="terminal-1636594121-r12" x="463.6" y="2045.2" textLength="97.6" clip-path="url(#terminal-1636594121-line-83)">encoding</text><text class="terminal-1636594121-r4" x="561.2" y="2045.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-83)">=</text><text class="terminal-1636594121-r9" x="573.4" y="2045.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-83)">None</text><text class="terminal-1636594121-r4" x="622.2" y="2045.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-83)">,&#160;</text><text class="terminal-1636594121-r12" x="646.6" y="2045.2" textLength="73.2" clip-path="url(#terminal-1636594121-line-83)">errors</text><text class="terminal-1636594121-r4" x="719.8" y="2045.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-83)">=</text><text class="terminal-1636594121-r9" x="732" y="2045.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-83)">None</text><text class="terminal-1636594121-r4" x="780.8" y="2045.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-83)">,&#160;</text><text class="terminal-1636594121-r12" x="805.2" y="2045.2" textLength="85.4" clip-path="url(#terminal-1636594121-line-83)">newline</text><text class="terminal-1636594121-r4" x="890.6" y="2045.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-83)">=</text><text class="terminal-1636594121-r9" x="902.8" y="2045.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-83)">None</text><text class="terminal-1636594121-r4" x="951.6" y="2045.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-83)">,&#160;</text><text class="terminal-1636594121-r12" x="976" y="2045.2" textLength="170.8" clip-path="url(#terminal-1636594121-line-83)">line_buffering</text><text class="terminal-1636594121-r4" x="1146.8" y="2045.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-83)">=</text><text class="terminal-1636594121-r9" x="1159" y="2045.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-83)">None</text><text class="terminal-1636594121-r4" x="1207.8" y="2045.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-83)">,&#160;</text><text class="terminal-1636594121-r1" x="1329.8" y="2045.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-83)"></text><text class="terminal-1636594121-r4" x="1342" y="2045.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-83)">
</text><text class="terminal-1636594121-r1" x="0" y="2069.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-84)"></text><text class="terminal-1636594121-r12" x="231.8" y="2069.6" textLength="158.6" clip-path="url(#terminal-1636594121-line-84)">write_through</text><text class="terminal-1636594121-r4" x="390.4" y="2069.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-84)">=</text><text class="terminal-1636594121-r9" x="402.6" y="2069.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-84)">None</text><text class="terminal-1636594121-r11" x="451.4" y="2069.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-84)">)</text><text class="terminal-1636594121-r4" x="463.6" y="2069.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-84)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="2069.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-84)"></text><text class="terminal-1636594121-r4" x="1342" y="2069.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-84)">
</text><text class="terminal-1636594121-r1" x="0" y="2094" textLength="12.2" clip-path="url(#terminal-1636594121-line-85)"></text><text class="terminal-1636594121-r17" x="231.8" y="2094" textLength="585.6" clip-path="url(#terminal-1636594121-line-85)">Reconfigure&#160;the&#160;text&#160;stream&#160;with&#160;new&#160;parameters.</text><text class="terminal-1636594121-r1" x="1329.8" y="2094" textLength="12.2" clip-path="url(#terminal-1636594121-line-85)"></text><text class="terminal-1636594121-r4" x="1342" y="2094" textLength="12.2" clip-path="url(#terminal-1636594121-line-85)">
</text><text class="terminal-1636594121-r1" x="0" y="2118.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-86)"></text><text class="terminal-1636594121-r1" x="1329.8" y="2118.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-86)"></text><text class="terminal-1636594121-r4" x="1342" y="2118.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-86)">
</text><text class="terminal-1636594121-r1" x="0" y="2142.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-87)"></text><text class="terminal-1636594121-r17" x="231.8" y="2142.8" textLength="488" clip-path="url(#terminal-1636594121-line-87)">This&#160;also&#160;does&#160;an&#160;implicit&#160;stream&#160;flush.</text><text class="terminal-1636594121-r1" x="1329.8" y="2142.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-87)"></text><text class="terminal-1636594121-r4" x="1342" y="2142.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-87)">
</text><text class="terminal-1636594121-r1" x="0" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)"></text><text class="terminal-1636594121-r13" x="146.4" y="2167.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-88)">seek</text><text class="terminal-1636594121-r4" x="195.2" y="2167.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-88)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="2167.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-88)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="2167.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-88)">seek</text><text class="terminal-1636594121-r11" x="329.4" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)">(</text><text class="terminal-1636594121-r4" x="341.6" y="2167.2" textLength="97.6" clip-path="url(#terminal-1636594121-line-88)">cookie,&#160;</text><text class="terminal-1636594121-r12" x="439.2" y="2167.2" textLength="73.2" clip-path="url(#terminal-1636594121-line-88)">whence</text><text class="terminal-1636594121-r4" x="512.4" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)">=</text><text class="terminal-1636594121-r8" x="524.6" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)">0</text><text class="terminal-1636594121-r4" x="536.8" y="2167.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-88)">,&#160;</text><text class="terminal-1636594121-r20" x="561.2" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)">/</text><text class="terminal-1636594121-r11" x="573.4" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)">)</text><text class="terminal-1636594121-r4" x="585.6" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)"></text><text class="terminal-1636594121-r4" x="1342" y="2167.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-88)">
</text><text class="terminal-1636594121-r1" x="0" y="2191.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-89)"></text><text class="terminal-1636594121-r17" x="231.8" y="2191.6" textLength="280.6" clip-path="url(#terminal-1636594121-line-89)">Change&#160;stream&#160;position.</text><text class="terminal-1636594121-r1" x="1329.8" y="2191.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-89)"></text><text class="terminal-1636594121-r4" x="1342" y="2191.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-89)">
</text><text class="terminal-1636594121-r1" x="0" y="2216" textLength="12.2" clip-path="url(#terminal-1636594121-line-90)"></text><text class="terminal-1636594121-r1" x="1329.8" y="2216" textLength="12.2" clip-path="url(#terminal-1636594121-line-90)"></text><text class="terminal-1636594121-r4" x="1342" y="2216" textLength="12.2" clip-path="url(#terminal-1636594121-line-90)">
</text><text class="terminal-1636594121-r1" x="0" y="2240.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-91)"></text><text class="terminal-1636594121-r17" x="231.8" y="2240.4" textLength="805.2" clip-path="url(#terminal-1636594121-line-91)">Change&#160;the&#160;stream&#160;position&#160;to&#160;the&#160;given&#160;byte&#160;offset.&#160;The&#160;offset&#160;is</text><text class="terminal-1636594121-r1" x="1329.8" y="2240.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-91)"></text><text class="terminal-1636594121-r4" x="1342" y="2240.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-91)">
</text><text class="terminal-1636594121-r1" x="0" y="2264.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-92)"></text><text class="terminal-1636594121-r17" x="231.8" y="2264.8" textLength="793" clip-path="url(#terminal-1636594121-line-92)">interpreted&#160;relative&#160;to&#160;the&#160;position&#160;indicated&#160;by&#160;whence.&#160;&#160;Values</text><text class="terminal-1636594121-r1" x="1329.8" y="2264.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-92)"></text><text class="terminal-1636594121-r4" x="1342" y="2264.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-92)">
</text><text class="terminal-1636594121-r1" x="0" y="2289.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-93)"></text><text class="terminal-1636594121-r17" x="231.8" y="2289.2" textLength="183" clip-path="url(#terminal-1636594121-line-93)">for&#160;whence&#160;are:</text><text class="terminal-1636594121-r1" x="1329.8" y="2289.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-93)"></text><text class="terminal-1636594121-r4" x="1342" y="2289.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-93)">
</text><text class="terminal-1636594121-r1" x="0" y="2313.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-94)"></text><text class="terminal-1636594121-r1" x="1329.8" y="2313.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-94)"></text><text class="terminal-1636594121-r4" x="1342" y="2313.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-94)">
</text><text class="terminal-1636594121-r1" x="0" y="2338" textLength="12.2" clip-path="url(#terminal-1636594121-line-95)"></text><text class="terminal-1636594121-r17" x="231.8" y="2338" textLength="24.4" clip-path="url(#terminal-1636594121-line-95)">*&#160;</text><text class="terminal-1636594121-r23" x="256.2" y="2338" textLength="12.2" clip-path="url(#terminal-1636594121-line-95)">0</text><text class="terminal-1636594121-r17" x="268.4" y="2338" textLength="244" clip-path="url(#terminal-1636594121-line-95)">&#160;--&#160;start&#160;of&#160;stream&#160;</text><text class="terminal-1636594121-r22" x="512.4" y="2338" textLength="12.2" clip-path="url(#terminal-1636594121-line-95)">(</text><text class="terminal-1636594121-r17" x="524.6" y="2338" textLength="134.2" clip-path="url(#terminal-1636594121-line-95)">the&#160;default</text><text class="terminal-1636594121-r22" x="658.8" y="2338" textLength="12.2" clip-path="url(#terminal-1636594121-line-95)">)</text><text class="terminal-1636594121-r17" x="671" y="2338" textLength="427" clip-path="url(#terminal-1636594121-line-95)">;&#160;offset&#160;should&#160;be&#160;zero&#160;or&#160;positive</text><text class="terminal-1636594121-r1" x="1329.8" y="2338" textLength="12.2" clip-path="url(#terminal-1636594121-line-95)"></text><text class="terminal-1636594121-r4" x="1342" y="2338" textLength="12.2" clip-path="url(#terminal-1636594121-line-95)">
</text><text class="terminal-1636594121-r1" x="0" y="2362.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-96)"></text><text class="terminal-1636594121-r17" x="231.8" y="2362.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-96)">*&#160;</text><text class="terminal-1636594121-r23" x="256.2" y="2362.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-96)">1</text><text class="terminal-1636594121-r17" x="268.4" y="2362.4" textLength="622.2" clip-path="url(#terminal-1636594121-line-96)">&#160;--&#160;current&#160;stream&#160;position;&#160;offset&#160;may&#160;be&#160;negative</text><text class="terminal-1636594121-r1" x="1329.8" y="2362.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-96)"></text><text class="terminal-1636594121-r4" x="1342" y="2362.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-96)">
</text><text class="terminal-1636594121-r1" x="0" y="2386.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-97)"></text><text class="terminal-1636594121-r17" x="231.8" y="2386.8" textLength="24.4" clip-path="url(#terminal-1636594121-line-97)">*&#160;</text><text class="terminal-1636594121-r23" x="256.2" y="2386.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-97)">2</text><text class="terminal-1636594121-r17" x="268.4" y="2386.8" textLength="549" clip-path="url(#terminal-1636594121-line-97)">&#160;--&#160;end&#160;of&#160;stream;&#160;offset&#160;is&#160;usually&#160;negative</text><text class="terminal-1636594121-r1" x="1329.8" y="2386.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-97)"></text><text class="terminal-1636594121-r4" x="1342" y="2386.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-97)">
</text><text class="terminal-1636594121-r1" x="0" y="2411.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-98)"></text><text class="terminal-1636594121-r1" x="1329.8" y="2411.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-98)"></text><text class="terminal-1636594121-r4" x="1342" y="2411.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-98)">
</text><text class="terminal-1636594121-r1" x="0" y="2435.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-99)"></text><text class="terminal-1636594121-r17" x="231.8" y="2435.6" textLength="402.6" clip-path="url(#terminal-1636594121-line-99)">Return&#160;the&#160;new&#160;absolute&#160;position.</text><text class="terminal-1636594121-r1" x="1329.8" y="2435.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-99)"></text><text class="terminal-1636594121-r4" x="1342" y="2435.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-99)">
</text><text class="terminal-1636594121-r1" x="0" y="2460" textLength="12.2" clip-path="url(#terminal-1636594121-line-100)"></text><text class="terminal-1636594121-r13" x="97.6" y="2460" textLength="97.6" clip-path="url(#terminal-1636594121-line-100)">seekable</text><text class="terminal-1636594121-r4" x="195.2" y="2460" textLength="24.4" clip-path="url(#terminal-1636594121-line-100)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="2460" textLength="48.8" clip-path="url(#terminal-1636594121-line-100)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="2460" textLength="97.6" clip-path="url(#terminal-1636594121-line-100)">seekable</text><text class="terminal-1636594121-r11" x="378.2" y="2460" textLength="12.2" clip-path="url(#terminal-1636594121-line-100)">(</text><text class="terminal-1636594121-r11" x="390.4" y="2460" textLength="12.2" clip-path="url(#terminal-1636594121-line-100)">)</text><text class="terminal-1636594121-r4" x="402.6" y="2460" textLength="12.2" clip-path="url(#terminal-1636594121-line-100)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="2460" textLength="12.2" clip-path="url(#terminal-1636594121-line-100)"></text><text class="terminal-1636594121-r4" x="1342" y="2460" textLength="12.2" clip-path="url(#terminal-1636594121-line-100)">
</text><text class="terminal-1636594121-r1" x="0" y="2484.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-101)"></text><text class="terminal-1636594121-r17" x="231.8" y="2484.4" textLength="549" clip-path="url(#terminal-1636594121-line-101)">Return&#160;whether&#160;object&#160;supports&#160;random&#160;access.</text><text class="terminal-1636594121-r1" x="1329.8" y="2484.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-101)"></text><text class="terminal-1636594121-r4" x="1342" y="2484.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-101)">
</text><text class="terminal-1636594121-r1" x="0" y="2508.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-102)"></text><text class="terminal-1636594121-r1" x="1329.8" y="2508.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-102)"></text><text class="terminal-1636594121-r4" x="1342" y="2508.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-102)">
</text><text class="terminal-1636594121-r1" x="0" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)"></text><text class="terminal-1636594121-r17" x="231.8" y="2533.2" textLength="36.6" clip-path="url(#terminal-1636594121-line-103)">If&#160;</text><text class="terminal-1636594121-r19" x="268.4" y="2533.2" textLength="61" clip-path="url(#terminal-1636594121-line-103)">False</text><text class="terminal-1636594121-r17" x="329.4" y="2533.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-103)">,&#160;</text><text class="terminal-1636594121-r21" x="353.8" y="2533.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-103)">seek</text><text class="terminal-1636594121-r22" x="402.6" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)">(</text><text class="terminal-1636594121-r22" x="414.8" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)">)</text><text class="terminal-1636594121-r17" x="427" y="2533.2" textLength="24.4" clip-path="url(#terminal-1636594121-line-103)">,&#160;</text><text class="terminal-1636594121-r21" x="451.4" y="2533.2" textLength="48.8" clip-path="url(#terminal-1636594121-line-103)">tell</text><text class="terminal-1636594121-r22" x="500.2" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)">(</text><text class="terminal-1636594121-r22" x="512.4" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)">)</text><text class="terminal-1636594121-r17" x="524.6" y="2533.2" textLength="61" clip-path="url(#terminal-1636594121-line-103)">&#160;and&#160;</text><text class="terminal-1636594121-r21" x="585.6" y="2533.2" textLength="97.6" clip-path="url(#terminal-1636594121-line-103)">truncate</text><text class="terminal-1636594121-r22" x="683.2" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)">(</text><text class="terminal-1636594121-r22" x="695.4" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)">)</text><text class="terminal-1636594121-r17" x="707.6" y="2533.2" textLength="244" clip-path="url(#terminal-1636594121-line-103)">&#160;will&#160;raise&#160;OSError.</text><text class="terminal-1636594121-r1" x="1329.8" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)"></text><text class="terminal-1636594121-r4" x="1342" y="2533.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-103)">
</text><text class="terminal-1636594121-r1" x="0" y="2557.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-104)"></text><text class="terminal-1636594121-r17" x="231.8" y="2557.6" textLength="414.8" clip-path="url(#terminal-1636594121-line-104)">This&#160;method&#160;may&#160;need&#160;to&#160;do&#160;a&#160;test&#160;</text><text class="terminal-1636594121-r21" x="646.6" y="2557.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-104)">seek</text><text class="terminal-1636594121-r22" x="695.4" y="2557.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-104)">(</text><text class="terminal-1636594121-r22" x="707.6" y="2557.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-104)">)</text><text class="terminal-1636594121-r17" x="719.8" y="2557.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-104)">.</text><text class="terminal-1636594121-r1" x="1329.8" y="2557.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-104)"></text><text class="terminal-1636594121-r4" x="1342" y="2557.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-104)">
</text><text class="terminal-1636594121-r1" x="0" y="2582" textLength="12.2" clip-path="url(#terminal-1636594121-line-105)"></text><text class="terminal-1636594121-r13" x="146.4" y="2582" textLength="48.8" clip-path="url(#terminal-1636594121-line-105)">tell</text><text class="terminal-1636594121-r4" x="195.2" y="2582" textLength="24.4" clip-path="url(#terminal-1636594121-line-105)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="2582" textLength="48.8" clip-path="url(#terminal-1636594121-line-105)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="2582" textLength="48.8" clip-path="url(#terminal-1636594121-line-105)">tell</text><text class="terminal-1636594121-r11" x="329.4" y="2582" textLength="12.2" clip-path="url(#terminal-1636594121-line-105)">(</text><text class="terminal-1636594121-r11" x="341.6" y="2582" textLength="12.2" clip-path="url(#terminal-1636594121-line-105)">)</text><text class="terminal-1636594121-r4" x="353.8" y="2582" textLength="12.2" clip-path="url(#terminal-1636594121-line-105)">:</text><text class="terminal-1636594121-r17" x="378.2" y="2582" textLength="378.2" clip-path="url(#terminal-1636594121-line-105)">Return&#160;current&#160;stream&#160;position.</text><text class="terminal-1636594121-r1" x="1329.8" y="2582" textLength="12.2" clip-path="url(#terminal-1636594121-line-105)"></text><text class="terminal-1636594121-r4" x="1342" y="2582" textLength="12.2" clip-path="url(#terminal-1636594121-line-105)">
</text><text class="terminal-1636594121-r1" x="0" y="2606.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-106)"></text><text class="terminal-1636594121-r13" x="97.6" y="2606.4" textLength="97.6" clip-path="url(#terminal-1636594121-line-106)">truncate</text><text class="terminal-1636594121-r4" x="195.2" y="2606.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-106)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="2606.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-106)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="2606.4" textLength="97.6" clip-path="url(#terminal-1636594121-line-106)">truncate</text><text class="terminal-1636594121-r11" x="378.2" y="2606.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-106)">(</text><text class="terminal-1636594121-r12" x="390.4" y="2606.4" textLength="36.6" clip-path="url(#terminal-1636594121-line-106)">pos</text><text class="terminal-1636594121-r4" x="427" y="2606.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-106)">=</text><text class="terminal-1636594121-r9" x="439.2" y="2606.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-106)">None</text><text class="terminal-1636594121-r4" x="488" y="2606.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-106)">,&#160;</text><text class="terminal-1636594121-r20" x="512.4" y="2606.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-106)">/</text><text class="terminal-1636594121-r11" x="524.6" y="2606.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-106)">)</text><text class="terminal-1636594121-r4" x="536.8" y="2606.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-106)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="2606.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-106)"></text><text class="terminal-1636594121-r4" x="1342" y="2606.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-106)">
</text><text class="terminal-1636594121-r1" x="0" y="2630.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-107)"></text><text class="terminal-1636594121-r17" x="231.8" y="2630.8" textLength="341.6" clip-path="url(#terminal-1636594121-line-107)">Truncate&#160;file&#160;to&#160;size&#160;bytes.</text><text class="terminal-1636594121-r1" x="1329.8" y="2630.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-107)"></text><text class="terminal-1636594121-r4" x="1342" y="2630.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-107)">
</text><text class="terminal-1636594121-r1" x="0" y="2655.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-108)"></text><text class="terminal-1636594121-r1" x="1329.8" y="2655.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-108)"></text><text class="terminal-1636594121-r4" x="1342" y="2655.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-108)">
</text><text class="terminal-1636594121-r1" x="0" y="2679.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-109)"></text><text class="terminal-1636594121-r17" x="231.8" y="2679.6" textLength="780.8" clip-path="url(#terminal-1636594121-line-109)">File&#160;pointer&#160;is&#160;left&#160;unchanged.&#160;&#160;Size&#160;defaults&#160;to&#160;the&#160;current&#160;IO</text><text class="terminal-1636594121-r1" x="1329.8" y="2679.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-109)"></text><text class="terminal-1636594121-r4" x="1342" y="2679.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-109)">
</text><text class="terminal-1636594121-r1" x="0" y="2704" textLength="12.2" clip-path="url(#terminal-1636594121-line-110)"></text><text class="terminal-1636594121-r17" x="231.8" y="2704" textLength="292.8" clip-path="url(#terminal-1636594121-line-110)">position&#160;as&#160;reported&#160;by&#160;</text><text class="terminal-1636594121-r21" x="524.6" y="2704" textLength="48.8" clip-path="url(#terminal-1636594121-line-110)">tell</text><text class="terminal-1636594121-r22" x="573.4" y="2704" textLength="12.2" clip-path="url(#terminal-1636594121-line-110)">(</text><text class="terminal-1636594121-r22" x="585.6" y="2704" textLength="12.2" clip-path="url(#terminal-1636594121-line-110)">)</text><text class="terminal-1636594121-r17" x="597.8" y="2704" textLength="292.8" clip-path="url(#terminal-1636594121-line-110)">.&#160;&#160;Returns&#160;the&#160;new&#160;size.</text><text class="terminal-1636594121-r1" x="1329.8" y="2704" textLength="12.2" clip-path="url(#terminal-1636594121-line-110)"></text><text class="terminal-1636594121-r4" x="1342" y="2704" textLength="12.2" clip-path="url(#terminal-1636594121-line-110)">
</text><text class="terminal-1636594121-r1" x="0" y="2728.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-111)"></text><text class="terminal-1636594121-r13" x="97.6" y="2728.4" textLength="97.6" clip-path="url(#terminal-1636594121-line-111)">writable</text><text class="terminal-1636594121-r4" x="195.2" y="2728.4" textLength="24.4" clip-path="url(#terminal-1636594121-line-111)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="2728.4" textLength="48.8" clip-path="url(#terminal-1636594121-line-111)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="2728.4" textLength="97.6" clip-path="url(#terminal-1636594121-line-111)">writable</text><text class="terminal-1636594121-r11" x="378.2" y="2728.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-111)">(</text><text class="terminal-1636594121-r11" x="390.4" y="2728.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-111)">)</text><text class="terminal-1636594121-r4" x="402.6" y="2728.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-111)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="2728.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-111)"></text><text class="terminal-1636594121-r4" x="1342" y="2728.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-111)">
</text><text class="terminal-1636594121-r1" x="0" y="2752.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-112)"></text><text class="terminal-1636594121-r17" x="231.8" y="2752.8" textLength="549" clip-path="url(#terminal-1636594121-line-112)">Return&#160;whether&#160;object&#160;was&#160;opened&#160;for&#160;writing.</text><text class="terminal-1636594121-r1" x="1329.8" y="2752.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-112)"></text><text class="terminal-1636594121-r4" x="1342" y="2752.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-112)">
</text><text class="terminal-1636594121-r1" x="0" y="2777.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-113)"></text><text class="terminal-1636594121-r1" x="1329.8" y="2777.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-113)"></text><text class="terminal-1636594121-r4" x="1342" y="2777.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-113)">
</text><text class="terminal-1636594121-r1" x="0" y="2801.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-114)"></text><text class="terminal-1636594121-r17" x="231.8" y="2801.6" textLength="36.6" clip-path="url(#terminal-1636594121-line-114)">If&#160;</text><text class="terminal-1636594121-r19" x="268.4" y="2801.6" textLength="61" clip-path="url(#terminal-1636594121-line-114)">False</text><text class="terminal-1636594121-r17" x="329.4" y="2801.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-114)">,&#160;</text><text class="terminal-1636594121-r21" x="353.8" y="2801.6" textLength="61" clip-path="url(#terminal-1636594121-line-114)">write</text><text class="terminal-1636594121-r22" x="414.8" y="2801.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-114)">(</text><text class="terminal-1636594121-r22" x="427" y="2801.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-114)">)</text><text class="terminal-1636594121-r17" x="439.2" y="2801.6" textLength="244" clip-path="url(#terminal-1636594121-line-114)">&#160;will&#160;raise&#160;OSError.</text><text class="terminal-1636594121-r1" x="1329.8" y="2801.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-114)"></text><text class="terminal-1636594121-r4" x="1342" y="2801.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-114)">
</text><text class="terminal-1636594121-r1" x="0" y="2826" textLength="12.2" clip-path="url(#terminal-1636594121-line-115)"></text><text class="terminal-1636594121-r13" x="134.2" y="2826" textLength="61" clip-path="url(#terminal-1636594121-line-115)">write</text><text class="terminal-1636594121-r4" x="195.2" y="2826" textLength="24.4" clip-path="url(#terminal-1636594121-line-115)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="2826" textLength="48.8" clip-path="url(#terminal-1636594121-line-115)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="2826" textLength="61" clip-path="url(#terminal-1636594121-line-115)">write</text><text class="terminal-1636594121-r11" x="341.6" y="2826" textLength="12.2" clip-path="url(#terminal-1636594121-line-115)">(</text><text class="terminal-1636594121-r4" x="353.8" y="2826" textLength="73.2" clip-path="url(#terminal-1636594121-line-115)">text,&#160;</text><text class="terminal-1636594121-r20" x="427" y="2826" textLength="12.2" clip-path="url(#terminal-1636594121-line-115)">/</text><text class="terminal-1636594121-r11" x="439.2" y="2826" textLength="12.2" clip-path="url(#terminal-1636594121-line-115)">)</text><text class="terminal-1636594121-r4" x="451.4" y="2826" textLength="12.2" clip-path="url(#terminal-1636594121-line-115)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="2826" textLength="12.2" clip-path="url(#terminal-1636594121-line-115)"></text><text class="terminal-1636594121-r4" x="1342" y="2826" textLength="12.2" clip-path="url(#terminal-1636594121-line-115)">
</text><text class="terminal-1636594121-r1" x="0" y="2850.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-116)"></text><text class="terminal-1636594121-r17" x="231.8" y="2850.4" textLength="280.6" clip-path="url(#terminal-1636594121-line-116)">Write&#160;string&#160;to&#160;stream.</text><text class="terminal-1636594121-r1" x="1329.8" y="2850.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-116)"></text><text class="terminal-1636594121-r4" x="1342" y="2850.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-116)">
</text><text class="terminal-1636594121-r1" x="0" y="2874.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-117)"></text><text class="terminal-1636594121-r17" x="231.8" y="2874.8" textLength="500.2" clip-path="url(#terminal-1636594121-line-117)">Returns&#160;the&#160;number&#160;of&#160;characters&#160;written&#160;</text><text class="terminal-1636594121-r22" x="732" y="2874.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-117)">(</text><text class="terminal-1636594121-r17" x="744.2" y="2874.8" textLength="292.8" clip-path="url(#terminal-1636594121-line-117)">which&#160;is&#160;always&#160;equal&#160;to</text><text class="terminal-1636594121-r1" x="1329.8" y="2874.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-117)"></text><text class="terminal-1636594121-r4" x="1342" y="2874.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-117)">
</text><text class="terminal-1636594121-r1" x="0" y="2899.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-118)"></text><text class="terminal-1636594121-r17" x="231.8" y="2899.2" textLength="292.8" clip-path="url(#terminal-1636594121-line-118)">the&#160;length&#160;of&#160;the&#160;string</text><text class="terminal-1636594121-r22" x="524.6" y="2899.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-118)">)</text><text class="terminal-1636594121-r17" x="536.8" y="2899.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-118)">.</text><text class="terminal-1636594121-r1" x="1329.8" y="2899.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-118)"></text><text class="terminal-1636594121-r4" x="1342" y="2899.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-118)">
</text><text class="terminal-1636594121-r1" x="0" y="2923.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-119)"></text><text class="terminal-1636594121-r13" x="73.2" y="2923.6" textLength="122" clip-path="url(#terminal-1636594121-line-119)">writelines</text><text class="terminal-1636594121-r4" x="195.2" y="2923.6" textLength="24.4" clip-path="url(#terminal-1636594121-line-119)">&#160;=</text><text class="terminal-1636594121-r15" x="231.8" y="2923.6" textLength="48.8" clip-path="url(#terminal-1636594121-line-119)">def&#160;</text><text class="terminal-1636594121-r16" x="280.6" y="2923.6" textLength="122" clip-path="url(#terminal-1636594121-line-119)">writelines</text><text class="terminal-1636594121-r11" x="402.6" y="2923.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-119)">(</text><text class="terminal-1636594121-r4" x="414.8" y="2923.6" textLength="85.4" clip-path="url(#terminal-1636594121-line-119)">lines,&#160;</text><text class="terminal-1636594121-r20" x="500.2" y="2923.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-119)">/</text><text class="terminal-1636594121-r11" x="512.4" y="2923.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-119)">)</text><text class="terminal-1636594121-r4" x="524.6" y="2923.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-119)">:</text><text class="terminal-1636594121-r1" x="1329.8" y="2923.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-119)"></text><text class="terminal-1636594121-r4" x="1342" y="2923.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-119)">
</text><text class="terminal-1636594121-r1" x="0" y="2948" textLength="12.2" clip-path="url(#terminal-1636594121-line-120)"></text><text class="terminal-1636594121-r17" x="231.8" y="2948" textLength="390.4" clip-path="url(#terminal-1636594121-line-120)">Write&#160;a&#160;list&#160;of&#160;lines&#160;to&#160;stream.</text><text class="terminal-1636594121-r1" x="1329.8" y="2948" textLength="12.2" clip-path="url(#terminal-1636594121-line-120)"></text><text class="terminal-1636594121-r4" x="1342" y="2948" textLength="12.2" clip-path="url(#terminal-1636594121-line-120)">
</text><text class="terminal-1636594121-r1" x="0" y="2972.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-121)"></text><text class="terminal-1636594121-r1" x="1329.8" y="2972.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-121)"></text><text class="terminal-1636594121-r4" x="1342" y="2972.4" textLength="12.2" clip-path="url(#terminal-1636594121-line-121)">
</text><text class="terminal-1636594121-r1" x="0" y="2996.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-122)"></text><text class="terminal-1636594121-r17" x="231.8" y="2996.8" textLength="744.2" clip-path="url(#terminal-1636594121-line-122)">Line&#160;separators&#160;are&#160;not&#160;added,&#160;so&#160;it&#160;is&#160;usual&#160;for&#160;each&#160;of&#160;the</text><text class="terminal-1636594121-r1" x="1329.8" y="2996.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-122)"></text><text class="terminal-1636594121-r4" x="1342" y="2996.8" textLength="12.2" clip-path="url(#terminal-1636594121-line-122)">
</text><text class="terminal-1636594121-r1" x="0" y="3021.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-123)"></text><text class="terminal-1636594121-r17" x="231.8" y="3021.2" textLength="622.2" clip-path="url(#terminal-1636594121-line-123)">lines&#160;provided&#160;to&#160;have&#160;a&#160;line&#160;separator&#160;at&#160;the&#160;end.</text><text class="terminal-1636594121-r1" x="1329.8" y="3021.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-123)"></text><text class="terminal-1636594121-r4" x="1342" y="3021.2" textLength="12.2" clip-path="url(#terminal-1636594121-line-123)">
</text><text class="terminal-1636594121-r1" x="0" y="3045.6" textLength="1342" clip-path="url(#terminal-1636594121-line-124)">╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-1636594121-r4" x="1342" y="3045.6" textLength="12.2" clip-path="url(#terminal-1636594121-line-124)">
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 124 KiB

BIN
docs/blog/images/puppy.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 KiB

View file

@ -0,0 +1,138 @@
<svg class="rich-terminal" viewBox="0 0 860 538.0" 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-1356838233-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-1356838233-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-1356838233-r1 { fill: #1e1e1e }
.terminal-1356838233-r2 { fill: #0178d4 }
.terminal-1356838233-r3 { fill: #c5c8c6 }
.terminal-1356838233-r4 { fill: #e2e2e2 }
.terminal-1356838233-r5 { fill: #787878;font-weight: bold }
.terminal-1356838233-r6 { fill: #e1e1e1 }
</style>
<defs>
<clipPath id="terminal-1356838233-clip-terminal">
<rect x="0" y="0" width="840.8" height="487.0" />
</clipPath>
<clipPath id="terminal-1356838233-line-0">
<rect x="0" y="1.5" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-1">
<rect x="0" y="25.9" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-2">
<rect x="0" y="50.3" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-3">
<rect x="0" y="74.7" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-4">
<rect x="0" y="99.1" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-5">
<rect x="0" y="123.5" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-6">
<rect x="0" y="147.9" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-7">
<rect x="0" y="172.3" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-8">
<rect x="0" y="196.7" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-9">
<rect x="0" y="221.1" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-10">
<rect x="0" y="245.5" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-11">
<rect x="0" y="269.9" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-12">
<rect x="0" y="294.3" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-13">
<rect x="0" y="318.7" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-14">
<rect x="0" y="343.1" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-15">
<rect x="0" y="367.5" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-16">
<rect x="0" y="391.9" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-17">
<rect x="0" y="416.3" width="841.8" height="24.65"/>
</clipPath>
<clipPath id="terminal-1356838233-line-18">
<rect x="0" y="440.7" width="841.8" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="858" height="536" rx="8"/><text class="terminal-1356838233-title" fill="#c5c8c6" text-anchor="middle" x="429" y="27">FruitsApp</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-1356838233-clip-terminal)">
<rect fill="#0178d4" x="0" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="12.2" y="1.5" width="817.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="829.6" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="0" y="25.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="12.2" y="25.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="36.6" y="25.9" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="97.6" y="25.9" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="158.6" y="25.9" width="646.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="805.2" y="25.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="829.6" y="25.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="0" y="50.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="12.2" y="50.3" width="817.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="829.6" y="50.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="841.8" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-1356838233-matrix">
<text class="terminal-1356838233-r1" x="0" y="20" textLength="12.2" clip-path="url(#terminal-1356838233-line-0)"></text><text class="terminal-1356838233-r2" x="12.2" y="20" textLength="817.4" clip-path="url(#terminal-1356838233-line-0)">▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔</text><text class="terminal-1356838233-r2" x="829.6" y="20" textLength="12.2" clip-path="url(#terminal-1356838233-line-0)"></text><text class="terminal-1356838233-r3" x="841.8" y="20" textLength="12.2" clip-path="url(#terminal-1356838233-line-0)">
</text><text class="terminal-1356838233-r1" x="0" y="44.4" textLength="12.2" clip-path="url(#terminal-1356838233-line-1)"></text><text class="terminal-1356838233-r4" x="36.6" y="44.4" textLength="61" clip-path="url(#terminal-1356838233-line-1)">straw</text><text class="terminal-1356838233-r5" x="97.6" y="44.4" textLength="61" clip-path="url(#terminal-1356838233-line-1)">berry</text><text class="terminal-1356838233-r2" x="829.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1356838233-line-1)"></text><text class="terminal-1356838233-r3" x="841.8" y="44.4" textLength="12.2" clip-path="url(#terminal-1356838233-line-1)">
</text><text class="terminal-1356838233-r1" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-1356838233-line-2)"></text><text class="terminal-1356838233-r2" x="12.2" y="68.8" textLength="817.4" clip-path="url(#terminal-1356838233-line-2)">▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁</text><text class="terminal-1356838233-r2" x="829.6" y="68.8" textLength="12.2" clip-path="url(#terminal-1356838233-line-2)"></text><text class="terminal-1356838233-r3" x="841.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1356838233-line-2)">
</text><text class="terminal-1356838233-r3" x="841.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1356838233-line-3)">
</text><text class="terminal-1356838233-r3" x="841.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1356838233-line-4)">
</text><text class="terminal-1356838233-r3" x="841.8" y="142" textLength="12.2" clip-path="url(#terminal-1356838233-line-5)">
</text><text class="terminal-1356838233-r3" x="841.8" y="166.4" textLength="12.2" clip-path="url(#terminal-1356838233-line-6)">
</text><text class="terminal-1356838233-r3" x="841.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1356838233-line-7)">
</text><text class="terminal-1356838233-r3" x="841.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1356838233-line-8)">
</text><text class="terminal-1356838233-r3" x="841.8" y="239.6" textLength="12.2" clip-path="url(#terminal-1356838233-line-9)">
</text><text class="terminal-1356838233-r3" x="841.8" y="264" textLength="12.2" clip-path="url(#terminal-1356838233-line-10)">
</text><text class="terminal-1356838233-r3" x="841.8" y="288.4" textLength="12.2" clip-path="url(#terminal-1356838233-line-11)">
</text><text class="terminal-1356838233-r3" x="841.8" y="312.8" textLength="12.2" clip-path="url(#terminal-1356838233-line-12)">
</text><text class="terminal-1356838233-r3" x="841.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1356838233-line-13)">
</text><text class="terminal-1356838233-r3" x="841.8" y="361.6" textLength="12.2" clip-path="url(#terminal-1356838233-line-14)">
</text><text class="terminal-1356838233-r3" x="841.8" y="386" textLength="12.2" clip-path="url(#terminal-1356838233-line-15)">
</text><text class="terminal-1356838233-r3" x="841.8" y="410.4" textLength="12.2" clip-path="url(#terminal-1356838233-line-16)">
</text><text class="terminal-1356838233-r3" x="841.8" y="434.8" textLength="12.2" clip-path="url(#terminal-1356838233-line-17)">
</text><text class="terminal-1356838233-r3" x="841.8" y="459.2" textLength="12.2" clip-path="url(#terminal-1356838233-line-18)">
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 134 KiB

232
docs/blog/images/trogon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 103 KiB

View file

@ -0,0 +1,155 @@
<svg class="rich-terminal" viewBox="0 0 1116 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-369012557-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-369012557-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-369012557-r1 { fill: #e1e1e1 }
.terminal-369012557-r2 { fill: #c5c8c6 }
.terminal-369012557-r3 { fill: #1e1e1e }
.terminal-369012557-r4 { fill: #b93c5b }
.terminal-369012557-r5 { fill: #e2e2e2 }
.terminal-369012557-r6 { fill: #e1e1e1;font-weight: bold }
.terminal-369012557-r7 { fill: #98a84b }
</style>
<defs>
<clipPath id="terminal-369012557-clip-terminal">
<rect x="0" y="0" width="1097.0" height="584.5999999999999" />
</clipPath>
<clipPath id="terminal-369012557-line-0">
<rect x="0" y="1.5" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-1">
<rect x="0" y="25.9" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-2">
<rect x="0" y="50.3" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-3">
<rect x="0" y="74.7" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-4">
<rect x="0" y="99.1" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-5">
<rect x="0" y="123.5" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-6">
<rect x="0" y="147.9" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-7">
<rect x="0" y="172.3" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-8">
<rect x="0" y="196.7" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-9">
<rect x="0" y="221.1" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-10">
<rect x="0" y="245.5" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-11">
<rect x="0" y="269.9" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-12">
<rect x="0" y="294.3" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-13">
<rect x="0" y="318.7" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-14">
<rect x="0" y="343.1" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-15">
<rect x="0" y="367.5" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-16">
<rect x="0" y="391.9" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-17">
<rect x="0" y="416.3" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-18">
<rect x="0" y="440.7" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-19">
<rect x="0" y="465.1" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-20">
<rect x="0" y="489.5" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-21">
<rect x="0" y="513.9" width="1098" height="24.65"/>
</clipPath>
<clipPath id="terminal-369012557-line-22">
<rect x="0" y="538.3" width="1098" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1114" height="633.6" rx="8"/><text class="terminal-369012557-title" fill="#c5c8c6" text-anchor="middle" x="557" y="27">InputApp</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-369012557-clip-terminal)">
<rect fill="#1e1e1e" x="0" y="1.5" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="25.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="24.4" y="25.9" width="793" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="817.4" y="25.9" width="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="50.3" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#b93c5b" x="12.2" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="24.4" y="74.7" width="1049.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1073.6" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1085.8" y="74.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#b93c5b" x="12.2" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="24.4" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="48.8" y="99.1" width="36.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="85.4" y="99.1" width="963.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="1049.2" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1073.6" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1085.8" y="99.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#b93c5b" x="12.2" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#262626" x="24.4" y="123.5" width="1049.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1073.6" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1085.8" y="123.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="24.4" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="36.6" y="172.3" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="341.6" y="172.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="366" y="172.3" width="244" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="610" y="172.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="634.4" y="172.3" width="341.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="976" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="988.2" y="172.3" width="85.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1073.6" y="172.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="1098" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="1098" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-369012557-matrix">
<text class="terminal-369012557-r2" x="1098" y="20" textLength="12.2" clip-path="url(#terminal-369012557-line-0)">
</text><text class="terminal-369012557-r1" x="24.4" y="44.4" textLength="793" clip-path="url(#terminal-369012557-line-1)">Enter&#160;an&#160;even&#160;number&#160;between&#160;1&#160;and&#160;100&#160;that&#160;is&#160;also&#160;a&#160;palindrome.</text><text class="terminal-369012557-r2" x="1098" y="44.4" textLength="12.2" clip-path="url(#terminal-369012557-line-1)">
</text><text class="terminal-369012557-r2" x="1098" y="68.8" textLength="12.2" clip-path="url(#terminal-369012557-line-2)">
</text><text class="terminal-369012557-r3" x="12.2" y="93.2" textLength="12.2" clip-path="url(#terminal-369012557-line-3)"></text><text class="terminal-369012557-r4" x="24.4" y="93.2" textLength="1049.2" clip-path="url(#terminal-369012557-line-3)">▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔</text><text class="terminal-369012557-r4" x="1073.6" y="93.2" textLength="12.2" clip-path="url(#terminal-369012557-line-3)"></text><text class="terminal-369012557-r2" x="1098" y="93.2" textLength="12.2" clip-path="url(#terminal-369012557-line-3)">
</text><text class="terminal-369012557-r3" x="12.2" y="117.6" textLength="12.2" clip-path="url(#terminal-369012557-line-4)"></text><text class="terminal-369012557-r5" x="48.8" y="117.6" textLength="36.6" clip-path="url(#terminal-369012557-line-4)">foo</text><text class="terminal-369012557-r4" x="1073.6" y="117.6" textLength="12.2" clip-path="url(#terminal-369012557-line-4)"></text><text class="terminal-369012557-r2" x="1098" y="117.6" textLength="12.2" clip-path="url(#terminal-369012557-line-4)">
</text><text class="terminal-369012557-r3" x="12.2" y="142" textLength="12.2" clip-path="url(#terminal-369012557-line-5)"></text><text class="terminal-369012557-r4" x="24.4" y="142" textLength="1049.2" clip-path="url(#terminal-369012557-line-5)">▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁</text><text class="terminal-369012557-r4" x="1073.6" y="142" textLength="12.2" clip-path="url(#terminal-369012557-line-5)"></text><text class="terminal-369012557-r2" x="1098" y="142" textLength="12.2" clip-path="url(#terminal-369012557-line-5)">
</text><text class="terminal-369012557-r2" x="1098" y="166.4" textLength="12.2" clip-path="url(#terminal-369012557-line-6)">
</text><text class="terminal-369012557-r6" x="24.4" y="190.8" textLength="12.2" clip-path="url(#terminal-369012557-line-7)">[</text><text class="terminal-369012557-r7" x="36.6" y="190.8" textLength="305" clip-path="url(#terminal-369012557-line-7)">&#x27;Must&#160;be&#160;a&#160;valid&#160;number.&#x27;</text><text class="terminal-369012557-r1" x="341.6" y="190.8" textLength="24.4" clip-path="url(#terminal-369012557-line-7)">,&#160;</text><text class="terminal-369012557-r7" x="366" y="190.8" textLength="244" clip-path="url(#terminal-369012557-line-7)">&#x27;Value&#160;is&#160;not&#160;even.&#x27;</text><text class="terminal-369012557-r1" x="610" y="190.8" textLength="24.4" clip-path="url(#terminal-369012557-line-7)">,&#160;</text><text class="terminal-369012557-r7" x="634.4" y="190.8" textLength="341.6" clip-path="url(#terminal-369012557-line-7)">&quot;That&#x27;s&#160;not&#160;a&#160;palindrome&#160;:/&quot;</text><text class="terminal-369012557-r6" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-369012557-line-7)">]</text><text class="terminal-369012557-r2" x="1098" y="190.8" textLength="12.2" clip-path="url(#terminal-369012557-line-7)">
</text><text class="terminal-369012557-r2" x="1098" y="215.2" textLength="12.2" clip-path="url(#terminal-369012557-line-8)">
</text><text class="terminal-369012557-r2" x="1098" y="239.6" textLength="12.2" clip-path="url(#terminal-369012557-line-9)">
</text><text class="terminal-369012557-r2" x="1098" y="264" textLength="12.2" clip-path="url(#terminal-369012557-line-10)">
</text><text class="terminal-369012557-r2" x="1098" y="288.4" textLength="12.2" clip-path="url(#terminal-369012557-line-11)">
</text><text class="terminal-369012557-r2" x="1098" y="312.8" textLength="12.2" clip-path="url(#terminal-369012557-line-12)">
</text><text class="terminal-369012557-r2" x="1098" y="337.2" textLength="12.2" clip-path="url(#terminal-369012557-line-13)">
</text><text class="terminal-369012557-r2" x="1098" y="361.6" textLength="12.2" clip-path="url(#terminal-369012557-line-14)">
</text><text class="terminal-369012557-r2" x="1098" y="386" textLength="12.2" clip-path="url(#terminal-369012557-line-15)">
</text><text class="terminal-369012557-r2" x="1098" y="410.4" textLength="12.2" clip-path="url(#terminal-369012557-line-16)">
</text><text class="terminal-369012557-r2" x="1098" y="434.8" textLength="12.2" clip-path="url(#terminal-369012557-line-17)">
</text><text class="terminal-369012557-r2" x="1098" y="459.2" textLength="12.2" clip-path="url(#terminal-369012557-line-18)">
</text><text class="terminal-369012557-r2" x="1098" y="483.6" textLength="12.2" clip-path="url(#terminal-369012557-line-19)">
</text><text class="terminal-369012557-r2" x="1098" y="508" textLength="12.2" clip-path="url(#terminal-369012557-line-20)">
</text><text class="terminal-369012557-r2" x="1098" y="532.4" textLength="12.2" clip-path="url(#terminal-369012557-line-21)">
</text><text class="terminal-369012557-r2" x="1098" y="556.8" textLength="12.2" clip-path="url(#terminal-369012557-line-22)">
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,138 @@
---
draft: false
date: 2023-03-15
categories:
- DevLog
authors:
- willmcgugan
---
# No-async async with Python
A (reasonable) criticism of async is that it tends to proliferate in your code. In order to `await` something, your functions must be `async` all the way up the call-stack. This tends to result in you making things `async` just to support that one call that needs it or, worse, adding `async` just-in-case. Given that going from `def` to `async def` is a breaking change there is a strong incentive to go straight there.
Before you know it, you have adopted a policy of "async all the things".
<!-- more -->
Textual is an async framework, but doesn't *require* the app developer to use the `async` and `await` keywords (but you can if you need to). This post is about how Textual accomplishes this async-agnosticism.
!!! info
See this [example](https://textual.textualize.io/guide/widgets/#attributes-down) from the docs for an async-less Textual app.
## An apology
But first, an apology! In a previous post I said Textual "doesn't do any IO of its own". This is not accurate. Textual responds to keys and mouse events (**I**nput) and writes content to the terminal (**O**utput).
Although Textual clearly does do IO, it uses `asyncio` mainly for *concurrency*. It allows each widget to update its part of the screen independently from the rest of the app.
## Await me (maybe)
The first no-async async technique is the "Await me maybe" pattern, a term first coined by [Simon Willison](https://simonwillison.net/2020/Sep/2/await-me-maybe/). This is particularly applicable to callbacks (or in Textual terms, message handlers).
The `await_me_maybe` function below can run a callback that is either a plain old function *or* a coroutine (`async def`). It does this by awaiting the result of the callback if it is awaitable, or simply returning the result if it is not.
```python
import asyncio
import inspect
def plain_old_function():
return "Plain old function"
async def async_function():
return "Async function"
async def await_me_maybe(callback):
result = callback()
if inspect.isawaitable(result):
return await result
return result
async def run_framework():
print(
await await_me_maybe(plain_old_function)
)
print(
await await_me_maybe(async_function)
)
if __name__ == "__main__":
asyncio.run(run_framework())
```
## Optionally awaitable
The "await me maybe" pattern is great when an async framework calls the app's code. The app developer can choose to write async code or not. Things get a little more complicated when the app wants to call the framework's API. If the API has *asynced all the things*, then it would force the app to do the same.
Textual's API consists of regular methods for the most part, but there are a few methods which are optionally awaitable. These are *not* coroutines (which must be awaited to do anything).
In practice, this means that those API calls initiate something which will complete a short time later. If you discard the return value then it won't prevent it from working. You only need to `await` if you want to know when it has finished.
The `mount` method is one such method. Calling it will add a widget to the screen:
```python
def on_key(self):
# Add MyWidget to the screen
self.mount(MyWidget("Hello, World!"))
```
In this example we don't care that the widget hasn't been mounted immediately, only that it will be soon.
!!! note
Textual awaits the result of mount after the message handler, so even if you don't *explicitly* await it, it will have been completed by the time the next message handler runs.
We might care if we want to mount a widget then make some changes to it. By making the handler `async` and awaiting the result of mount, we can be sure that the widget has been initialized before we update it:
```python
async def on_key(self):
# Add MyWidget to the screen
await self.mount(MyWidget("Hello, World!"))
# add a border
self.query_one(MyWidget).styles.border = ("heavy", "red")
```
Incidentally, I found there were very few examples of writing awaitable objects in Python. So here is the code for `AwaitMount` which is returned by the `mount` method:
```python
class AwaitMount:
"""An awaitable returned by mount() and mount_all()."""
def __init__(self, parent: Widget, widgets: Sequence[Widget]) -> None:
self._parent = parent
self._widgets = widgets
async def __call__(self) -> None:
"""Allows awaiting via a call operation."""
await self
def __await__(self) -> Generator[None, None, None]:
async def await_mount() -> None:
if self._widgets:
aws = [
create_task(widget._mounted_event.wait(), name="await mount")
for widget in self._widgets
]
if aws:
await wait(aws)
self._parent.refresh(layout=True)
return await_mount().__await__()
```
## Summing up
Textual did initially "async all the things", which you might see if you find some old Textual code. Now async is optional.
This is not because I dislike async. I'm a fan! But it does place a small burden on the developer (more to type and think about). With the current API you generally don't need to write coroutines, or remember to await things. But async is there if you need it.
We're finding that Textual is increasingly becoming a UI to things which are naturally concurrent, so async was a good move. Concurrency can be a tricky subject, so we're planning some API magic to take the pain out of running tasks, threads, and processes. Stay tuned!
Join us on our [Discord server](https://discord.gg/Enf6Z3qhVr) if you want to talk about these things with the Textualize developers.

View file

@ -0,0 +1,58 @@
---
draft: false
date: 2023-07-29
categories:
- DevLog
authors:
- willmcgugan
title: "Pull Requests are cake or puppies"
---
# Pull Requests are cake or puppies
Broadly speaking, there are two types of contributions you can make to an Open Source project.
<!-- more -->
The first type is typically a bug fix, but could also be a documentation update, linting fix, or other change which doesn't impact core functionality.
Such a contribution is like *cake*.
It's a simple, delicious, gift to the project.
The second type of contribution often comes in the form of a new feature.
This contribution likely represents a greater investment of time and effort than a bug fix.
It is still a gift to the project, but this contribution is *not* cake.
A feature PR has far more in common with a puppy.
The maintainer(s) may really like the feature but hesitate to merge all the same.
They may even reject the contribution entirely.
This is because a feature PR requires an ongoing burden to maintain.
In the same way that a puppy needs food and walkies, a new feature will require updates and fixes long after the original contribution.
Even if it is an amazing feature, the maintainer may not want to commit to that ongoing work.
![Puppy cake](../images/puppy.jpg)
The chances of a feature being merged can depend on the maturity of the project.
At the beginning of a project, a maintainer may be delighted with a new feature contribution.
After all, having others join you to build something is the joy of Open Source.
And yet when a project gets more mature there may be a growing resistance to adding new features, and a greater risk that a feature PR is rejected or sits unappreciated in the PR queue.
So how should a contributor avoid this?
If there is any doubt, it's best to propose the feature to the maintainers before undertaking the work.
In all likelihood they will be happy for your contribution, just be prepared for them to say "thanks but no thanks".
Don't take it as a rejection of your gift: it's just that the maintainer can't commit to taking on a puppy.
There are other ways to contribute code to a project that don't require the code to be merged in to the core.
You could publish your change as a third party library.
Take it from me: maintainers love it when their project spawns an ecosystem.
You could also blog about how you solved your problem without an update to the core project.
Having a resource that can be googled for, or a maintainer can direct people to, can be a huge help.
What prompted me to think about this is that my two main projects, [Rich](https://github.com/Textualize/rich) and [Textual](https://github.com/Textualize/textual), are at quite different stages in their lifetime. Rich is relatively mature, and I'm unlikely to accept a puppy. If you can achieve what you need without adding to the core library, I am *probably* going to decline a new feature. Textual is younger and still accepting puppies &mdash; in addition to stick insects, gerbils, capybaras and giraffes.
!!! tip
If you are maintainer, and you do have to close a feature PR, feel free to link to this post.
---
Join us on the [Discord Server](https://discord.gg/Enf6Z3qhVr) if you want to discuss puppies and other creatures.

View file

@ -38,7 +38,7 @@ Additionally there are new [update_cell][textual.widgets.DataTable.update_cell]
## Tree control
The [Tree](../../api/tree.md) widget has grown a few methods to programmatically expand, collapse and toggle tree nodes.
The [Tree](../../widgets/tree.md) widget has grown a few methods to programmatically expand, collapse and toggle tree nodes.
## Breaking changes

View file

@ -0,0 +1,66 @@
---
draft: false
date: 2023-03-22
categories:
- Release
title: "Textual 0.16.0 adds TabbedContent and border titles"
authors:
- willmcgugan
---
# Textual 0.16.0 adds TabbedContent and border titles
Textual 0.16.0 lands 9 days after the previous release. We have some new features to show you.
<!-- more -->
There are two highlights in this release. In no particular order, the first is [TabbedContent](../../widgets/tabbed_content.md) which uses a row of *tabs* to navigate content. You will have likely encountered this UI in the desktop and web. I think in Windows they are known as "Tabbed Dialogs".
This widget combines existing [Tabs](../../widgets/tabs.md) and [ContentSwitcher](../../api/content_switcher.md) widgets and adds an expressive interface for composing. Here's a trivial example to use content tabs to navigate a set of three markdown documents:
```python
def compose(self) -> ComposeResult:
with TabbedContent("Leto", "Jessica", "Paul"):
yield Markdown(LETO)
yield Markdown(JESSICA)
yield Markdown(PAUL)
```
Here's an example of the UI you can create with this widget (note the nesting)!
```{.textual path="docs/examples/widgets/tabbed_content.py" press="j"}
```
## Border titles
The second highlight is a frequently requested feature (FRF?). Widgets now have the two new string properties, `border_title` and `border_subtitle`, which will be displayed within the widget's border.
You can set the alignment of these titles via [`border-title-align`](../../styles/border_title_align.md) and [`border-subtitle-align`](../../styles/border_subtitle_align.md). Titles may contain [Console Markup](https://rich.readthedocs.io/en/latest/markup.html), so you can add additional color and style to the labels.
Here's an example of a widget with a title:
<div>
--8<-- "docs/blog/images/border-title.svg"
</div>
BTW the above is a command you can run to see the various border styles you can apply to widgets.
```
textual borders
```
## Container changes
!!! warning "Breaking change"
If you have an app that uses any container classes, you should read this section.
We've made a change to containers in this release. Previously all containers had *auto* scrollbars, which means that any container would scroll if its children didn't fit. With nested layouts, it could be tricky to understand exactly which containers were scrolling. In 0.16.0 we split containers in to scrolling and non-scrolling versions. So `Horizontal` will now *not* scroll by default, but `HorizontalScroll` will have automatic scrollbars.
## What else?
As always, see the [release notes](https://github.com/Textualize/textual/releases/tag/v0.16.0) for the full details on this update.
If you want to talk about this update or anything else Textual related, join us on our [Discord server](https://discord.gg/Enf6Z3qhVr).

Some files were not shown because too many files have changed in this diff Show more