Repository: Textualize/textual
Pull request: Raise clearer exception when `none` is in a space-separated list of text styles.
**Please review the following checklist.**

- [x] Docstrings on all new or modified functions / classes 
- ~[ ] Updated documentation~
- [x] Updated CHANGELOG.md (where appropriate)

**Note**: This PR should only be merged if we agree that the behaviour of [`rich.Style.parse`](https://github.com/Textualize/rich/blob/0c1aedac9c004d45d111c5258fe0f36ccbd88c91/rich/style.py#L498) is correct in that it fails when trying to parse a combination of styles with `"none"` in there.

So, we short-circuit the parsing when `"none"` shows up mixed with other styles.

If rich is "wrong" and it should treat a sequence of styles that contain `"none"` as the style `"none"`, then I'll PR a fix on rich instead.

This PR will close #1420 

Problem statement:
Improve error message when value `none` is in a list of text styles
When you provide an illegal value for the CSS rule `link-style`, you get a helpful message displaying all legal values, saying that `text-style` expects a space-separated list of those.

If you set `text-style: bold italic reverse` it works fine.

If you set `text-style: none bold italic reverse` you are being silly, but there is no real reason for this to fail (I think). Yet, the error we get is 

```py
StyleSyntaxError: unable to parse 'none' as color; 'none' is not a valid color
```

To repro:

```py
from textual.app import App

class MyApp(App):
    DEFAULT_CSS = "* { text-style: bold italic none }"
```

Hints from issue discussion:
We found the following entry in the [FAQ](https://github.com/textualize/textual/blob/main/FAQ.md) which you may find helpful:


- [Does Textual support images?](https://github.com/textualize/textual/blob/main/FAQ.md#does-textual-support-images)

Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.

This is an automated reply, generated by [FAQtory](https://github.com/willmcgugan/faqtory)
This is because the parsing is handle by Rich with does expect a color. But you're right, we can do better. Text-style doesn't take a color so we shouldn't complain about it.

I think the solution is to validate that this attribute contains only the supported text styles.

Commit message: Short-circuit text style parsing when unnecessary.

Patch to review:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af9c300121..9d61abc6a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 - The styles `scrollbar-background-active` and `scrollbar-color-hover` are no longer ignored https://github.com/Textualize/textual/pull/1480
 - The widget `Placeholder` can now have its width set to `auto` https://github.com/Textualize/textual/pull/1508
+- The style `text-style` option `none` can also be mixed with other options https://github.com/Textualize/textual/issues/1420
 
 ## [0.9.1] - 2022-12-30
 
diff --git a/src/textual/css/_style_properties.py b/src/textual/css/_style_properties.py
index 266b1a5a17..edb3d68b30 100644
--- a/src/textual/css/_style_properties.py
+++ b/src/textual/css/_style_properties.py
@@ -891,6 +891,7 @@ def __set__(self, obj: StylesBase, style_flags: Style | str | None):
         Raises:
             StyleValueError: If the value is an invalid style flag
         """
+        print(repr(style_flags))
         _rich_traceback_omit = True
         if style_flags is None:
             if obj.clear_rule(self.name):
@@ -909,7 +910,8 @@ def __set__(self, obj: StylesBase, style_flags: Style | str | None):
                             self.name, word, context="inline"
                         ),
                     )
-            style = Style.parse(style_flags)
+            # rich doesn't like "none" mixed with other styles, so short-circuit here.
+            style = Style() if "none" in words else Style.parse(style_flags)
             if obj.set_rule(self.name, style):
                 obj.refresh()
 
diff --git a/tests/css/test_text_style.py b/tests/css/test_text_style.py
new file mode 100644
index 0000000000..ea4c7f1fac
--- /dev/null
+++ b/tests/css/test_text_style.py
@@ -0,0 +1,20 @@
+from rich.style import Style
+
+from textual.css.styles import Styles
+
+
+def test_text_style_none():
+    styles = Styles()
+    styles.text_style = "none"
+    assert styles.text_style == Style()
+
+
+def test_text_style_none_with_others():
+    """Style "none" mixed with others should result in empty style."""
+    styles = Styles()
+    styles.text_style = "bold none underline italic"
+
+    none_styles = Styles()
+    styles.text_style = "none"
+
+    assert styles.text_style == none_styles.text_style


Code review comments:
diff_hunk: @@ -891,6 +891,7 @@ def __set__(self, obj: StylesBase, style_flags: Style | str | None):
         Raises:
             StyleValueError: If the value is an invalid style flag
         """
+        print(repr(style_flags))
path: src/textual/css/_style_properties.py
text: @user1:
stray debug print?

@author:
Yes 🙃

diff_hunk: @@ -909,7 +910,8 @@ def __set__(self, obj: StylesBase, style_flags: Style | str | None):
                             self.name, word, context="inline"
                         ),
                     )
-            style = Style.parse(style_flags)
+            # rich doesn't like "none" mixed with other styles, so short-circuit here.
+            style = Style() if "none" in words else Style.parse(style_flags)
path: src/textual/css/_style_properties.py
text: @user1:
If I enter `none red` won't that result in an empty Style? Indeed `none` plus any combination would result in an empty style.

I think if `none` is used, then its only valid by itself. It should be an error if there are any other words.

@author:
`none red` raises an error in rich because the `rich.style.Style.parse` method starts by checking if `none` is alone. Because it isn't, parsing will fail later on because `none` isn't a recognised color.

So, we are mimicking the rich behavior and saying that `none` can only show up by itself?

@user1:
Yes. But with a better error.

A single word in Rich may be a theme color, which is why that happens.

Textual doesn't support Rich's themes, so the styles are a subset of what Rich does. `none` by itself has a special meaning in Textual.

@author:
Addressed 👍