From ebc421338e94c9ac0d96a154b82ed033ba1507d6 Mon Sep 17 00:00:00 2001 From: Billy Date: Thu, 22 Jun 2023 01:08:19 +0800 Subject: [PATCH] GIT, DIFF EDITOR reimplemented - readded git pane, statusbar info, diff editor - added minimalist optimized mode for text editor --- biscuit/__main__.py | 1 - biscuit/app.py | 46 ++--- biscuit/core/components/editors/__init__.py | 15 +- .../editors/breadcrumbs/__init__.py | 17 +- .../components/editors/diffeditor/__init__.py | 19 +- .../components/editors/diffeditor/differ.py | 2 +- .../components/editors/diffeditor/pane.py | 5 +- .../core/components/editors/misc/welcome.py | 6 +- .../components/editors/texteditor/__init__.py | 16 +- .../texteditor/{syntax => }/highlighter.py | 0 .../{syntax/__init__.py => syntax.py} | 5 - .../components/editors/texteditor/text.py | 20 +- biscuit/core/components/games/__init__.py | 1 + biscuit/core/components/games/game.py | 7 + biscuit/core/components/games/page404.py | 0 biscuit/core/components/games/tetris.py | 5 +- biscuit/core/components/games/whoops.py | 5 + biscuit/core/components/git/__init__.py | 16 +- biscuit/core/components/lsp/test.py | 19 +- biscuit/core/components/utils/iconbutton.py | 2 +- .../views/sidebar/explorer/directorytree.py | 2 +- .../views/sidebar/sourcecontrol/__init__.py | 28 +-- .../sidebar/sourcecontrol/changestree.py | 78 ++++++-- .../sidebar/sourcecontrol/placeholder.py | 5 +- .../views/sidebar/sourcecontrol/toolbar.py | 46 ----- .../views/sidebar/sourcecontrol/utils.py | 8 - biscuit/core/config/languages/__init__.py | 2 - biscuit/core/config/languages/cpp.py | 188 ------------------ biscuit/core/config/languages/language.py | 5 - .../layout/base/content/editors/__init__.py | 49 ++++- .../core/layout/base/content/editors/tab.py | 3 +- .../core/layout/base/content/editors/tabs.py | 9 +- biscuit/core/layout/statusbar/__init__.py | 20 +- biscuit/core/layout/statusbar/utils/button.py | 2 +- biscuit/core/utils/events.py | 6 +- 35 files changed, 246 insertions(+), 412 deletions(-) rename biscuit/core/components/editors/texteditor/{syntax => }/highlighter.py (100%) rename biscuit/core/components/editors/texteditor/{syntax/__init__.py => syntax.py} (71%) delete mode 100644 biscuit/core/components/games/page404.py create mode 100644 biscuit/core/components/games/whoops.py delete mode 100644 biscuit/core/components/views/sidebar/sourcecontrol/toolbar.py delete mode 100644 biscuit/core/components/views/sidebar/sourcecontrol/utils.py delete mode 100644 biscuit/core/config/languages/__init__.py delete mode 100644 biscuit/core/config/languages/cpp.py delete mode 100644 biscuit/core/config/languages/language.py diff --git a/biscuit/__main__.py b/biscuit/__main__.py index 392a6bee..fcc50749 100644 --- a/biscuit/__main__.py +++ b/biscuit/__main__.py @@ -1,5 +1,4 @@ import sys - from app import App dir = None diff --git a/biscuit/app.py b/biscuit/app.py index 2dfc9ae5..d68b0c26 100644 --- a/biscuit/app.py +++ b/biscuit/app.py @@ -78,20 +78,29 @@ def open_directory(self, dir): self.active_directory = dir self.explorer.directory.change_path(dir) self.set_title(os.path.basename(self.active_directory)) - - # self.check_git() - # self.update_git() + self.update_git() - def close_active_dir(self): + def close_active_directory(self): self.active_directory = None - self.active_directory_name = None self.explorer.directory.close_directory() + self.editorsmanager.delete_all_editors() + self.set_title() + self.update_git() + + def close_active_editor(self): + self.editorsmanager.close_active_editor() def open_editor(self, path, exists=True): - if not os.path.isfile(path): + if exists and not os.path.isfile(path): return self.editorsmanager.open_editor(path, exists) + + def open_diff(self, path, exists=True): + if exists and not os.path.isfile(path): + return + + self.editorsmanager.open_diff_editor(path, exists) # games ---- def open_tetris(self, *_): @@ -99,18 +108,10 @@ def open_tetris(self, *_): # ---------- - # def update_git(self): - # if self.git_found: - # self.active_branch_name = self.git.get_active_branch() - - # self.statusbar.configure_git_info(True) - # self.update_statusbar_git_info() - - # self.source_control_ref.create_root() - # self.source_control_ref.update_panes() - # else: - # self.statusbar.configure_git_info(False) - # self.source_control_ref.disable_tree() + def update_git(self): + self.git.check_git() + self.statusbar.update_git_info() + self.source_control.refresh() def open_in_new_window(self, dir): subprocess.Popen(["python", sys.argv[0], dir]) @@ -118,14 +119,13 @@ def open_in_new_window(self, dir): def open_new_window(self): subprocess.Popen(["python", sys.argv[0]]) - def set_title(self, name): + def set_title(self, name=None): + if name: + return self.title("Biscuit") self.title(f"{name} - Biscuit") - # def update_statusbar_git_info(self): - # self.statusbar.set_git_info(self.git.get_active_branch()) - def update_statusbar(self): - if editor := self.editorsmanager.get_active_editor(): + if editor := self.editorsmanager.active_editor: if editor.content and editor.content.editable: self.statusbar.toggle_editmode(True) active_text = editor.content.text diff --git a/biscuit/core/components/editors/__init__.py b/biscuit/core/components/editors/__init__.py index faa4ab55..1909e272 100644 --- a/biscuit/core/components/editors/__init__.py +++ b/biscuit/core/components/editors/__init__.py @@ -5,14 +5,17 @@ from ..utils import FileType from .breadcrumbs import BreadCrumbs -#TODO from .diffeditor import DiffViewer +from .diffeditor import DiffEditor from .imageviewer import ImageViewer from .texteditor import TextEditor from .misc import Welcome -def get_editor(path): +def get_editor(path, diff): "picks the right editor for the given path" + if diff: + return DiffEditor + if os.path.isfile(path): if FileType.is_image(path): return ImageViewer @@ -32,15 +35,17 @@ class Editor(tk.Frame): 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 """ - def __init__(self, master, path=None, exists=True, showpath=True, *args, **kwargs): + def __init__(self, master, path=None, exists=True, diff=False, showpath=True, *args, **kwargs): super().__init__(master, *args, **kwargs) self.master = master self.base = master.base self.path = path self.exists = exists + self.diff = diff self.showpath = showpath self.filename = os.path.basename(self.path) if path else None # TODO for now, this @@ -48,9 +53,9 @@ def __init__(self, master, path=None, exists=True, showpath=True, *args, **kwarg self.filename = self.filename[:-2] self.grid_columnconfigure(0, weight=1) - self.content = get_editor(path=path)(self, path, exists) + self.content = get_editor(path=path, diff=diff)(self, path, exists) - if self.showpath: + if 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)) diff --git a/biscuit/core/components/editors/breadcrumbs/__init__.py b/biscuit/core/components/editors/breadcrumbs/__init__.py index 9581f6f3..49e14190 100644 --- a/biscuit/core/components/editors/breadcrumbs/__init__.py +++ b/biscuit/core/components/editors/breadcrumbs/__init__.py @@ -22,20 +22,19 @@ def __init__(self, master, path=None, *args, **kwargs): # if the file does not belong to active directory, use the absolute path instead if not (self.base.active_directory and - os.path.commonpath([self.base.active_directory, path]) == os.path.abspath(self.base.active_directory)): + os.path.commonpath([self.base.active_directory, os.path.abspath(path)]) == os.path.abspath(self.base.active_directory)): path = os.path.abspath(path).split('\\') for i, item in enumerate(path): text = item if item == path[-1] else f"{item} ›" - - btn = Item(self, "\\".join(path[:i]), text=text) - btn.bind("", self.pathview.show) - btn.pack(side=tk.LEFT) + self.additem("\\".join(path[:i]), text) else: # otherwise use the relative path to active directory - path = os.path.relpath(path, self.base.active_directory).split('\\') + path = os.path.relpath(path, self.base.active_directory).split('\\') for i, item in enumerate(path): text = item if item == path[-1] else f"{item} ›" + self.additem(os.path.join(self.base.active_directory, "\\".join(path[:i])), text) - btn = Item(self, os.path.join(self.base.active_directory, "\\".join(path[:i])), text=text) - btn.bind("", self.pathview.show) - btn.pack(side=tk.LEFT) + def additem(self, path, text): + btn = Item(self, path, text=text) + btn.bind("", self.pathview.show) + btn.pack(side=tk.LEFT) diff --git a/biscuit/core/components/editors/diffeditor/__init__.py b/biscuit/core/components/editors/diffeditor/__init__.py index 1b11784e..9bd65c79 100644 --- a/biscuit/core/components/editors/diffeditor/__init__.py +++ b/biscuit/core/components/editors/diffeditor/__init__.py @@ -2,11 +2,12 @@ from .pane import DiffPane from .differ import Differ +from ..editor import BaseEditor -#TODO reimplement diff editor + git -class DiffViewer(tk.Frame): + +class DiffEditor(BaseEditor): def __init__(self, master, path, *args, **kwargs): - super().__init__(master, orient=tk.HORIZONTAL, *args, **kwargs) + super().__init__(master, *args, **kwargs) self.base = master.base self.master = master self.path = path @@ -17,16 +18,16 @@ def __init__(self, master, path, *args, **kwargs): self.rhs_data = [] self.lhs = DiffPane(self, path) - self.add(self.lhs, stretch='always') + self.lhs.pack(side=tk.LEFT, expand=True, fill=tk.BOTH) self.rhs = DiffPane(self, path) - self.add(self.rhs, stretch='always') + self.rhs.pack(side=tk.RIGHT, expand=True, fill=tk.BOTH) - self.left = self.lhs.content.text - self.right = self.text = self.rhs.content.text + self.left = self.lhs.text + self.right = self.text = self.rhs.text - self.lhs.content.scrollbar['command'] = self.on_scrollbar - self.rhs.content.scrollbar['command'] = self.on_scrollbar + self.lhs.scrollbar['command'] = self.on_scrollbar + self.rhs.scrollbar['command'] = self.on_scrollbar self.left['yscrollcommand'] = self.on_textscroll self.right['yscrollcommand'] = self.on_textscroll diff --git a/biscuit/core/components/editors/diffeditor/differ.py b/biscuit/core/components/editors/diffeditor/differ.py index d741323a..6d6ceca4 100644 --- a/biscuit/core/components/editors/diffeditor/differ.py +++ b/biscuit/core/components/editors/diffeditor/differ.py @@ -1,4 +1,4 @@ -import difflib, sys +import difflib class Differ(difflib.Differ): diff --git a/biscuit/core/components/editors/diffeditor/pane.py b/biscuit/core/components/editors/diffeditor/pane.py index 374912a0..85704e4d 100644 --- a/biscuit/core/components/editors/diffeditor/pane.py +++ b/biscuit/core/components/editors/diffeditor/pane.py @@ -1,7 +1,10 @@ from ..texteditor import TextEditor - +# 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) + def load_file(self): self.text.load_file() diff --git a/biscuit/core/components/editors/misc/welcome.py b/biscuit/core/components/editors/misc/welcome.py index 34951a7b..e27ba31f 100644 --- a/biscuit/core/components/editors/misc/welcome.py +++ b/biscuit/core/components/editors/misc/welcome.py @@ -51,11 +51,11 @@ def create_start_group(self): #TODO add recents - def new_file(self, _): + def new_file(self, *_): self.base.events.new_file() - def open_file(self, _): + def open_file(self, *_): self.base.events.open_file() - def open_folder(self, _): + def open_folder(self, *_): self.base.events.open_directory() diff --git a/biscuit/core/components/editors/texteditor/__init__.py b/biscuit/core/components/editors/texteditor/__init__.py index 341c6885..b3735e7a 100644 --- a/biscuit/core/components/editors/texteditor/__init__.py +++ b/biscuit/core/components/editors/texteditor/__init__.py @@ -9,24 +9,27 @@ class TextEditor(BaseEditor): - def __init__(self, master, path=None, exists=True, *args, **kwargs): + def __init__(self, master, path=None, exists=True, minimalist=False, *args, **kwargs): super().__init__(master, path, exists, *args, **kwargs) self.font = self.base.settings.font + self.minimalist = minimalist self.rowconfigure(0, weight=1) self.columnconfigure(1, weight=1) - self.text = Text(self, path=self.path, exists=self.exists) + self.text = Text(self, path=self.path, exists=self.exists, minimalist=minimalist) self.linenumbers = LineNumbers(self, text=self.text) - self.minimap = Minimap(self, self.text) self.scrollbar = Scrollbar(self, orient=tk.VERTICAL, command=self.text.yview) self.text.config(font=self.font) self.text.configure(yscrollcommand=self.scrollbar.set) - + + if not self.minimalist: + self.minimap = Minimap(self, self.text) + self.minimap.grid(row=0, column=2, sticky=tk.NS) + self.linenumbers.grid(row=0, column=0, sticky=tk.NS) self.text.grid(row=0, column=1, sticky=tk.NSEW) - self.minimap.grid(row=0, column=2, sticky=tk.NS) self.scrollbar.grid(row=0, column=3, sticky=tk.NS) if self.exists: @@ -47,7 +50,8 @@ def focus(self): def on_change(self, event=None): self.linenumbers.redraw() - self.minimap.redraw() + if not self.minimalist: + self.minimap.redraw() self.text.on_change() self.event_generate("<>") self.base.update_statusbar() diff --git a/biscuit/core/components/editors/texteditor/syntax/highlighter.py b/biscuit/core/components/editors/texteditor/highlighter.py similarity index 100% rename from biscuit/core/components/editors/texteditor/syntax/highlighter.py rename to biscuit/core/components/editors/texteditor/highlighter.py diff --git a/biscuit/core/components/editors/texteditor/syntax/__init__.py b/biscuit/core/components/editors/texteditor/syntax.py similarity index 71% rename from biscuit/core/components/editors/texteditor/syntax/__init__.py rename to biscuit/core/components/editors/texteditor/syntax.py index 240bc72d..3310e303 100644 --- a/biscuit/core/components/editors/texteditor/syntax/__init__.py +++ b/biscuit/core/components/editors/texteditor/syntax.py @@ -1,8 +1,3 @@ -from .highlighter import Highlighter - -from core.config.languages import CPP - - class Syntax: def __init__(self, master): self.master = master diff --git a/biscuit/core/components/editors/texteditor/text.py b/biscuit/core/components/editors/texteditor/text.py index aa0e137b..9003d2f0 100644 --- a/biscuit/core/components/editors/texteditor/text.py +++ b/biscuit/core/components/editors/texteditor/text.py @@ -1,12 +1,12 @@ import re import tkinter as tk -from .syntax import Highlighter -from .autocomplete import AutoComplete from .syntax import Syntax +from .highlighter import Highlighter +from .autocomplete import AutoComplete class Text(tk.Text): - def __init__(self, master, path=None, exists=True, *args, **kwargs): + def __init__(self, master, path=None, exists=True, minimalist=False, *args, **kwargs): super().__init__(master, *args, **kwargs) self.base = master.base self.master = master @@ -14,6 +14,7 @@ def __init__(self, master, path=None, exists=True, *args, **kwargs): self.path = path self.data = None self.exists = exists + self.minimalist = minimalist self.syntax = Syntax(self) self.highlighter = Highlighter(self) @@ -21,7 +22,7 @@ def __init__(self, master, path=None, exists=True, *args, **kwargs): self.current_word = None self.words = [] self.auto_completion = AutoComplete( - self, items=self.syntax.get_autocomplete_list()) + self, items=self.syntax.get_autocomplete_list()) if not minimalist else None self.configure(wrap=tk.NONE, relief=tk.FLAT, bg="white", fg="#3b3b3b") self.tag_config(tk.SEL, background="#b98852") @@ -48,6 +49,9 @@ def config_bindings(self): self.bind("", self.enter_key_events) self.bind("", self.tab_key_events) + if self.minimalist: + return + self.bind("", self.hide_autocomplete) self.bind("", self.hide_autocomplete) self.bind("", self.auto_completion.move_up) @@ -118,6 +122,9 @@ def update_words(self, *_): self.after(1000, self.update_words) def update_completions(self): + if self.minimalist: + return + self.auto_completion.update_completions() def confirm_autocomplete(self, text): @@ -153,10 +160,13 @@ def cursor_screen_location(self): return (pos_x + bbx_x - 1, pos_y + bbx_y + bbx_h) def hide_autocomplete(self, *_): + if self.minimalist: + return + self.auto_completion.hide() def show_autocomplete(self, event): - if not self.check_autocomplete_keys(event): + if self.minimalist or not self.check_autocomplete_keys(event): return if self.current_word.strip() not in ["{", "}", ":", "", None, "\""] and not self.current_word.strip()[0].isdigit(): diff --git a/biscuit/core/components/games/__init__.py b/biscuit/core/components/games/__init__.py index fcbe123f..9e80b06b 100644 --- a/biscuit/core/components/games/__init__.py +++ b/biscuit/core/components/games/__init__.py @@ -1,4 +1,5 @@ from .tetris import Tetris +from .whoops import Whoops def get_game(name): "picks the right game for the given name" diff --git a/biscuit/core/components/games/game.py b/biscuit/core/components/games/game.py index 32315336..a422859e 100644 --- a/biscuit/core/components/games/game.py +++ b/biscuit/core/components/games/game.py @@ -16,6 +16,13 @@ def __init__(self, master, path=None, *args, **kwargs): self.exists = False self.showpath = False self.content = None + self.diff = False + self.editable = False + + self.__buttons__ = () def reload(self, *_): + ... + + def save(self, *_): ... diff --git a/biscuit/core/components/games/page404.py b/biscuit/core/components/games/page404.py deleted file mode 100644 index e69de29b..00000000 diff --git a/biscuit/core/components/games/tetris.py b/biscuit/core/components/games/tetris.py index 496cabe4..dc69df7a 100644 --- a/biscuit/core/components/games/tetris.py +++ b/biscuit/core/components/games/tetris.py @@ -3,14 +3,14 @@ import random from collections import Counter -from core.components.editors.editor import BaseEditor +from .game import BaseGame SIDE = 25 WIDTH = 10 * SIDE HEIGHT = 15 * SIDE -class Tetris(BaseEditor): +class Tetris(BaseGame): def __init__(self, master, *args, **kwargs): super().__init__(master, None, None, *args, **kwargs) self.master = master @@ -19,6 +19,7 @@ def __init__(self, master, *args, **kwargs): self.config(bg='#F4EEE0') self.path = "games/tetris" + self.diff = False self.exists = False self.filename = "Tetris" self.content = None diff --git a/biscuit/core/components/games/whoops.py b/biscuit/core/components/games/whoops.py new file mode 100644 index 00000000..006ceafd --- /dev/null +++ b/biscuit/core/components/games/whoops.py @@ -0,0 +1,5 @@ +from .game import BaseGame + + +class Whoops(BaseGame): + ... \ No newline at end of file diff --git a/biscuit/core/components/git/__init__.py b/biscuit/core/components/git/__init__.py index 81016047..7656da0f 100644 --- a/biscuit/core/components/git/__init__.py +++ b/biscuit/core/components/git/__init__.py @@ -11,17 +11,19 @@ def __init__(self, master, *args, **kwargs): self.repo = None def check_git(self): - self.open_repo() - - def open_repo(self): + if not self.base.active_directory: + self.base.git_found = False + return + try: - self.repo = GitRepo(self.base.active_dir) - self.base.set_git_found(True) + self.repo = GitRepo(self.base.active_directory) + self.base.git_found = True except git.exc.InvalidGitRepositoryError: - self.base.set_git_found(False) + self.base.git_found = False def get_version(self): return self.version() - def get_active_branch(self): + @property + def active_branch(self): return self.repo.active_branch diff --git a/biscuit/core/components/lsp/test.py b/biscuit/core/components/lsp/test.py index 86572aae..7308c3c6 100644 --- a/biscuit/core/components/lsp/test.py +++ b/biscuit/core/components/lsp/test.py @@ -9,9 +9,6 @@ """ -from ...config import languages - - class LSP: def __init__(self, master, *args, **kwargs): self.master = master @@ -20,26 +17,16 @@ def get_language(self, filename): """ Get the language of a file """ - ext = filename.split('.')[-1] - if ext in languages: - return ext - else: - return 'plain' + ... def get_language_name(self, language): """ Get the name of a language """ - if language in languages: - return self.languages[language]['name'] - else: - return 'Plain Text' + ... def get_language_extensions(self, language): """ Get the extensions of a language """ - if language in languages: - return self.languages[language]['extensions'] - else: - return [] + ... diff --git a/biscuit/core/components/utils/iconbutton.py b/biscuit/core/components/utils/iconbutton.py index ab3b395b..710700e4 100644 --- a/biscuit/core/components/utils/iconbutton.py +++ b/biscuit/core/components/utils/iconbutton.py @@ -19,7 +19,7 @@ def __init__(self, master, icon, event=lambda *_:..., icon2=None, iconsize=12, f self.bind("", self.onclick) - def onclick(self, _): + def onclick(self, *_): self.event() if not self.icon2: return diff --git a/biscuit/core/components/views/sidebar/explorer/directorytree.py b/biscuit/core/components/views/sidebar/explorer/directorytree.py index 643a12ea..ee60d715 100644 --- a/biscuit/core/components/views/sidebar/explorer/directorytree.py +++ b/biscuit/core/components/views/sidebar/explorer/directorytree.py @@ -39,8 +39,8 @@ def change_path(self, path): self.nodes.clear() self.path = path if self.path: - self.tree.grid() self.placeholder.grid_remove() + self.tree.grid() self.watcher.watch() self.tree.clear_tree() self.create_root() diff --git a/biscuit/core/components/views/sidebar/sourcecontrol/__init__.py b/biscuit/core/components/views/sidebar/sourcecontrol/__init__.py index 350f0e92..945f6ee7 100644 --- a/biscuit/core/components/views/sidebar/sourcecontrol/__init__.py +++ b/biscuit/core/components/views/sidebar/sourcecontrol/__init__.py @@ -4,33 +4,17 @@ from ..sidebarview import SidebarView from .changestree import ChangesTree -from ....utils import Button, IconButton -from .placeholder import ChangesTreePlaceholder - class SourceControl(SidebarView): def __init__(self, master, *args, **kwargs): self.__buttons__ = (('list-tree',), ('check',), ('refresh',), ('ellipsis',)) self.__icon__ = 'source-control' super().__init__(master, *args, **kwargs) - # self.placeholder = ChangesTreePlaceholder(self) - # self.placeholder.pack(fill=BOTH, padx=(15, 10), pady=5) - - self.container = tk.Frame(self, bg='#f8f8f8') - self.container.base = self.base - self.container.pack(fill=BOTH, padx=(15, 10), pady=5) - - self.commit_message = tk.StringVar() - self.commit_message.set('Message') - self.commit_message_entry = tk.Entry(self.container, textvariable=self.commit_message, relief=tk.FLAT, bd=5, bg='white') - self.commit_message_entry.pack(fill=X, pady=(0, 5)) - - self.commit_button = Button(self.container, text='Commit') - self.commit_button.pack(fill=BOTH, side=LEFT, expand=True) - tk.Label(self.container, text="|", fg='white', bg="#dc8c34").pack(side=LEFT, fill=Y) - self.more = IconButton(self.container, icon='chevron-down', - bg="#dc8c34", fg="white", activebackground="#ffaf3c", activeforeground="white") - self.more.pack(fill=Y) - self.tree = ChangesTree(self) self.add_widget(self.tree) + + def refresh(self): + if self.base.git_found: + self.tree.enable_tree() + else: + self.tree.disable_tree() \ No newline at end of file diff --git a/biscuit/core/components/views/sidebar/sourcecontrol/changestree.py b/biscuit/core/components/views/sidebar/sourcecontrol/changestree.py index caf26674..dd895887 100644 --- a/biscuit/core/components/views/sidebar/sourcecontrol/changestree.py +++ b/biscuit/core/components/views/sidebar/sourcecontrol/changestree.py @@ -1,30 +1,76 @@ -from tkinter.constants import * +import os +import tkinter as tk from ....utils import Tree from ..item import SidebarViewItem +from .placeholder import ChangesTreePlaceholder + +from ....utils import Button, IconButton +from .placeholder import ChangesTreePlaceholder + class ChangesTree(SidebarViewItem): def __init__(self, master, *args, **kwargs): self.__buttons__ = (('discard',), ('add',)) - self.title = 'Changes' + self.title = 'No folder opened' super().__init__(master, *args, **kwargs) - self.tree = Tree(self.content, *args, **kwargs) - self.tree.grid(row=0, column=0, sticky=NSEW) + # --- COMMIT MESSAGE, BUTTON --- + self.commitbox = tk.Frame(self.content, bg='#f8f8f8') + self.commitbox.base = self.base + self.commitbox.grid(row=0, padx=(15, 10), pady=5, column=0, sticky=tk.NSEW) + self.commitbox.grid_remove() + + self.commit_message = tk.StringVar() + self.commit_message.set('Message') + self.commit_message_entry = tk.Entry(self.commitbox, textvariable=self.commit_message, relief=tk.FLAT, bd=5, bg='white') + self.commit_message_entry.pack(fill=tk.X, pady=(0, 5)) + + self.commit_button = Button(self.commitbox, text='Commit') + self.commit_button.pack(fill=tk.BOTH, side=tk.LEFT, expand=True) + tk.Label(self.commitbox, text="|", fg='white', bg="#dc8c34").pack(side=tk.LEFT, fill=tk.Y) + self.more = IconButton(self.commitbox, icon='chevron-down', + bg="#dc8c34", fg="white", activebackground="#ffaf3c", activeforeground="white") + self.more.pack(fill=tk.Y) + # ------------------------------ + + self.tree = Tree(self.content, doubleclick=self.opendiff, *args, **kwargs) + self.tree.grid(row=1, column=0, sticky=tk.NSEW) + self.tree.grid_remove() - # def openfile(self, event): - # item = self.focus() - # path = self.set(item, "fullpath") - # self.base.set_active_file(path, diff=True) + self.placeholder = ChangesTreePlaceholder(self.content) + self.placeholder.grid(row=0, column=0, sticky=tk.NSEW) + + def opendiff(self, event): + path = self.tree.selected_path() + self.base.open_diff(path) def add_files(self, parent='', changed_files=()): for file in changed_files: - oid = self.insert(parent, END, text=f" {file}", values=[file], image='fileicon') + self.tree.insert(parent, tk.END, text=f" {file}", values=[file, 'file'], image='document') - # def open_repo(self, repo): - # changed_files = repo.get_changed_files() - # untracked_files = repo.get_untracked_files() - - # self.clean_tree() - # self.add_tree("Changes", changed_files) - # self.add_tree("Untracked Files", untracked_files) + def open_repo(self): + self.tree.clear_tree() + self.set_title(f"{os.path.basename(self.base.active_directory)}({self.base.git.active_branch})") + + changes = self.tree.insert('', tk.END, text=f" Changes", image='foldericon') + untracked = self.tree.insert('', tk.END, text=f" Untracked Files", image='foldericon') + + self.add_files(changes, self.base.git.repo.get_changed_files()) + self.add_files(untracked, self.base.git.repo.get_untracked_files()) + + def enable_tree(self): + self.content.grid_rowconfigure(0, weight=0) + self.content.grid_rowconfigure(1, weight=1) + self.placeholder.grid_remove() + self.commitbox.grid() + self.tree.grid() + self.tree.clear_tree() + self.open_repo() + + def disable_tree(self): + self.content.grid_rowconfigure(0, weight=1) + self.commitbox.grid_remove() + self.tree.grid_remove() + self.placeholder.grid() + self.set_title('No folder opened') \ No newline at end of file diff --git a/biscuit/core/components/views/sidebar/sourcecontrol/placeholder.py b/biscuit/core/components/views/sidebar/sourcecontrol/placeholder.py index 5dd8633c..e4b0d9b4 100644 --- a/biscuit/core/components/views/sidebar/sourcecontrol/placeholder.py +++ b/biscuit/core/components/views/sidebar/sourcecontrol/placeholder.py @@ -8,9 +8,10 @@ def __init__(self, master, *args, **kwargs): super().__init__(master, *args, **kwargs) self.base = master.base + self.config(padx=10, pady=10, bg='#f8f8f8') self.columnconfigure(0, weight=1) - WrappingLabel(self, font=("Segoe UI", 10), anchor=tk.W, fg="#616161", + WrappingLabel(self, font=("Segoe UI", 10), anchor=tk.W, fg="#424242", bg='#f8f8f8', text="In order to use git features, you can open a folder containing a git repository or clone from a URL.").grid(row=0, sticky=tk.EW) open_btn = Button(self, text="Open Folder") @@ -22,7 +23,7 @@ def __init__(self, master, *args, **kwargs): clone_btn.grid(row=2, pady=5, sticky=tk.EW) def open_folder(self, _): - pass + self.base.events.open_directory() def clone_repo(self, *_): pass diff --git a/biscuit/core/components/views/sidebar/sourcecontrol/toolbar.py b/biscuit/core/components/views/sidebar/sourcecontrol/toolbar.py deleted file mode 100644 index 5027f88c..00000000 --- a/biscuit/core/components/views/sidebar/sourcecontrol/toolbar.py +++ /dev/null @@ -1,46 +0,0 @@ -import tkinter as tk - - -class GitTreeToolbar(tk.Frame): - def __init__(self, master, *args, **kwargs): - tk.Frame.__init__(self, master, *args, **kwargs) - self.base = master.base - self.master = master - - self.config(bg="#f3f3f3") - self.grid_columnconfigure(0, weight=1) - - self.label = tk.Label(self) - self.label.config( - text="SOURCE CONTROL", font=("Segoe UI", 10), anchor=tk.W, - bg="#f3f3f3", fg="#6f6f6f") - - self.more_actions = tk.Menubutton(self) - self.more_actions.config( - text="\uea7c", bg="#f3f3f3", fg="#424242", font=("codicon", 12), - width=2, activebackground="#e1e1e1", activeforeground="#424242") - - self.refresh = tk.Menubutton(self) - self.refresh.config( - text="\ueb37", bg="#f3f3f3", fg="#424242", font=("codicon", 12), - width=2, activebackground="#e1e1e1", activeforeground="#424242") - - self.commit = tk.Menubutton(self) - self.commit.config( - text="\ueab2", fg="#424242", bg="#f3f3f3", font=("codicon", 12), - width=2, activebackground="#e1e1e1", activeforeground="#424242") - - self.label.grid(row=0, column=0, sticky=tk.EW, padx=(25, 0)) - self.more_actions.grid(row=0, column=1) - self.refresh.grid(row=0, column=2) - self.commit.grid(row=0, column=3) - - def disable_tools(self): - self.commit.grid_remove() - self.refresh.grid_remove() - self.more_actions.grid_remove() - - def enable_tools(self): - self.commit.grid() - self.refresh.grid() - self.more_actions.grid() \ No newline at end of file diff --git a/biscuit/core/components/views/sidebar/sourcecontrol/utils.py b/biscuit/core/components/views/sidebar/sourcecontrol/utils.py deleted file mode 100644 index 9e99f485..00000000 --- a/biscuit/core/components/views/sidebar/sourcecontrol/utils.py +++ /dev/null @@ -1,8 +0,0 @@ -import git - -def is_git_repo(path): - try: - _ = git.Repo(path).git_dir - return True - except Exception: - return False diff --git a/biscuit/core/config/languages/__init__.py b/biscuit/core/config/languages/__init__.py deleted file mode 100644 index 20543f19..00000000 --- a/biscuit/core/config/languages/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .language import Language -from .cpp import CPP diff --git a/biscuit/core/config/languages/cpp.py b/biscuit/core/config/languages/cpp.py deleted file mode 100644 index 31271c1e..00000000 --- a/biscuit/core/config/languages/cpp.py +++ /dev/null @@ -1,188 +0,0 @@ -from .language import Language - - -class CPP(Language): - keywords = [ - "abstract", - "amp", - "array", - "auto", - "bool", - "break", - "case", - "catch", - "char", - "class", - "const", - "constexpr", - "const_cast", - "continue", - "cpu", - "decltype", - "default", - "delegate", - "delete", - "do", - "double", - "dynamic_cast", - "each", - "else", - "enum", - "event", - "explicit", - "export", - "extern", - "false", - "final", - "finally", - "float", - "for", - "friend", - "gcnew", - "generic", - "goto", - "if", - "in", - "initonly", - "inline", - "int", - "interface", - "interior_ptr", - "internal", - "literal", - "long", - "mutable", - "namespace", - "new", - "noexcept", - "nullptr", - "__nullptr", - "operator", - "override", - "partial", - "pascal", - "pin_ptr", - "private", - "property", - "protected", - "public", - "ref", - "register", - "reinterpret_cast", - "restrict", - "return", - "safe_cast", - "sealed", - "short", - "signed", - "sizeof", - "static", - "static_assert", - "static_cast", - "struct", - "switch", - "template", - "this", - "thread_local", - "throw", - "tile_static", - "true", - "try", - "typedef", - "typeid", - "typename", - "union", - "unsigned", - "using", - "virtual", - "void", - "volatile", - "wchar_t", - "where", - "while", - - "_asm", - "_based", - "_cdecl", - "_declspec", - "_fastcall", - "_if_exists", - "_if_not_exists", - "_inline", - "_multiple_inheritance", - "_pascal", - "_single_inheritance", - "_stdcall", - "_virtual_inheritance", - "_w64", - - "__abstract", - "__alignof", - "__asm", - "__assume", - "__based", - "__box", - "__builtin_alignof", - "__cdecl", - "__clrcall", - "__declspec", - "__delegate", - "__event", - "__except", - "__fastcall", - "__finally", - "__forceinline", - "__gc", - "__hook", - "__identifier", - "__if_exists", - "__if_not_exists", - "__inline", - "__int128", - "__int16", - "__int32", - "__int64", - "__int8", - "__interface", - "__leave", - "__m128", - "__m128d", - "__m128i", - "__m256", - "__m256d", - "__m256i", - "__m64", - "__multiple_inheritance", - "__newslot", - "__nogc", - "__noop", - "__nounwind", - "__novtordisp", - "__pascal", - "__pin", - "__pragma", - "__property", - "__ptr32", - "__ptr64", - "__raise", - "__restrict", - "__resume", - "__sealed", - "__single_inheritance", - "__stdcall", - "__super", - "__thiscall", - "__try", - "__try_cast", - "__typeof", - "__unaligned", - "__unhook", - "__uuidof", - "__value", - "__virtual_inheritance", - "__w64", - "__wchar_t"] - - strings = ["(\\'(.)\\')", "(\"(.)*\")"] - numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] - comments = ["(//(.)*)", "(\/\\*(.*?)\\*\/)"] diff --git a/biscuit/core/config/languages/language.py b/biscuit/core/config/languages/language.py deleted file mode 100644 index 70bd2801..00000000 --- a/biscuit/core/config/languages/language.py +++ /dev/null @@ -1,5 +0,0 @@ -class Language: - keywords: list - strings: list - numbers: list - comments: list diff --git a/biscuit/core/layout/base/content/editors/__init__.py b/biscuit/core/layout/base/content/editors/__init__.py index 80f45ec4..94621f09 100644 --- a/biscuit/core/layout/base/content/editors/__init__.py +++ b/biscuit/core/layout/base/content/editors/__init__.py @@ -1,5 +1,4 @@ import tkinter as tk -from tkinter.constants import * from .editorsbar import Editorsbar from .empty import Empty @@ -32,15 +31,16 @@ def __init__(self, master, *args, **kwargs): self.grid_columnconfigure(0, weight=1) self.editorsbar = Editorsbar(self) - self.editorsbar.grid(row=0, column=0, sticky=EW, pady=(0,1)) + self.editorsbar.grid(row=0, column=0, sticky=tk.EW, pady=(0,1)) self.tabs = self.editorsbar.tabs self.editors = [] + self.closed_editors = {} self.empty = True self.emptytab = Empty(self) - self.emptytab.grid(column=0, row=1, sticky=NSEW) + self.emptytab.grid(column=0, row=1, sticky=tk.NSEW) - self.default_editors = [Editor(self, '::welcome::', False, False)] + self.default_editors = [Editor(self, '::welcome::', False, False, False)] self.add_editors(self.default_editors) def add_editors(self, editors): @@ -58,25 +58,52 @@ def delete_all_editors(self): for editor in self.editors: editor.destroy() + self.editorsbar.clear() + self.tabs.clear_all_tabs() self.editors.clear() def open_editor(self, path, exists): "open Editor with path and exists values passed" + if path in self.closed_editors: + return self.add_editor(self.closed_editors[path]) self.add_editor(Editor(self, path, exists)) + def open_diff_editor(self, path, exists): + "open Editor with path and exists values passed" + self.add_editor(Editor(self, path, exists, diff=True)) + + def close_editor(self, editor): + "removes an editor, keeping it in cache." + self.editors.remove(editor) + + # not keeping diff in cache + if not editor.diff: + self.closed_editors[editor.path] = editor + self.refresh() + + def close_active_editor(self): + "Closes the active tab" + self.close_editor(self.active_editor) + def delete_editor(self, editor): "Permanently delete a editor." self.editors.remove(editor) + if editor.path in self.closed_editors: + self.closed_editors.remove(editor) + editor.destroy() self.refresh() - - def set_active_editor(self, editor): - "Set active editor and active tab." - ... - - def get_active_editor(self): + + def delete_editor(self, editor): + "Permanently delete a editor." + self.editors.remove(editor) + editor.destroy() + self.refresh() + + @property + def active_editor(self): "Get active editor." - return self.editorsbar.tabs.active_tab.editor + return self.tabs.active_tab.editor def refresh(self): if not len(self.editors) and self.empty: diff --git a/biscuit/core/layout/base/content/editors/tab.py b/biscuit/core/layout/base/content/editors/tab.py index 1cfd508a..a98d26ef 100644 --- a/biscuit/core/layout/base/content/editors/tab.py +++ b/biscuit/core/layout/base/content/editors/tab.py @@ -19,7 +19,8 @@ def __init__(self, master, editor, *args, **kwargs): self.editor = editor self.selected = False - self.name = tk.Label(self, text=editor.filename, padx=5, pady=5, font=('Segoe UI', 10), bg='#f8f8f8') + self.name = tk.Label(self, text=f"{editor.filename} (working tree)" if editor.diff else editor.filename, + padx=5, pady=5, font=('Segoe UI', 10), bg='#f8f8f8') self.name.pack(side=tk.LEFT) self.closebtn = IconButton(self, 'close', event=self.close, activebackground="#e9e9e9") diff --git a/biscuit/core/layout/base/content/editors/tabs.py b/biscuit/core/layout/base/content/editors/tabs.py index caafa496..aa668bc1 100644 --- a/biscuit/core/layout/base/content/editors/tabs.py +++ b/biscuit/core/layout/base/content/editors/tabs.py @@ -24,7 +24,8 @@ def add_tab(self, view): def close_tab(self, tab): i = self.tabs.index(tab) self.tabs.remove(tab) - self.master.master.delete_editor(tab.editor) + tab.editor.grid_forget() + self.master.master.close_editor(tab.editor) tab.destroy() if self.tabs: @@ -40,3 +41,9 @@ def set_active_tab(self, selected_tab): for tab in self.tabs: if tab != selected_tab: tab.deselect() + + def clear_all_tabs(self): + for tab in self.tabs: + tab.destroy() + + self.tabs.clear() diff --git a/biscuit/core/layout/statusbar/__init__.py b/biscuit/core/layout/statusbar/__init__.py index c082074b..ff992806 100644 --- a/biscuit/core/layout/statusbar/__init__.py +++ b/biscuit/core/layout/statusbar/__init__.py @@ -33,7 +33,7 @@ def __init__(self, master, *args, **kwargs): [("main", lambda e=None: print("main", e)), ("rewrite", lambda e=None: print("rewrite", e))], ) self.base.palette.register_actionset(self.git_actionset) - self.branch = SButton(self, text="master", icon="\uea68", function=lambda e: self.base.palette.show_prompt('branch:')) + self.branch = SButton(self, text="master", icon="\uea68", function=lambda *_: self.base.palette.show_prompt('branch:')) self.branch.set_pack_data(side=tk.LEFT, padx=(10, 0)) # line and column info @@ -42,7 +42,7 @@ def __init__(self, master, *args, **kwargs): [("goto line", lambda e=None: print("goto line", e))], ) self.base.palette.register_actionset(self.lc_actionset) - self.line_col_info = SButton(self, text="Ln 1, Col 1", function=lambda e: self.base.palette.show_prompt(':')) + self.line_col_info = SButton(self, text="Ln 1, Col 1", function=lambda *_: self.base.palette.show_prompt(':')) self.line_col_info.set_pack_data(side=tk.RIGHT) # indentation @@ -52,7 +52,7 @@ def __init__(self, master, *args, **kwargs): ("4", lambda e=None: print("indent 2", e))], ) self.base.palette.register_actionset(self.indent_actionset) - self.indentation = SButton(self, text="Spaces: 4", function=lambda e: self.base.palette.show_prompt('indent:')) + self.indentation = SButton(self, text="Spaces: 4", function=lambda *_: self.base.palette.show_prompt('indent:')) self.indentation.set_pack_data(side=tk.RIGHT) # encoding @@ -61,7 +61,7 @@ def __init__(self, master, *args, **kwargs): [("UTF-8", lambda e=None: print("encoding UTF-8", e))], ) self.base.palette.register_actionset(self.encoding_actionset) - self.encoding = SButton(self, text="UTF-8", function=lambda e: self.base.palette.show_prompt('encoding:')) + self.encoding = SButton(self, text="UTF-8", function=lambda *_: self.base.palette.show_prompt('encoding:')) self.encoding.set_pack_data(side=tk.RIGHT) # end of line @@ -71,7 +71,7 @@ def __init__(self, master, *args, **kwargs): ("CRLF", lambda e=None: print("eol crlf", e))], ) self.base.palette.register_actionset(self.eol_actionset) - self.eol = SButton(self, text="CRLF", function=lambda e: self.base.palette.show_prompt('eol:')) + self.eol = SButton(self, text="CRLF", function=lambda *_: self.base.palette.show_prompt('eol:')) self.eol.set_pack_data(side=tk.RIGHT) # TODO use pyglet @@ -82,7 +82,7 @@ def __init__(self, master, *args, **kwargs): ("c++", lambda e=None: print("filetype c++", e))], ) self.base.palette.register_actionset(self.filetype_actionset) - self.file_type = SButton(self, text="Plain Text", function=lambda e: self.base.palette.show_prompt('syntax:')) + self.file_type = SButton(self, text="Plain Text", function=lambda *_: self.base.palette.show_prompt('syntax:')) self.file_type.set_pack_data(side=tk.RIGHT) self.clock = SClock(self, text="H:M:S") @@ -106,14 +106,12 @@ def toggle_editmode(self, state): self.indentation.hide() self.line_col_info.hide() - def configure_git_info(self, state): - if state: + def update_git_info(self): + if self.base.git_found: self.branch.show() + self.branch.change_text("{0}".format(self.base.git.active_branch)) else: self.branch.hide() - - def set_git_info(self, branch): - self.branch.change_text("{0}".format(branch)) def set_line_col_info(self, line, col, selected): self.line_col_info.change_text(text="Ln {0}, Col {1}{2}".format(line, col, f" ({selected} selected)" if selected else "")) diff --git a/biscuit/core/layout/statusbar/utils/button.py b/biscuit/core/layout/statusbar/utils/button.py index 702a22ec..5223fd26 100644 --- a/biscuit/core/layout/statusbar/utils/button.py +++ b/biscuit/core/layout/statusbar/utils/button.py @@ -49,7 +49,7 @@ def on_leave(self, _): if self.icon: self.icon_label.config(bg=self.bg) - def on_click(self, _): + def on_click(self, *_): self.function() def change_text(self, text): diff --git a/biscuit/core/utils/events.py b/biscuit/core/utils/events.py index bba4aa95..4c368eee 100644 --- a/biscuit/core/utils/events.py +++ b/biscuit/core/utils/events.py @@ -22,7 +22,7 @@ def open_directory(self, *_): self.base.open_directory(filedialog.askdirectory()) def save(self, *_): - editor = self.base.editorsmanager.get_active_editor() + editor = self.base.editorsmanager.active_editor if editor.content: if not editor.content.exists: return self.save_as() @@ -31,7 +31,7 @@ def save(self, *_): def save_as(self, *_): #TODO set initial filename to a range of text inside the editor - if editor := self.base.editorsmanager.get_active_editor(): + if editor := self.base.editorsmanager.active_editor: if editor.content: if editor.content.editable: if path := asksaveasfilename(title="Save As...", defaultextension=".txt", initialfile=("Untitled")): @@ -50,7 +50,7 @@ def close_file(self, *_): self.base.close_active_file() def close_dir(self, *_): - self.base.close_active_dir() + self.base.close_active_directory() def quit(self, *_): self.base.destroy()