diff --git a/cat_win/cat.py b/cat_win/cat.py index 1a49f251..80ef190e 100644 --- a/cat_win/cat.py +++ b/cat_win/cat.py @@ -70,7 +70,6 @@ converter = Converter() holder = Holder() tmp_file_helper = TmpFileHelper() -Editor.set_indentation(const_dic[DKW.EDITOR_INDENTATION], const_dic[DKW.EDITOR_AUTO_INDENT]) on_windows_os = platform.system() == 'Windows' file_uri_prefix = 'file://' + '/' * on_windows_os @@ -1091,6 +1090,9 @@ def init(shell: bool = False) -> tuple: echo_args = echo_args.encode(arg_parser.file_encoding).decode('unicode_escape') break + Editor.set_indentation(const_dic[DKW.EDITOR_INDENTATION], const_dic[DKW.EDITOR_AUTO_INDENT]) + Editor.set_flags(holder.args_id[ARGS_STDIN] and on_windows_os, holder.args_id[ARGS_DEBUG]) + return (known_files, unknown_files, echo_args, valid_urls) @@ -1126,8 +1128,7 @@ def main(): elif holder.args_id[ARGS_EDITOR]: unknown_files = [file for file in unknown_files if Editor.open( file, holder.get_file_display_name(file), arg_parser.file_encoding, - stdinhelper.write_file, on_windows_os, - holder.args_id[ARGS_PLAIN_ONLY], holder.args_id[ARGS_DEBUG])] + stdinhelper.write_file, on_windows_os, holder.args_id[ARGS_PLAIN_ONLY])] else: unknown_files = stdinhelper.read_write_files_from_stdin( unknown_files, arg_parser.file_encoding, on_windows_os, @@ -1138,10 +1139,17 @@ def main(): if holder.args_id[ARGS_STDIN]: tty = os.open('CONIN$' if on_windows_os else '/dev/tty', os.O_RDONLY) os.dup2(tty, sys.stdin.fileno()) + if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): # pyinstaller + import ctypes +# stdin, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, +# None security, OPEN_EXISTING, 0 flags, None template + conin_handle = ctypes.windll.kernel32.CreateFileW( + "CONIN$", 0x80000000, 3, None, 3, 0, None + ) # os.dup2 does not work on pyinstaller + ctypes.windll.kernel32.SetStdHandle(-10, conin_handle) for file in known_files: Editor.open(file, holder.get_file_display_name(file), arg_parser.file_encoding, - stdinhelper.write_file, on_windows_os, - holder.args_id[ARGS_PLAIN_ONLY], holder.args_id[ARGS_DEBUG]) + stdinhelper.write_file, on_windows_os, holder.args_id[ARGS_PLAIN_ONLY]) os.dup2(stdin_backup, sys.stdin.fileno()) if len(known_files) + len(unknown_files) == 0: diff --git a/cat_win/tests/test_editor.py b/cat_win/tests/test_editor.py index 7fec6191..b55e8ee8 100644 --- a/cat_win/tests/test_editor.py +++ b/cat_win/tests/test_editor.py @@ -389,7 +389,8 @@ def test_editor_key_string(self): self.assertListEqual(editor.window_content, ['ltest\t', '!!!!!!ine 1', 'line 2']) def test_editor_action_save(self): - editor = Editor(test_file_path, '', 'utf-8', True) + Editor.debug_mode = True + editor = Editor(test_file_path, '', 'utf-8') exc = OSError('TestError') error_def = ErrorDefGen.get_def(exc) with patch('cat_win.cat.sys.stderr', new=StdOutMock()) as fake_out: @@ -400,17 +401,20 @@ def test_editor_action_save(self): no_error_def = lambda *_: None self.assertEqual(editor._action_save(no_error_def), True) self.assertEqual(editor.error_bar, '') + Editor.debug_mode = False def test_editor_action_quit(self): editor = Editor(test_file_path, '', 'utf-8') self.assertEqual(editor._action_quit(None), False) def test_editor_interrupt(self): - editor = Editor(test_file_path_oneline, '', 'utf-8', True) + Editor.debug_mode = True + editor = Editor(test_file_path_oneline, '', 'utf-8') with self.assertRaises(KeyboardInterrupt): with patch('cat_win.cat.sys.stderr', new=StdOutMock()) as fake_out: editor._action_interrupt(None) self.assertEqual('Interrupting...\n', fake_out.getvalue()) + Editor.debug_mode = False @patch('cat_win.util.editor.CURSES_MODULE_ERROR', new=True) def test_editor_no_curses_error(self): diff --git a/cat_win/util/editor.py b/cat_win/util/editor.py index 77adfa91..d6ddbf77 100644 --- a/cat_win/util/editor.py +++ b/cat_win/util/editor.py @@ -58,8 +58,10 @@ class Editor: special_indentation = '\t' auto_indent = False - def __init__(self, file: str, display_name: str, - file_encoding: str, debug_mode: bool = False) -> None: + debug_mode = False + save_with_alt = False + + def __init__(self, file: str, display_name: str, file_encoding: str) -> None: """ defines an Editor object. @@ -70,8 +72,6 @@ def __init__(self, file: str, display_name: str, the display name for the current file file_encoding: the encoding to read and write the given file - debug_mode (bool) - if True debug-statements will be printed to stderr """ self.curse_window = None self.history = History() @@ -83,7 +83,6 @@ def __init__(self, file: str, display_name: str, self.line_sep = '\n' self.window_content = [] - self.debug_mode = debug_mode self.special_chars: dict = {} self.search = '' @@ -772,14 +771,17 @@ def _render_scr(self) -> None: self.curse_window.addstr(max_y + self.status_bar_size - 2, 0, self.error_bar[:max_x].ljust(max_x), self._get_color(2)) - status_bar = f"File: {self.display_name} | Exit: ^q | Save: ^s | Pos: {self.cpos.col+1}" + save_hotkey = ('alt+' if self.save_with_alt else '^') + 's' + status_bar = f"File: {self.display_name} | Exit: ^q | Save: {save_hotkey} | " + status_bar += f"Pos: {self.cpos.col+1}" status_bar += f", {self.cpos.row+1} | {'NOT ' * self.unsaved_progress}Saved!" if self.debug_mode: status_bar += f" - Win: {self.wpos.col+1} {self.wpos.row+1} | {max_y}x{max_x}" if len(status_bar) > max_x: necc_space = max(0, max_x - (len(status_bar) - len(self.display_name) + 3)) status_bar = f"File: ...{self.display_name[-necc_space:] * bool(necc_space)} " - status_bar += f"| Exit: ^q | Save: ^s | Pos: {self.cpos.col+1}, {self.cpos.row+1} " + status_bar += f"| Exit: ^q | Save: {save_hotkey} | " + status_bar += f"Pos: {self.cpos.col+1}, {self.cpos.row+1} " status_bar += f"| {'NOT ' * self.unsaved_progress}Saved!"[:max_x] if self.debug_mode: status_bar += f" - Win: {self.wpos.col+1} {self.wpos.row+1} | {max_y}x{max_x}" @@ -908,8 +910,7 @@ def _open(self, write_func) -> None: @classmethod def open(cls, file: str, display_name: str, file_encoding: str, - write_func, on_windows_os: bool, - skip_binary: bool = False, debug_mode: bool = False) -> bool: + write_func, on_windows_os: bool, skip_binary: bool = False) -> bool: """ simple editor to change the contents of any provided file. @@ -924,8 +925,8 @@ def open(cls, file: str, display_name: str, file_encoding: str, stdinhelper.write_file [simply writes a file] on_windows_os (bool): indicates if the user is on windows OS using platform.system() == 'Windows' - debug_mode (bool): - indicates if debug information should be displayed + skip_binary (bool): + indicates if the Editor should skip non-plaintext files Returns: (bool): @@ -943,7 +944,7 @@ def open(cls, file: str, display_name: str, file_encoding: str, Editor.loading_failed = True return False - editor = cls(file, display_name, file_encoding, debug_mode) + editor = cls(file, display_name, file_encoding) if skip_binary and editor.error_bar: return False special_chars = dict(map(lambda x: (chr(x[0]), x[2]), SPECIAL_CHARS)) @@ -960,7 +961,7 @@ def open(cls, file: str, display_name: str, file_encoding: str, return editor.changes_made @staticmethod - def set_indentation(indentation: str = '\t', auto_indent: bool = True): + def set_indentation(indentation: str = '\t', auto_indent: bool = True) -> None: """ set the indentation when using tab on an empty line @@ -973,3 +974,17 @@ def set_indentation(indentation: str = '\t', auto_indent: bool = True): """ Editor.special_indentation = indentation Editor.auto_indent = auto_indent + + @staticmethod + def set_flags(save_with_alt: bool, debug_mode: bool) -> None: + """ + set the config flags for the Editor + + Parameters: + save_with_alt (bool): + indicates whetcher the stdin pipe has been used (and therefor tampered) + debug_mode (bool) + indicates if debug info should be displayed + """ + Editor.save_with_alt = save_with_alt + Editor.debug_mode = debug_mode