Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fix & Improve #47

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5687dbe
I think it is useless, idk why I add it before
littlewhitecloud Jun 30, 2023
90744a5
Update README.md
littlewhitecloud Jun 30, 2023
da01331
Update README_CH.md
littlewhitecloud Jun 30, 2023
4556674
better logic than switch dev flag
littlewhitecloud Jul 8, 2023
fd31b90
of course
littlewhitecloud Jul 8, 2023
8e61a6a
black
littlewhitecloud Jul 8, 2023
267deb2
Update tkterm.py
littlewhitecloud Jul 8, 2023
61540a3
move check to __init__
littlewhitecloud Jul 8, 2023
05d7508
Update __init__.py
littlewhitecloud Jul 8, 2023
429d8da
nope
littlewhitecloud Jul 8, 2023
da8a730
Update pages.yml
littlewhitecloud Jul 8, 2023
8753a2b
Refact ```self.index``` (fix #49) and fix typo (fix #48)
littlewhitecloud Jul 8, 2023
deb7529
black ruff
littlewhitecloud Jul 8, 2023
0a573f3
Update __init__.py
littlewhitecloud Jul 8, 2023
70c0867
a bit improve...
littlewhitecloud Jul 9, 2023
5227691
LOL rebuild !
littlewhitecloud Jul 12, 2023
2127bf7
s, w p
littlewhitecloud Jul 12, 2023
2d12f27
s, w p
littlewhitecloud Jul 12, 2023
c50ac35
LOL REBUILD
littlewhitecloud Jul 12, 2023
d46ddc6
good bye /
littlewhitecloud Jul 12, 2023
76c5fe6
black, isort, ruff check . --fix!
littlewhitecloud Jul 12, 2023
21a4ac2
document?
littlewhitecloud Jul 12, 2023
1f187c3
Update widgets.py
littlewhitecloud Jul 12, 2023
e38f1a4
fix #35
littlewhitecloud Jul 12, 2023
5c2d8db
black isort ruff check
littlewhitecloud Jul 12, 2023
aedd22f
o, f
littlewhitecloud Jul 12, 2023
7258fdd
Update __init__.py
littlewhitecloud Jul 16, 2023
d21f184
move checks to the utils and some small tweaks
littlewhitecloud Jul 17, 2023
6815dab
nvm
littlewhitecloud Jul 17, 2023
d35f1b4
Update style.py
littlewhitecloud Jul 17, 2023
fc616ed
black isort ruff check and small tweaks
littlewhitecloud Jul 17, 2023
788dfd0
fix #51 and also fix #52
littlewhitecloud Jul 17, 2023
a546fa0
I forget what I did I changed
littlewhitecloud Jul 17, 2023
ec0f3e7
fix SyntaxError: encoding problem: gbk
littlewhitecloud Jul 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions .github/pull_request_template.md

This file was deleted.

4 changes: 3 additions & 1 deletion .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ name: Deploy Jekyll with GitHub Pages dependencies preinstalled
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
branches: ["main"] # Only merge pull_request on main
# Don't create any single commit on main
# Get less github action use

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<h1 align="center"> TkTerminal </h1>

[![PyPI](https://img.shields.io/pypi/v/tktermwidget)](https://pypi.org/project/tktermwidget)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Platform](https://img.shields.io/powershellgallery/p/Pester?color=blue)
[![PyPI](https://img.shields.io/pypi/v/tktermwidget)](https://pypi.org/project/tktermwidget)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black)

### 🌏 [简体中文](README_CH.md)

Expand Down
6 changes: 4 additions & 2 deletions README_CH.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<h1 align="center"> TkTerminal </h1>

[![PyPI](https://img.shields.io/pypi/v/tktermwidget)](https://pypi.org/project/tktermwidget)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Platform](https://img.shields.io/powershellgallery/p/Pester?color=blue)
[![PyPI](https://img.shields.io/pypi/v/tktermwidget)](https://pypi.org/project/tktermwidget)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black)

```TkTermianl``` 是一个使用 tkinter 用 Python 编写的终端模拟器

Expand Down Expand Up @@ -57,7 +59,7 @@ pip install tktermwidget

## 样例:
```python
# -*- coding: gbk -*-
"""An example for tktermwidget"""
from tkinter import Tk

from tkterm import Terminal
Expand Down
11 changes: 8 additions & 3 deletions tktermwidget/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""Tktermwidget package"""
from .style import * # noqa: F401
from .tkterm import Terminal # noqa: F401
"""Import tktermwidget package"""
from .utils import check

check() # Check the files

# Import them after the check
from .style import * # noqa: F401, F403, E402
from .widgets import Terminal # noqa: F401, E402
127 changes: 69 additions & 58 deletions tktermwidget/style.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Styles for terminal widget"""
"""Write or config styles for terminal widget"""
from __future__ import annotations

from json import dump, load
Expand All @@ -14,14 +14,16 @@
STYLE_PATH = Path(user_cache_dir("tktermwidget"))
JSON_FILE = STYLE_PATH / "styles.json"

# Styles format:
# {yourstylename}: dict[str] = {
# "background": "{yourhexcolor}",
# "insertbackground": "{yourhexcolor}",
# "selectbackground": "{yourhexcolor}",
# "selectforeground": "{yourhexcolor}",
# "foreground": "{yourhexcolor}",
# }
"""
# A style example
{stylename}: dict[str] = { # Style for {...}
"background": "{hexcolor}",
"insertbackground": "{hexcolor}",
"selectbackground": "{hexcolor}",
"selectforeground": "{hexcolor}",
"foreground": "{hexcolor}",
}
"""

# Built-in styles
DEFAULT: dict[str] = { # Style for normal tkterminalwidget
Expand Down Expand Up @@ -56,17 +58,7 @@
"foreground": "#efefef",
}

# Check the style file
if not STYLE_PATH.exists():
STYLE_PATH.mkdir(parents=True)
with open(JSON_FILE, "w", encoding="utf-8") as f:
dump("{}", f)
if not (JSON_FILE).exists():
with open(JSON_FILE, "w", encoding="utf-8") as f:
dump("{}", f)


# Functions
def write_style(**styles) -> None:
"""Write the style into the json file"""
# User can call this function to write the style without gui
Expand All @@ -82,37 +74,51 @@ def load_style() -> dict:
return load(f)


# Class
class Config(Tk):
""" "A config gui for user to edit their custom styles"""
"""A config gui for user to edit their custom styles

def __init__(self, usetheme: bool = False, basedon: dict[str] = DEFAULT):
Args:
edit (bool): Enable the edit the text in the render
basedon (dict): Create a style based on the style you choose
usetheme (bool): Enable the apply sv_ttk theme to the window
"""

def __init__(self, edit: bool = False, basedon: dict[str] = DEFAULT, usetheme: bool = False):
super().__init__()

# Setup window
self.geometry("855x525")
self.title("Config your custom style")
self.resizable(False, False)
self.iconbitmap("") # Must call this function or we can't get the hwnd
self.iconbitmap("")

# Apply sv_ttk theme to the window
if usetheme:
from darkdetect import isDark
from sv_ttk import set_theme

set_theme("dark" if isDark() else "light")
self.option_add("*font", ("Cascadia Mono", 9))

if isDark():
from ctypes import byref, c_int, sizeof, windll

windll.dwmapi.DwmSetWindowAttribute(
windll.user32.GetParent(self.winfo_id()), 20, byref(c_int(2)), sizeof(c_int(2))
)
self.withdraw()
self.deiconify()

try:
from darkdetect import isDark
from sv_ttk import set_theme
except ImportError:
usetheme = False
else:
set_theme("dark" if isDark() else "light")
self.option_add("*font", ("Cascadia Mono", 9))

# Enable window's darkmode
if isDark():
from ctypes import byref, c_int, sizeof, windll

windll.dwmapi.DwmSetWindowAttribute(
windll.user32.GetParent(self.winfo_id()), 20, byref(c_int(2)), sizeof(c_int(2))
)
self.withdraw()
self.deiconify()

# If basedon is not DEFAULT then use basedon
# If basedon is DEFAULT then use load_style()
# If load_style() return a empty dict then use DEFAULT
self.style: dict[str] = basedon if basedon != DEFAULT else load_style() if load_style() != {} else DEFAULT

# Color choose or input widgets
# TODO: check the hex color is it vaild
buttonframe = Frame(self)
save = Button(buttonframe, text="Save", width=6, command=self.savestyle)
cancel = Button(buttonframe, text="Cancel", width=6, command=self.destroy)
Expand All @@ -123,6 +129,7 @@ def __init__(self, usetheme: bool = False, basedon: dict[str] = DEFAULT):
backgroundentry = Entry(backgroundframe)
backgroundbutton = Button(backgroundframe, command=lambda: self.selectcolor(backgroundentry, "background"))

# TODO: improve all the labels' text
insertbackgroundframe = Frame(self)
insertbackground = Label(insertbackgroundframe, text="Choose or input your insertbackground hex color")
insertbackgroundentry = Entry(insertbackgroundframe)
Expand Down Expand Up @@ -152,27 +159,28 @@ def __init__(self, usetheme: bool = False, basedon: dict[str] = DEFAULT):
foregroundentry = Entry(foregroundframe)
foregroundbutton = Button(foregroundframe, command=lambda: self.selectcolor(foregroundentry, "foreground"))

# Style render configs
# Config style render
self.render = Text(
self,
width=40,
relief="flat",
font=("Cascadia Mono", 9, "normal"),
foreground=self.style["foreground"],
background=self.style["background"],
insertbackground=self.style["insertbackground"],
selectbackground=self.style["selectbackground"],
selectforeground=self.style["selectforeground"],
foreground=self.style["foreground"],
font=("Cascadia Mono", 9, "normal"),
relief="flat",
)

# Write down some example text
self.render.insert("insert", "This is a normal text for test style.")
self.render.tag_add("select", "1.31", "1.36")
self.render.tag_add("select", "1.28", "1.39")
self.render.tag_config(
"select", background=self.style["selectbackground"], foreground=self.style["selectforeground"]
)
self.render["state"] = "disable"
self.render["state"] = "normal" if edit else "disable"

# add the theme to the button widgets if usetheme == True
# Apply the theme to the button widgets if usetheme is True
if usetheme:
for widget in (
backgroundbutton,
Expand All @@ -184,13 +192,20 @@ def __init__(self, usetheme: bool = False, basedon: dict[str] = DEFAULT):
widget.config(style="Accent.TButton", width=2, text="🎨")
save.config(style="Accent.TButton")

# fill the entry with hexcolor before pack
# Fill the entry with hexcolor
for widget, hexcolor in zip(
(backgroundentry, insertbackgroundentry, selectbackgroundentry, selectforegroundentry, foregroundentry),
self.style.values(),
):
widget.insert("insert", hexcolor)

# Bind some events
backgroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "background"))
insertbackgroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "insertbackground"))
selectbackgroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "selectbackground"))
selectforegroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "selectforeground"))
foregroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "foreground"))

# Pack the widgets
cancel.pack(side="right", padx=1)
save.pack(side="right", padx=3)
Expand Down Expand Up @@ -218,12 +233,6 @@ def __init__(self, usetheme: bool = False, basedon: dict[str] = DEFAULT):
):
widget.pack(side="left", padx=3)

backgroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "background"))
insertbackgroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "insertbackground"))
selectbackgroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "selectbackground"))
selectforegroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "selectforeground"))
foregroundentry.bind("<KeyPress>", lambda event: self.checkhexcolor(event, "foreground"))

for widget in (
backgroundframe,
insertbackgroundframe,
Expand All @@ -243,7 +252,7 @@ def selectcolor(self, entry: Entry, name: str) -> None:
self.updaterender() # update the render to show the latest style

def updaterender(self) -> None:
"""Let the render show with the latest style"""
"""Let the render widget render with the latest style"""
self.render.config(
background=self.style["background"],
insertbackground=self.style["insertbackground"],
Expand All @@ -257,7 +266,7 @@ def updaterender(self) -> None:
self.update()

def savestyle(self) -> None:
"""Save the style"""
"""Save the style to the json file"""
write_style(
background=self.style["background"],
insertbackground=self.style["insertbackground"],
Expand All @@ -268,7 +277,7 @@ def savestyle(self) -> None:
self.destroy()

def checkhexcolor(self, event: Event, name: str) -> None:
"""Check the hex color"""
"""Check the hex color is vaild"""
if match(r"^#(?:[0-9a-fA-F]{3}){1,2}$", event.widget.get()):
event.widget.state(["invalid"])
self.style[name] = event.widget.get()
Expand All @@ -277,8 +286,10 @@ def checkhexcolor(self, event: Event, name: str) -> None:
event.widget.state(["!invalid"])


CUSTOM: dict[str] = load_style()
# Load the custom style
CUSTOM: dict[str] = load_style() if load_style() != {} else DEFAULT

if __name__ == "__main__":
configstyle = Config(True, basedon=POWERSHELL)
# An example basedon "powershell" style and also use sv_ttk theme
configstyle = Config(edit=True, basedon=POWERSHELL, usetheme=True)
configstyle.mainloop()
33 changes: 33 additions & 0 deletions tktermwidget/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Some useful tools"""
from pathlib import Path

from platformdirs import user_cache_dir

# Get the package path
PACKAGE_PATH = Path(user_cache_dir("tktermwidget"))
# Get the history file
HISTORY_FILE = PACKAGE_PATH / "history.txt"
# Get the json file (style)
JSON_FILE = PACKAGE_PATH / "styles.json"


def check():
"""Check files and create them if they don't exsit"""
from json import dump

# Check the "tktermwidget" is exsit
if not PACKAGE_PATH.exists():
PACKAGE_PATH.mkdir(parents=True)

# Check that the history file exists
if not (HISTORY_FILE).exists():
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
f.close()

# Check that the json file exists
if not (JSON_FILE).exists():
with open(JSON_FILE, "w", encoding="utf-8") as f:
dump("{}", f)


check()
Loading