summaryrefslogtreecommitdiffstats
path: root/cli/openbb_cli/config/style.py
diff options
context:
space:
mode:
Diffstat (limited to 'cli/openbb_cli/config/style.py')
-rw-r--r--cli/openbb_cli/config/style.py108
1 files changed, 108 insertions, 0 deletions
diff --git a/cli/openbb_cli/config/style.py b/cli/openbb_cli/config/style.py
new file mode 100644
index 00000000000..439d2a410d4
--- /dev/null
+++ b/cli/openbb_cli/config/style.py
@@ -0,0 +1,108 @@
+"""Chart and style helpers for Plotly."""
+
+# pylint: disable=C0302,R0902,W3301
+import json
+from pathlib import Path
+from typing import Any, Dict, List, Optional
+
+from rich.console import Console
+
+from openbb_cli.config.constants import STYLES_DIRECTORY
+
+console = Console()
+
+
+class Style:
+ """The class that helps with handling of style configurations.
+
+ It serves styles for 2 libraries. For `Plotly` this class serves absolute paths
+ to the .pltstyle files. For `Plotly` and `Rich` this class serves custom
+ styles as python dictionaries.
+ """
+
+ STYLES_REPO = STYLES_DIRECTORY
+
+ console_styles_available: Dict[str, Path] = {}
+ console_style: Dict[str, Any] = {}
+
+ line_color: str = ""
+ up_color: str = ""
+ down_color: str = ""
+ up_colorway: List[str] = []
+ down_colorway: List[str] = []
+ up_color_transparent: str = ""
+ down_color_transparent: str = ""
+
+ line_width: float = 1.5
+
+ def __init__(
+ self,
+ style: Optional[str] = "",
+ directory: Optional[Path] = None,
+ ):
+ """Initialize the class."""
+ self._load(directory)
+ self.apply(style, directory)
+
+ def apply(
+ self, style: Optional[str] = None, directory: Optional[Path] = None
+ ) -> None:
+ """Apply the style to the console."""
+ if style:
+ if style in self.console_styles_available:
+ json_path: Optional[Path] = self.console_styles_available[style]
+ else:
+ self._load(directory)
+ if style in self.console_styles_available:
+ json_path = self.console_styles_available[style]
+ else:
+ console.print(f"\nInvalid console style '{style}', using default.")
+ json_path = self.console_styles_available.get("dark", None)
+
+ if json_path:
+ self.console_style = self._from_json(json_path)
+ else:
+ console.print("Error loading default.")
+
+ def _from_directory(self, folder: Optional[Path]) -> None:
+ """Load custom styles from folder.
+
+ Parses the styles/default and styles/user folders and loads style files.
+ To be recognized files need to follow a naming convention:
+ *.pltstyle - plotly stylesheets
+ *.richstyle.json - rich stylesheets
+
+ Parameters
+ ----------
+ folder : str
+ Path to the folder containing the stylesheets
+ """
+ if not folder or not folder.exists():
+ return
+
+ for attr, ext in zip(
+ ["console_styles_available"],
+ [".richstyle.json"],
+ ):
+ for file in folder.rglob(f"*{ext}"):
+ getattr(self, attr)[file.name.replace(ext, "")] = file
+
+ def _load(self, directory: Optional[Path] = None) -> None:
+ """Load custom styles from default and user folders."""
+ self._from_directory(self.STYLES_REPO)
+ self._from_directory(directory)
+
+ def _from_json(self, file: Path) -> Dict[str, Any]:
+ """Load style from json file."""
+ with open(file) as f:
+ json_style: dict = json.load(f)
+ for key, value in json_style.items():
+ json_style[key] = value.replace(
+ " ", ""
+ ) # remove whitespaces so Rich can parse it
+ return json_style
+
+ @property
+ def available_styles(self) -> List[str]:
+ """Return available styles."""
+ return list(self.console_styles_available.keys())