17 changed files with 898 additions and 5 deletions
@ -1,5 +1,6 @@ |
|||||||
{ |
{ |
||||||
"libs/pyTermTk": "0.41.17-a.0", |
"libs/pyTermTk": "0.41.17-a.0", |
||||||
|
"apps/ttkode": "0.2.14-a.2", |
||||||
"apps/ttkDesigner": "0.41.4-a.54", |
"apps/ttkDesigner": "0.41.4-a.54", |
||||||
"apps/dumbPaintTool": "0.41.8-a.54" |
"apps/dumbPaintTool": "0.41.8-a.54" |
||||||
} |
} |
||||||
|
|||||||
@ -0,0 +1,40 @@ |
|||||||
|
 |
||||||
|
 |
||||||
|
 |
||||||
|
 |
||||||
|
[](https://pypi.org/project/ttkode) |
||||||
|
[](https://twitter.com/hashtag/pyTermTk?src=hashtag_click&f=live) |
||||||
|
|
||||||
|
# ttkode |
||||||
|
TerminalToolKit (Studio) Code (editor) |
||||||
|
|
||||||
|
A hopefully fast and mesmerizingly advanced [text-based](https://en.wikipedia.org/wiki/Text-based_user_interface) code editor inspired by [vscode](https://code.visualstudio.com) |
||||||
|
|
||||||
|
## Features (TBD) |
||||||
|
- Search Panel |
||||||
|
- Highlight |
||||||
|
- Bookmarks |
||||||
|
- Shiny ASCII Red Peppers |
||||||
|
|
||||||
|
[](https://pypi.org/project/tlogg) |
||||||
|
|
||||||
|
[Peek 2022-10-08 22-25.webm](https://user-images.githubusercontent.com/8876552/195099208-65d4707e-0340-4077-835a-87ae6c8ae3b6.webm) |
||||||
|
|
||||||
|
# Install from [pypi](https://pypi.org/project/ttkode) |
||||||
|
```bash |
||||||
|
pip install ttkode |
||||||
|
``` |
||||||
|
# QuickRun |
||||||
|
```bash |
||||||
|
$ ttkode -h |
||||||
|
usage: ttkode [-h] [-c C] path [path ...] |
||||||
|
|
||||||
|
positional arguments: |
||||||
|
path the dir/filename/s |
||||||
|
|
||||||
|
optional arguments: |
||||||
|
-h, --help show this help message and exit |
||||||
|
-c C config folder (default: "/home/user/.config/ttkode") |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,46 @@ |
|||||||
|
[build-system] |
||||||
|
requires = ["setuptools>=45", "wheel"] |
||||||
|
build-backend = "setuptools.build_meta" |
||||||
|
|
||||||
|
[project] |
||||||
|
name = "ttkode" |
||||||
|
dynamic = ["version"] |
||||||
|
readme = {file = "README.md", content-type = "text/markdown"} |
||||||
|
authors = [ |
||||||
|
{name = "Eugenio Parodi", email = "ceccopierangiolieugenio@googlemail.com"}, |
||||||
|
] |
||||||
|
description = "Terminal ToolKit Studio Code editor" |
||||||
|
requires-python = ">=3.9" |
||||||
|
license = {text = "MIT"} |
||||||
|
classifiers = [ |
||||||
|
"Programming Language :: Python :: 3", |
||||||
|
"License :: OSI Approved :: MIT License", |
||||||
|
"Operating System :: OS Independent", |
||||||
|
"Development Status :: 3 - Alpha", |
||||||
|
"Environment :: Console", |
||||||
|
"Intended Audience :: Developers", |
||||||
|
"Intended Audience :: Information Technology", |
||||||
|
"Topic :: Terminals", |
||||||
|
"Topic :: Software Development :: User Interfaces", |
||||||
|
] |
||||||
|
dependencies = [ |
||||||
|
'pyTermTk>=0.41.17-a.0', |
||||||
|
'appdirs', |
||||||
|
'copykitten', |
||||||
|
'pygments' |
||||||
|
] |
||||||
|
|
||||||
|
[project.urls] |
||||||
|
Homepage = "https://github.com/ceccopierangiolieugenio/pyTermTk/tree/main/apps/ttkode" |
||||||
|
Repository = "https://github.com/ceccopierangiolieugenio/pyTermTk.git" |
||||||
|
Issues = "https://github.com/ceccopierangiolieugenio/pyTermTk/issues" |
||||||
|
Changelog = "https://github.com/ceccopierangiolieugenio/pyTermTk/blob/main/apps/ttkDesigner/CHANGELOG.md" |
||||||
|
|
||||||
|
[project.scripts] |
||||||
|
ttkode = "ttkode:main" |
||||||
|
|
||||||
|
[tool.setuptools] |
||||||
|
packages = ["ttkode", "ttkode.app"] |
||||||
|
|
||||||
|
[tool.setuptools.dynamic] |
||||||
|
version = {attr = "ttkode.__version__"} |
||||||
@ -0,0 +1,30 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
|
||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
__version__:str = '0.2.4-a.15' |
||||||
|
|
||||||
|
from .app import * |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
|
||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
from .app import main |
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
main() |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
|
||||||
|
#!/usr/bin/env python3 |
||||||
|
|
||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
from .cfg import * |
||||||
|
# from .glbl import * |
||||||
|
from .main import * |
||||||
|
from .kodetextdocument import KodeTextDocument |
||||||
@ -0,0 +1,59 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
|
||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
from TermTk.TTkCore.log import TTkLog |
||||||
|
from TermTk.TTkCore.color import TTkColor |
||||||
|
from TermTk import TTkAbout, TTkWindow |
||||||
|
from .cfg import TTKodeCfg |
||||||
|
|
||||||
|
class About(TTkAbout): |
||||||
|
ttkode = [ |
||||||
|
"__________________ __ ", |
||||||
|
"\_______________ / / / ┌─┐ ", |
||||||
|
" /\ /\ | |__/ /___ __| |_____ ", |
||||||
|
" | | | | | _ // _ \ / _ | ___ |", |
||||||
|
" | | | | | | \ \ |_| ( (_| | ____|", |
||||||
|
" | | | | └─┘ \_)___/ \____|_____)", |
||||||
|
" | | | | ", |
||||||
|
" └──┘ └──┘ ",] |
||||||
|
|
||||||
|
__slots__=('_image') |
||||||
|
def __init__(self, *args, **kwargs): |
||||||
|
TTkAbout.__init__(self, *args, **kwargs) |
||||||
|
self._name = kwargs.get('name' , 'About' ) |
||||||
|
self.setTitle('[PierCecco Cecco] Eugenio Parodi proudly presents...') |
||||||
|
self.resize(56,16) |
||||||
|
|
||||||
|
def paintEvent(self, canvas): |
||||||
|
c = [0xFF,0xFF,0xFF] |
||||||
|
for y, line in enumerate(About.ttkode): |
||||||
|
canvas.drawText(pos=(13,3+y),text=line, color=TTkColor.fg(f'#{c[0]:02X}{c[1]:02X}{c[2]:02X}')) |
||||||
|
c[2]-=0x18 |
||||||
|
c[0]-=0x08 |
||||||
|
canvas.drawText(pos=(26, 9),text=f" Version: {TTKodeCfg.version}", color=TTkColor.fg('#AAAAFF')) |
||||||
|
canvas.drawText(pos=(14,11),text=f"Powered By, pyTermTk") |
||||||
|
canvas.drawText(pos=( 2,13),text=f"https://github.com/ceccopierangiolieugenio/ttkode", color=TTkColor.fg('#44FFFF')) |
||||||
|
canvas.drawText(pos=( 2,14),text=f"https://github.com/ceccopierangiolieugenio/pyTermTk", color=TTkColor.fg('#44FFFF')) |
||||||
|
|
||||||
|
TTkWindow.paintEvent(self, canvas) |
||||||
@ -0,0 +1,56 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
|
||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
import os |
||||||
|
import json |
||||||
|
|
||||||
|
class TTKodeCfg: |
||||||
|
version="__VERSION__" |
||||||
|
name="__NAME__" |
||||||
|
cfgVersion = '1.0' |
||||||
|
pathCfg="." |
||||||
|
options={} |
||||||
|
maxsearches=200 |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def save(searches=True, filters=True, colors=True, options=True): |
||||||
|
os.makedirs(TTKodeCfg.pathCfg, exist_ok=True) |
||||||
|
optionsPath = os.path.join(TTKodeCfg.pathCfg,'options.json') |
||||||
|
|
||||||
|
def writeCfg(path, cfg): |
||||||
|
fullCfg = { |
||||||
|
'version':TTKodeCfg.cfgVersion, |
||||||
|
'cfg':cfg } |
||||||
|
# with open(path, 'w') as f: |
||||||
|
# json.dump(fullCfg, f, sort_keys=False, default_flow_style=False) |
||||||
|
|
||||||
|
if options: writeCfg(optionsPath, TTKodeCfg.options) |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def load(): |
||||||
|
optionsPath = os.path.join(TTKodeCfg.pathCfg,'options.json') |
||||||
|
|
||||||
|
# if os.path.exists(optionsPath): |
||||||
|
# with open(optionsPath) as f: |
||||||
|
# TTKodeCfg.options = json.load(f, Loader=json.SafeLoader)['cfg'] |
||||||
@ -0,0 +1,142 @@ |
|||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
from pygments.formatter import Formatter |
||||||
|
from pygments.token import Keyword, Name, Comment, String, Error, \ |
||||||
|
Number, Operator, Generic, Token, Whitespace |
||||||
|
|
||||||
|
from TermTk import TTkString, TTkColor, TTkLog |
||||||
|
|
||||||
|
#: Map token types to a tuple of color values for light and dark |
||||||
|
#: backgrounds. |
||||||
|
TTKODE_COLORS = { |
||||||
|
Token: TTkColor.RST, # ('', ''), |
||||||
|
|
||||||
|
Whitespace: TTkColor.fg('#888888') , # ('gray', 'brightblack'), |
||||||
|
Comment: TTkColor.fg('#888888') , # ('gray', 'brightblack'), |
||||||
|
Comment.Preproc: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'), |
||||||
|
Keyword: TTkColor.fg('#0000FF') , # ('blue', 'brightblue'), |
||||||
|
Keyword.Type: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'), |
||||||
|
Operator.Word: TTkColor.fg('#FF8800') , # ('magenta', 'brightmagenta'), |
||||||
|
Name.Builtin: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'), |
||||||
|
Name.Function: TTkColor.fg('#00FF00') , # ('green', 'brightgreen'), |
||||||
|
Name.Namespace: TTkColor.fg('#00FFFF') , # ('_cyan_', '_brightcyan_'), |
||||||
|
Name.Class: TTkColor.fg('#00FF00') , # ('_green_', '_brightgreen_'), |
||||||
|
Name.Exception: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'), |
||||||
|
Name.Decorator: TTkColor.fg('#888888') , # ('brightblack', 'gray'), |
||||||
|
Name.Variable: TTkColor.fg('#888888') , # ('red', 'brightred'), |
||||||
|
Name.Constant: TTkColor.fg('#888888') , # ('red', 'brightred'), |
||||||
|
Name.Attribute: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'), |
||||||
|
Name.Tag: TTkColor.fg('#0000FF') , # ('brightblue', 'brightblue'), |
||||||
|
String: TTkColor.fg('#FFFF00') , # ('yellow', 'yellow'), |
||||||
|
Number: TTkColor.fg('#0000FF') , # ('blue', 'brightblue'), |
||||||
|
|
||||||
|
Generic.Deleted: TTkColor.fg('#FF0000') , # ('brightred', 'brightred'), |
||||||
|
Generic.Inserted: TTkColor.fg('#00FF00') , # ('green', 'brightgreen'), |
||||||
|
Generic.Heading: TTkColor.fg('#888888') , # ('**', '**'), |
||||||
|
Generic.Subheading: TTkColor.fg('#FF8800') , # ('*magenta*', '*brightmagenta*'), |
||||||
|
Generic.Prompt: TTkColor.fg('#888888') , # ('**', '**'), |
||||||
|
Generic.Error: TTkColor.fg('#FF0000') , # ('brightred', 'brightred'), |
||||||
|
|
||||||
|
Error: TTkColor.fg('#FF0000') , # ('_brightred_', '_brightred_'), |
||||||
|
} |
||||||
|
|
||||||
|
class KodeFormatter(Formatter): |
||||||
|
class Data(): |
||||||
|
__slots__=('lines', 'block', 'error', 'multiline') |
||||||
|
def __init__(self, lines, block): |
||||||
|
self.lines = lines |
||||||
|
self.block = block |
||||||
|
self.error = None |
||||||
|
self.multiline = False |
||||||
|
|
||||||
|
__slots__ = ('_dl', '_blockNum', '_kodeStyles') |
||||||
|
def __init__(self, *args, **kwargs): |
||||||
|
super().__init__(*args, **kwargs) |
||||||
|
self._kodeStyles = {} |
||||||
|
self._blockNum = 1 |
||||||
|
for token, style in self.style: |
||||||
|
# Token = Token.Comment.PreprocFile |
||||||
|
# style = { |
||||||
|
# 'color': '6272a4', |
||||||
|
# 'bgcolor': None, |
||||||
|
# 'bold': False, 'italic': False, 'underline': False, |
||||||
|
# 'border': None, |
||||||
|
# 'roman': None, 'sans': None, 'mono': None, |
||||||
|
# 'ansicolor': None, 'bgansicolor': None} |
||||||
|
|
||||||
|
# TTkLog.debug(f"{token=} {style=}") |
||||||
|
color = TTkColor.RST |
||||||
|
if style['color']: |
||||||
|
color += TTkColor.fg(f"#{style['color']}") |
||||||
|
if style['bgcolor']: |
||||||
|
color += TTkColor.bg(f"#{style['bgcolor']}") |
||||||
|
if style['bold']: |
||||||
|
color += TTkColor.BOLD |
||||||
|
if style['italic']: |
||||||
|
color += TTkColor.ITALIC |
||||||
|
if style['underline']: |
||||||
|
color += TTkColor.UNDERLINE |
||||||
|
self._kodeStyles[token] = color |
||||||
|
|
||||||
|
super().__init__() |
||||||
|
|
||||||
|
def setDl(self,dl): |
||||||
|
self._dl = dl |
||||||
|
|
||||||
|
def format(self, tokensource, _): |
||||||
|
multiline = False |
||||||
|
multilineId = 0 |
||||||
|
for ttype, value in tokensource: |
||||||
|
if ttype == Error and self._dl.error is None: |
||||||
|
self._dl.error = len(self._dl.lines)-1 |
||||||
|
# self._dl.multiline = ttype == Comment.Multiline |
||||||
|
multiline = ttype == Comment.Multiline |
||||||
|
|
||||||
|
while ttype not in self._kodeStyles: |
||||||
|
ttype = ttype.parent |
||||||
|
# TTkLog.debug (f"{ttype=}") |
||||||
|
# TTkLog.debug (f"{value=}") |
||||||
|
color = self._kodeStyles[ttype] |
||||||
|
|
||||||
|
values = value.split('\n') |
||||||
|
|
||||||
|
self._dl.lines[-1] += TTkString(values[0],color) |
||||||
|
self._dl.lines += [TTkString(t,color) for t in values[1:]] |
||||||
|
self._dl.block[-1] = self._blockNum |
||||||
|
self._dl.block += [self._blockNum]*(len(values)-1) |
||||||
|
|
||||||
|
# self._dl.lines += [TTkString(t) for t in value.split('\n')] |
||||||
|
|
||||||
|
# multiline = len(values)>1 if self._dl.lines[-1]._text == values[-1] else self._dl.multiline |
||||||
|
# if self._dl.lines[-1]._text == '' or not multiline: |
||||||
|
# self._blockNum += 1 |
||||||
|
# multilineId = len(self._dl.lines) |
||||||
|
|
||||||
|
if multiline: |
||||||
|
multilineId += len(values) |
||||||
|
else: |
||||||
|
multilineId = 0 |
||||||
|
self._blockNum += 1 |
||||||
|
|
||||||
|
if multiline: |
||||||
|
self._dl.multiline = multilineId |
||||||
@ -0,0 +1,165 @@ |
|||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
from threading import Lock |
||||||
|
|
||||||
|
from pygments import highlight |
||||||
|
from pygments.util import ClassNotFound |
||||||
|
from pygments.lexers import guess_lexer, guess_lexer_for_filename, special |
||||||
|
from pygments.formatters import TerminalFormatter, Terminal256Formatter, TerminalTrueColorFormatter |
||||||
|
|
||||||
|
from TermTk import TTk, TTkK, TTkLog, TTkCfg, TTkTheme, TTkTerm, TTkHelper, TTkTimer |
||||||
|
from TermTk import TTkString |
||||||
|
from TermTk import TTkColor, TTkColorGradient |
||||||
|
from TermTk import pyTTkSlot, pyTTkSignal |
||||||
|
|
||||||
|
from TermTk import TTkTextDocument |
||||||
|
from .kodeformatter import KodeFormatter |
||||||
|
|
||||||
|
class KodeTextDocument(TTkTextDocument): |
||||||
|
_linesRefreshed = 30 |
||||||
|
__slots__ = ( |
||||||
|
'_filePath', '_timerRefresh', |
||||||
|
'kodeHighlightUpdate', '_kodeDocMutex', |
||||||
|
'_blocks', '_changedContent', '_refreshContent', |
||||||
|
'_lexer', '_formatter') |
||||||
|
def __init__(self, filePath:str="", **kwargs): |
||||||
|
self.kodeHighlightUpdate = pyTTkSignal() |
||||||
|
self._kodeDocMutex = Lock() |
||||||
|
self._lexer = None |
||||||
|
self._blocks = [] |
||||||
|
# self._formatter = KodeFormatter(style='dracula') |
||||||
|
self._filePath = filePath |
||||||
|
self._formatter = KodeFormatter(style='gruvbox-dark') |
||||||
|
self._timerRefresh = TTkTimer() |
||||||
|
super().__init__(**kwargs) |
||||||
|
self._changedContent = (0,0,len(self._dataLines)) |
||||||
|
self._refreshContent = (0,KodeTextDocument._linesRefreshed) |
||||||
|
self._timerRefresh.timeout.connect(self._refreshEvent) |
||||||
|
self._timerRefresh.start(0.3) |
||||||
|
self.contentsChange.connect(lambda a,b,c: TTkLog.debug(f"{a=} {b=} {c=}")) |
||||||
|
self.contentsChange.connect(self._saveChangedContent) |
||||||
|
|
||||||
|
@pyTTkSlot(int,int,int) |
||||||
|
def _saveChangedContent(self,a,b,c): |
||||||
|
if self._changedContent: |
||||||
|
self._changedContent = TTkTextDocument._mergeChangesSlices(self._changedContent,(a,b,c)) |
||||||
|
else: |
||||||
|
self._changedContent = (a,b,c) |
||||||
|
if not self._refreshContent: |
||||||
|
self._refreshContent = (self._changedContent[0], KodeTextDocument._linesRefreshed) |
||||||
|
self._timerRefresh.start(0.1) |
||||||
|
|
||||||
|
@pyTTkSlot() |
||||||
|
def _refreshEvent(self): |
||||||
|
if not self._refreshContent: return |
||||||
|
self._kodeDocMutex.acquire() |
||||||
|
|
||||||
|
ra,rb = self._refreshContent |
||||||
|
|
||||||
|
if self._changedContent: |
||||||
|
ca,cb,cc = self._changedContent |
||||||
|
self._changedContent = None |
||||||
|
self._blocks[ca:ca+cb] = [0]*cc |
||||||
|
ra = min(ra,ca) |
||||||
|
|
||||||
|
# find the beginning of the current block |
||||||
|
# TTkLog.debug(self._blocks) |
||||||
|
if ra and self._blocks: |
||||||
|
blockId = self._blocks[ra] |
||||||
|
for i,v in enumerate(reversed(self._blocks[:ra])): |
||||||
|
# TTkLog.debug(f"{i=}:{v=} {blockId=}") |
||||||
|
if v == blockId or not blockId: |
||||||
|
blockId = v |
||||||
|
ra -= 1 |
||||||
|
rb += 1 |
||||||
|
else: |
||||||
|
break |
||||||
|
|
||||||
|
# TTkLog.debug(f"{ra=} {rb=}") |
||||||
|
|
||||||
|
eof = False |
||||||
|
if (ra+rb) >= len(self._dataLines): |
||||||
|
rb = len(self._dataLines)-ra |
||||||
|
eof=True |
||||||
|
|
||||||
|
tsl = self._dataLines[ra:ra+rb] |
||||||
|
# Find the offset from the first not empty line |
||||||
|
# because pygments autostrip the heading empty lines |
||||||
|
offset = 0 |
||||||
|
for i,l in enumerate(tsl): |
||||||
|
if l != '': |
||||||
|
offset = i |
||||||
|
break |
||||||
|
|
||||||
|
rawl = [l._text for l in tsl[offset:]] |
||||||
|
rawt = '\n'.join(rawl) |
||||||
|
if not self._lexer: |
||||||
|
try: |
||||||
|
self._lexer = guess_lexer_for_filename(self._filePath, rawt) |
||||||
|
except ClassNotFound: |
||||||
|
self._lexer = special.TextLexer() |
||||||
|
|
||||||
|
# TTkLog.debug(f"Refresh {self._lexer.name} {ra=} {rb=}") |
||||||
|
tsl1 = [TTkString()]*(offset+1) |
||||||
|
block = [0]*(offset+1) |
||||||
|
|
||||||
|
kfd = KodeFormatter.Data(tsl1, block) |
||||||
|
self._formatter.setDl(kfd) |
||||||
|
|
||||||
|
highlight(rawt, self._lexer, self._formatter) |
||||||
|
|
||||||
|
# for ll in tsl: |
||||||
|
# TTkLog.debug(f"1: -{ll}-") |
||||||
|
# for ll in tsl1: |
||||||
|
# TTkLog.debug(f"2: -{ll}-") |
||||||
|
|
||||||
|
tsl1 = tsl1[:rb] |
||||||
|
block = block[:rb] |
||||||
|
self._dataLines[ra:ra+rb] = tsl1 + tsl[len(tsl1):] |
||||||
|
self._blocks[ra:ra+rb] = block + [-1]*(rb-len(block)) |
||||||
|
# TTkLog.debug(self._blocks) |
||||||
|
|
||||||
|
if kfd.error is not None: |
||||||
|
self._refreshContent = (ra+kfd.error,rb<<1) |
||||||
|
# TTkLog.debug(f"Error: {self._refreshContent=}") |
||||||
|
elif kfd.multiline is not None: |
||||||
|
self._refreshContent = (ra+kfd.multiline,rb<<1) |
||||||
|
elif (ra+rb) < len(self._dataLines): |
||||||
|
self._refreshContent = (ra+rb,KodeTextDocument._linesRefreshed) |
||||||
|
else: |
||||||
|
self._refreshContent = None |
||||||
|
# TTkLog.debug(f"{self._refreshContent=}") |
||||||
|
|
||||||
|
if not eof: |
||||||
|
self._timerRefresh.start(0.03) |
||||||
|
else: |
||||||
|
TTkLog.debug(f"Refresh {self._lexer.name} DONE!!!") |
||||||
|
|
||||||
|
self._kodeDocMutex.release() |
||||||
|
self.kodeHighlightUpdate.emit() |
||||||
|
|
||||||
|
def getLock(self): |
||||||
|
return self._kodeDocMutex |
||||||
|
|
||||||
|
def filePath(self): |
||||||
|
return self._filePath |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
from TermTk import TTkLog |
||||||
|
from TermTk import TTkTextEditView |
||||||
|
|
||||||
|
class KodeTextEditView(TTkTextEditView): |
||||||
|
def keyEvent(self, evt) -> bool: |
||||||
|
self.document().getLock().acquire() |
||||||
|
ret = super().keyEvent(evt) |
||||||
|
self.document().getLock().release() |
||||||
|
return ret |
||||||
@ -0,0 +1,158 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
|
||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
import os |
||||||
|
import re |
||||||
|
import sys |
||||||
|
import argparse |
||||||
|
|
||||||
|
import appdirs |
||||||
|
|
||||||
|
from pygments import highlight |
||||||
|
from pygments.lexers import PythonLexer |
||||||
|
from pygments.formatters import TerminalFormatter, Terminal256Formatter, TerminalTrueColorFormatter |
||||||
|
|
||||||
|
from TermTk import TTk, TTkK, TTkLog, TTkCfg, TTkColor, TTkTheme, TTkTerm, TTkHelper |
||||||
|
from TermTk import TTkString |
||||||
|
from TermTk import TTkColorGradient |
||||||
|
from TermTk import pyTTkSlot, pyTTkSignal |
||||||
|
|
||||||
|
from TermTk import TTkFrame, TTkButton |
||||||
|
from TermTk import TTkTabWidget, TTkKodeTab |
||||||
|
from TermTk import TTkAbstractScrollArea, TTkAbstractScrollView |
||||||
|
from TermTk import TTkFileDialogPicker |
||||||
|
from TermTk import TTkFileTree, TTkTextEdit |
||||||
|
|
||||||
|
from TermTk import TTkGridLayout |
||||||
|
from TermTk import TTkSplitter |
||||||
|
|
||||||
|
from .cfg import * |
||||||
|
from .about import * |
||||||
|
# from .options import optionsFormLayout, optionsLoadTheme |
||||||
|
from .kodetextedit import KodeTextEditView |
||||||
|
from .kodetextdocument import KodeTextDocument |
||||||
|
|
||||||
|
class TTKode(TTkGridLayout): |
||||||
|
__slots__ = ('_kodeTab', '_documents') |
||||||
|
def __init__(self, *, files, **kwargs): |
||||||
|
self._documents = {} |
||||||
|
|
||||||
|
super().__init__(**kwargs) |
||||||
|
|
||||||
|
self.addWidget(splitter := TTkSplitter()) |
||||||
|
|
||||||
|
layoutLeft = TTkGridLayout() |
||||||
|
splitter.addItem(layoutLeft, 20) |
||||||
|
|
||||||
|
hSplitter = TTkSplitter(parent=splitter, orientation=TTkK.HORIZONTAL) |
||||||
|
|
||||||
|
menuFrame = TTkFrame(border=False, maxHeight=1) |
||||||
|
|
||||||
|
self._kodeTab = TTkKodeTab(parent=hSplitter, border=False, closable=True) |
||||||
|
|
||||||
|
fileMenu = menuFrame.newMenubarTop().addMenu("&File") |
||||||
|
fileMenu.addMenu("Open").menuButtonClicked.connect(self._showFileDialog) |
||||||
|
fileMenu.addMenu("Close") # .menuButtonClicked.connect(self._closeFile) |
||||||
|
fileMenu.addMenu("Exit").menuButtonClicked.connect(lambda _:TTkHelper.quit()) |
||||||
|
|
||||||
|
def _showAbout(btn): |
||||||
|
TTkHelper.overlay(None, About(), 30,10) |
||||||
|
def _showAboutTTk(btn): |
||||||
|
TTkHelper.overlay(None, TTkAbout(), 30,10) |
||||||
|
|
||||||
|
helpMenu = menuFrame.newMenubarTop().addMenu("&Help", alignment=TTkK.RIGHT_ALIGN) |
||||||
|
helpMenu.addMenu("About ...").menuButtonClicked.connect(_showAbout) |
||||||
|
helpMenu.addMenu("About ttk").menuButtonClicked.connect(_showAboutTTk) |
||||||
|
|
||||||
|
fileTree = TTkFileTree(path='.') |
||||||
|
|
||||||
|
layoutLeft.addWidget(menuFrame, 0,0) |
||||||
|
layoutLeft.addWidget(fileTree, 1,0) |
||||||
|
layoutLeft.addWidget(quitbtn := TTkButton(border=True, text="Quit", maxHeight=3), 2,0) |
||||||
|
|
||||||
|
quitbtn.clicked.connect(TTkHelper.quit) |
||||||
|
|
||||||
|
for file in files: |
||||||
|
self._openFile(file) |
||||||
|
|
||||||
|
fileTree.fileActivated.connect(lambda x: self._openFile(x.path())) |
||||||
|
|
||||||
|
pyTTkSlot() |
||||||
|
def _showFileDialog(self): |
||||||
|
filePicker = TTkFileDialogPicker(pos = (3,3), size=(75,24), caption="Pick Something", path=".", fileMode=TTkK.FileMode.AnyFile ,filter="All Files (*);;Python Files (*.py);;Bash scripts (*.sh);;Markdown Files (*.md)") |
||||||
|
filePicker.pathPicked.connect(self._openFile) |
||||||
|
TTkHelper.overlay(None, filePicker, 20, 5, True) |
||||||
|
|
||||||
|
def _openFile(self, filePath): |
||||||
|
filePath = os.path.realpath(filePath) |
||||||
|
if filePath in self._documents: |
||||||
|
doc = self._documents[filePath]['doc'] |
||||||
|
else: |
||||||
|
with open(filePath, 'r') as f: |
||||||
|
content = f.read() |
||||||
|
doc = KodeTextDocument(text=content, filePath=filePath) |
||||||
|
self._documents[filePath] = {'doc':doc,'tabs':[]} |
||||||
|
tview = KodeTextEditView(document=doc, readOnly=False) |
||||||
|
tedit = TTkTextEdit(textEditView=tview, lineNumber=True) |
||||||
|
doc.kodeHighlightUpdate.connect(tedit.update) |
||||||
|
label = TTkString(TTkCfg.theme.fileIcon.getIcon(filePath),TTkCfg.theme.fileIconColor) + TTkColor.RST + " " + os.path.basename(filePath) |
||||||
|
|
||||||
|
self._kodeTab.addTab(tedit, label) |
||||||
|
self._kodeTab.setCurrentWidget(tedit) |
||||||
|
|
||||||
|
# def _closeFile(): |
||||||
|
# if (index := KodeTab.lastUsed.currentIndex()) >= 0: |
||||||
|
# KodeTab.lastUsed.removeTab(index) |
||||||
|
|
||||||
|
def main(): |
||||||
|
TTKodeCfg.pathCfg = appdirs.user_config_dir("ttkode") |
||||||
|
|
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
# parser.add_argument('-f', help='Full Screen', action='store_true') |
||||||
|
parser.add_argument('-c', help=f'config folder (default: "{TTKodeCfg.pathCfg}")', default=TTKodeCfg.pathCfg) |
||||||
|
parser.add_argument('filename', type=str, nargs='*', |
||||||
|
help='the filename/s') |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
# TTkLog.use_default_file_logging() |
||||||
|
|
||||||
|
TTKodeCfg.pathCfg = args.c |
||||||
|
TTkLog.debug(f"Config Path: {TTKodeCfg.pathCfg}") |
||||||
|
|
||||||
|
TTKodeCfg.load() |
||||||
|
|
||||||
|
# if 'theme' not in TTKodeCfg.options: |
||||||
|
# TTKodeCfg.options['theme'] = 'NERD' |
||||||
|
# optionsLoadTheme(TTKodeCfg.options['theme']) |
||||||
|
|
||||||
|
TTkTheme.loadTheme(TTkTheme.NERD) |
||||||
|
|
||||||
|
root = TTk( layout=TTKode(files=args.filename), title="TTkode", |
||||||
|
sigmask=( |
||||||
|
# TTkTerm.Sigmask.CTRL_C | |
||||||
|
TTkTerm.Sigmask.CTRL_Q | |
||||||
|
TTkTerm.Sigmask.CTRL_S | |
||||||
|
TTkTerm.Sigmask.CTRL_Z )) |
||||||
|
|
||||||
|
root.mainloop() |
||||||
@ -0,0 +1,74 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
|
||||||
|
# MIT License |
||||||
|
# |
||||||
|
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||||
|
# |
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||||
|
# in the Software without restriction, including without limitation the rights |
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||||
|
# furnished to do so, subject to the following conditions: |
||||||
|
# |
||||||
|
# The above copyright notice and this permission notice shall be included in all |
||||||
|
# copies or substantial portions of the Software. |
||||||
|
# |
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
# SOFTWARE. |
||||||
|
|
||||||
|
import copy |
||||||
|
|
||||||
|
from . import TTKodeCfg, TloggGlbl |
||||||
|
|
||||||
|
from TermTk import * |
||||||
|
|
||||||
|
def optionsLoadTheme(theme): |
||||||
|
if theme == 'ASCII': |
||||||
|
TTkTheme.loadTheme(TTkTheme.ASCII) |
||||||
|
elif theme == 'UTF8': |
||||||
|
TTkTheme.loadTheme(TTkTheme.UTF8) |
||||||
|
elif theme == 'NERD': |
||||||
|
TTkTheme.loadTheme(TTkTheme.NERD) |
||||||
|
|
||||||
|
def optionsFormLayout(win): |
||||||
|
options = copy.deepcopy(TTKodeCfg.options) |
||||||
|
|
||||||
|
retLayout = TTkGridLayout() |
||||||
|
bottomLayout = TTkGridLayout() |
||||||
|
|
||||||
|
themesFrame = TTkFrame(title="Theme", border=True, layout=TTkVBoxLayout(), maxHeight=5, minHeight=5) |
||||||
|
# Themes |
||||||
|
themesFrame.layout().addWidget(r1 := TTkRadioButton(text="ASCII", name="theme", checked=options['theme'] == 'ASCII')) |
||||||
|
themesFrame.layout().addWidget(r2 := TTkRadioButton(text="UTF-8", name="theme", checked=options['theme'] == 'UTF8')) |
||||||
|
themesFrame.layout().addWidget(r3 := TTkRadioButton(text="Nerd", name="theme", checked=options['theme'] == 'NERD')) |
||||||
|
|
||||||
|
retLayout.addWidget(themesFrame,0,0) |
||||||
|
retLayout.addWidget(TTkSpacer() ,1,0,1,2) |
||||||
|
|
||||||
|
retLayout.addItem(bottomLayout ,2,0,1,2) |
||||||
|
bottomLayout.addWidget(applyBtn := TTkButton(text="Apply", border=True, maxHeight=3),0,1) |
||||||
|
bottomLayout.addWidget(cancelBtn := TTkButton(text="Cancel", border=True, maxHeight=3),0,2) |
||||||
|
bottomLayout.addWidget(okBtn := TTkButton(text="OK", border=True, maxHeight=3),0,3) |
||||||
|
|
||||||
|
def _saveOptions(): |
||||||
|
if r1.checkState() == TTkK.Checked: options['theme'] = 'ASCII' |
||||||
|
if r2.checkState() == TTkK.Checked: options['theme'] = 'UTF8' |
||||||
|
if r3.checkState() == TTkK.Checked: options['theme'] = 'NERD' |
||||||
|
TTKodeCfg.options = options |
||||||
|
TTKodeCfg.save(searches=False, filters=False, colors=False, options=True) |
||||||
|
optionsLoadTheme(options['theme']) |
||||||
|
TloggGlbl.refreshViews() |
||||||
|
TTkHelper.updateAll() |
||||||
|
|
||||||
|
applyBtn.clicked.connect(_saveOptions) |
||||||
|
okBtn.clicked.connect(_saveOptions) |
||||||
|
okBtn.clicked.connect(win.close) |
||||||
|
cancelBtn.clicked.connect(win.close) |
||||||
|
|
||||||
|
return retLayout |
||||||
Loading…
Reference in new issue