テキスト行頭整形ツール『断罪刻環』 ソースコード

以下は『断罪刻環』のソースコード全文です:


        import tkinter as tk
        from tkinter import simpledialog, messagebox
        
        class PrefixInserterApp:
            def __init__(self, master):
                self.master = master
                self.master.title("Insert&Trimer - 断罪刻環")
                self.master.geometry("1000x600")
                self.master.minsize(600, 400)
                self.master.protocol("WM_DELETE_WINDOW", self.on_close)
                        
                self.is_dark_mode = False  # 初期状態はノーマルモード
        
                # グリッド設定
                self.master.columnconfigure(0, weight=1)
                self.master.columnconfigure(1, weight=1)
                self.master.rowconfigure(0, weight=1)
                self.master.rowconfigure(1, weight=0)
                self.master.rowconfigure(2, weight=0)
        
                # 左フレーム
                self.left_frame = tk.Frame(master)
                self.left_frame.grid(row=0, column=0, sticky="nsew", padx=5, pady=5)
                self.left_frame.rowconfigure(0, weight=1)
                self.left_frame.columnconfigure(0, weight=1)
        
                self.left_text = tk.Text(self.left_frame)
                self.left_text.grid(row=0, column=0, sticky="nsew")
        
                self.left_button_frame = tk.Frame(self.left_frame)
                self.left_button_frame.grid(row=1, column=0, pady=5, sticky="e")
        
                self.clear_button = tk.Button(self.left_button_frame, text="クリア", command=self.clear_text)
                self.clear_button.pack(side=tk.LEFT, padx=5)
        
                self.paste_button = tk.Button(self.left_button_frame, text="貼り付け", command=self.paste_text)
                self.paste_button.pack(side=tk.LEFT, padx=5)
        
                # 右フレーム
                self.right_frame = tk.Frame(master)
                self.right_frame.grid(row=0, column=1, sticky="nsew", padx=5, pady=5)
                self.right_frame.rowconfigure(0, weight=1)
                self.right_frame.columnconfigure(0, weight=1)
        
                self.right_text = tk.Text(self.right_frame)
                self.right_text.grid(row=0, column=0, sticky="nsew")
        
                self.copy_button = tk.Button(self.right_frame, text="コピー", command=self.copy_to_clipboard)
                self.copy_button.grid(row=1, column=0, pady=5, sticky="e")
        
                # 下部ボタン
                self.button_frame = tk.Frame(master)
                self.button_frame.grid(row=1, column=0, columnspan=2, pady=10)
        
                self.space_button = tk.Button(self.button_frame, text="スペースを挿入", command=self.insert_spaces)
                self.space_button.grid(row=0, column=0, padx=10)
        
                self.char_button = tk.Button(self.button_frame, text="文字を指定して挿入", command=self.insert_custom_char)
                self.char_button.grid(row=0, column=1, padx=10)
                
                self.trim_button = tk.Button(self.button_frame, text="詰める", command=self.trim_prefix)
                self.trim_button.grid(row=1, column=0, columnspan=2, pady=5)
        
        
                # モード切替ボタン
                self.mode_button = tk.Button(master, text="🌙 ダークモード", command=self.toggle_mode)
                self.mode_button.grid(row=2, column=0, columnspan=2, pady=10)
        
                self.apply_theme()
        
            def on_close(self):
                print("アプリケーションを終了します。")
                self.master.destroy()
        
            def clear_text(self):
                self.left_text.delete("1.0", tk.END)
        
            def paste_text(self):
                try:
                    clipboard = self.master.clipboard_get()
                    self.left_text.insert(tk.END, clipboard)
                except:
                    messagebox.showwarning("貼り付け失敗", "クリップボードから読み取れませんでした。", parent=self.master)
        
            def copy_to_clipboard(self):
                output = self.right_text.get("1.0", tk.END)
                self.master.clipboard_clear()
                self.master.clipboard_append(output)
                messagebox.showinfo("コピー", "出力内容をクリップボードにコピーしました", parent=self.master)
        
            def insert_spaces(self):
                count = simpledialog.askinteger("スペースの数", "挿入する数を入力してください", minvalue=0, parent=self.master)
                if count is not None:
                    confirm = messagebox.askokcancel("確認", f"スペースを{count}個挿入します", parent=self.master)
                    if confirm:
                        self.apply_prefix(" " * count)
        
            def insert_custom_char(self):
                char = simpledialog.askstring("文字の入力", "挿入する文字を入力してください", parent=self.master)
                if char:
                    count = simpledialog.askinteger("回数の入力", "挿入する数を入力してください", minvalue=0, parent=self.master)
                    if count is not None:
                        confirm = messagebox.askokcancel("確認", f"{char}を{count}個挿入します", parent=self.master)
                        if confirm:
                            self.apply_prefix(char * count)
        
            def apply_prefix(self, prefix):
                original_text = self.left_text.get("1.0", tk.END).splitlines()
                modified_lines = [prefix + line for line in original_text]
                result = "\n".join(modified_lines)
                self.right_text.delete("1.0", tk.END)
                self.right_text.insert("1.0", result)
        
            def trim_prefix(self):
                count = simpledialog.askinteger("文字を詰める", "削除する文頭の文字数を入力してください", minvalue=0, parent=self.master)
                if count is not None:
                    confirm = messagebox.askokcancel("確認", f"文頭から{count}文字を削除します", parent=self.master)
                    if confirm:
                        original_text = self.left_text.get("1.0", tk.END).splitlines()
                        modified_lines = [line[count:] if len(line) >= count else "" for line in original_text]
                        result = "\n".join(modified_lines)
                        self.right_text.delete("1.0", tk.END)
                        self.right_text.insert("1.0", result)
        
            def toggle_mode(self):
                self.is_dark_mode = not self.is_dark_mode
                self.apply_theme()
        
            def apply_theme(self):
                if self.is_dark_mode:
                    bg = "#2e2e2e"
                    fg = "#ffffff"
                    btn_bg = "#444444"
                    btn_fg = "#ffffff"
                    mode_label = "☀ ノーマルモード"
                else:
                    bg = "#ffffff"
                    fg = "#000000"
                    btn_bg = "#f0f0f0"
                    btn_fg = "#000000"
                    mode_label = "🌙 ダークモード"
        
                widgets = [
                    self.master,
                    self.left_text,
                    self.right_text,
                    self.clear_button,
                    self.paste_button,
                    self.copy_button,
                    self.space_button,
                    self.char_button,
                    self.mode_button,
                    self.trim_button,
                ]
        
                for widget in widgets:
                    try:
                        widget.configure(bg=btn_bg, fg=btn_fg)
                    except:
                        pass
                self.left_text.configure(bg=bg, fg=fg, insertbackground=fg)
                self.right_text.configure(bg=bg, fg=fg, insertbackground=fg)
                self.mode_button.configure(text=mode_label)
        
        # 実行
        if __name__ == "__main__":
            root = tk.Tk()
            app = PrefixInserterApp(root)
            root.mainloop()