diff --git a/.editorconfig b/.editorconfig index f36951e..14a84bb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,9 +4,17 @@ root = true charset = utf-8 insert_final_newline = true -[*.py] +# Special file +[tktermwidget/term.py] indent_style = space indent_size = 4 end_of_line = lf trim_trailing_whitespace = true max_line_length = 125 + +[tktermwidget/__init__.py] +indent_style = space +indent_size = 4 +end_of_line = lf +trim_trailing_whitespace = true +max_line_length = 88 diff --git a/README.md b/README.md index 5b96ef0..ea3fca1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ -# `tkterm` - -> A terminal emulator written in Python using tkinter +# TkTerminal +A terminal emulator written in Python using tkinter ## Views: ### Windows @@ -56,6 +55,3 @@ root.mainloop() ```batch pip install tktermwidget ``` - -### Coming soon - diff --git a/setup.py b/setup.py index f23ac03..3810bc5 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="tktermwidget", - version="0.0.2", + version="0.0.3", description="A terminal emulator for Tkinter", long_description=long_description, long_description_content_type="text/markdown", diff --git a/tktermwidget/tkterm.py b/tktermwidget/tkterm.py index 4da5f75..7c7416c 100644 --- a/tktermwidget/tkterm.py +++ b/tktermwidget/tkterm.py @@ -1,3 +1,4 @@ +"""Terminal widget for tkinter""" from __future__ import annotations from os import getcwd @@ -10,7 +11,6 @@ from platformdirs import user_cache_dir # Set constants - HISTORY_PATH = Path(user_cache_dir("tkterm")) SYSTEM = system() CREATE_NEW_CONSOLE = 0 @@ -30,21 +30,18 @@ if not (HISTORY_PATH / "history.txt").exists(): open(HISTORY_PATH / "history.txt", "w").close() - class AutoHideScrollbar(Scrollbar): """Scrollbar that automatically hides when not needed""" def __init__(self, master=None, **kwargs): Scrollbar.__init__(self, master=master, **kwargs) - def set(self, length, height): - if float(length) <= 0.0 and float(height) >= 1.0: + def set(self, first: int, last: int): + if float(first) <= 0.0 and float(last) >= 1.0: self.grid_remove() else: self.grid() - - Scrollbar.set(self, length, height) - + Scrollbar.set(self, first, last) class Terminal(Frame): """A terminal widget for tkinter applications @@ -60,8 +57,10 @@ class Terminal(Frame): Methods for internal use: up (Event) -> str: Goes up in the history - down (Event) -> str: Goes down in the history (if the user is at the bottom of the history, it clears the command) - left (Event) -> str: Goes left in the command if the index is greater than the length of the directory (so the user can't delete the directory or go left of it) + down (Event) -> str: Goes down in the history + (if the user is at the bottom of the history, it clears the command) + left (Event) -> str: Goes left in the command if the index is greater than the length of the directory + (so the user can't delete the directory or go left of it) kill (Event) -> str: Kills the current command loop (Event) -> str: Runs the command typed""" @@ -104,13 +103,13 @@ def __init__(self, master: Misc, autohide: bool = True, *args, **kwargs): self.index = 1 self.current_process: Popen | None = None - # Bind events + # Bind events & tags self.text.bind("", self.up, add=True) self.text.bind("", self.down, add=True) self.text.bind("", self.left, add=True) self.text.bind("", self.loop, add=True) self.text.bind("", self.left, add=True) - + # TODO: Refactor the way we get output from subprocess self.text.bind("", self.kill, add=True) # Isn't working @@ -118,7 +117,8 @@ def __init__(self, master: Misc, autohide: bool = True, *args, **kwargs): self.history = open(HISTORY_PATH / "history.txt", "r+") self.historys = [i.strip() for i in self.history.readlines() if i.strip()] self.hi = len(self.historys) - 1 - + + def directory(self): """Insert the directory""" self.text.insert( @@ -171,15 +171,18 @@ def loop(self, _: Event) -> str: """Create an input loop""" cmd = self.text.get(f"{self.index}.0", "end-1c") # Determine command based on system - cmd = cmd.split("$")[-1] # Unix - if SYSTEM == "Windows": - cmd = cmd.split(">")[-1].strip() + cmd = cmd.split("$")[-1].strip() if not SYSTEM == "Windows" else cmd.split(">")[-1].strip() # Record the command if cmd != "": self.history.write(cmd + "\n") self.historys.append(cmd) self.hi = len(self.historys) - 1 + else: + self.text.insert("insert", "\n") + self.index += 1 + self.directory() + return "break" # Check that the insert position is at the end if self.text.index("insert") != f"{self.index}.end": @@ -199,23 +202,25 @@ def loop(self, _: Event) -> str: stderr=PIPE, stdin=PIPE, text=True, - cwd=getcwd(), # Until a solution for changing the working directory is found, this will have to do + cwd=getcwd(), # Until a solution for changing the working directory is found, this will have to do creationflags=CREATE_NEW_CONSOLE, - ) # The following needs to be put in an after so the kill command works and the program doesn't freeze + ) + # The following needs to be put in an after so the kill command works and the program doesn't freeze + # Check if the command was successful - returncode = self.current_process.wait() - process = self.current_process + returnlines, errors, = self.current_process.communicate() + returncode = self.current_process.returncode self.current_process = None - returnlines = process.stdout.readlines() if returncode != 0: - returnlines += process.stderr.readlines() # If the command was unsuccessful, it doesn't give stdout + returnlines += errors # If the command was unsuccessful, it doesn't give stdout # TODO: Get the success message from the command (see #16) self.text.insert("insert", "\n") self.index += 1 for line in returnlines: self.text.insert("insert", line) - self.index += 1 + if line == "\n": + self.index += 1 self.directory() return "break" # Prevent the default newline character insertion