Skip to content

Commit

Permalink
fix: Update cupcake core
Browse files Browse the repository at this point in the history
- merge cupcake updates
- consider tomlin7/cupcake#37
  • Loading branch information
tomlin7 committed Jul 27, 2023
1 parent be488d1 commit beff32b
Show file tree
Hide file tree
Showing 26 changed files with 1,010 additions and 305 deletions.
26 changes: 26 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import toml, os
from tkinter.font import Font
from types import SimpleNamespace

from .styles import Style

class Config:
def __init__(self, master, config_file=None, darkmode=True, font=None, uifont=None):
self.base = master
self.dir = os.path.dirname(__file__)

self.stipple = os.path.join(self.dir, 'stipple.xbm')
if not config_file:
config_file = os.path.join(self.dir, 'dark.toml') if darkmode else os.path.join(self.dir, 'light.toml')

self.font = font or Font(family="Consolas", size=11)
self.uifont = uifont or Font(family="Segoi UI", size=10)
self.load_from(config_file)

def load_from(self, config_file: str):
self.theme = SimpleNamespace(**toml.load(config_file))
self.theme.editor = SimpleNamespace(**self.theme.editor)
self.theme.diffeditor = SimpleNamespace(**self.theme.diffeditor)
self.syntax = self.theme.syntax

self.style = Style(self.base, self)
121 changes: 78 additions & 43 deletions biscuit/core/components/editors/__init__.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,116 @@
import os
from tkinter.constants import *
"""The Cupcake Editor is an embeddable text editor with autocompletions."""

__version__ = '0.25.6'
__version_info__ = tuple([ int(num) for num in __version__.split('.')])

from biscuit.core.components.games.whoops import Whoops
from biscuit.core.settings.editor import SettingsEditor
__all__ = ["Editor", "get_editor", "DiffEditor", "ImageViewer", "TextEditor", "Config", "Languages"]


import os
import tkinter as tk
from tkinter.font import Font

from ..utils import FileType, Frame
from .breadcrumbs import BreadCrumbs
from .diffeditor import DiffEditor
from .editor import BaseEditor
from .imageviewer import ImageViewer
from .languages import Languages
from .misc import Welcome
from .texteditor import TextEditor

editors = {f"::{i.name}":i for i in (Welcome, SettingsEditor)}

def get_editors(base):
"helper function to generate actionset items"
return [(f"Open {i}", lambda i=i: base.open_game(i)) for i in editors.keys()]

def register_editor(editor):
"registers a custome editor"
global editors
try:
editors[editor.name] = editor
except AttributeError:
editors[f"Editor {len(editors) + 1}"] = editor

def get_editor(path, diff):
"picks the right editor for the given path"
def get_editor(base, path=None, path2=None, diff=False, language=None):
"picks the right editor for the given values"
if diff:
return DiffEditor
return DiffEditor(base, path, path2, language=language)

if os.path.isfile(path):
if path and os.path.isfile(path):
if FileType.is_image(path):
return ImageViewer
return ImageViewer(base, path)

return TextEditor(base, path, language=language)

if path in editors.keys():
return editors.get(path, Whoops)

return TextEditor
return TextEditor(base, language=language)


class Editor(Frame):
"""
Editor class
Picks the right editor based on the path, path2, diff values passed. Supports showing diff, images, text files.
If nothing is passed, empty text editor is opened.
Attributes
----------
path : str
path of the file to be opened
exists : bool
if this file exists actually
path2 : str
path of file to be opened in diff, required if diff=True is passed
diff : bool
whether this is to be opened in diff editor
language : str
Use the `Languages` enum provided (eg. Languages.PYTHON, Languages.TYPESCRIPT)
This is given priority while picking suitable highlighter. If not passed, guesses from file extension.
dark_mode : str
Sets the editor theme to cupcake dark if True, or cupcake light by default
This is ignored if custom config_file path is passed
config_file : str
path to the custom config (TOML) file, uses theme defaults if not passed
showpath : bool
whether to show the breadcrumbs for editor or not
font : str | Font
Font used in line numbers, text editor, autocomplete. defaults to Consolas(11)
uifont : str | Font
Font used for other UI components (breadcrumbs, trees)
preview_file_callback : function(path)
called when files in breadcrumbs-pathview are single clicked. MUST take an argument (path)
open_file_callback : function(path)
called when files in breadcrumbs-pathview are double clicked. MUST take an argument (path)
This class is the base class for all editors. It is responsible for
picking the right editor based on the path & exists values passed.
NOTE: All the *tk.Text* methods are available under *Editor.content* (eg. Editor.content.insert, Editor.content.get)
path - the path to the file to be opened
exists - whether the file exists or not
diff - whether this is a git diff
showpath - whether to show the breadcrumbs or not
Methods
-------
save(path: str=None)
If the content is editable writes to the specified path.
focus()
Gives focus to the content.
"""
def __init__(self, master, path=None, exists=True, diff=False, showpath=True, *args, **kwargs):
def __init__(self, master,
path: str=None, exists: bool=False, path2: str=None, diff: bool=False, language: str=None,
darkmode=True, config_file: str=None, showpath: bool=True,
font: str|Font=None, uifont: str|Font=None,
preview_file_callback=None, open_file_callback=None,
*args, **kwargs) -> None:
super().__init__(master, *args, **kwargs)
self.config(bg=self.base.theme.border)

self.path = path
self.exists = exists
self.path2 = path2
self.diff = diff
self.showpath = showpath
self.filename = os.path.basename(self.path) if path else None
self.darkmode = darkmode
self.config_file = config_file
self.preview_file_callback = preview_file_callback
self.open_file_callback = open_file_callback

self.config(bg=self.base.theme.border)
self.grid_columnconfigure(0, weight=1)
self.content = get_editor(path=path, diff=diff)(self, path, exists)

if self.showpath and not diff:
self.content = get_editor(self, path, path2, diff, language)
self.filename = os.path.basename(self.path) if path else None
if path and self.showpath and not diff:
self.breadcrumbs = BreadCrumbs(self, path)
self.grid_rowconfigure(1, weight=1)
self.breadcrumbs.grid(row=0, column=0, sticky=EW, pady=(0, 1))
self.content.grid(row=1, column=0, sticky=NSEW)
self.breadcrumbs.grid(row=0, column=0, sticky=tk.EW, pady=(0, 1))
self.content.grid(row=1, column=0, sticky=tk.NSEW)
else:
self.grid_rowconfigure(0, weight=1)
self.content.grid(row=0, column=0, sticky=NSEW)
self.content.grid(row=0, column=0, sticky=tk.NSEW)

def save(self, path=None):
def save(self, path: str=None) -> None:
self.content.save(path)

def focus(self):
def focus(self) -> None:
self.content.focus()
7 changes: 3 additions & 4 deletions biscuit/core/components/editors/breadcrumbs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import os
import tkinter as tk
from .pathview import PathView

from biscuit.core.components.utils import Frame, Menubutton
from ...utils import Frame, Menubutton
from .pathview import PathView


class Item(Menubutton):
def __init__(self, master, path, *args, **kwargs):
super().__init__(master, font=("Segoe UI", 10), *args, **kwargs)
super().__init__(master, *args, **kwargs)
self.path = path
self.config(height=1, pady=2, padx=1, **self.base.theme.editors.breadcrumbs.item)


class BreadCrumbs(Frame):
def __init__(self, master, path=None, *args, **kwargs):
super().__init__(master, *args, **kwargs)
Expand Down
5 changes: 3 additions & 2 deletions biscuit/core/components/editors/breadcrumbs/pathview.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from biscuit.core.components.views.sidebar.explorer import DirectoryTree
from biscuit.core.components.utils import Toplevel
from biscuit.core.components.views.sidebar.explorer import DirectoryTree


class PathView(Toplevel):
Expand Down Expand Up @@ -37,8 +37,9 @@ def show(self, e):
x = w.winfo_rootx()
y = w.winfo_rooty() + w.winfo_height()

if not w.path:
return
self.tree.change_path(w.path)
self.geometry(f"+{x}+{y}")
self.deiconify()
self.focus_set()

24 changes: 12 additions & 12 deletions biscuit/core/components/editors/diffeditor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@
import threading
import tkinter as tk

from .pane import DiffPane
from .differ import Differ
from ..editor import BaseEditor
from .differ import Differ
from .pane import DiffPane


class DiffEditor(BaseEditor):
def __init__(self, master, path, kind, *args, **kwargs):
def __init__(self, master, path, language=None, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.config(bg=self.base.theme.border)
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1)
self.grid_rowconfigure(0, weight=1)
self.path = path
self.kind = kind
self.editable = True

self.lhs_data = []
Expand All @@ -24,10 +23,10 @@ def __init__(self, master, path, kind, *args, **kwargs):
self.lhs_last_line = 0
self.rhs_last_line = 0

self.lhs = DiffPane(self, path)
self.lhs = DiffPane(self)
self.lhs.grid(row=0, column=0, sticky=tk.NSEW, padx=(0, 1))

self.rhs = DiffPane(self, path)
self.rhs = DiffPane(self)
self.rhs.grid(row=0, column=1, sticky=tk.NSEW)

self.left = self.lhs.text
Expand All @@ -42,16 +41,15 @@ def __init__(self, master, path, kind, *args, **kwargs):

self.left.tag_config("addition", background=self.base.theme.editors.diff.not_exist, bgstipple=f"@{self.stipple}")
self.left.tag_config("removal", background=self.base.theme.editors.diff.removed)
self.left.tag_config("uhhh", background="red")
self.left.tag_config("removedword", background="red")

self.right.tag_config("addition", background=self.base.theme.editors.diff.addition)
self.right.tag_config("removal", background=self.base.theme.editors.diff.not_exist, bgstipple=f"@{self.stipple}")
self.right.tag_config("uhhh", background="green")
self.right.tag_config("addedword", background="green")

self.differ = Differ(self)

self.show_diff()

self.left.set_active(False)

def on_scrollbar(self, *args):
self.left.yview(*args)
Expand Down Expand Up @@ -129,14 +127,14 @@ def show_diff(self):
for match in matches:
start = f"{self.rhs_last_line}.{match.start()}"
end = f"{self.rhs_last_line}.{match.end()}"
self.right.tag_add("uhhh", start, end)
self.right.tag_add("addedword", start, end)

if matches := re.finditer(r'-+', content):
self.right.delete(str(float(self.lhs_last_line+1)), str(float(int(float(self.right.index(tk.INSERT))))))
for match in matches:
start = f"{self.lhs_last_line}.{match.start()}"
end = f"{self.lhs_last_line}.{match.end()}"
self.left.tag_add("uhhh", start, end)
self.left.tag_add("removedword", start, end)

self.left.update()
self.right.update()
Expand All @@ -155,3 +153,5 @@ def show_diff(self):
extra_newlines = rhs_line_count - lhs_line_count
for _ in range(extra_newlines):
self.left.newline()

self.left.set_active(False)
14 changes: 0 additions & 14 deletions biscuit/core/components/editors/diffeditor/lcs_demo.py

This file was deleted.

2 changes: 1 addition & 1 deletion biscuit/core/components/editors/diffeditor/pane.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# TODO currently using TextEditor, use Editor instead
class DiffPane(TextEditor):
def __init__(self, master, *args, **kwargs):
super().__init__(master, exists=False, minimalist=True, *args, **kwargs)
super().__init__(master, minimalist=True, *args, **kwargs)

def load_file(self):
self.text.load_file()
Expand Down
11 changes: 5 additions & 6 deletions biscuit/core/components/editors/editor.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
from biscuit.core.components.utils import Frame, IconButton
from ..utils import Frame, IconButton


class BaseEditor(Frame):
"""
Base class for editors.
"""
def __init__(self, master, path=None, exists=None, editable=True, *args, **kwargs):
def __init__(self, master, path=None, path2=None, editable=True, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.config(**self.base.theme.editors)

self.path = path
self.exists = exists
self.path2 = path2
self.editable = editable

# TODO temp fix for settings, misc editor types
self.showpath = False
self.content = None
self.diff = False

self.__buttons__ = ()

def create_buttons(self, editorbar):
self.__buttons__ = [IconButton(editorbar, *button) for button in self.__buttons__]
def create_buttons(self, panelbar):
self.__buttons__ = [IconButton(panelbar, *button) for button in self.__buttons__]

def save(self, *_):
...
5 changes: 3 additions & 2 deletions biscuit/core/components/editors/imageviewer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import tkinter as tk

from PIL import Image, ImageTk

from ..editor import BaseEditor


#TODO: zooming in and out
class ImageViewer(BaseEditor):
def __init__(self, master, path, exists=True, *args, **kwargs):
super().__init__(master, path, exists=True, editable=False, *args, **kwargs)
super().__init__(master, path, *args, **kwargs)
self.open_image()

def open_image(self):
self.image = Image.open(self.path)
self.image.thumbnail((500, 500))
self.image.thumbnail((700, 700))
self.tk_image = ImageTk.PhotoImage(self.image)

self.image_label = tk.Label(self, image=self.tk_image, **self.base.theme.editors)
Expand Down
Loading

0 comments on commit beff32b

Please sign in to comment.