Skip to content

Commit

Permalink
Merge branch 'tomlin7:main' into fix/linux-icon
Browse files Browse the repository at this point in the history
  • Loading branch information
vyshnav-vinod authored May 13, 2024
2 parents d75fd94 + 2187f3f commit bf3bb6b
Show file tree
Hide file tree
Showing 30 changed files with 414 additions and 43 deletions.
2 changes: 1 addition & 1 deletion biscuit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.75.2"
__version__ = "2.76.0"
__version_info__ = tuple([int(num) for num in __version__.split(".")])

# For tests to run successfully
Expand Down
6 changes: 6 additions & 0 deletions biscuit/core/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,12 @@ def show_google_search(self, *_) -> None:
def configure_run_command(self, *_) -> None:
self.base.palette.show('runconf:')

def search_github_issues(self, *_) -> None:
self.base.palette.show('issue:')

def search_github_prs(self, *_) -> None:
self.base.palette.show('pr:')

def show_file_search(self, *_) -> None:
self.base.palette.show()

Expand Down
10 changes: 10 additions & 0 deletions biscuit/core/components/editors/html/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import tkinter as tk
from typing import Any

from biscuit.core.components.editors.texteditor import TextEditor

Expand Down Expand Up @@ -36,6 +37,15 @@ def __init__(self, master, path, exists=False, *args, **kwargs) -> None:
self.edit_undo = self.editor.edit_undo
self.editor_redo = self.editor.edit_redo


@property
def unsaved_changes(self) -> bool:
return self.editor.unsaved_changes

@property
def debugger(self) -> Any:
return self.editor.debugger

def toggle_preview(self,*_):
if self.preview_enabled:
self.grid_columnconfigure(1, weight=0)
Expand Down
9 changes: 9 additions & 0 deletions biscuit/core/components/editors/markdown/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import tkinter as tk
from typing import Any

from biscuit.core.components.editors.texteditor import TextEditor

Expand Down Expand Up @@ -35,6 +36,14 @@ def __init__(self, master, path, exists=False, *args, **kwargs) -> None:
self.editor.bind("<<Change>>", self.on_change)
self.edit_undo = self.editor.edit_undo
self.editor_redo = self.editor.edit_redo

@property
def unsaved_changes(self) -> bool:
return self.editor.unsaved_changes

@property
def debugger(self) -> Any:
return self.editor.debugger

def toggle_preview(self,*_):
if self.preview_enabled:
Expand Down
2 changes: 1 addition & 1 deletion biscuit/core/components/editors/texteditor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(self, master, path=None, exists=True, language=None, minimalist=Fal
self.content_hash = ''

if not self.standalone:
self.__buttons__ = [('sync', self.base.editorsmanager.reopen_active_editor),]
self.__buttons__ = [('refresh', self.base.editorsmanager.reopen_active_editor),]

self.rowconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
Expand Down
27 changes: 26 additions & 1 deletion biscuit/core/components/git/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,29 @@ def do(self, fn, *args, **kwargs):
try:
return fn(*args, **kwargs)
except Exception as e:
self.master.base.notifications.error(e)
self.master.base.notifications.error(e)

def get_remote(self, name):
return self.remotes[name]

def get_remote_origin(self):
return self.get_remote("origin")

def get_remote_url(self, name):
return self.strip_github_url(self.get_remote(name).url)

def get_remote_origin_url(self):
return self.get_remote_url("origin")

def strip_github_url(self, url):
if url.endswith(".git"):
url = url[:-4]
return url

def get_owner_and_repo(self, url):
url = self.strip_github_url(url).split("/")
return url[-2], url[-1]

#TODO: push, pull, fetch
def get_active_branch(self):
return self.active_branch.name
1 change: 1 addition & 0 deletions biscuit/core/components/views/sidebar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from .debug import Debug
from .explorer import Explorer
from .extensions import Extensions
from .github import GitHub
from .outline import Outline
from .search import Search
from .sidebarview import SidebarView
Expand Down
10 changes: 5 additions & 5 deletions biscuit/core/components/views/sidebar/ai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ def __init__(self, master, *args, **kwargs) -> None:
self.add_placeholder()

def add_placeholder(self) -> None:
self.add_widget(self.placeholder)
self.add_item(self.placeholder)
if self.api_key:
self.placeholder.api_key.set(self.api_key)

if self.chat:
self.remove_widget(self.chat)
self.remove_item(self.chat)
self.chat.destroy()

def add_chat(self, api_key: str=None) -> None:
Expand All @@ -60,13 +60,13 @@ def add_chat(self, api_key: str=None) -> None:
self.db.commit()

if self.chat:
self.remove_widget(self.chat)
self.remove_item(self.chat)
self.chat.destroy()
self.chat = None

self.chat = Chat(self)
self.add_widget(self.chat)
self.remove_widget(self.placeholder)
self.add_item(self.chat)
self.remove_item(self.placeholder)

def new_chat(self) -> None:
if self.chat:
Expand Down
8 changes: 4 additions & 4 deletions biscuit/core/components/views/sidebar/debug/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, master, *args, **kwargs) -> None:
self.callstack = CallStack(self)

self.placeholder = DebugPlaceholder(self)
self.add_widget(self.placeholder)
self.add_item(self.placeholder)

def refresh(self):
"""Refresh the debug view."""
Expand All @@ -41,12 +41,12 @@ def show(self):
"""Show the debug view."""

self.placeholder.pack_forget()
self.add_widget(self.variables)
self.add_widget(self.callstack)
self.add_item(self.variables)
self.add_item(self.callstack)

def hide(self):
"""Hide the debug view and show the placeholder."""

self.variables.pack_forget()
self.callstack.pack_forget()
self.add_widget(self.placeholder)
self.add_item(self.placeholder)
2 changes: 1 addition & 1 deletion biscuit/core/components/views/sidebar/explorer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, master, *args, **kwargs) -> None:
self.open_editors = OpenEditors(self)
self.open_editors.pack(fill=tk.X)
self.directory = DirectoryTree(self, observe_changes=True)
self.add_widget(self.directory)
self.add_item(self.directory)

self.filesearch_actionset = ActionSet("Search files", "file:", [])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, master, startpath=None, observe_changes=False, itembar=True,
self.__buttons__ = (('new-file', lambda: self.base.palette.show('newfile:')),
('new-folder', lambda: self.base.palette.show('newfolder:')),
('refresh', self.refresh_root), ('collapse-all', self.collapse_all))
super().__init__(master, itembar, *args, **kwargs)
super().__init__(master, itembar=itembar, *args, **kwargs)

self.nodes = {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class OpenEditors(SidebarViewItem):
def __init__(self, master, startpath=None, itembar=True, *args, **kwargs) -> None:
self.title = 'Open Editors'
self.__buttons__ = (('new-file', lambda: self.base.palette.show('newfile:')),)
super().__init__(master, itembar, *args, **kwargs)
super().__init__(master, itembar=itembar, *args, **kwargs)
self.path = startpath
self.nodes = {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __init__(self, master, *args, **kwargs) -> None:
self.searchbox.pack(fill=tk.X, anchor=tk.N, padx=10, pady=7)

self.results = Results(self)
self.add_widget(self.results)
self.add_item(self.results)
self.add_button('refresh', self.results.refresh)
self.add_button('clear-all', self.results.clear)

Expand Down
110 changes: 110 additions & 0 deletions biscuit/core/components/views/sidebar/github/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import os
import threading
import tkinter as tk

from biscuit.core.components.floating.palette import ActionSet
from biscuit.core.utils import WrappingLabel

from ..sidebarview import SidebarView
from .issues import Issues
from .menu import GitHubMenu
from .prs import PRs


class GitHub(SidebarView):
def __init__(self, master, *args, **kwargs) -> None:
self.__buttons__ = [('refresh', self.on_directory_change)]
super().__init__(master, *args, **kwargs)
self.__icon__ = 'github'
self.name = 'GitHub'

self.menu = GitHubMenu(self, 'files')
self.menu.add_checkable("Open Issues", self.toggle_issues, checked=True)
self.menu.add_checkable("Pull Requests", self.toggle_prs, checked=True)
self.add_button('ellipsis', self.menu.show)

self.issues_enabled = True
self.prs_enabled = True

self.git = self.base.git
self.issues = Issues(self)
self.prs = PRs(self)

self.placeholder = WrappingLabel(self, text="Open a GitHub repository to see issues & pull requests.", font=self.base.settings.uifont,
**self.base.theme.utils.label)
self.placeholder.pack(fill=tk.X, side=tk.TOP)

self.base.bind("<<DirectoryChanged>>", self.on_directory_change, add=True)

def on_directory_change(self, e) -> None:
"""Event handler for directory change event."""

if not (self.base.active_directory and self.base.git_found):
self.show_placeholder("Open a GitHub repository to see issues & pull requests.")
return

repo = self.git.repo
remote = repo.get_remote_origin()
if not remote:
self.base.notifications.info("No remote found.")
self.show_placeholder("No remote found.")
return

if not "github.com" in remote.url:
self.base.notifications.info("Remote is not a GitHub repository.")
self.show_placeholder("Remote is not a GitHub repository.")
return

try:
owner, repo_name = repo.get_owner_and_repo(remote.url)
self.issues.set_url(owner, repo_name)
self.prs.set_url(owner, repo_name)
except Exception as e:
self.base.notifications.error(f"Failed to fetch remote info.")
self.base.logger.error(f"Failed to fetch remote info: {e}")
self.show_placeholder("Failed to fetch remote info.")
return

self.show_content()
threading.Thread(target=self.fetch_issues_and_prs, daemon=True).start()

def fetch_issues_and_prs(self) -> None:
"""Fetches issues and PRs from the current repository."""

self.issues.fetch()
self.prs.fetch()

def show_placeholder(self, text: str) -> None:
"""Adds a placeholder label to the view."""

self.issues.pack_forget()
self.prs.pack_forget()
self.placeholder.config(text=text)
self.placeholder.pack(fill=tk.X, side=tk.TOP)

def show_content(self) -> None:
"""Shows the content of the view."""

self.placeholder.pack_forget()
if self.issues_enabled:
self.issues.pack(fill=tk.BOTH, expand=True)
if self.prs_enabled:
self.prs.pack(fill=tk.BOTH, expand=True)

def toggle_issues(self) -> None:
"""Toggles the visibility of the issues view."""

if self.issues_enabled:
self.issues.pack_forget()
else:
self.issues.pack(fill=tk.BOTH, expand=True)
self.issues_enabled = not self.issues_enabled

def toggle_prs(self) -> None:
"""Toggles the visibility of the PRs view."""

if self.prs_enabled:
self.prs.pack_forget()
else:
self.prs.pack(fill=tk.BOTH, expand=True)
self.prs_enabled = not self.prs_enabled
72 changes: 72 additions & 0 deletions biscuit/core/components/views/sidebar/github/issues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import json
import tkinter as tk
import typing
import webbrowser
from tkinter import ttk

import requests

from biscuit.core.components.floating.palette.actionset import ActionSet
from biscuit.core.utils.scrollbar import Scrollbar

from ..item import SidebarViewItem


class Issues(SidebarViewItem):
def __init__(self, master, itembar=True, *args, **kwargs) -> None:
self.title = 'Open Issues'
self.__buttons__ = ()
super().__init__(master, itembar=itembar, *args, **kwargs)

self.url_template = "https://api.github.com/repos/{}/{}/issues"
self.url = None
self.owner = None
self.repo = None

self.tree = ttk.Treeview(self.content, selectmode=tk.BROWSE,
show="tree", displaycolumns='', columns=("link"))
self.tree.grid(row=0, column=0, sticky=tk.NSEW)
self.tree.bind("<Double-Button-1>", self.on_click)

self.scrollbar = Scrollbar(self.content, style='TreeScrollbar', orient=tk.VERTICAL, command=self.tree.yview)
self.scrollbar.grid(row=0, column=1, sticky=tk.NS)
self.tree.config(yscrollcommand=self.scrollbar.set)

self.issues_actionset = ActionSet("Search GitHub issues", "issue:", [])
self.base.palette.register_actionset(lambda: self.issues_actionset)

def set_url(self, owner: str, repo: str) -> None:
"""Sets the URL for the current repository."""

self.owner = owner
self.repo = repo
self.url = self.url_template.format(owner, repo)

def on_click(self, *_) -> None:
"""Event handler for treeview item click event."""

try:
item = self.tree.selection()[0]
link = self.tree.item(item, "values")[0]
webbrowser.open(link)
except Exception as e:
pass

def fetch(self) -> typing.List[dict]:
"""Fetches issues from the current repository."""

response = requests.get(self.url)
if response.status_code != 200:
self.base.notifications.error(f"Failed to fetch issues from {self.owner}/{self.repo}")
return

issues = json.loads(response.text)
if not issues:
return

self.issues_actionset.update([(f"{issue['title']} #{issue['number']}", lambda *_, link=issue['html_url']: webbrowser.open(link)) for issue in issues])
issues = ((f"{issue['title']} #{issue['number']}", issue['html_url']) for issue in issues)

self.tree.delete(*self.tree.get_children())
for issue in issues:
self.tree.insert('', tk.END, text=issue[0], values=(issue[1],))
6 changes: 6 additions & 0 deletions biscuit/core/components/views/sidebar/github/menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from biscuit.core.components.floating import Menu


class GitHubMenu(Menu):
def get_coords(self, e) -> list:
return e.widget.winfo_rootx(), e.widget.winfo_rooty() + e.widget.winfo_height()
Loading

0 comments on commit bf3bb6b

Please sign in to comment.