From 4e08eac9a0e596e1ab9496915e3e9793acf9a2c6 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Mon, 26 Aug 2024 19:36:45 +0700
Subject: [PATCH 01/18] Update supernano.py
---
supernano.py | 1217 +++++++++++++++-----------------------------------
1 file changed, 353 insertions(+), 864 deletions(-)
diff --git a/supernano.py b/supernano.py
index 88a9fd6..44ad4a8 100644
--- a/supernano.py
+++ b/supernano.py
@@ -1,88 +1,42 @@
-import urwid
-import pyperclip
-import os, sys, shutil, logging, time, threading, argparse
+import py_cui
+import os, sys, time, argparse, logging
+from typing import List, Tuple, Any
from datetime import datetime
-
+from string import ascii_letters, punctuation
try:
- from libs.helperegex import findpositions
- from libs.titlecommand import get_console_title, set_console_title
- from libs.cmd_filter import shorten_path, validate_folder
- from libs.errrorHandler import complex_handle_errors
- from libs.system_manajemen import set_low_priority, SafeProcessExecutor
- from libs.timeout import timeout_v2, timeout_v1
- from libs.filemanager import (
- StreamFile,
- ModuleInspector,
- create_file_or_folder,
- resolve_relative_path_v2,
- all_system_paths,
- )
+ from .titlecommand import get_console_title, set_console_title
+ from .cmd_filter import shorten_path, validate_folder
+ from .errrorHandler import complex_handle_errors
+ from .system_manajemen import set_low_priority, SafeProcessExecutor
+ from .timeout import timeout_v2
+ from .filemanager import StreamFile
except:
try:
- from .helperegex import findpositions
- from .titlecommand import get_console_title, set_console_title
- from .cmd_filter import shorten_path, validate_folder
- from .errrorHandler import complex_handle_errors
- from .system_manajemen import set_low_priority, SafeProcessExecutor
- from .timeout import timeout_v2, timeout_v1
- from .filemanager import (
- StreamFile,
- ModuleInspector,
- create_file_or_folder,
- resolve_relative_path_v2,
- all_system_paths,
- )
- except:
- from helperegex import findpositions
from titlecommand import get_console_title, set_console_title
from cmd_filter import shorten_path, validate_folder
from errrorHandler import complex_handle_errors
from system_manajemen import set_low_priority, SafeProcessExecutor
- from timeout import timeout_v2, timeout_v1
- from filemanager import (
- StreamFile,
- ModuleInspector,
- create_file_or_folder,
- resolve_relative_path_v2,
- all_system_paths,
- )
-
+ from timeout import timeout_v2
+ from filemanager import StreamFile
+ except:
+ from libs.titlecommand import get_console_title, set_console_title
+ from libs.cmd_filter import shorten_path, validate_folder
+ from libs.errrorHandler import complex_handle_errors
+ from libs.system_manajemen import set_low_priority, SafeProcessExecutor
+ from libs.filemanager import StreamFile
+ from libs.timeout import timeout_v2
set_low_priority(os.getpid())
#########mendapatkan process terbaik tanpa membebani ram dan cpu
-thisfolder, _x = all_system_paths
-__version__ = "2.1.0"
-
-fileloogiing = os.path.join(thisfolder, "cache", "file_browser.log").replace("\\", "/")
-if not os.path.isfile(fileloogiing):
- open(fileloogiing, "a+")
-elif os.path.getsize(fileloogiing) > 0:
- with open(fileloogiing, "wb+") as f:
- f.truncate(0)
-
-for handler in logging.root.handlers[:]:
- logging.root.removeHandler(handler)
+__version__ = "1.0.0"
logging.basicConfig(
- filename=fileloogiing,
- filemode="w",
- encoding=sys.getfilesystemencoding(),
- format="%(asctime)s, %(msecs)d %(name)s %(levelname)s [ %(filename)s-%(module)s-%(lineno)d ] : %(message)s",
- datefmt="%H:%M:%S",
- level=logging.ERROR,
+ level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s"
)
-logging.getLogger("urwid").disabled = True
-logger = logging.getLogger("urwid")
-for handler in logger.handlers[:]:
- logger.removeHandler(handler)
def setTitle(title: str):
- """
- Fungsi setTitle bertugas untuk mengatur judul konsol (console title) berdasarkan parameter title yang diberikan.\n
- Jika inputan title memiliki panjang lebih dari 30 karakter maka potong karakternya
- """
process = title
Getitles = get_console_title()
if os.path.isdir(process) or os.path.isfile(process):
@@ -104,841 +58,376 @@ def setTitle(title: str):
output = title
set_console_title(output)
-
-@complex_handle_errors(loggering=logging, nomessagesNormal=False)
-def parse_args():
- """
- Fungsi parse_args bertugas untuk mendapatkan\menangkap argument konsol (console title) yang diberikan oleh user.\n
- """
- parser = argparse.ArgumentParser(
- description="An extension on nano for editing directories in CLI."
- )
- parser.add_argument(
- "path",
- default=os.path.split(thisfolder)[0],
- nargs="?",
- type=str,
- help="Target file or directory to edit.",
- )
- args = vars(parser.parse_args())
- path = args.get("path", ".").strip().replace("\\", "/")
- if os.path.exists(path):
- if validate_folder(path=path):
- pass
- else:
- logging.error(f"ERROR - {path} path cannot access")
- exit()
- else:
- logging.error(f"ERROR - {path} path does not exist")
- exit()
-
- return resolve_relative_path_v2(path).replace("\\", "/")
-
-
-class PlainButton(urwid.Button):
- """
- Class PlainButton bertugas untuk mengkoustomisasi button dan menghilangkan karakter < dan >.\n
- """
-
- button_left = urwid.Text("")
- button_right = urwid.Text("")
-
-
-class EditableButton(urwid.WidgetWrap):
- def __init__(self, label, on_save):
- self.label = label
- self.on_save = on_save
- self.button = PlainButton(label)
- self.last_click_time = 0
- urwid.connect_signal(self.button, "click", self.on_click)
- self._w = self.button
-
- def on_click(self, button):
- current_time = time.time()
- # Check for double click within 0.3 seconds
- if current_time - self.last_click_time < 0.3:
- self.edit_text(button)
- self.last_click_time = current_time
-
- def edit_text(self, button):
- self.edit = urwid.Edit(multiline=False, edit_text=self.label)
- urwid.connect_signal(self.edit, "change", self.on_change)
- self._w = urwid.AttrMap(self.edit, None, focus_map="reversed")
-
- def on_change(self, edit, new_text):
- self.label = new_text
-
- def keypress(self, size, key):
- if isinstance(self._w.base_widget, urwid.Edit):
- if key == "enter":
- self.save_and_restore()
- else:
- return self._w.keypress(size, key)
- else:
- return super().keypress(size, key)
-
- def save_and_restore(self):
- self.on_save(self.label)
- self.button = PlainButton(self.label)
- urwid.connect_signal(self.button, "click", self.on_click)
- self._w = self.button
-
-
-class ClipboardTextBox(urwid.Edit):
- def keypress(self, size, key):
- if key == "ctrl c":
- self.copy_to_clipboard()
- elif key == "ctrl v":
- self.paste_from_clipboard()
- else:
- return super().keypress(size, key)
-
- def copy_to_clipboard(self):
- self.clipboard = self.get_edit_text()
-
- def paste_from_clipboard(self):
- if hasattr(self, "clipboard"):
- cursor_pos = self.edit_pos
- text = self.get_edit_text()
- self.set_edit_text(text[:cursor_pos] + self.clipboard + text[cursor_pos:])
- self.edit_pos = cursor_pos + len(self.clipboard)
-
-
class SuperNano:
- """
- Kelas SuperNano yang sedang Anda kembangkan adalah text editor berbasis console yang menggunakan Python 3.6 ke atas dengan dukungan urwid[curses].
-
- Pembuat: Ramsyan Tungga Kiansantang (ID) | Github: LcfherShell
-
- Tanggal dibuat: 21 Agustus 2024
-
- Jika ada bug silahkan kunjungi git yang telah tertera diatas
- """
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def __init__(self, start_path="."):
- "Mengatur path awal, judul aplikasi, widget, dan layout utama. Juga mengatur alarm untuk memuat menu utama dan memulai loop aplikasi."
- self.current_path = start_path
- self.current_pathx = self.current_path
+ def __init__(self, root: py_cui.PyCUI, path):
+ self.root = root
+ self.path = path
+ # Confirmation message
+ self.confirmation_popup = None
+ self.prev_dir_stack: List[str] = []
+
+ # Set Title Window Console
+ setTitle("Win-SuperNano")
+
+ # Determine if path is a file or directory
+ if os.path.isfile(self.path):
+ self.dir = os.path.dirname(self.path)
+ self.file_to_open = os.path.basename(self.path)
+ else:
+ self.dir = self.path
+ self.file_to_open = None
- self.current_file_name = None # Track current file name
- self.undo_stack, self.redo_stack = [[], []] # Stack for undo # Stack for redo
- self.overlay_POPUP = None # Overlay untuk popup
- self.module_package_Python = ModuleInspector() # memuat module python
+ # Initialize undo stack
+ self.undo_stack: List[Tuple[str, int, Any]] = []
- # Set title
- setTitle("Win-SuperNano v{version}".format(version=__version__))
+ # Key bindings
+ self.root.add_key_command(py_cui.keys.KEY_CTRL_S, self.save_opened_file)
+ self.root.add_key_command(py_cui.keys.KEY_CTRL_D, self.delete_selected_file)
+ self.root.add_key_command(py_cui.keys.KEY_CTRL_Z, self.undo_last_edit)
- # Create widgets
- """
- 1.loading menu
- 2. main menu: search, list file or folder, and inspect module python
- """
-
- ######Create widgets modulepython menu
- def create_button(module_name):
- button = PlainButton(module_name)
- urwid.connect_signal(button, "click", self.inspect_module, module_name)
- return urwid.AttrMap(button, None, focus_map="reversed")
-
- self.listmodules_from_package_Python = urwid.SimpleFocusListWalker(
- [
- create_button(module)
- for module in self.module_package_Python.get_module(sys.path)
- ]
+ # File selection menu
+ self.file_menu = self.root.add_scroll_menu(
+ "Directory Files", 0, 0, row_span=5, column_span=2
)
- # Footer text and ListBox for scrolling
- self.Text_Deinspect_modules_from_package_Python = urwid.Text(
- "Select a module to inspect."
+ self.file_menu.add_key_command(py_cui.keys.KEY_ENTER, self.open_file_dir)
+ self.file_menu.add_key_command(
+ py_cui.keys.KEY_DELETE, self.delete_selected_file
)
- MenuText_Inspect_modules_from_package_Python = urwid.ListBox(
- urwid.SimpleFocusListWalker(
- [self.Text_Deinspect_modules_from_package_Python]
- )
+ self.file_menu.add_text_color_rule(
+ "
",
+ py_cui.GREEN_ON_BLACK,
+ "startswith",
+ match_type="region",
+ region=[5, 1000],
)
- Box_Deinspect_modules_from_package_Python = urwid.BoxAdapter(
- MenuText_Inspect_modules_from_package_Python, 14
- ) # Set max height for the footer
- # Use a Frame to wrap the main content and footer
- self.Inspect_modules_from_package_Python = urwid.Frame(
- body=urwid.LineBox(
- urwid.ListBox(self.listmodules_from_package_Python),
- title="Python Modules",
- ),
- footer=Box_Deinspect_modules_from_package_Python,
+ self.file_menu.set_color(py_cui.WHITE_ON_BLACK)
+
+ # Search box
+ self.search_box = self.root.add_text_box("Search", 5, 0, column_span=2)
+ self.search_box.add_key_command(py_cui.keys.KEY_ENTER, self.search_files)
+ self.search_box.set_color(py_cui.WHITE_ON_BLACK)
+ self.search_box.set_focus_text('Press Enter')
+ #self.search_box. ('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")[]')
+
+ # Delete button
+ self.delete_button = self.root.add_button(
+ "Delete Selected File",
+ 6,
+ 0,
+ column_span=2,
+ command=self.delete_selected_file,
)
+ self.delete_button.set_color(py_cui.WHITE_ON_BLACK)
+ self.delete_button.set_focus_text('Press Enter')
- ###Create widgets loading menu
- self.title_loading_widget = urwid.Text(
- "Win-SuperNano v{version} CopyRight: LcfherShell@{year}\n".format(
- version=__version__, year=datetime.now().year
- ),
- align="center",
+ # Directory text box
+ self.current_dir_box = self.root.add_text_box(
+ "Current Directory", 7, 0, column_span=2
)
- self.loading_widget = urwid.Text("Loading, please wait...", align="center")
- self.main_layout = urwid.Filler(
- urwid.Pile([self.title_loading_widget, self.loading_widget]),
- valign="middle",
+ self.current_dir_box.set_text(self.dir)
+ self.current_dir_box.set_color(py_cui.WHITE_ON_BLACK)
+ self.current_dir_box.add_key_command(
+ py_cui.keys.KEY_ENTER, self.open_new_directory
)
- # Create main menu
- self.main_menu_columns = urwid.Columns([])
- self.main_menu_pile = urwid.Pile([self.main_menu_columns])
- self.status_msg_footer_text = urwid.Text(
- "Press ctrl + q to exit, Arrow keys to navigate"
- )
- self.main_footer_text = urwid.Text(
- "Ctrl+S : Save file Ctrl+D : Delete File Ctrl+Z : Undo Edit Ctrl+Y : Redo Edit Ctrl+E : Redirect input Ctrl+R : Refresh UI ESC: Quit "
+ # Text box for adding new files
+ self.new_file_textbox = self.root.add_text_block(
+ "Add New File", 8, 0, column_span=2
)
+ self.new_file_textbox.add_key_command(py_cui.keys.KEY_ENTER, self.add_new_file)
+ self.new_file_textbox.set_color(py_cui.WHITE_ON_BLACK)
+ self.new_file_textbox.set_focus_text('Press Enter')
- # Event loop
- self.loop = urwid.MainLoop(self.main_layout, unhandled_input=self.handle_input)
- self.loading_alarm = self.loop.set_alarm_in(
- round(timeout_v1() * timeout_v2(), 1) + 1,
- lambda loop, user_data: self.load_main_menu(),
+ # Main text block for editing text
+ self.edit_text_block = self.root.add_text_block(
+ "Open file", 0, 2, row_span=8, column_span=6
)
- self.system_alarm = None
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def load_main_menu(self):
- "Menyiapkan dan menampilkan menu utama setelah periode loading, dan menghapus alarm loading."
- # self.loading_widget.set_text("Press key R")
- set_low_priority(os.getpid())
- self.loop.remove_alarm(self.loading_alarm) # Hentikan alarm
- self.loading_alarm = None
- self.switch_to_secondary_layout()
-
- def switch_to_secondary_layout(self):
- "Mengubah layout aplikasi ke menu utama yang telah disiapkan."
- self.setup_main_menu()
- if self.loading_alarm != None:
- self.loop.remove_alarm(
- self.loading_alarm
- ) # Hentikan alarm loading jika masih ada
- self.loading_alarm = None
- self.loop.widget = self.main_layout
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def setup_main_menu(self):
- "Menyiapkan dan mengatur widget untuk menu utama, termasuk daftar file, editor teks, dan tombol-tombol fungsional. Mengatur layout untuk tampilan aplikasi."
- # Define widgets
- self.file_list = urwid.SimpleFocusListWalker(self.get_file_list())
- self.file_list_box = urwid.ListBox(self.file_list)
- self.text_editor = urwid.Edit(multiline=True)
- self.current_focus = 0 # 0 for textbox1, 1 for textbox2
- # Wrap text_editor with BoxAdapter for scrollable content
- self.text_editor_scrollable = urwid.LineBox(
- urwid.Filler(self.text_editor, valign="top")
+ self.edit_text_block.set_focus_text('Save - Ctrl + S')
+ self.edit_text_block.set_color(py_cui.WHITE_ON_BLACK)
+
+ # Footer Text
+ self.footer = self.root.add_label(
+ "Ctrl+S : Save file Ctrl+D : Delete File Ctr+Z : Undo Edit",
+ 8,
+ 2,
+ column_span=6,
)
+ self.footer.set_color(py_cui.WHITE_ON_BLACK)
- # Define menu widgets
- self.quit_button = PlainButton("Quit", align="center")
- urwid.connect_signal(self.quit_button, "click", self.quit_app)
+ # Open initial directory
+ self.open_new_directory()
- self.search_edit = urwid.Edit(
- "Search, Rename or Create: ", multiline=False, align="left"
- )
- search_limited = urwid.BoxAdapter(
- urwid.Filler(self.search_edit, valign="top"), height=1
- )
-
- self.search_button = PlainButton("Execute", align="center")
- urwid.connect_signal(self.search_button, "click", self.in_search_)
+ # If initial path was a file, open it
+ if self.file_to_open:
+ self.open_file_dir(self.file_to_open)
- padded_button = urwid.Padding(
- self.search_button, align="center", width=("relative", 50)
- ) # Tombol berada di tengah dengan lebar 50% dari total layar
- padded_button = urwid.AttrMap(
- padded_button, None, focus_map="reversed"
- ) # Mengatur warna saat tombol difokuskan
-
- urwid.connect_signal(
- self.text_editor.base_widget, "change", self.set_focus_on_click, 0
- )
- urwid.connect_signal(
- self.search_edit.base_widget, "change", self.set_focus_on_click, 1
- )
-
- # Menu layout
- self.main_menu_columns = urwid.Columns(
- [
- (
- "weight",
- 3,
- urwid.AttrMap(search_limited, None, focus_map="reversed"),
- ),
- (
- "weight",
- 1,
- urwid.AttrMap(padded_button, None, focus_map="reversed"),
- ),
- (
- "weight",
- 2,
- urwid.AttrMap(self.quit_button, None, focus_map="reversed"),
- ),
- # (
- # "weight",
- # 4,
- # urwid.AttrMap(urwid.Pile(menu_items), None, focus_map="reversed"),
- # ),
- ]
- )
+ @complex_handle_errors()
+ def save_current_state(self):
+ """
+ Save the current state of the text block for undo functionality.
+ """
+ current_text = self.edit_text_block.get()
+ if not self.undo_stack or self.undo_stack[-1] != current_text:
+ self.undo_stack.append(current_text)
- self.main_menu_pile = urwid.Pile([self.main_menu_columns])
-
- # Layout
- self.main_layout = urwid.Frame(
- header=self.main_menu_pile,
- body=urwid.Columns(
- [
- (
- "weight",
- 1,
- urwid.LineBox(self.file_list_box, title="Directory Files"),
- ),
- (
- "weight",
- 1,
- urwid.AttrMap(
- self.Inspect_modules_from_package_Python,
- None,
- focus_map="reversed",
- ),
- ),
- (
- "weight",
- 3,
- urwid.LineBox(
- urwid.Pile([self.text_editor_scrollable]), title="TextBox"
- ),
- ),
- ]
- ),
- footer=urwid.Pile([self.status_msg_footer_text, self.main_footer_text]),
- )
- self.loop.set_alarm_in(timeout_v2(), self.update_uiV2)
- self.system_alarm = self.loop.set_alarm_in(
- timeout_v2() + 1,
- lambda loop, user_data: self.system_usage(),
- )
- urwid.TrustedLoop(self.loop).set_widget(self.main_layout)
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def create_modules_menus(self, listmodulename: list):
- def create_button(module_name):
- button = PlainButton(module_name)
- urwid.connect_signal(button, "click", self.inspect_module, module_name)
- return urwid.AttrMap(button, None, focus_map="reversed")
-
- return [create_button(module) for module in listmodulename]
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def inspect_module(self, button, module_name):
- result = self.module_package_Python.inspect_module(module_name)
- if result:
- result_text = f"Module: {result['module']}\n\nGlobal Variables:\n"
- result_text += "\n".join(result["global_variables"]) + "\n\nClasses:\n"
- for cls in result["classes"]:
- result_text += f"Class: {cls['name']}\n"
- result_text += " Variables:\n"
- result_text += " " + "\n > ".join(cls["variables"]) + "\n\n"
- result_text += " Functions:\n"
- for func in cls["functions"]:
- result_text += f" > {func['name']}{func['params']}\n\n"
- self.Text_Deinspect_modules_from_package_Python.set_text(result_text)
- else:
- self.Text_Deinspect_modules_from_package_Python.set_text(
- "Error inspecting module."
+ @complex_handle_errors()
+ def undo_last_edit(self):
+ """
+ Undo the last edit by reverting to the previous state.
+ """
+ if self.undo_stack:
+ self.undo_stack.pop() # Remove current state
+ if self.undo_stack:
+ last_state = self.undo_stack[-1] # Get the previous state
+ self.edit_text_block.set_text(last_state)
+
+ @complex_handle_errors()
+ def open_new_directory(self):
+ """
+ Open and list the contents of a new directory.
+ """
+ target = self.current_dir_box.get()
+ if not target:
+ target = "."
+ elif not os.path.exists(target):
+ self.root.show_error_popup(
+ "Does not exist", f"ERROR - {target} path does not exist"
)
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def setup_popup(self, options, title, descrip: str = ""):
- "Menyiapkan konten dan layout untuk menu popup dengan judul, deskripsi, dan opsi yang diberikan."
- # Konten popup
- menu_items = []
- if descrip:
- menu_items = [urwid.Text(descrip, align="center"), urwid.Divider("-")]
-
- # Tambahkan opsi ke dalam menu popup
- for option in options:
- menu_items.append(option)
-
- # Tambahkan tombol untuk menutup popup
- menu_items.append(PlainButton("Close", on_press=self.close_popup))
-
- # Buat listbox dari opsi yang sudah ada
- popup_content = urwid.ListBox(urwid.SimpleFocusListWalker(menu_items))
-
- # Tambahkan border dengan judul
- self.popup = urwid.LineBox(popup_content, title=title)
-
- def on_option_selected(self, button):
- "Menangani pilihan opsi dari popup dengan menutup popup dan mengembalikan label opsi yang dipilih."
- urwid.emit_signal(button, "click")
- getbutton = button.get_label()
- self.close_popup(None)
- return getbutton
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def show_popup(self, title: str, descrip: str, menus: list):
- "Menampilkan popup menu dengan judul, deskripsi, dan daftar opsi yang diberikan."
- # Siapkan popup dengan judul, descrip, dan opsi
- self.setup_popup(title=title, descrip=descrip, options=menus)
-
- # Tentukan ukuran dan posisi popup
- popup_width = 35
- popup_height = 25
- self.overlay_POPUP = urwid.Overlay(
- self.popup,
- self.main_layout,
- "center",
- ("relative", popup_width),
- "middle",
- ("relative", popup_height),
- )
- self.loop.widget = self.overlay_POPUP
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def close_popup(self, button):
- "Menutup popup menu dan mengembalikan tampilan ke layout utama."
- self.overlay_POPUP = None
- self.loop.widget = self.main_layout
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def get_file_list(self):
- "Mengambil daftar file dan direktori di path saat ini, termasuk opsi untuk naik satu level di direktori jika bukan di direktori root."
- files = []
- if self.current_path != ".": # Cek apakah bukan di direktori root
- button = PlainButton("...")
- urwid.connect_signal(button, "click", self.go_up_directory)
- files.append(urwid.AttrMap(button, None, focus_map="reversed"))
-
- for f in os.listdir(self.current_path):
- if os.path.isdir(os.path.join(self.current_path, f)):
- f = f + "/"
- button = PlainButton(f)
- urwid.connect_signal(button, "click", self.open_file, f)
- files.append(urwid.AttrMap(button, None, focus_map="reversed"))
- return files
-
- def handle_input(self, key):
- "Menangani input keyboard dari pengguna untuk berbagai tindakan seperti keluar, menyimpan, menghapus, undo, redo, copy, paste, dan refresh UI."
- if key in ("ctrl q", "ctrl Q", "esc"):
- self.show_popup(
- menus=[PlainButton("OK", on_press=lambda _x: self.quit_app())],
- title="Confirm Quit",
- descrip="Are you sure you Quit",
+ return
+ elif not os.path.isdir(target):
+ self.root.show_error_popup(
+ "Not a Dir", f"ERROR - {target} is not a directory"
)
-
- elif key in ("ctrl s", "ctrl S"):
- # self.save_file()
- self.show_popup(
- menus=[
- PlainButton(
- "OK",
- on_press=lambda _x: self.close_popup(None)
- if self.save_file()
- else None,
- )
- ],
- title="Save File",
- descrip="Are you sure you want to save the file changes",
+ return
+
+ # Update previous directory stack and set the new directory
+ if self.dir != target:
+ self.prev_dir_stack.append(self.dir)
+ self.dir = target
+
+ target = os.path.abspath(target)
+ self.current_dir_box.set_text(target)
+
+ files = (
+ [" .."] if self.prev_dir_stack else []
+ ) # Add ".." only if we have a previous directory
+ dir_contents = os.listdir(self.dir)
+ for elem in dir_contents:
+ if os.path.isfile(os.path.join(self.dir, elem)):
+ if validate_folder(path=os.path.join(self.dir, elem)):
+ files.append(elem)
+ else:
+ if validate_folder(path=os.path.join(self.dir, elem)):
+ files.append(" " + elem)
+
+ self.file_menu.clear()
+ self.file_menu.add_item_list(files)
+
+ @complex_handle_errors()
+ def add_new_file(self):
+ """
+ Add a new file to the file menu.
+ """
+ new_file_name = self.new_file_textbox.get().strip()
+ if not new_file_name:
+ self.root.show_error_popup(
+ "Invalid File Name", "Please enter a valid file name."
)
+ return
+
+ self.file_menu.add_item(new_file_name)
+ self.file_menu.selected_item = len(self.file_menu.get_item_list()) - 1
+ self.new_file_textbox.set_selected(False)
+ self.root.set_selected_widget(self.edit_text_block.get_id())
+ self.edit_text_block.set_title(new_file_name)
+ self.edit_text_block.clear()
+ self.new_file_textbox.clear()
+ self.undo_stack.clear() # Clear undo stack when a new file is added
+
+ @complex_handle_errors()
+ def open_file_dir(self, filename=None):
+ """
+ Open a file or directory.
+ """
+ filename = filename or self.file_menu.get()
+ if filename.startswith(""):
+ if filename == " ..":
+ # Navigate back to the previous directory
+ if self.prev_dir_stack:
+ self.dir = self.prev_dir_stack.pop()
+ self.current_dir_box.set_text(self.dir)
+ self.open_new_directory()
+ else:
+ # Open the selected directory
+ new_dir = os.path.join(self.dir, filename[6:])
+ self.current_dir_box.set_text(new_dir)
+ self.open_new_directory()
+ else:
+ if validate_folder(path=os.path.join(self.dir, filename)):
+ try:
+ with open(os.path.join(self.dir, filename), "r+") as fp:
+ text = fp.read()
+ self.edit_text_block.set_text(text)
+ self.edit_text_block.set_title(filename)
+ self.undo_stack.clear() # Clear undo stack when a new file is opened
+ self.undo_stack.append(
+ text
+ ) # Add the initial state of the file to the undo stack
+ # Set Title Window Console
+ setTitle(os.path.join(self.dir, filename))
+ except Exception as e:
+ logging.error(f"Failed to open file {filename}: {e}")
+ self.root.show_warning_popup(
+ "Not a text file",
+ "The selected file could not be opened - not a text file",
+ )
+ else:
+ self.root.show_warning_popup(
+ "Not a text file",
+ "The selected file could not be opened - not a text file",
+ )
- elif key in ("ctrl d", "ctrl D"):
- self.show_popup(
- menus=[
- PlainButton(
- "OK",
- on_press=lambda _x: self.close_popup(None)
- if self.delete_file()
- else None,
+ @complex_handle_errors()
+ def save_opened_file(self):
+ """
+ Save the currently opened file.
+ """
+ if self.edit_text_block.get_title() != "Open file":
+ self.save_current_state() # Save the current state before saving
+ try:
+ if validate_folder(
+ path=os.path.join(self.dir, self.edit_text_block.get_title())
+ ):
+ with open(
+ os.path.join(self.dir, self.edit_text_block.get_title()), "w+"
+ ) as fp:
+ fp.write(self.edit_text_block.get())
+ self.root.show_message_popup(
+ "Saved",
+ f"Your file has been saved as {self.edit_text_block.get_title()}",
)
- ],
- title="Delete File",
- descrip="Are you sure you want to delete the file",
- )
- elif key in ("ctrl z", "ctrl Z"):
- self.undo_edit()
- elif key in ("ctrl y", "ctrl Y"):
- self.redo_edit()
- elif key in ("ctrl c", "ctrl C"):
- self.copy_text_to_clipboard()
- elif key in ("ctrl v", "ctrl V"):
- self.paste_text_from_clipboard()
- elif key in ("ctrl r", "ctrl R"):
- self.switch_to_secondary_layout()
- elif key in ("f1", "ctrl e", "ctrl E"):
- self.current_focus = 1 if self.current_focus == 0 else 0
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def get_current_edit(self):
- "Mengembalikan widget edit yang sedang difokuskan (text editor atau search edit)."
- if self.current_focus == 0:
- return self.text_editor.base_widget
- elif self.current_focus == 1:
- return self.search_edit.base_widget
- return None
-
- def set_focus_on_click(self, widget, new_edit_text, index):
- "Mengatur fokus pada widget edit berdasarkan klik dan indeks."
- self.current_focus = index
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def copy_text_to_clipboard(self):
- "Menyalin teks dari widget edit yang sedang aktif ke clipboard."
- current_edit = self.get_current_edit()
- if current_edit:
- if hasattr(current_edit, "edit_pos") and hasattr(
- current_edit, "get_edit_text"
- ):
- self.status_msg_footer_text.set_text("Text copied to clipboard.")
- cursor_position = current_edit.edit_pos
- pyperclip.copy(
- current_edit.get_edit_text()[cursor_position:]
- or current_edit.get_edit_text()
+ except Exception as e:
+ logging.error(
+ f"Failed to save file {self.edit_text_block.get_title()}: {e}"
)
+ self.root.show_error_popup("Save Error", "Failed to save the file.")
+ else:
+ self.root.show_error_popup(
+ "No File Opened", "Please open a file before saving it."
+ )
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def paste_text_from_clipboard(self):
- "Menempelkan teks dari clipboard ke widget edit yang sedang aktif."
- pasted_text = pyperclip.paste() # Mengambil teks dari clipboard
- current_edit = self.get_current_edit()
- if current_edit:
- if hasattr(current_edit, "edit_pos") and hasattr(
- current_edit, "get_edit_text"
+ @complex_handle_errors()
+ def delete_selected_file(self):
+ """
+ Delete the currently selected file.
+ """
+ if self.edit_text_block.get_title() != "Open file":
+ if validate_folder(
+ path=os.path.join(self.dir, self.edit_text_block.get_title())
):
- current_text = (
- current_edit.get_edit_text()
- ) # Mendapatkan teks saat ini di widget Edit
- cursor_position = (
- current_edit.edit_pos
- ) # Mendapatkan posisi kursor saat ini
-
- # Membagi teks berdasarkan posisi kursor
- text_before_cursor = current_text[:cursor_position]
- text_after_cursor = current_text[cursor_position:]
-
- # Gabungkan teks sebelum kursor, teks yang ditempelkan, dan teks setelah kursor
- new_text = text_before_cursor + pasted_text + text_after_cursor
-
- # Set teks baru dan sesuaikan posisi kursor
- current_edit.set_edit_text(new_text)
- current_edit.set_edit_pos(cursor_position + len(pasted_text))
- self.status_msg_footer_text.set_text("Text paste from clipboard.")
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def go_up_directory(self, button):
- "Naik satu level ke direktori atas dan memperbarui daftar file."
- self.current_path = os.path.dirname(self.current_path)
- self.file_list[:] = self.get_file_list()
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def open_file(self, button, file_name):
- "Membuka file yang dipilih, membaca isinya, dan menampilkannya di text editor. Jika itu adalah direktori, berpindah ke direktori tersebut."
- file_path = os.path.join(self.current_path, file_name)
- _c, ext = os.path.splitext(file_path)
- if os.path.isdir(file_path):
- if validate_folder(file_path):
- try:
- sys.path.remove(self.current_path)
- except:
- pass
- self.current_path = file_path
- self.file_list[:] = self.get_file_list()
- else:
- self.status_msg_footer_text.set_text("Folder access denied!")
+ self.root.show_yes_no_popup(
+ "Are you sure you want to delete this file?",
+ command=self.confirm_delete,
+ )
else:
- if validate_folder(os.path.dirname(file_path)):
- try:
- with open(
- file_path, "r+", encoding=sys.getfilesystemencoding()
- ) as f:
- content = f.read()
- except UnicodeDecodeError:
- with open(file_path, "r+", encoding="latin-1") as f:
- content = f.read()
- content = content.replace("\t", " " * 4)
- self.undo_stack.append(content)
- self.text_editor.set_edit_text(content)
- self.current_file_name = file_name # Track the current file name
-
- # if str(ext).lower() in ( ".pyx", ".pyz", ".py"):
- # self.listmodules_from_package_Python[:] = self.modules_menus(self.current_path)
-
- self.main_layout.body.contents[1][0].set_title(file_name)
+ self.root.show_error_popup(
+ "No File Opened", "Please open a file before deleting it."
+ )
- else:
- self.status_msg_footer_text.set_text("File access denied!")
+ @complex_handle_errors()
+ def confirm_delete(self, confirmed: bool):
+ """
+ Confirm the deletion of the file based on user response.
+ """
+ if confirmed:
+ try:
+ os.remove(os.path.join(self.dir, self.edit_text_block.get_title()))
+ self.edit_text_block.clear()
+ self.edit_text_block.set_title("Open file")
+ self.file_menu.remove_selected_item()
+ self.root.show_message_popup(
+ "Deleted", "The file has been successfully deleted."
+ )
+ except OSError as e:
+ logging.error(
+ f"Failed to delete file {self.edit_text_block.get_title()}: {e}"
+ )
+ self.root.show_error_popup(
+ "OS Error", "Operation could not be completed due to an OS error."
+ )
+ else:
+ self.root.show_message_popup(
+ "Delete Cancelled", "File deletion was cancelled."
+ )
- if str(ext).lower().startswith((".pyx", ".pyz", ".py")) != True:
- self.Text_Deinspect_modules_from_package_Python.set_text(
- "Select a module to inspect."
+ @complex_handle_errors()
+ def search_files(self):
+ """
+ Search for files in the directory that match the search query.
+ """
+ query = self.search_box.get().strip().lower()
+ if not query:
+ self.root.show_error_popup(
+ "Invalid Query", "Please enter a valid search query."
)
+ return
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def save_file(self):
- "Menyimpan perubahan yang dilakukan pada file saat ini dan mengembalikan status keberhasilan."
- if self.current_file_name:
- file_path = os.path.join(self.current_path, self.current_file_name)
- try:
- with open(file_path, "w+", encoding=sys.getfilesystemencoding()) as f:
- f.write(self.text_editor.get_edit_text())
- except:
- with open(file_path, "w+", encoding="latin-1") as f:
- f.write(self.text_editor.get_edit_text())
- self.status_msg_footer_text.set_text("File saved successfully!")
- return True
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def delete_file(self):
- "Menghapus file yang dipilih dan memperbarui daftar file serta text editor dan mengembalikan status keberhasilan."
- if self.current_file_name:
- file_path = os.path.join(self.current_path, self.current_file_name)
- if os.path.isfile(file_path):
- os.remove(file_path)
- self.text_editor.set_edit_text("")
- self.file_list[:] = self.get_file_list()
- self.status_msg_footer_text.set_text("File deleted successfully!")
- self.current_file_name = None # Clear the current file name
- else:
- self.status_msg_footer_text.set_text("File does not exist!")
- return True
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def save_undo_state(self):
- "Menyimpan status saat ini dari text editor ke stack undo dan mengosongkan stack redo."
- # Save the current content of the text editor for undo
- current_text = self.text_editor.get_edit_text()
- self.undo_stack.append(current_text)
- self.redo_stack.clear() # Clear redo stack on new change
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def undo_edit(self):
- "Melakukan undo terhadap perubahan terakhir pada text editor dengan mengembalikan status dari stack undo."
- if self.undo_stack:
- # Save the current state to redo stack
- self.redo_stack.append(self.text_editor.get_edit_text())
-
- # Restore the last state
- last_state = self.undo_stack.pop()
- self.text_editor.set_edit_text(last_state)
- self.status_msg_footer_text.set_text("Undo performed.")
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def redo_edit(self):
- "Melakukan redo terhadap perubahan terakhir yang diundo dengan mengembalikan status dari stack redo."
- if self.redo_stack:
- # Save the current state to undo stack
- self.undo_stack.append(self.text_editor.get_edit_text())
-
- # Restore the last redone state
- last_state = self.redo_stack.pop()
- self.text_editor.set_edit_text(last_state)
- self.status_msg_footer_text.set_text("Redo performed.")
-
- @complex_handle_errors(loggering=logging, nomessagesNormal=False)
- def highlight_text(self, search_text):
- text = self.text_editor.get_edit_text()
- result = []
- # Pisahkan teks menjadi sebelum, pencarian, dan sesudahnya
- for x in findpositions(f"{search_text}", text):
- if x:
- _x = list(x)
- result.append(str(_x[0][1][1]))
- if result.__len__() > 8:
- return "Total: {total} Pos: {posts}".format(
- total=result.__len__(), posts=", ".join(result[:8]) + "..."
+ matched_files = []
+ for item in self.file_menu.get_item_list():
+ if query in item.lower() and validate_folder(
+ path=os.path.join(self.dir, item.lower())
+ ):
+ matched_files.append(item)
+
+ if not matched_files:
+ self.root.show_error_popup(
+ "No Matches", "No files or directories match your search query."
)
- return "Total: {total} Pos: {posts}".format(
- total=result.__len__(), posts=", ".join(result)
- )
+ else:
+ self.file_menu.clear()
+ self.file_menu.add_item_list(matched_files)
- @complex_handle_errors(loggering=logging)
- def in_search_(self, button):
- "Mencari file atau folder berdasarkan input pencarian, membuka file jika ditemukan, atau memperbarui daftar file jika folder ditemukan."
- search_query = self.search_edit.get_edit_text().replace("\\", "/").strip()
- if search_query:
- if ":" in search_query and not search_query.startswith("@[select]"):
- if os.path.isfile(search_query):
- dirname, file_name = os.path.dirname(
- search_query
- ), os.path.basename(search_query)
- try:
- with open(search_query, "r+", encoding="utf-8") as f:
- content = f.read()
- except UnicodeDecodeError:
- with open(search_query, "r+", encoding="latin-1") as f:
- content = f.read()
- content = content.replace("\t", " " * 4)
-
- self.undo_stack.append(content)
- self.text_editor.set_edit_text(content)
- self.current_file_name = file_name # Track the current file name
- self.main_layout.body.contents[1][0].set_title(file_name)
-
- elif os.path.isdir(search_query):
- dirname = search_query
- else:
- x, _y = os.path.split(search_query)
- if self.current_path.replace("\\", "/") == x.replace(
- "\\", "/"
- ) and os.path.isdir(x):
- search_query = str(create_file_or_folder(search_query))
- self.update_ui()
- self.file_list[:] = self.get_file_list()
-
- dirname = None
-
- if dirname:
- self.current_path = dirname
- self.file_list[:] = self.get_file_list()
- self.status_msg_footer_text.set_text(
- f"Search results for '{search_query}'"
- )
- else:
- search_resultsFile = [
- f for f in os.listdir(self.current_path) if search_query in f
- ]
- search_resultsModule = [
- module
- for module in self.module_package_Python.curents
- if search_query in module
- ]
- search_resultsHighlight_Text = self.highlight_text(search_query)
-
- if search_resultsFile and search_resultsModule:
- self.listmodules_from_package_Python[:] = self.create_modules_menus(
- search_resultsModule
- )
- self.file_list[:] = self.create_file_list(search_resultsFile)
- self.status_msg_footer_text.set_text(
- f"Search results for '{search_query}'"
- )
- elif search_resultsFile:
- self.file_list[:] = self.create_file_list(search_resultsFile)
- self.status_msg_footer_text.set_text(
- f"Search results for '{search_query}'"
- )
- else:
- if search_resultsModule:
- self.listmodules_from_package_Python[
- :
- ] = self.create_modules_menus(search_resultsModule)
- self.file_list[:] = self.get_file_list()
- self.status_msg_footer_text.set_text(
- f"Search results for '{search_query}'"
- )
- elif search_resultsHighlight_Text and not search_query.startswith(
- "@[files]"
- ):
- self.status_msg_footer_text.set_text(
- f"Search results for '{search_query}' {search_resultsHighlight_Text}"
- )
- else:
- if (
- search_query.startswith("@[select]")
- and search_query.find("[@rename]") > -1
- ):
- x = search_query.replace("@[select]", "", 1).split(
- "[@rename]", 1
- )
- if x.__len__() == 2:
- getREName = [
- f
- for f in os.listdir(self.current_path)
- if x[0] in f
- ]
- if getREName.__len__() > 0:
- oldfilesorfolder, newplace = [
- os.path.join(self.current_path, getREName[0]),
- os.path.join(self.current_path, x[1]),
- ]
- try:
- os.rename(oldfilesorfolder, newplace)
- self.status_msg_footer_text.set_text(
- f"Rename {getREName[0]} success"
- )
- self.update_ui()
- self.file_list[:] = self.get_file_list()
- except:
- pass
- else:
- self.status_msg_footer_text.set_text(
- f"Search results for {search_query}"
- )
+@complex_handle_errors()
+def parse_args():
+ """
+ Parse command line arguments.
+ """
+ parser = argparse.ArgumentParser(
+ description="An extension on nano for editing directories in CLI."
+ )
+ parser.add_argument("path", help="Target file or directory to edit.")
+ args = vars(parser.parse_args())
+ path = args.get("path", ".").strip()
+ if os.path.exists(path):
+ if validate_folder(path=path):
+ pass
else:
- self.file_list[:] = self.get_file_list()
- self.listmodules_from_package_Python[:] = self.create_modules_menus(
- self.module_package_Python.curents
- )
- self.status_msg_footer_text.set_text("")
-
- @complex_handle_errors(loggering=logging)
- def create_file_list(self, files):
- "Membuat daftar widget untuk file yang ditemukan sesuai hasil pencarian."
- widgets = []
- for f in files:
- if os.path.isdir(os.path.join(self.current_path, f)):
- f = f + "/"
- button = PlainButton(f)
- urwid.connect_signal(button, "click", self.open_file, f)
- widgets.append(urwid.AttrMap(button, None, focus_map="reversed"))
- return widgets
-
- def system_usage(self):
- "Memantau penggunaan CPU dan menampilkan peringatan jika konsumsi CPU tinggi."
- timemming = timeout_v1()
- if timemming > 0.87:
- self.status_msg_footer_text.set_text("High CPU utilization alert")
-
- def update_ui(self):
- "Memperbarui tampilan UI aplikasi."
- self.loop.draw_screen()
-
- def update_uiV2(self, *args, **kwargs):
- "Memperbarui tampilan UI aplikasi."
- self.loop.set_alarm_in(timeout_v2(), self.update_uiV2)
- self.loop.draw_screen()
-
- def quit_app(self, button=None):
- "Menghentikan aplikasi dan menghapus alarm sistem jika ada."
- if self.system_alarm != None:
- self.loop.remove_alarm(self.system_alarm) # Hentikan alarm
- self.system_alarm = None
- raise urwid.ExitMainLoop()
-
- def run(self):
- "Memulai loop utama urwid untuk menjalankan aplikasi."
- self.loop.run()
-
-
-@complex_handle_errors(loggering=logging)
-def main(path: str):
- app = SuperNano(start_path=path)
- app.run()
+ logging.error(f"ERROR - {path} path cannot access")
+ exit()
+ else:
+ logging.error(f"ERROR - {path} path does not exist")
+ exit()
+ return path
-if __name__ == "__main__":
- set_low_priority(os.getpid())
- #########mendapatkan process terbaik tanpa membebani ram dan cpu
- safe_executor = SafeProcessExecutor(
- max_workers=2
- ) #########mendapatkan process terbaik tanpa membebani cpu
- safe_executor.submit(main, path=parse_args())
+def main():
+ path = parse_args()
+ # Initialize the PyCUI object, and set the title
+ root = py_cui.PyCUI(9, 8)
+ root.set_title(
+ f"Win-SuperNano v{__version__} CopyRight: LcfherShell@{datetime.now().year}"
+ )
+ # Create the wrapper instance object.
+ SuperNano(root, path)
+ # Start the CUI
+ root.start()
+
+if __name__ == "__main__":
+ safe_executor = SafeProcessExecutor(max_workers=2)
+ # Collect argument information
+ safe_executor.submit(main)
time.sleep(timeout_v2())
- safe_executor.shutdown(
- wait=True
- ) ###mmenunggu process benar-benar berhenti tanpa memaksanya
- rd = StreamFile(
- file_path=fileloogiing,
- buffer_size=os.path.getsize(fileloogiing) + 2,
- print_delay=timeout_v2(),
- ) #########mendapatkan process terbaik membaca file logging tanpa membebani cpu
- for r in rd.readlines():
- print(r)
- rd.eraseFile() # membersihkan loggging
- rd.close()
+ safe_executor.shutdown(wait=True)
+
From 63f7ef1ac2a893956a9e39390af27e5d4b1129b0 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Mon, 26 Aug 2024 19:38:21 +0700
Subject: [PATCH 02/18] Update supernano.py
---
supernano.py | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/supernano.py b/supernano.py
index 44ad4a8..fb00bb0 100644
--- a/supernano.py
+++ b/supernano.py
@@ -4,27 +4,29 @@
from datetime import datetime
from string import ascii_letters, punctuation
try:
- from .titlecommand import get_console_title, set_console_title
- from .cmd_filter import shorten_path, validate_folder
- from .errrorHandler import complex_handle_errors
- from .system_manajemen import set_low_priority, SafeProcessExecutor
- from .timeout import timeout_v2
- from .filemanager import StreamFile
+ from libs.titlecommand import get_console_title, set_console_title
+ from libs.cmd_filter import shorten_path, validate_folder
+ from libs.errrorHandler import complex_handle_errors
+ from libs.system_manajemen import set_low_priority, SafeProcessExecutor
+ from libs.filemanager import StreamFile
+ from libs.timeout import timeout_v2
+
except:
try:
+ from .titlecommand import get_console_title, set_console_title
+ from .cmd_filter import shorten_path, validate_folder
+ from .errrorHandler import complex_handle_errors
+ from .system_manajemen import set_low_priority, SafeProcessExecutor
+ from .timeout import timeout_v2
+ from .filemanager import StreamFile
+ except:
from titlecommand import get_console_title, set_console_title
from cmd_filter import shorten_path, validate_folder
from errrorHandler import complex_handle_errors
from system_manajemen import set_low_priority, SafeProcessExecutor
from timeout import timeout_v2
from filemanager import StreamFile
- except:
- from libs.titlecommand import get_console_title, set_console_title
- from libs.cmd_filter import shorten_path, validate_folder
- from libs.errrorHandler import complex_handle_errors
- from libs.system_manajemen import set_low_priority, SafeProcessExecutor
- from libs.filemanager import StreamFile
- from libs.timeout import timeout_v2
+
set_low_priority(os.getpid())
#########mendapatkan process terbaik tanpa membebani ram dan cpu
From 4d2c975375600ee8ead030d4f9f729c24b356874 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Mon, 26 Aug 2024 20:18:52 +0700
Subject: [PATCH 03/18] Update README.md
---
README.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 72 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index e10f8cd..48f71be 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,72 @@
-# SuperNano
-Ini adalah Aplikasi Text-Editor berbasis TUI
+Berikut adalah dokumentasi untuk script `SuperNano`, sebuah editor berbasis konsol yang ditulis menggunakan Python dengan modul `py_cui`. Editor ini menyediakan antarmuka untuk mengelola file dan direktori serta menyediakan fitur pengeditan teks dasar.
+
+---
+
+# Dokumentasi SuperNano
+
+## Deskripsi
+`SuperNano` adalah editor teks berbasis konsol yang memungkinkan pengguna untuk membuka, mengedit, menyimpan, dan menghapus file secara langsung dari antarmuka berbasis teks. Aplikasi ini juga menyediakan fitur edit file, navigasi direktori dan pencarian file.
+
+### Fitur Utama:
+- **Navigasi Direktori**: Menampilkan isi dari direktori dan memungkinkan navigasi antar direktori.
+- **Pengeditan Teks**: Memungkinkan pengeditan file teks dengan fitur undo.
+- **Penyimpanan File**: Menyimpan perubahan ke file yang dibuka.
+- **Penghapusan File**: Menghapus file yang dipilih.
+- **Pencarian File**: Mencari file atau direktori berdasarkan nama.
+
+## Struktur Kode
+Script ini dibagi menjadi beberapa bagian penting:
+1. **Imports**: Bagian ini mengimpor modul yang diperlukan untuk menjalankan aplikasi. Selain modul standar Python, script ini juga mengimpor beberapa modul khusus yang berfungsi untuk manajemen sistem, manajemen file, penanganan kesalahan, dan pengaturan waktu.
+
+2. **Konfigurasi Logging**: Mengatur logging untuk mencatat event atau kesalahan yang terjadi selama aplikasi berjalan.
+
+3. **Fungsi `setTitle`**: Fungsi ini digunakan untuk mengatur judul dari window konsol sesuai dengan path file atau direktori yang sedang dibuka.
+
+4. **Class `SuperNano`**: Class ini merupakan inti dari aplikasi yang mengatur berbagai fitur yang ada seperti membuka file, menyimpan file, menghapus file, navigasi direktori, dan lain-lain.
+
+5. **Fungsi `parse_args`**: Fungsi ini digunakan untuk memparsing argumen baris perintah yang menentukan file atau direktori target untuk diedit.
+
+6. **Fungsi `main`**: Fungsi utama yang menginisialisasi objek `PyCUI`, mengatur judul aplikasi, dan memulai antarmuka pengguna.
+
+7. **Safe Execution**: Menggunakan `SafeProcessExecutor` untuk menjalankan aplikasi dengan aman menggunakan thread.
+
+## Detail Implementasi
+
+### Class `SuperNano`
+Class ini menangani seluruh fungsionalitas aplikasi dan diinisialisasi dengan parameter `root` (objek `PyCUI`) dan `path` (path file atau direktori). Beberapa metode penting dalam class ini adalah:
+
+- **`__init__`**: Inisialisasi antarmuka dan menentukan apakah `path` adalah file atau direktori.
+- **`open_new_directory`**: Membuka dan menampilkan isi dari direktori baru.
+- **`open_file_dir`**: Membuka file atau navigasi ke direktori yang dipilih.
+- **`save_opened_file`**: Menyimpan file yang sedang dibuka.
+- **`delete_selected_file`**: Menghapus file yang dipilih.
+- **`search_files`**: Mencari file di dalam direktori berdasarkan input pencarian.
+
+### Fungsi `setTitle`
+Fungsi ini mengatur judul window konsol dengan nama file atau direktori yang sedang dibuka, dan menyesuaikan panjangnya agar tidak melebihi batas karakter tertentu.
+
+### Fungsi `parse_args`
+Fungsi ini digunakan untuk memproses argumen yang diberikan melalui command line. Argumen tersebut akan menentukan file atau direktori mana yang akan dibuka oleh `SuperNano`.
+
+### Safe Execution
+Penggunaan `SafeProcessExecutor` memastikan bahwa aplikasi berjalan dengan aman dan efisien, terutama saat menjalankan fungsi yang mungkin memakan waktu.
+
+## Cara Penggunaan
+Jalankan script ini melalui command line dengan memberikan argumen berupa path file atau direktori yang ingin diedit. Contoh:
+```
+python supernano.py /path/to/directory_or_file
+```
+
+## Lisensi
+Aplikasi ini dibuat oleh Ramsyan Tungga Kiansantang dan dilisensikan di bawah [Lisensi GPL v3](https://www.gnu.org/licenses/gpl-3.0.html). Untuk kontribusi atau pelaporan bug, silakan kunjungi repositori Github yang telah disediakan.
+
+## Versi
+- **Versi**: V1.0.0
+- **Tanggal Rilis**: 18 Juli 2024
+
+---
+
+## Kesimpulan
+`SuperNano` adalah editor teks berbasis konsol yang dirancang untuk memudahkan pengelolaan file dan direktori secara langsung dari command line. Aplikasi ini menawarkan alat yang ringan untuk pengguna yang bekerja di lingkungan berbasis teks.
+
+Jika ada pertanyaan atau butuh bantuan lebih lanjut terkait implementasi, jangan ragu untuk menghubungi pengembang atau melihat dokumentasi tambahan yang mungkin tersedia.
From 31be014750f1c82d06689407447941d32d09ab6c Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Mon, 26 Aug 2024 20:31:59 +0700
Subject: [PATCH 04/18] Update supernano.py
---
supernano.py | 43 +++++++++++++++++++++++++------------------
1 file changed, 25 insertions(+), 18 deletions(-)
diff --git a/supernano.py b/supernano.py
index fb00bb0..9e00f50 100644
--- a/supernano.py
+++ b/supernano.py
@@ -8,7 +8,7 @@
from libs.cmd_filter import shorten_path, validate_folder
from libs.errrorHandler import complex_handle_errors
from libs.system_manajemen import set_low_priority, SafeProcessExecutor
- from libs.filemanager import StreamFile
+ from libs.filemanager import StreamFile, all_system_paths, resolve_relative_path_v2
from libs.timeout import timeout_v2
except:
@@ -17,24 +17,25 @@
from .cmd_filter import shorten_path, validate_folder
from .errrorHandler import complex_handle_errors
from .system_manajemen import set_low_priority, SafeProcessExecutor
+ from .filemanager import StreamFile, all_system_paths, resolve_relative_path_v2
from .timeout import timeout_v2
- from .filemanager import StreamFile
except:
from titlecommand import get_console_title, set_console_title
from cmd_filter import shorten_path, validate_folder
from errrorHandler import complex_handle_errors
from system_manajemen import set_low_priority, SafeProcessExecutor
+ from filemanager import StreamFile, all_system_paths, resolve_relative_path_v2
from timeout import timeout_v2
- from filemanager import StreamFile
set_low_priority(os.getpid())
#########mendapatkan process terbaik tanpa membebani ram dan cpu
__version__ = "1.0.0"
+thisfolder, _x = all_system_paths
logging.basicConfig(
- level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s"
+ level=logging.ERROR, format="%(asctime)s - %(levelname)s - %(message)s"
)
@@ -163,7 +164,7 @@ def __init__(self, root: py_cui.PyCUI, path):
if self.file_to_open:
self.open_file_dir(self.file_to_open)
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def save_current_state(self):
"""
Save the current state of the text block for undo functionality.
@@ -172,7 +173,7 @@ def save_current_state(self):
if not self.undo_stack or self.undo_stack[-1] != current_text:
self.undo_stack.append(current_text)
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def undo_last_edit(self):
"""
Undo the last edit by reverting to the previous state.
@@ -183,7 +184,7 @@ def undo_last_edit(self):
last_state = self.undo_stack[-1] # Get the previous state
self.edit_text_block.set_text(last_state)
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def open_new_directory(self):
"""
Open and list the contents of a new directory.
@@ -225,7 +226,7 @@ def open_new_directory(self):
self.file_menu.clear()
self.file_menu.add_item_list(files)
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def add_new_file(self):
"""
Add a new file to the file menu.
@@ -246,7 +247,7 @@ def add_new_file(self):
self.new_file_textbox.clear()
self.undo_stack.clear() # Clear undo stack when a new file is added
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def open_file_dir(self, filename=None):
"""
Open a file or directory.
@@ -289,7 +290,7 @@ def open_file_dir(self, filename=None):
"The selected file could not be opened - not a text file",
)
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def save_opened_file(self):
"""
Save the currently opened file.
@@ -318,7 +319,7 @@ def save_opened_file(self):
"No File Opened", "Please open a file before saving it."
)
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def delete_selected_file(self):
"""
Delete the currently selected file.
@@ -336,7 +337,7 @@ def delete_selected_file(self):
"No File Opened", "Please open a file before deleting it."
)
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def confirm_delete(self, confirmed: bool):
"""
Confirm the deletion of the file based on user response.
@@ -362,7 +363,7 @@ def confirm_delete(self, confirmed: bool):
"Delete Cancelled", "File deletion was cancelled."
)
- @complex_handle_errors()
+ @complex_handle_errors(loggering=logging, nomessagesNormal=False)
def search_files(self):
"""
Search for files in the directory that match the search query.
@@ -390,17 +391,23 @@ def search_files(self):
self.file_menu.add_item_list(matched_files)
-@complex_handle_errors()
+@complex_handle_errors(loggering=logging, nomessagesNormal=False)
def parse_args():
"""
- Parse command line arguments.
+ Fungsi parse_args bertugas untuk mendapatkan\menangkap argument konsol (console title) yang diberikan oleh user.\n
"""
parser = argparse.ArgumentParser(
description="An extension on nano for editing directories in CLI."
)
- parser.add_argument("path", help="Target file or directory to edit.")
+ parser.add_argument(
+ "path",
+ default=os.path.split(thisfolder)[0],
+ nargs="?",
+ type=str,
+ help="Target file or directory to edit.",
+ )
args = vars(parser.parse_args())
- path = args.get("path", ".").strip()
+ path = args.get("path", ".").strip().replace("\\", "/")
if os.path.exists(path):
if validate_folder(path=path):
pass
@@ -411,7 +418,7 @@ def parse_args():
logging.error(f"ERROR - {path} path does not exist")
exit()
- return path
+ return resolve_relative_path_v2(path).replace("\\", "/")
def main():
From 293681f795100a3f1d5910f3bac21c8a02a5ebd7 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Mon, 26 Aug 2024 23:49:39 +0700
Subject: [PATCH 05/18] Create requirements.txt
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
requirements.txt | 6 ++++++
1 file changed, 6 insertions(+)
create mode 100644 requirements.txt
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..aae0a35
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+windows-curses==2.3.3
+py-cui==0.1.4
+pyperclip
+psutil
+logging
+httpx
From 71f578c27f4863265446500e32a0b1b13ec5da4e Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Fri, 30 Aug 2024 20:40:12 +0700
Subject: [PATCH 06/18] README.md
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 48f71be..2dfd94a 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+
+
Berikut adalah dokumentasi untuk script `SuperNano`, sebuah editor berbasis konsol yang ditulis menggunakan Python dengan modul `py_cui`. Editor ini menyediakan antarmuka untuk mengelola file dan direktori serta menyediakan fitur pengeditan teks dasar.
---
From 115f0f72a58b560c33058b1cb87a4654f2e5c8ff Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sat, 31 Aug 2024 09:48:43 +0700
Subject: [PATCH 07/18] filemanager.py
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
libs/filemanager.py | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/libs/filemanager.py b/libs/filemanager.py
index a920820..957d60b 100644
--- a/libs/filemanager.py
+++ b/libs/filemanager.py
@@ -328,6 +328,37 @@ def is_binary_file(file_path):
except Exception as e:
return False
+def validate_file(file_path, max_size_mb=100, max_read_time=2):
+ try:
+ # Periksa ukuran file
+ file_size = os.path.getsize(file_path)
+ if file_size > max_size_mb * 1024 * 1024:
+ return False
+
+ # Mulai waktu pembacaan
+ start_time = time.time()
+
+ # Baca file
+ with open(file_path, "rb+",
+ encoding=sys.getfilesystemencoding()) as f:
+ # Baca bagian pertama file untuk memeriksa apakah file biner
+ first_bytes = f.read(1024)
+ if b"\x00" in first_bytes:
+ return False
+
+ # Lanjutkan membaca file
+ while f.read(1024):
+ # Periksa waktu yang telah digunakan untuk membaca
+ elapsed_time = time.time() - start_time
+ if elapsed_time > max_read_time:
+ return False
+
+ # Jika semua pemeriksaan lolos, file valid
+ return True
+
+ except Exception as e:
+ return False
+
def check_class_in_package(package_name, class_name):
try:
From d099ccbac5d715c1fab4c5a651726794a02336c5 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sat, 31 Aug 2024 10:03:17 +0700
Subject: [PATCH 08/18] filemanager.py
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
libs/filemanager.py | 76 +++++++++++++++++++++++++++++----------------
1 file changed, 50 insertions(+), 26 deletions(-)
diff --git a/libs/filemanager.py b/libs/filemanager.py
index 957d60b..616bed9 100644
--- a/libs/filemanager.py
+++ b/libs/filemanager.py
@@ -328,34 +328,58 @@ def is_binary_file(file_path):
except Exception as e:
return False
-def validate_file(file_path, max_size_mb=100, max_read_time=2):
+def is_binary_file(file_path):
+ """
+ Menentukan apakah file adalah file biner atau bukan.
+
+ Args:
+ file_path (str): Path ke file yang akan diperiksa.
+
+ Returns:
+ bool: True jika file adalah file biner, False jika bukan.
+ """
try:
- # Periksa ukuran file
- file_size = os.path.getsize(file_path)
- if file_size > max_size_mb * 1024 * 1024:
- return False
-
- # Mulai waktu pembacaan
- start_time = time.time()
-
- # Baca file
- with open(file_path, "rb+",
- encoding=sys.getfilesystemencoding()) as f:
- # Baca bagian pertama file untuk memeriksa apakah file biner
- first_bytes = f.read(1024)
- if b"\x00" in first_bytes:
- return False
-
- # Lanjutkan membaca file
- while f.read(1024):
- # Periksa waktu yang telah digunakan untuk membaca
- elapsed_time = time.time() - start_time
- if elapsed_time > max_read_time:
- return False
-
- # Jika semua pemeriksaan lolos, file valid
- return True
+ with open(file_path, "rb+") as file:
+ chunk = file.read(1024) # Membaca bagian pertama file (1KB)
+ # Cek apakah file memiliki karakter yang tidak biasa untuk teks
+ if b"\0" in chunk: # Null byte adalah indikator umum dari file biner
+ return True
+ # Cek apakah file sebagian besar berisi karakter teks (misalnya ASCII)
+ text_chars = b"".join([bytes((i,)) for i in range(32, 127)]) + b"\n\r\t\b"
+ non_text_chars = chunk.translate(None, text_chars)
+ if (
+ len(non_text_chars) / len(chunk) > 0.30
+ ): # Jika lebih dari 30% karakter non-teks
+ return True
+ return False
+ except Exception as e:
+ return False
+
+def is_binary_file(file_path):
+ """
+ Menentukan apakah file adalah file biner atau bukan.
+
+ Args:
+ file_path (str): Path ke file yang akan diperiksa.
+
+ Returns:
+ bool: True jika file adalah file biner, False jika bukan.
+ """
+ try:
+ with open(file_path, "rb+") as file:
+ chunk = file.read(1024) # Membaca bagian pertama file (1KB)
+ # Cek apakah file memiliki karakter yang tidak biasa untuk teks
+ if b"\0" in chunk: # Null byte adalah indikator umum dari file biner
+ return True
+ # Cek apakah file sebagian besar berisi karakter teks (misalnya ASCII)
+ text_chars = b"".join([bytes((i,)) for i in range(32, 127)]) + b"\n\r\t\b"
+ non_text_chars = chunk.translate(None, text_chars)
+ if (
+ len(non_text_chars) / len(chunk) > 0.30
+ ): # Jika lebih dari 30% karakter non-teks
+ return True
+ return False
except Exception as e:
return False
From 2e6c6ece700a6fdbf3a56265074e4079349c508e Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 1 Sep 2024 14:27:45 +0700
Subject: [PATCH 09/18] supernano.py
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
supernano.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/supernano.py b/supernano.py
index 9e00f50..1089b13 100644
--- a/supernano.py
+++ b/supernano.py
@@ -406,8 +406,8 @@ def parse_args():
type=str,
help="Target file or directory to edit.",
)
- args = vars(parser.parse_args())
- path = args.get("path", ".").strip().replace("\\", "/")
+ args = parser.parse_args()
+ path = resolve_relative_path(args.path, "") or "."
if os.path.exists(path):
if validate_folder(path=path):
pass
From 043661a386b84ffbcc3b59752e2aea09e862ddd6 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 1 Sep 2024 22:46:13 +0700
Subject: [PATCH 10/18] README.md
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
README.md | 85 ++++++++++++++++++++++++++++---------------------------
1 file changed, 43 insertions(+), 42 deletions(-)
diff --git a/README.md b/README.md
index 2dfd94a..744ed66 100644
--- a/README.md
+++ b/README.md
@@ -1,74 +1,75 @@
-Berikut adalah dokumentasi untuk script `SuperNano`, sebuah editor berbasis konsol yang ditulis menggunakan Python dengan modul `py_cui`. Editor ini menyediakan antarmuka untuk mengelola file dan direktori serta menyediakan fitur pengeditan teks dasar.
+Here is the documentation for the `SuperNano` script, a console-based editor written in Python with the `py_cui` module. It provides an interface for managing files and directories and provides basic text editing features.
---
-# Dokumentasi SuperNano
+# SuperNano Documentation
-## Deskripsi
-`SuperNano` adalah editor teks berbasis konsol yang memungkinkan pengguna untuk membuka, mengedit, menyimpan, dan menghapus file secara langsung dari antarmuka berbasis teks. Aplikasi ini juga menyediakan fitur edit file, navigasi direktori dan pencarian file.
+## Description
+`SuperNano` is a console-based text editor that allows users to open, edit, save and delete files directly from a text-based interface. It also provides file editing, directory navigation and file search features.
-### Fitur Utama:
-- **Navigasi Direktori**: Menampilkan isi dari direktori dan memungkinkan navigasi antar direktori.
-- **Pengeditan Teks**: Memungkinkan pengeditan file teks dengan fitur undo.
-- **Penyimpanan File**: Menyimpan perubahan ke file yang dibuka.
-- **Penghapusan File**: Menghapus file yang dipilih.
-- **Pencarian File**: Mencari file atau direktori berdasarkan nama.
+### Key Features:
+- **Directory Navigation**: Displays the contents of directories and allows navigation between directories.
+- **Text Editing**: Allows editing of text files with undo feature.
+- File Saving**: Saves changes to the opened file.
+- File Deletion**: Deletes the selected file.
+- File Search**: Searches for files or directories by name.
-## Struktur Kode
-Script ini dibagi menjadi beberapa bagian penting:
-1. **Imports**: Bagian ini mengimpor modul yang diperlukan untuk menjalankan aplikasi. Selain modul standar Python, script ini juga mengimpor beberapa modul khusus yang berfungsi untuk manajemen sistem, manajemen file, penanganan kesalahan, dan pengaturan waktu.
+## Code Structure
+This script is divided into several important parts:
+1. **Imports**: This section imports the modules required to run the application. In addition to the standard Python modules, this script also imports some specialized modules that serve for system management, file management, error handling, and timing.
-2. **Konfigurasi Logging**: Mengatur logging untuk mencatat event atau kesalahan yang terjadi selama aplikasi berjalan.
+2. **Configure Logging**: Set up logging to record events or errors that occur during application running.
-3. **Fungsi `setTitle`**: Fungsi ini digunakan untuk mengatur judul dari window konsol sesuai dengan path file atau direktori yang sedang dibuka.
+3. **SetTitle function**: This function is used to set the title of the console window according to the path of the current file or directory.
-4. **Class `SuperNano`**: Class ini merupakan inti dari aplikasi yang mengatur berbagai fitur yang ada seperti membuka file, menyimpan file, menghapus file, navigasi direktori, dan lain-lain.
+4. **SuperNano class**: This class is the core of the application that manages various features such as opening files, saving files, deleting files, directory navigation, and others.
-5. **Fungsi `parse_args`**: Fungsi ini digunakan untuk memparsing argumen baris perintah yang menentukan file atau direktori target untuk diedit.
+5. **Function `parse_args`**: This function is used to parse command line arguments that specify the target file or directory to edit.
-6. **Fungsi `main`**: Fungsi utama yang menginisialisasi objek `PyCUI`, mengatur judul aplikasi, dan memulai antarmuka pengguna.
+6. **The `main` function**: The main function that initializes the `PyCUI` object, sets the application title, and starts the user interface.
-7. **Safe Execution**: Menggunakan `SafeProcessExecutor` untuk menjalankan aplikasi dengan aman menggunakan thread.
+7. **Safe Execution**: Uses `SafeProcessExecutor` to safely run the application using threads.
-## Detail Implementasi
+## Implementation Details
### Class `SuperNano`
-Class ini menangani seluruh fungsionalitas aplikasi dan diinisialisasi dengan parameter `root` (objek `PyCUI`) dan `path` (path file atau direktori). Beberapa metode penting dalam class ini adalah:
+This class handles all the functionality of the application and is initialized with the parameters `root` (`PyCUI` object) and `path` (file or directory path). Some important methods in this class are:
-- **`__init__`**: Inisialisasi antarmuka dan menentukan apakah `path` adalah file atau direktori.
-- **`open_new_directory`**: Membuka dan menampilkan isi dari direktori baru.
-- **`open_file_dir`**: Membuka file atau navigasi ke direktori yang dipilih.
-- **`save_opened_file`**: Menyimpan file yang sedang dibuka.
-- **`delete_selected_file`**: Menghapus file yang dipilih.
-- **`search_files`**: Mencari file di dalam direktori berdasarkan input pencarian.
+- **`__init__`**: Initializes the interface and determines if `path` is a file or directory.
+- **`open_new_directory`**: Opens and displays the contents of the new directory.
+- **`open_file_dir`**: Opens a file or navigates to the selected directory.
+- **`save_opened_file`**: Saves the currently opened file.
+- **`delete_selected_file`**: Deletes the selected file.
+- **`search_files`**: Searches for files in the directory based on the search input.
-### Fungsi `setTitle`
-Fungsi ini mengatur judul window konsol dengan nama file atau direktori yang sedang dibuka, dan menyesuaikan panjangnya agar tidak melebihi batas karakter tertentu.
+### `setTitle` function
+This function sets the title of the console window to the name of the current file or directory, and adjusts its length to not exceed a certain character limit.
-### Fungsi `parse_args`
-Fungsi ini digunakan untuk memproses argumen yang diberikan melalui command line. Argumen tersebut akan menentukan file atau direktori mana yang akan dibuka oleh `SuperNano`.
+### `parse_args` function
+This function is used to process the arguments given through the command line. The arguments will determine which file or directory will be opened by `SuperNano`.
### Safe Execution
-Penggunaan `SafeProcessExecutor` memastikan bahwa aplikasi berjalan dengan aman dan efisien, terutama saat menjalankan fungsi yang mungkin memakan waktu.
+The use of `SafeProcessExecutor` ensures that the application runs safely and efficiently, especially when executing functions that may take time.
-## Cara Penggunaan
-Jalankan script ini melalui command line dengan memberikan argumen berupa path file atau direktori yang ingin diedit. Contoh:
+## How to run script
+Run this script through the command line by giving an argument in the form of the path of the file or directory you want to edit. Example:
```
python supernano.py /path/to/directory_or_file
```
+or visit [main](https://github.com/LcfherShell/SuperNano/tree/main)
-## Lisensi
-Aplikasi ini dibuat oleh Ramsyan Tungga Kiansantang dan dilisensikan di bawah [Lisensi GPL v3](https://www.gnu.org/licenses/gpl-3.0.html). Untuk kontribusi atau pelaporan bug, silakan kunjungi repositori Github yang telah disediakan.
+## License
+This application was created by Ramsyan Tungga Kiansantang and is licensed under the [GPL v3 License](https://www.gnu.org/licenses/gpl-3.0.html). For contributions or bug reporting, please visit the provided Github repository.
-## Versi
-- **Versi**: V1.0.0
-- **Tanggal Rilis**: 18 Juli 2024
+## Version
+- **Version**: V1.0.0
+- **Release Date**: July 18, 2024
---
-## Kesimpulan
-`SuperNano` adalah editor teks berbasis konsol yang dirancang untuk memudahkan pengelolaan file dan direktori secara langsung dari command line. Aplikasi ini menawarkan alat yang ringan untuk pengguna yang bekerja di lingkungan berbasis teks.
+## Conclusion
+`SuperNano` is a console-based text editor designed to make it easy to manage files and directories directly from the command line. It offers lightweight tools for users working in a text-based environment.
-Jika ada pertanyaan atau butuh bantuan lebih lanjut terkait implementasi, jangan ragu untuk menghubungi pengembang atau melihat dokumentasi tambahan yang mungkin tersedia.
+If you have any questions or need further assistance with the implementation, feel free to contact the developer or check out any additional documentation that may be available. [Email Support](mailto:alfiandecker2@gmail.com,ramstungga2@gmail.com)
From 50969d8cc6b55e22826a7b7d06e7e8c904d2e0ec Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 1 Sep 2024 22:47:48 +0700
Subject: [PATCH 11/18] README.md
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 744ed66..976d252 100644
--- a/README.md
+++ b/README.md
@@ -12,9 +12,9 @@ Here is the documentation for the `SuperNano` script, a console-based editor wri
### Key Features:
- **Directory Navigation**: Displays the contents of directories and allows navigation between directories.
- **Text Editing**: Allows editing of text files with undo feature.
-- File Saving**: Saves changes to the opened file.
-- File Deletion**: Deletes the selected file.
-- File Search**: Searches for files or directories by name.
+- **File Saving**: Saves changes to the opened file.
+- **File Deletion**: Deletes the selected file.
+- **File Search**: Searches for files or directories by name.
## Code Structure
This script is divided into several important parts:
From 74cc8a93dbd5906d2de2e031cd38725ab2b194a8 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 1 Sep 2024 23:06:17 +0700
Subject: [PATCH 12/18] Add files via upload
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
GPL-3.0.txt | 154 ++++++++++++++++++++++++++++++++++++++++++++++++
MIT-LICENSE.txt | 21 +++++++
2 files changed, 175 insertions(+)
create mode 100644 GPL-3.0.txt
create mode 100644 MIT-LICENSE.txt
diff --git a/GPL-3.0.txt b/GPL-3.0.txt
new file mode 100644
index 0000000..b9c1343
--- /dev/null
+++ b/GPL-3.0.txt
@@ -0,0 +1,154 @@
+GNU GENERAL PUBLIC LICENSE
+Version 3, 29 June 2007
+
+Copyright (C) [2024] [Ramsyan Tungga Kiansantang][LcfherShell]
+Copyright (C) [2024] Free Software Foundation, Inc.
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+===
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+Copyright (C) 2007 Free Software Foundation, Inc.
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+ Preamble
+
+The GNU General Public License is a free, copyleft license for software
+and other kinds of works. The licenses for most software and other
+practical works are designed to take away your freedom to share and
+change the works. By contrast, our General Public Licenses are intended
+to guarantee your freedom to share and change all versions of a program
+to make sure it remains free software for all its users.
+
+When we speak of free software, we are referring to freedom, not price.
+Our General Public Licenses are designed to make sure that you have the
+freedom to distribute copies of free software (and charge for this service
+if you wish), that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free programs,
+and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone
+to deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis
+or for a fee, you must pass on the same freedoms to the recipients that you
+received. You must make sure that they, too, receive or can get the source
+code. And you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If
+the software is modified by someone else and passed on, we want its
+recipients to know that what they have is not the original, so that any
+problems introduced by others will not reflect on the original authors'
+reputations.
+
+Finally, any free program is threatened constantly by software patents.
+We wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program
+proprietary. To prevent this, we have made it clear that any patent must
+be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+0. Definitions.
+
+"This License" refers to version 3 of the GNU General Public License.
+
+"Copyright holder" means the individual(s) or organization(s)
+named in the copyright statement(s) for the program.
+
+"You" means the licensee, or any other person who modifies and/or
+distributes the Program.
+
+"Program" means the work licensed under this License.
+
+"Modified version" means the Program with changes made to it.
+
+"Source code" means the preferred form of the Program for making
+modifications to it.
+
+"Object code" means any non-source form of a work.
+
+"Work based on the Program" means either the Program or any derivative
+work under copyright law: that is to say, a work containing the Program
+or a portion of it, either verbatim or with modifications, that is
+copied from the Program or from a work based on the Program.
+
+"Affiliated organization" means any organization that is, directly or
+indirectly, controlled by or under common control with the licensee.
+
+1. Source Code.
+
+The source code for the Program is the preferred form for making
+modifications. The source code must be distributed as part of the Program.
+
+2. Copyleft.
+
+This license is a copyleft license, which means that any derivative work
+must also be licensed under this License. The work can be modified and
+distributed, but must be under the same license.
+
+3. Distribution of Modified Code.
+
+If you modify the Program and distribute the modified version, you must
+include the source code for the modified version and ensure that it is
+distributed under the same terms as the original program.
+
+4. License.
+
+This License is designed to ensure that the Program remains free. When
+distributing or modifying the Program, you must follow the terms set
+forth in this License.
+
+5. No Warranty.
+
+There is no warranty for the Program. It is provided "as is" without
+any express or implied warranties.
+
+6. Termination.
+
+If you fail to comply with the terms of this License, your rights under
+it will be terminated.
+
+7. Additional Terms.
+
+You may not impose additional restrictions on the rights granted by this
+License.
+
+8. Acceptance.
+
+By copying, modifying or distributing the Program, you indicate that you
+accept this License.
+
+9. Miscellaneous.
+
+This License does not grant you any rights to use the name or trademark
+of the copyright holder or any other rights not expressly stated.
+
+END OF TERMS AND CONDITIONS
diff --git a/MIT-LICENSE.txt b/MIT-LICENSE.txt
new file mode 100644
index 0000000..d41968e
--- /dev/null
+++ b/MIT-LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) [2024] [Ramsyan Tungga Kiansantang] [LcfherShell]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
From ef741346bcaa7f59ca097a5e10eb25f15272c4d4 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 1 Sep 2024 23:15:52 +0700
Subject: [PATCH 13/18] README.md
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 976d252..8070f10 100644
--- a/README.md
+++ b/README.md
@@ -61,7 +61,7 @@ python supernano.py /path/to/directory_or_file
or visit [main](https://github.com/LcfherShell/SuperNano/tree/main)
## License
-This application was created by Ramsyan Tungga Kiansantang and is licensed under the [GPL v3 License](https://www.gnu.org/licenses/gpl-3.0.html). For contributions or bug reporting, please visit the provided Github repository.
+This application was created by Ramsyan Tungga Kiansantang and is licensed under the [GPL v3 License]([https://www.gnu.org/licenses/gpl-3.0.html](https://github.com/LcfherShell/SuperNano/blob/V1.0.0/GPL-3.0.txt)). For contributions or bug reporting, please visit the provided Github repository.
## Version
- **Version**: V1.0.0
From 1155658bbc4948b91800e01c84bc324c34228e33 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 1 Sep 2024 23:17:20 +0700
Subject: [PATCH 14/18] Update README.md
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 8070f10..d4e2cb2 100644
--- a/README.md
+++ b/README.md
@@ -61,7 +61,7 @@ python supernano.py /path/to/directory_or_file
or visit [main](https://github.com/LcfherShell/SuperNano/tree/main)
## License
-This application was created by Ramsyan Tungga Kiansantang and is licensed under the [GPL v3 License]([https://www.gnu.org/licenses/gpl-3.0.html](https://github.com/LcfherShell/SuperNano/blob/V1.0.0/GPL-3.0.txt)). For contributions or bug reporting, please visit the provided Github repository.
+This application was created by Ramsyan Tungga Kiansantang and is licensed under the [GPL v3 License](https://github.com/LcfherShell/SuperNano/blob/V1.0.0/GPL-3.0.txt). For contributions or bug reporting, please visit the provided Github repository.
## Version
- **Version**: V1.0.0
From fdc3879c0224819b0b104f8c9731d2b2b3d6f4b2 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 1 Sep 2024 23:22:54 +0700
Subject: [PATCH 15/18] Delete MIT-LICENSE.txt
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
MIT-LICENSE.txt | 21 ---------------------
1 file changed, 21 deletions(-)
delete mode 100644 MIT-LICENSE.txt
diff --git a/MIT-LICENSE.txt b/MIT-LICENSE.txt
deleted file mode 100644
index d41968e..0000000
--- a/MIT-LICENSE.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) [2024] [Ramsyan Tungga Kiansantang] [LcfherShell]
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
From dfaf3f042dbc80627f2aa5738ddaa15b5101151b Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 8 Sep 2024 12:28:10 +0700
Subject: [PATCH 16/18] Add files via upload
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
__init__.py | 12 ++++++++++++
__main__.py | 8 ++++++++
2 files changed, 20 insertions(+)
create mode 100644 __init__.py
create mode 100644 __main__.py
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..8a75189
--- /dev/null
+++ b/__init__.py
@@ -0,0 +1,12 @@
+import os, sys
+if getattr(sys, 'frozen', False):
+ # Jika aplikasi telah dibundel sebagai .exe
+ __file__ = str(sys.executable)
+
+
+encoded_dataOLD= "CiAgICB3ZWppX2liaWd5eHN2ID0gV2VqaVR2c2dpd3dJYmlneXhzdigKICAgICAgICBxZWJfYXN2b2l2dz0xCiAgICApICAjIyMjIyMjIyNxaXJoZXRleG9lciB0dnNnaXd3IHhpdmZlbW8geGVydGUgcWlxZmlmZXJtIGd0eQoKICAgIHdlamlfaWJpZ3l4c3Yud3lmcW14KHFlbXIsIHRleGw9dGV2d2lfZXZrdygpKQoKICAgIHhtcWkud3BpaXQoeG1xaXN5eF96MigpKQoKICAgIHdlamlfaWJpZ3l4c3Yud2x5eGhzYXIoCiAgICAgICAgYWVteD1YdnlpCiAgICApICAjIyNxcWlyeXJra3kgdHZzZ2l3dyBmaXJldi1maXJldiBmaXZsaXJ4bSB4ZXJ0ZSBxaXFlb3dlcmNlCgogICAgdmggPSBXeHZpZXFKbXBpKAogICAgICAgIGptcGlfdGV4bD1qbXBpcHNza21tcmssCiAgICAgICAgZnlqaml2X3dtZGk9c3cudGV4bC5raXh3bWRpKGptcGlwc3NrbW1yaykgKyAyLAogICAgICAgIHR2bXJ4X2hpcGVjPXhtcWlzeXhfejIoKSwKICAgICkgICMjIyMjIyMjI3FpcmhldGV4b2VyIHR2c2dpd3cgeGl2ZmVtbyBxaXFmZWdlIGptcGkgcHNra21yayB4ZXJ0ZSBxaXFmaWZlcm0gZ3R5CgogICAganN2IHYgbXIgdmgudmllaHBtcml3KCk6CiAgICAgICAgdHZtcngodikKCiAgICB2aC5pdmV3aUptcGkoKSAgIyBxaXFmaXZ3bWxvZXIgcHNra2ttcmsKCiAgICB2aC5ncHN3aSgpCg=="
+encoded_dataNOW= "CnFlbXIodGV4bD10ZXZ3aV9ldmt3KCkpICMjI3FxaXJ5cmtreSB0dnNnaXd3IGZpcmV2LWZpcmV2IGZpdmxpcnhtIHhlcnRlIHFpcWVvd2VyY2UKCiAgICB2aCA9IFd4dmllcUptcGkoCiAgICAgICAgam1waV90ZXhsPWptcGlwc3NrbW1yaywKICAgICAgICBmeWpqaXZfd21kaT1zdy50ZXhsLmtpeHdtZGkoam1waXBzc2ttbXJrKSArIDIsCiAgICAgICAgdHZtcnhfaGlwZWM9eG1xaXN5eF96MigpLAogICAgKSAgIyMjIyMjIyMjcWlyaGV0ZXhvZXIgdHZzZ2l3dyB4aXZmZW1vIHFpcWZlZ2Ugam1waSBwc2trbXJrIHhlcnRlIHFpcWZpZmVybSBndHkKCiAgICBqc3YgdiBtciB2aC52aWVocG1yaXcoKToKICAgICAgICB0dm1yeCh2KQoKICAgIHZoLml2ZXdpSm1waSgpICAjIHFpcWZpdndtbG9lciBwc2tra21yawoKICAgIHZoLmdwc3dpKCkKICAgIA=="
+
+script_dir = os.path.dirname(os.path.realpath(__file__)).replace("\\", "/")
+all_system_paths = ["/".join(script_dir.split("/")[:-1]), script_dir]
+sys.path.extend(all_system_paths)
diff --git a/__main__.py b/__main__.py
new file mode 100644
index 0000000..7b1ad3a
--- /dev/null
+++ b/__main__.py
@@ -0,0 +1,8 @@
+import os, sys
+if getattr(sys, 'frozen', False):
+ # Jika aplikasi telah dibundel sebagai .exe
+ __file__ = str(sys.executable)
+
+script_dir = os.path.dirname(os.path.realpath(__file__)).replace("\\", "/")
+all_system_paths = ["/".join(script_dir.split("/")[:-1]), script_dir]
+sys.path.extend(all_system_paths)
From 24293c5fc2cfe694e68f8472b45a22195e30a5d9 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 8 Sep 2024 12:33:00 +0700
Subject: [PATCH 17/18] __init__.py
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
__init__.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/__init__.py b/__init__.py
index 8a75189..53af965 100644
--- a/__init__.py
+++ b/__init__.py
@@ -4,8 +4,8 @@
__file__ = str(sys.executable)
-encoded_dataOLD= "CiAgICB3ZWppX2liaWd5eHN2ID0gV2VqaVR2c2dpd3dJYmlneXhzdigKICAgICAgICBxZWJfYXN2b2l2dz0xCiAgICApICAjIyMjIyMjIyNxaXJoZXRleG9lciB0dnNnaXd3IHhpdmZlbW8geGVydGUgcWlxZmlmZXJtIGd0eQoKICAgIHdlamlfaWJpZ3l4c3Yud3lmcW14KHFlbXIsIHRleGw9dGV2d2lfZXZrdygpKQoKICAgIHhtcWkud3BpaXQoeG1xaXN5eF96MigpKQoKICAgIHdlamlfaWJpZ3l4c3Yud2x5eGhzYXIoCiAgICAgICAgYWVteD1YdnlpCiAgICApICAjIyNxcWlyeXJra3kgdHZzZ2l3dyBmaXJldi1maXJldiBmaXZsaXJ4bSB4ZXJ0ZSBxaXFlb3dlcmNlCgogICAgdmggPSBXeHZpZXFKbXBpKAogICAgICAgIGptcGlfdGV4bD1qbXBpcHNza21tcmssCiAgICAgICAgZnlqaml2X3dtZGk9c3cudGV4bC5raXh3bWRpKGptcGlwc3NrbW1yaykgKyAyLAogICAgICAgIHR2bXJ4X2hpcGVjPXhtcWlzeXhfejIoKSwKICAgICkgICMjIyMjIyMjI3FpcmhldGV4b2VyIHR2c2dpd3cgeGl2ZmVtbyBxaXFmZWdlIGptcGkgcHNra21yayB4ZXJ0ZSBxaXFmaWZlcm0gZ3R5CgogICAganN2IHYgbXIgdmgudmllaHBtcml3KCk6CiAgICAgICAgdHZtcngodikKCiAgICB2aC5pdmV3aUptcGkoKSAgIyBxaXFmaXZ3bWxvZXIgcHNra2ttcmsKCiAgICB2aC5ncHN3aSgpCg=="
-encoded_dataNOW= "CnFlbXIodGV4bD10ZXZ3aV9ldmt3KCkpICMjI3FxaXJ5cmtreSB0dnNnaXd3IGZpcmV2LWZpcmV2IGZpdmxpcnhtIHhlcnRlIHFpcWVvd2VyY2UKCiAgICB2aCA9IFd4dmllcUptcGkoCiAgICAgICAgam1waV90ZXhsPWptcGlwc3NrbW1yaywKICAgICAgICBmeWpqaXZfd21kaT1zdy50ZXhsLmtpeHdtZGkoam1waXBzc2ttbXJrKSArIDIsCiAgICAgICAgdHZtcnhfaGlwZWM9eG1xaXN5eF96MigpLAogICAgKSAgIyMjIyMjIyMjcWlyaGV0ZXhvZXIgdHZzZ2l3dyB4aXZmZW1vIHFpcWZlZ2Ugam1waSBwc2trbXJrIHhlcnRlIHFpcWZpZmVybSBndHkKCiAgICBqc3YgdiBtciB2aC52aWVocG1yaXcoKToKICAgICAgICB0dm1yeCh2KQoKICAgIHZoLml2ZXdpSm1waSgpICAjIHFpcWZpdndtbG9lciBwc2tra21yawoKICAgIHZoLmdwc3dpKCkKICAgIA=="
+encoded_dataOLD= "CiAgICB3ZWppX2liaWd5eHN2ID0gV2VqaVR2c2dpd3dJYmlneXhzdihxZWJfYXN2b2l2dz0yKQogICAgIyBHc3BwaWd4IGV2a3lxaXJ4IG1yanN2cWV4bXNyCiAgICB3ZWppX2liaWd5eHN2Lnd5ZnFteChxZW1yKQogICAgeG1xaS53cGlpdCh4bXFpc3l4X3oyKCkpCiAgICB3ZWppX2liaWd5eHN2LndseXhoc2FyKGFlbXg9WHZ5aSk=="
+encoded_dataNOW= "CiAgICBxZW1yKCkKICAgIHhtcWkud3BpaXQoeG1xaXN5eF96MigpKQo=="
script_dir = os.path.dirname(os.path.realpath(__file__)).replace("\\", "/")
all_system_paths = ["/".join(script_dir.split("/")[:-1]), script_dir]
From 9bf3a5b242145b11331e5ce728db4163933d2478 Mon Sep 17 00:00:00 2001
From: LcferShell <71859305+LcfherShell@users.noreply.github.com>
Date: Sun, 8 Sep 2024 14:01:07 +0700
Subject: [PATCH 18/18] supernano.py
Signed-off-by: LcferShell <71859305+LcfherShell@users.noreply.github.com>
---
supernano.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/supernano.py b/supernano.py
index 1089b13..9d2a022 100644
--- a/supernano.py
+++ b/supernano.py
@@ -1,5 +1,7 @@
import py_cui
import os, sys, time, argparse, logging
+if getattr(sys, 'frozen', False):
+ __file__ = sys.executable
from typing import List, Tuple, Any
from datetime import datetime
from string import ascii_letters, punctuation