IncludeCPP 4.5.2__py3-none-any.whl → 4.9.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- includecpp/CHANGELOG.md +241 -0
- includecpp/__init__.py +89 -3
- includecpp/__init__.pyi +2 -1
- includecpp/cli/commands.py +1747 -266
- includecpp/cli/config_parser.py +1 -1
- includecpp/core/build_manager.py +64 -13
- includecpp/core/cpp_api_extensions.pyi +43 -270
- includecpp/core/cssl/CSSL_DOCUMENTATION.md +1799 -1445
- includecpp/core/cssl/cpp/build/api.pyd +0 -0
- includecpp/core/cssl/cpp/build/api.pyi +274 -0
- includecpp/core/cssl/cpp/build/cssl_core.pyi +0 -99
- includecpp/core/cssl/cpp/cssl_core.cp +2 -23
- includecpp/core/cssl/cssl_builtins.py +2116 -171
- includecpp/core/cssl/cssl_builtins.pyi +1324 -104
- includecpp/core/cssl/cssl_compiler.py +4 -1
- includecpp/core/cssl/cssl_modules.py +605 -6
- includecpp/core/cssl/cssl_optimizer.py +12 -1
- includecpp/core/cssl/cssl_parser.py +1048 -52
- includecpp/core/cssl/cssl_runtime.py +2041 -131
- includecpp/core/cssl/cssl_syntax.py +405 -277
- includecpp/core/cssl/cssl_types.py +5891 -1655
- includecpp/core/cssl_bridge.py +429 -3
- includecpp/core/error_catalog.py +54 -10
- includecpp/core/homeserver.py +1037 -0
- includecpp/generator/parser.cpp +203 -39
- includecpp/generator/parser.h +15 -1
- includecpp/templates/cpp.proj.template +1 -1
- includecpp/vscode/cssl/snippets/cssl.snippets.json +163 -0
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +87 -12
- {includecpp-4.5.2.dist-info → includecpp-4.9.3.dist-info}/METADATA +81 -10
- {includecpp-4.5.2.dist-info → includecpp-4.9.3.dist-info}/RECORD +35 -33
- {includecpp-4.5.2.dist-info → includecpp-4.9.3.dist-info}/WHEEL +1 -1
- {includecpp-4.5.2.dist-info → includecpp-4.9.3.dist-info}/entry_points.txt +0 -0
- {includecpp-4.5.2.dist-info → includecpp-4.9.3.dist-info}/licenses/LICENSE +0 -0
- {includecpp-4.5.2.dist-info → includecpp-4.9.3.dist-info}/top_level.txt +0 -0
|
@@ -366,7 +366,10 @@ def compile_cssl_core(force: bool = False) -> Optional[Path]:
|
|
|
366
366
|
|
|
367
367
|
if result.returncode == 0:
|
|
368
368
|
# Find built module and copy to bundled folder
|
|
369
|
-
|
|
369
|
+
if sys.platform == 'win32':
|
|
370
|
+
appdata = Path(os.environ.get('APPDATA', Path.home() / 'AppData' / 'Roaming'))
|
|
371
|
+
else:
|
|
372
|
+
appdata = Path.home() / '.local' / 'share'
|
|
370
373
|
icpp_build = appdata / 'cssl_core-g-build-proj' / 'bindings'
|
|
371
374
|
|
|
372
375
|
# Copy api.pyd to bundled folder
|
|
@@ -1551,11 +1551,8 @@ class ConsoleModule(CSSLModuleBase):
|
|
|
1551
1551
|
self._methods['beep'] = self.beep
|
|
1552
1552
|
|
|
1553
1553
|
def clear(self):
|
|
1554
|
-
"""Clear the console screen."""
|
|
1555
|
-
|
|
1556
|
-
os.system('cls')
|
|
1557
|
-
else:
|
|
1558
|
-
print('\033[2J\033[H', end='')
|
|
1554
|
+
"""Clear the console screen using ANSI escape codes (works on all modern terminals)."""
|
|
1555
|
+
print('\033[2J\033[H', end='', flush=True)
|
|
1559
1556
|
|
|
1560
1557
|
def print_styled(self, text: str, color: str = None) -> None:
|
|
1561
1558
|
"""Print text with optional color."""
|
|
@@ -1708,6 +1705,496 @@ class ConsoleModule(CSSLModuleBase):
|
|
|
1708
1705
|
print('\a', end='')
|
|
1709
1706
|
|
|
1710
1707
|
|
|
1708
|
+
# =============================================================================
|
|
1709
|
+
# @fmt Module - Text formatting and colors (ANSI)
|
|
1710
|
+
# =============================================================================
|
|
1711
|
+
|
|
1712
|
+
class FmtModule(CSSLModuleBase):
|
|
1713
|
+
"""
|
|
1714
|
+
@fmt - Text formatting with ANSI colors and utilities
|
|
1715
|
+
|
|
1716
|
+
Usage: fmt::green("Success!"), fmt::bold("Important")
|
|
1717
|
+
|
|
1718
|
+
Colors (basic):
|
|
1719
|
+
red, green, blue, yellow, cyan, magenta, white, black
|
|
1720
|
+
|
|
1721
|
+
Colors (extended):
|
|
1722
|
+
pink, purple, orange, gold, lime, teal, navy, olive,
|
|
1723
|
+
maroon, coral, salmon, turquoise, silver, brown, gray
|
|
1724
|
+
|
|
1725
|
+
Light/Dark variants:
|
|
1726
|
+
light_red, dark_red, light_green, dark_green, etc.
|
|
1727
|
+
|
|
1728
|
+
Styles:
|
|
1729
|
+
bold, dim, italic, underline, blink, reverse
|
|
1730
|
+
|
|
1731
|
+
Advanced:
|
|
1732
|
+
color(text, fg, bg) - Custom foreground/background
|
|
1733
|
+
rgb(text, r, g, b) - RGB color (24-bit)
|
|
1734
|
+
hex(text, "#rrggbb") - Hex color
|
|
1735
|
+
reset() - Reset all formatting
|
|
1736
|
+
|
|
1737
|
+
Utilities:
|
|
1738
|
+
clear() - Clear screen
|
|
1739
|
+
log(msg) - Log with timestamp [INFO]
|
|
1740
|
+
error(msg) - Log error in red [ERROR]
|
|
1741
|
+
warning(msg) - Log warning in yellow [WARNING]
|
|
1742
|
+
success(msg) - Log success in green [SUCCESS]
|
|
1743
|
+
debug(msg) - Log debug in gray [DEBUG]
|
|
1744
|
+
hidden_input(prompt) - Hidden input (for passwords)
|
|
1745
|
+
cursor_up(n) - Move cursor up n lines
|
|
1746
|
+
cursor_down(n) - Move cursor down n lines
|
|
1747
|
+
cursor_hide() - Hide cursor
|
|
1748
|
+
cursor_show() - Show cursor
|
|
1749
|
+
"""
|
|
1750
|
+
|
|
1751
|
+
def __init__(self, runtime=None):
|
|
1752
|
+
super().__init__(runtime)
|
|
1753
|
+
|
|
1754
|
+
def _register_methods(self):
|
|
1755
|
+
# Basic colors
|
|
1756
|
+
self._methods['red'] = self.red
|
|
1757
|
+
self._methods['green'] = self.green
|
|
1758
|
+
self._methods['blue'] = self.blue
|
|
1759
|
+
self._methods['yellow'] = self.yellow
|
|
1760
|
+
self._methods['cyan'] = self.cyan
|
|
1761
|
+
self._methods['magenta'] = self.magenta
|
|
1762
|
+
self._methods['white'] = self.white
|
|
1763
|
+
self._methods['black'] = self.black
|
|
1764
|
+
# Bright colors
|
|
1765
|
+
self._methods['bright_red'] = self.bright_red
|
|
1766
|
+
self._methods['bright_green'] = self.bright_green
|
|
1767
|
+
self._methods['bright_blue'] = self.bright_blue
|
|
1768
|
+
self._methods['bright_yellow'] = self.bright_yellow
|
|
1769
|
+
self._methods['bright_cyan'] = self.bright_cyan
|
|
1770
|
+
self._methods['bright_magenta'] = self.bright_magenta
|
|
1771
|
+
self._methods['bright_white'] = self.bright_white
|
|
1772
|
+
# Extended colors (24-bit RGB)
|
|
1773
|
+
self._methods['pink'] = self.pink
|
|
1774
|
+
self._methods['purple'] = self.purple
|
|
1775
|
+
self._methods['orange'] = self.orange
|
|
1776
|
+
self._methods['gold'] = self.gold
|
|
1777
|
+
self._methods['lime'] = self.lime
|
|
1778
|
+
self._methods['teal'] = self.teal
|
|
1779
|
+
self._methods['navy'] = self.navy
|
|
1780
|
+
self._methods['olive'] = self.olive
|
|
1781
|
+
self._methods['maroon'] = self.maroon
|
|
1782
|
+
self._methods['coral'] = self.coral
|
|
1783
|
+
self._methods['salmon'] = self.salmon
|
|
1784
|
+
self._methods['turquoise'] = self.turquoise
|
|
1785
|
+
self._methods['silver'] = self.silver
|
|
1786
|
+
self._methods['brown'] = self.brown
|
|
1787
|
+
self._methods['gray'] = self.gray
|
|
1788
|
+
self._methods['grey'] = self.gray # Alias
|
|
1789
|
+
# Light variants
|
|
1790
|
+
self._methods['light_red'] = self.light_red
|
|
1791
|
+
self._methods['light_green'] = self.light_green
|
|
1792
|
+
self._methods['light_blue'] = self.light_blue
|
|
1793
|
+
self._methods['light_yellow'] = self.light_yellow
|
|
1794
|
+
self._methods['light_cyan'] = self.light_cyan
|
|
1795
|
+
self._methods['light_magenta'] = self.light_magenta
|
|
1796
|
+
self._methods['light_pink'] = self.light_pink
|
|
1797
|
+
self._methods['light_purple'] = self.light_purple
|
|
1798
|
+
self._methods['light_gray'] = self.light_gray
|
|
1799
|
+
self._methods['light_grey'] = self.light_gray # Alias
|
|
1800
|
+
# Dark variants
|
|
1801
|
+
self._methods['dark_red'] = self.dark_red
|
|
1802
|
+
self._methods['dark_green'] = self.dark_green
|
|
1803
|
+
self._methods['dark_blue'] = self.dark_blue
|
|
1804
|
+
self._methods['dark_yellow'] = self.dark_yellow
|
|
1805
|
+
self._methods['dark_cyan'] = self.dark_cyan
|
|
1806
|
+
self._methods['dark_magenta'] = self.dark_magenta
|
|
1807
|
+
self._methods['dark_gray'] = self.dark_gray
|
|
1808
|
+
self._methods['dark_grey'] = self.dark_gray # Alias
|
|
1809
|
+
# Styles
|
|
1810
|
+
self._methods['bold'] = self.bold
|
|
1811
|
+
self._methods['dim'] = self.dim
|
|
1812
|
+
self._methods['italic'] = self.italic
|
|
1813
|
+
self._methods['underline'] = self.underline
|
|
1814
|
+
self._methods['blink'] = self.blink
|
|
1815
|
+
self._methods['reverse'] = self.reverse
|
|
1816
|
+
# Advanced
|
|
1817
|
+
self._methods['color'] = self.color
|
|
1818
|
+
self._methods['rgb'] = self.rgb
|
|
1819
|
+
self._methods['hex'] = self.hex_color
|
|
1820
|
+
# v4.8.8: Code-only variants (return just ANSI code, no text)
|
|
1821
|
+
self._methods['rgb_code'] = self.rgb_code
|
|
1822
|
+
self._methods['hex_code'] = self.hex_code_only
|
|
1823
|
+
self._methods['reset'] = self.reset
|
|
1824
|
+
self._methods['strip'] = self.strip_ansi
|
|
1825
|
+
# Utilities
|
|
1826
|
+
self._methods['clear'] = self.clear
|
|
1827
|
+
self._methods['log'] = self.log
|
|
1828
|
+
self._methods['error'] = self.error
|
|
1829
|
+
self._methods['warning'] = self.warning
|
|
1830
|
+
self._methods['warn'] = self.warning # Alias
|
|
1831
|
+
self._methods['success'] = self.success
|
|
1832
|
+
self._methods['debug'] = self.debug
|
|
1833
|
+
self._methods['info'] = self.info
|
|
1834
|
+
self._methods['hidden_input'] = self.hidden_input
|
|
1835
|
+
self._methods['password'] = self.hidden_input # Alias
|
|
1836
|
+
self._methods['cursor_up'] = self.cursor_up
|
|
1837
|
+
self._methods['cursor_down'] = self.cursor_down
|
|
1838
|
+
self._methods['cursor_hide'] = self.cursor_hide
|
|
1839
|
+
self._methods['cursor_show'] = self.cursor_show
|
|
1840
|
+
self._methods['cursor_save'] = self.cursor_save
|
|
1841
|
+
self._methods['cursor_restore'] = self.cursor_restore
|
|
1842
|
+
self._methods['erase_line'] = self.erase_line
|
|
1843
|
+
self._methods['move_to'] = self.move_to
|
|
1844
|
+
self._methods['progress'] = self.progress
|
|
1845
|
+
|
|
1846
|
+
def _to_str(self, value) -> str:
|
|
1847
|
+
"""Convert value to string."""
|
|
1848
|
+
return str(value) if value is not None else "null"
|
|
1849
|
+
|
|
1850
|
+
# Basic colors
|
|
1851
|
+
def red(self, text) -> str:
|
|
1852
|
+
return f'\033[31m{self._to_str(text)}\033[0m'
|
|
1853
|
+
|
|
1854
|
+
def green(self, text) -> str:
|
|
1855
|
+
return f'\033[32m{self._to_str(text)}\033[0m'
|
|
1856
|
+
|
|
1857
|
+
def blue(self, text) -> str:
|
|
1858
|
+
return f'\033[34m{self._to_str(text)}\033[0m'
|
|
1859
|
+
|
|
1860
|
+
def yellow(self, text) -> str:
|
|
1861
|
+
return f'\033[33m{self._to_str(text)}\033[0m'
|
|
1862
|
+
|
|
1863
|
+
def cyan(self, text) -> str:
|
|
1864
|
+
return f'\033[36m{self._to_str(text)}\033[0m'
|
|
1865
|
+
|
|
1866
|
+
def magenta(self, text) -> str:
|
|
1867
|
+
return f'\033[35m{self._to_str(text)}\033[0m'
|
|
1868
|
+
|
|
1869
|
+
def white(self, text) -> str:
|
|
1870
|
+
return f'\033[37m{self._to_str(text)}\033[0m'
|
|
1871
|
+
|
|
1872
|
+
def black(self, text) -> str:
|
|
1873
|
+
return f'\033[30m{self._to_str(text)}\033[0m'
|
|
1874
|
+
|
|
1875
|
+
# Bright colors
|
|
1876
|
+
def bright_red(self, text) -> str:
|
|
1877
|
+
return f'\033[91m{self._to_str(text)}\033[0m'
|
|
1878
|
+
|
|
1879
|
+
def bright_green(self, text) -> str:
|
|
1880
|
+
return f'\033[92m{self._to_str(text)}\033[0m'
|
|
1881
|
+
|
|
1882
|
+
def bright_blue(self, text) -> str:
|
|
1883
|
+
return f'\033[94m{self._to_str(text)}\033[0m'
|
|
1884
|
+
|
|
1885
|
+
def bright_yellow(self, text) -> str:
|
|
1886
|
+
return f'\033[93m{self._to_str(text)}\033[0m'
|
|
1887
|
+
|
|
1888
|
+
def bright_cyan(self, text) -> str:
|
|
1889
|
+
return f'\033[96m{self._to_str(text)}\033[0m'
|
|
1890
|
+
|
|
1891
|
+
def bright_magenta(self, text) -> str:
|
|
1892
|
+
return f'\033[95m{self._to_str(text)}\033[0m'
|
|
1893
|
+
|
|
1894
|
+
def bright_white(self, text) -> str:
|
|
1895
|
+
return f'\033[97m{self._to_str(text)}\033[0m'
|
|
1896
|
+
|
|
1897
|
+
# Extended colors (24-bit RGB)
|
|
1898
|
+
def pink(self, text) -> str:
|
|
1899
|
+
return f'\033[38;2;255;105;180m{self._to_str(text)}\033[0m'
|
|
1900
|
+
|
|
1901
|
+
def purple(self, text) -> str:
|
|
1902
|
+
return f'\033[38;2;128;0;128m{self._to_str(text)}\033[0m'
|
|
1903
|
+
|
|
1904
|
+
def orange(self, text) -> str:
|
|
1905
|
+
return f'\033[38;2;255;165;0m{self._to_str(text)}\033[0m'
|
|
1906
|
+
|
|
1907
|
+
def gold(self, text) -> str:
|
|
1908
|
+
return f'\033[38;2;255;215;0m{self._to_str(text)}\033[0m'
|
|
1909
|
+
|
|
1910
|
+
def lime(self, text) -> str:
|
|
1911
|
+
return f'\033[38;2;0;255;0m{self._to_str(text)}\033[0m'
|
|
1912
|
+
|
|
1913
|
+
def teal(self, text) -> str:
|
|
1914
|
+
return f'\033[38;2;0;128;128m{self._to_str(text)}\033[0m'
|
|
1915
|
+
|
|
1916
|
+
def navy(self, text) -> str:
|
|
1917
|
+
return f'\033[38;2;0;0;128m{self._to_str(text)}\033[0m'
|
|
1918
|
+
|
|
1919
|
+
def olive(self, text) -> str:
|
|
1920
|
+
return f'\033[38;2;128;128;0m{self._to_str(text)}\033[0m'
|
|
1921
|
+
|
|
1922
|
+
def maroon(self, text) -> str:
|
|
1923
|
+
return f'\033[38;2;128;0;0m{self._to_str(text)}\033[0m'
|
|
1924
|
+
|
|
1925
|
+
def coral(self, text) -> str:
|
|
1926
|
+
return f'\033[38;2;255;127;80m{self._to_str(text)}\033[0m'
|
|
1927
|
+
|
|
1928
|
+
def salmon(self, text) -> str:
|
|
1929
|
+
return f'\033[38;2;250;128;114m{self._to_str(text)}\033[0m'
|
|
1930
|
+
|
|
1931
|
+
def turquoise(self, text) -> str:
|
|
1932
|
+
return f'\033[38;2;64;224;208m{self._to_str(text)}\033[0m'
|
|
1933
|
+
|
|
1934
|
+
def silver(self, text) -> str:
|
|
1935
|
+
return f'\033[38;2;192;192;192m{self._to_str(text)}\033[0m'
|
|
1936
|
+
|
|
1937
|
+
def brown(self, text) -> str:
|
|
1938
|
+
return f'\033[38;2;139;69;19m{self._to_str(text)}\033[0m'
|
|
1939
|
+
|
|
1940
|
+
def gray(self, text) -> str:
|
|
1941
|
+
return f'\033[38;2;128;128;128m{self._to_str(text)}\033[0m'
|
|
1942
|
+
|
|
1943
|
+
# Light color variants
|
|
1944
|
+
def light_red(self, text) -> str:
|
|
1945
|
+
return f'\033[38;2;255;102;102m{self._to_str(text)}\033[0m'
|
|
1946
|
+
|
|
1947
|
+
def light_green(self, text) -> str:
|
|
1948
|
+
return f'\033[38;2;144;238;144m{self._to_str(text)}\033[0m'
|
|
1949
|
+
|
|
1950
|
+
def light_blue(self, text) -> str:
|
|
1951
|
+
return f'\033[38;2;173;216;230m{self._to_str(text)}\033[0m'
|
|
1952
|
+
|
|
1953
|
+
def light_yellow(self, text) -> str:
|
|
1954
|
+
return f'\033[38;2;255;255;224m{self._to_str(text)}\033[0m'
|
|
1955
|
+
|
|
1956
|
+
def light_cyan(self, text) -> str:
|
|
1957
|
+
return f'\033[38;2;224;255;255m{self._to_str(text)}\033[0m'
|
|
1958
|
+
|
|
1959
|
+
def light_magenta(self, text) -> str:
|
|
1960
|
+
return f'\033[38;2;255;119;255m{self._to_str(text)}\033[0m'
|
|
1961
|
+
|
|
1962
|
+
def light_pink(self, text) -> str:
|
|
1963
|
+
return f'\033[38;2;255;182;193m{self._to_str(text)}\033[0m'
|
|
1964
|
+
|
|
1965
|
+
def light_purple(self, text) -> str:
|
|
1966
|
+
return f'\033[38;2;221;160;221m{self._to_str(text)}\033[0m'
|
|
1967
|
+
|
|
1968
|
+
def light_gray(self, text) -> str:
|
|
1969
|
+
return f'\033[38;2;211;211;211m{self._to_str(text)}\033[0m'
|
|
1970
|
+
|
|
1971
|
+
# Dark color variants
|
|
1972
|
+
def dark_red(self, text) -> str:
|
|
1973
|
+
return f'\033[38;2;139;0;0m{self._to_str(text)}\033[0m'
|
|
1974
|
+
|
|
1975
|
+
def dark_green(self, text) -> str:
|
|
1976
|
+
return f'\033[38;2;0;100;0m{self._to_str(text)}\033[0m'
|
|
1977
|
+
|
|
1978
|
+
def dark_blue(self, text) -> str:
|
|
1979
|
+
return f'\033[38;2;0;0;139m{self._to_str(text)}\033[0m'
|
|
1980
|
+
|
|
1981
|
+
def dark_yellow(self, text) -> str:
|
|
1982
|
+
return f'\033[38;2;204;153;0m{self._to_str(text)}\033[0m'
|
|
1983
|
+
|
|
1984
|
+
def dark_cyan(self, text) -> str:
|
|
1985
|
+
return f'\033[38;2;0;139;139m{self._to_str(text)}\033[0m'
|
|
1986
|
+
|
|
1987
|
+
def dark_magenta(self, text) -> str:
|
|
1988
|
+
return f'\033[38;2;139;0;139m{self._to_str(text)}\033[0m'
|
|
1989
|
+
|
|
1990
|
+
def dark_gray(self, text) -> str:
|
|
1991
|
+
return f'\033[38;2;105;105;105m{self._to_str(text)}\033[0m'
|
|
1992
|
+
|
|
1993
|
+
# Styles
|
|
1994
|
+
def bold(self, text) -> str:
|
|
1995
|
+
return f'\033[1m{self._to_str(text)}\033[0m'
|
|
1996
|
+
|
|
1997
|
+
def dim(self, text) -> str:
|
|
1998
|
+
return f'\033[2m{self._to_str(text)}\033[0m'
|
|
1999
|
+
|
|
2000
|
+
def italic(self, text) -> str:
|
|
2001
|
+
return f'\033[3m{self._to_str(text)}\033[0m'
|
|
2002
|
+
|
|
2003
|
+
def underline(self, text) -> str:
|
|
2004
|
+
return f'\033[4m{self._to_str(text)}\033[0m'
|
|
2005
|
+
|
|
2006
|
+
def blink(self, text) -> str:
|
|
2007
|
+
return f'\033[5m{self._to_str(text)}\033[0m'
|
|
2008
|
+
|
|
2009
|
+
def reverse(self, text) -> str:
|
|
2010
|
+
return f'\033[7m{self._to_str(text)}\033[0m'
|
|
2011
|
+
|
|
2012
|
+
# Advanced
|
|
2013
|
+
def color(self, text, fg: str = None, bg: str = None) -> str:
|
|
2014
|
+
"""Apply custom foreground and/or background color."""
|
|
2015
|
+
colors = {
|
|
2016
|
+
'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
|
|
2017
|
+
'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37,
|
|
2018
|
+
'bright_black': 90, 'bright_red': 91, 'bright_green': 92,
|
|
2019
|
+
'bright_yellow': 93, 'bright_blue': 94, 'bright_magenta': 95,
|
|
2020
|
+
'bright_cyan': 96, 'bright_white': 97
|
|
2021
|
+
}
|
|
2022
|
+
codes = []
|
|
2023
|
+
if fg and fg.lower() in colors:
|
|
2024
|
+
codes.append(str(colors[fg.lower()]))
|
|
2025
|
+
if bg and bg.lower() in colors:
|
|
2026
|
+
codes.append(str(colors[bg.lower()] + 10))
|
|
2027
|
+
if codes:
|
|
2028
|
+
return f'\033[{";".join(codes)}m{self._to_str(text)}\033[0m'
|
|
2029
|
+
return self._to_str(text)
|
|
2030
|
+
|
|
2031
|
+
def rgb(self, text, r: int, g: int, b: int) -> str:
|
|
2032
|
+
"""Apply 24-bit RGB color."""
|
|
2033
|
+
return f'\033[38;2;{r};{g};{b}m{self._to_str(text)}\033[0m'
|
|
2034
|
+
|
|
2035
|
+
def hex_color(self, text, hex_code: str) -> str:
|
|
2036
|
+
"""Apply hex color (#rrggbb or rrggbb)."""
|
|
2037
|
+
hex_code = hex_code.lstrip('#')
|
|
2038
|
+
if len(hex_code) == 6:
|
|
2039
|
+
r = int(hex_code[0:2], 16)
|
|
2040
|
+
g = int(hex_code[2:4], 16)
|
|
2041
|
+
b = int(hex_code[4:6], 16)
|
|
2042
|
+
return self.rgb(text, r, g, b)
|
|
2043
|
+
return self._to_str(text)
|
|
2044
|
+
|
|
2045
|
+
def rgb_code(self, r: int, g: int, b: int) -> str:
|
|
2046
|
+
"""v4.8.8: Return just the RGB ANSI code (no text, no reset).
|
|
2047
|
+
|
|
2048
|
+
Usage:
|
|
2049
|
+
OUTPUT_PREFIX = fmt::rgb_code(180, 66, 175); // Just the color code
|
|
2050
|
+
println(OUTPUT_PREFIX + "colored text" + fmt::reset());
|
|
2051
|
+
"""
|
|
2052
|
+
return f'\033[38;2;{r};{g};{b}m'
|
|
2053
|
+
|
|
2054
|
+
def hex_code_only(self, hex_code: str) -> str:
|
|
2055
|
+
"""v4.8.8: Return just the hex color ANSI code (no text, no reset).
|
|
2056
|
+
|
|
2057
|
+
Usage:
|
|
2058
|
+
OUTPUT_PREFIX = fmt::hex_code("#b442af"); // Just the color code
|
|
2059
|
+
println(OUTPUT_PREFIX + "colored text" + fmt::reset());
|
|
2060
|
+
"""
|
|
2061
|
+
hex_code = hex_code.lstrip('#')
|
|
2062
|
+
if len(hex_code) == 6:
|
|
2063
|
+
r = int(hex_code[0:2], 16)
|
|
2064
|
+
g = int(hex_code[2:4], 16)
|
|
2065
|
+
b = int(hex_code[4:6], 16)
|
|
2066
|
+
return f'\033[38;2;{r};{g};{b}m'
|
|
2067
|
+
return ''
|
|
2068
|
+
|
|
2069
|
+
def reset(self) -> str:
|
|
2070
|
+
"""Return ANSI reset code."""
|
|
2071
|
+
return '\033[0m'
|
|
2072
|
+
|
|
2073
|
+
def strip_ansi(self, text) -> str:
|
|
2074
|
+
"""Strip all ANSI codes from text."""
|
|
2075
|
+
import re
|
|
2076
|
+
return re.sub(r'\033\[[0-9;]*m', '', self._to_str(text))
|
|
2077
|
+
|
|
2078
|
+
# Utilities
|
|
2079
|
+
def clear(self) -> str:
|
|
2080
|
+
"""Clear screen and move cursor to top-left."""
|
|
2081
|
+
import sys
|
|
2082
|
+
sys.stdout.write('\033[2J\033[H')
|
|
2083
|
+
sys.stdout.flush()
|
|
2084
|
+
return ''
|
|
2085
|
+
|
|
2086
|
+
def log(self, msg, level: str = 'INFO') -> str:
|
|
2087
|
+
"""Log message with timestamp and level."""
|
|
2088
|
+
from datetime import datetime
|
|
2089
|
+
timestamp = datetime.now().strftime('%H:%M:%S')
|
|
2090
|
+
colors = {
|
|
2091
|
+
'INFO': '\033[36m', # Cyan
|
|
2092
|
+
'DEBUG': '\033[90m', # Gray
|
|
2093
|
+
'WARNING': '\033[33m', # Yellow
|
|
2094
|
+
'ERROR': '\033[31m', # Red
|
|
2095
|
+
'SUCCESS': '\033[32m', # Green
|
|
2096
|
+
}
|
|
2097
|
+
color = colors.get(level.upper(), '\033[0m')
|
|
2098
|
+
return f'\033[90m[{timestamp}]\033[0m {color}[{level.upper()}]\033[0m {self._to_str(msg)}'
|
|
2099
|
+
|
|
2100
|
+
def info(self, msg) -> str:
|
|
2101
|
+
"""Log info message."""
|
|
2102
|
+
return self.log(msg, 'INFO')
|
|
2103
|
+
|
|
2104
|
+
def error(self, msg) -> str:
|
|
2105
|
+
"""Log error message in red."""
|
|
2106
|
+
return self.log(msg, 'ERROR')
|
|
2107
|
+
|
|
2108
|
+
def warning(self, msg) -> str:
|
|
2109
|
+
"""Log warning message in yellow."""
|
|
2110
|
+
return self.log(msg, 'WARNING')
|
|
2111
|
+
|
|
2112
|
+
def success(self, msg) -> str:
|
|
2113
|
+
"""Log success message in green."""
|
|
2114
|
+
return self.log(msg, 'SUCCESS')
|
|
2115
|
+
|
|
2116
|
+
def debug(self, msg) -> str:
|
|
2117
|
+
"""Log debug message in gray."""
|
|
2118
|
+
return self.log(msg, 'DEBUG')
|
|
2119
|
+
|
|
2120
|
+
def hidden_input(self, prompt: str = '') -> str:
|
|
2121
|
+
"""Get hidden input (for passwords). Returns the input string."""
|
|
2122
|
+
import getpass
|
|
2123
|
+
import sys
|
|
2124
|
+
# Print prompt with formatting
|
|
2125
|
+
if prompt:
|
|
2126
|
+
sys.stdout.write(self._to_str(prompt))
|
|
2127
|
+
sys.stdout.flush()
|
|
2128
|
+
try:
|
|
2129
|
+
return getpass.getpass(prompt='')
|
|
2130
|
+
except Exception:
|
|
2131
|
+
return input()
|
|
2132
|
+
|
|
2133
|
+
def cursor_up(self, n: int = 1) -> str:
|
|
2134
|
+
"""Move cursor up n lines."""
|
|
2135
|
+
import sys
|
|
2136
|
+
sys.stdout.write(f'\033[{n}A')
|
|
2137
|
+
sys.stdout.flush()
|
|
2138
|
+
return ''
|
|
2139
|
+
|
|
2140
|
+
def cursor_down(self, n: int = 1) -> str:
|
|
2141
|
+
"""Move cursor down n lines."""
|
|
2142
|
+
import sys
|
|
2143
|
+
sys.stdout.write(f'\033[{n}B')
|
|
2144
|
+
sys.stdout.flush()
|
|
2145
|
+
return ''
|
|
2146
|
+
|
|
2147
|
+
def cursor_hide(self) -> str:
|
|
2148
|
+
"""Hide cursor."""
|
|
2149
|
+
import sys
|
|
2150
|
+
sys.stdout.write('\033[?25l')
|
|
2151
|
+
sys.stdout.flush()
|
|
2152
|
+
return ''
|
|
2153
|
+
|
|
2154
|
+
def cursor_show(self) -> str:
|
|
2155
|
+
"""Show cursor."""
|
|
2156
|
+
import sys
|
|
2157
|
+
sys.stdout.write('\033[?25h')
|
|
2158
|
+
sys.stdout.flush()
|
|
2159
|
+
return ''
|
|
2160
|
+
|
|
2161
|
+
def cursor_save(self) -> str:
|
|
2162
|
+
"""Save cursor position."""
|
|
2163
|
+
import sys
|
|
2164
|
+
sys.stdout.write('\033[s')
|
|
2165
|
+
sys.stdout.flush()
|
|
2166
|
+
return ''
|
|
2167
|
+
|
|
2168
|
+
def cursor_restore(self) -> str:
|
|
2169
|
+
"""Restore cursor position."""
|
|
2170
|
+
import sys
|
|
2171
|
+
sys.stdout.write('\033[u')
|
|
2172
|
+
sys.stdout.flush()
|
|
2173
|
+
return ''
|
|
2174
|
+
|
|
2175
|
+
def erase_line(self) -> str:
|
|
2176
|
+
"""Erase current line."""
|
|
2177
|
+
import sys
|
|
2178
|
+
sys.stdout.write('\033[2K\r')
|
|
2179
|
+
sys.stdout.flush()
|
|
2180
|
+
return ''
|
|
2181
|
+
|
|
2182
|
+
def move_to(self, row: int, col: int) -> str:
|
|
2183
|
+
"""Move cursor to specific position (1-indexed)."""
|
|
2184
|
+
import sys
|
|
2185
|
+
sys.stdout.write(f'\033[{row};{col}H')
|
|
2186
|
+
sys.stdout.flush()
|
|
2187
|
+
return ''
|
|
2188
|
+
|
|
2189
|
+
def progress(self, current: int, total: int, width: int = 40, prefix: str = '', suffix: str = '') -> str:
|
|
2190
|
+
"""Create a progress bar string."""
|
|
2191
|
+
percent = current / total if total > 0 else 0
|
|
2192
|
+
filled = int(width * percent)
|
|
2193
|
+
bar = '█' * filled + '░' * (width - filled)
|
|
2194
|
+
percent_str = f'{percent * 100:.1f}%'
|
|
2195
|
+
return f'{prefix}|{bar}| {percent_str} {suffix}'
|
|
2196
|
+
|
|
2197
|
+
|
|
1711
2198
|
# =============================================================================
|
|
1712
2199
|
# @Process Module - Process and subprocess management
|
|
1713
2200
|
# =============================================================================
|
|
@@ -1872,7 +2359,9 @@ class ProcessModule(CSSLModuleBase):
|
|
|
1872
2359
|
|
|
1873
2360
|
def shell_command(self, cmd: str) -> int:
|
|
1874
2361
|
"""Run command in system shell, returns exit code."""
|
|
1875
|
-
|
|
2362
|
+
import subprocess
|
|
2363
|
+
result = subprocess.run(cmd, shell=True)
|
|
2364
|
+
return result.returncode
|
|
1876
2365
|
|
|
1877
2366
|
def popen_process(self, cmd: Union[str, List[str]], cwd: str = None) -> int:
|
|
1878
2367
|
"""Open process for streaming, returns handle ID."""
|
|
@@ -2732,6 +3221,113 @@ class AppServiceBuilder:
|
|
|
2732
3221
|
return None
|
|
2733
3222
|
|
|
2734
3223
|
|
|
3224
|
+
# =============================================================================
|
|
3225
|
+
# @Async Module - Async/await operations (v4.9.3)
|
|
3226
|
+
# =============================================================================
|
|
3227
|
+
|
|
3228
|
+
class AsyncCSSLModule(CSSLModuleBase):
|
|
3229
|
+
"""
|
|
3230
|
+
@Async - Async/await operations for concurrent execution
|
|
3231
|
+
|
|
3232
|
+
v4.9.3: Full async support for CSSL.
|
|
3233
|
+
|
|
3234
|
+
Methods:
|
|
3235
|
+
run(func, *args) - Run function asynchronously, returns Future
|
|
3236
|
+
stop(future) - Cancel an async operation
|
|
3237
|
+
wait(future, timeout) - Wait for a Future to complete
|
|
3238
|
+
all(futures, timeout) - Wait for all Futures to complete
|
|
3239
|
+
race(futures, timeout) - Return first completed Future's result
|
|
3240
|
+
sleep(ms) - Async sleep for milliseconds
|
|
3241
|
+
create_generator(name) - Create a generator
|
|
3242
|
+
|
|
3243
|
+
Example:
|
|
3244
|
+
async define fetchData(url) {
|
|
3245
|
+
return http.get(url);
|
|
3246
|
+
}
|
|
3247
|
+
|
|
3248
|
+
future f = Async.run(fetchData, "http://example.com");
|
|
3249
|
+
data = await f;
|
|
3250
|
+
|
|
3251
|
+
// Or with async function call:
|
|
3252
|
+
future f = fetchData("http://example.com");
|
|
3253
|
+
data = await f;
|
|
3254
|
+
|
|
3255
|
+
// Wait for multiple:
|
|
3256
|
+
results = Async.all([f1, f2, f3]);
|
|
3257
|
+
|
|
3258
|
+
// First to complete:
|
|
3259
|
+
result = Async.race([f1, f2, f3]);
|
|
3260
|
+
"""
|
|
3261
|
+
|
|
3262
|
+
def _register_methods(self):
|
|
3263
|
+
self._methods['run'] = self.run
|
|
3264
|
+
self._methods['stop'] = self.stop
|
|
3265
|
+
self._methods['wait'] = self.wait
|
|
3266
|
+
self._methods['all'] = self.all_futures
|
|
3267
|
+
self._methods['race'] = self.race
|
|
3268
|
+
self._methods['sleep'] = self.sleep
|
|
3269
|
+
self._methods['create_generator'] = self.create_generator
|
|
3270
|
+
|
|
3271
|
+
def run(self, func, *args, **kwargs):
|
|
3272
|
+
"""Run a function asynchronously."""
|
|
3273
|
+
from .cssl_types import AsyncModule, CSSLFuture
|
|
3274
|
+
from .cssl_parser import ASTNode
|
|
3275
|
+
|
|
3276
|
+
# If func is a CSSL ASTNode function, wrap it for async execution
|
|
3277
|
+
if isinstance(func, ASTNode) and func.type == 'function':
|
|
3278
|
+
func_name = func.value.get('name', 'anonymous') if isinstance(func.value, dict) else 'anonymous'
|
|
3279
|
+
future = CSSLFuture(func_name)
|
|
3280
|
+
future._state = CSSLFuture.RUNNING
|
|
3281
|
+
|
|
3282
|
+
import threading
|
|
3283
|
+
def execute():
|
|
3284
|
+
try:
|
|
3285
|
+
if self.runtime:
|
|
3286
|
+
result = self.runtime._call_function(func, list(args), kwargs)
|
|
3287
|
+
else:
|
|
3288
|
+
result = None
|
|
3289
|
+
future.set_result(result)
|
|
3290
|
+
except Exception as e:
|
|
3291
|
+
future.set_exception(e)
|
|
3292
|
+
|
|
3293
|
+
thread = threading.Thread(target=execute, daemon=True)
|
|
3294
|
+
future._thread = thread
|
|
3295
|
+
thread.start()
|
|
3296
|
+
return future
|
|
3297
|
+
|
|
3298
|
+
return AsyncModule.run(func, *args, runtime=self.runtime, **kwargs)
|
|
3299
|
+
|
|
3300
|
+
def stop(self, future_or_name):
|
|
3301
|
+
"""Stop an async operation."""
|
|
3302
|
+
from .cssl_types import AsyncModule
|
|
3303
|
+
return AsyncModule.stop(future_or_name)
|
|
3304
|
+
|
|
3305
|
+
def wait(self, future, timeout=None):
|
|
3306
|
+
"""Wait for a future to complete."""
|
|
3307
|
+
from .cssl_types import AsyncModule
|
|
3308
|
+
return AsyncModule.wait(future, timeout)
|
|
3309
|
+
|
|
3310
|
+
def all_futures(self, futures, timeout=None):
|
|
3311
|
+
"""Wait for all futures to complete."""
|
|
3312
|
+
from .cssl_types import AsyncModule
|
|
3313
|
+
return AsyncModule.all(futures, timeout)
|
|
3314
|
+
|
|
3315
|
+
def race(self, futures, timeout=None):
|
|
3316
|
+
"""Return result of first completed future."""
|
|
3317
|
+
from .cssl_types import AsyncModule
|
|
3318
|
+
return AsyncModule.race(futures, timeout)
|
|
3319
|
+
|
|
3320
|
+
def sleep(self, ms):
|
|
3321
|
+
"""Async sleep for ms milliseconds."""
|
|
3322
|
+
from .cssl_types import AsyncModule
|
|
3323
|
+
return AsyncModule.sleep(ms)
|
|
3324
|
+
|
|
3325
|
+
def create_generator(self, name, values=None):
|
|
3326
|
+
"""Create a generator."""
|
|
3327
|
+
from .cssl_types import AsyncModule
|
|
3328
|
+
return AsyncModule.create_generator(name, values)
|
|
3329
|
+
|
|
3330
|
+
|
|
2735
3331
|
# =============================================================================
|
|
2736
3332
|
# Module Registry
|
|
2737
3333
|
# =============================================================================
|
|
@@ -2765,9 +3361,12 @@ class CSSLModuleRegistry:
|
|
|
2765
3361
|
'Queue': QueueModule(),
|
|
2766
3362
|
'Format': FormatModule(),
|
|
2767
3363
|
'Console': ConsoleModule(),
|
|
3364
|
+
'fmt': FmtModule(),
|
|
2768
3365
|
'Process': ProcessModule(),
|
|
2769
3366
|
'Config': ConfigModule(),
|
|
2770
3367
|
'Server': ServerModule(),
|
|
3368
|
+
'Async': AsyncCSSLModule(), # v4.9.3: Async module
|
|
3369
|
+
'async': AsyncCSSLModule(), # v4.9.3: Async module (lowercase alias)
|
|
2771
3370
|
}
|
|
2772
3371
|
|
|
2773
3372
|
# Register Desktop module (lazy loaded)
|