Repository: mitmproxy/mitmproxy
Pull request: Prompt user before clearing screen
#### Description
Fixes #7413 
Refs #7282


~- Added prompts for destructive shortcuts~
~- Mapped the no-prompts version to `ctrl+[key]`~


~Yet to add tests and update [KeyMapConfig.load_path](https://github.com/mitmproxy/mitmproxy/blob/6e4cb235fdc7d0f55b8edcda37e9f7cb0c8fda22/mitmproxy/tools/console/keymap.py#L209), wanted to get feedback before proceeding further.~

Prompts user before clearing screen

#### Checklist

 - [ ] I have updated tests where applicable.
 - [x] I have added an entry to the CHANGELOG.


Problem statement:
Ask confirmation before clearing flow list (key z)
#### Problem Description
The `z` keybinding, used to clear flow list, doesn't ask for confirmation, immediately and irreversibly deleting all flows.
It's not impossible to accidentally hit the z key and lose all the flows after a long debugging session.

#### Proposal
Similar to the exit key (`q` or `esc`), it would be nice to add an action confirmation for `z` keybinding to prevent accidental clearing of the flow list.

#### Alternatives


#### Additional context

Hints from issue discussion:
I agree with this change and can send a PR if @mhils is okay with this
Yes, sounds good to me. 👍

On Wed, Dec 25, 2024, 12:01 Gaurav Jain ***@***.***> wrote:

> I agree with this change and can send a PR if @mhils
> <https://github.com/mhils> is okay with this
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/mitmproxy/mitmproxy/issues/7413#issuecomment-2561837206>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAHY2PXENXIXZLGJQCGVTB32HKF6ZAVCNFSM6AAAAABUFKKH3GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNRRHAZTOMRQGY>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>

Refs #7282
Hello @ntqbit, @mhils, I want to contribute to this issue.
but which files are used to be edited?
I tried but not find the actual code.
Hey @AdityaPatadiya, sorry for the delay but I'm already in the middle of fixing this. I'll let you know if I'm no longer working on it.
Ohh! okay

Commit message: [autofix.ci] apply automated fixes

Patch to review:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d2022b5f35..a1b6388cc1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,8 @@
   ([#7456](https://github.com/mitmproxy/mitmproxy/pull/7456), @jwadolowski)
 - Remove check for status codes in the blocklist add-on.
   ([#7453](https://github.com/mitmproxy/mitmproxy/pull/7453), @lups2000, @AdityaPatadiya)
+- Prompt user before clearing screen
+  ([#7445](https://github.com/mitmproxy/mitmproxy/pull/7445), @errorxyz)
 
 ## 05 December 2024: mitmproxy 11.0.2
 
@@ -76,7 +78,7 @@
   ([#6720](https://github.com/mitmproxy/mitmproxy/pull/6720), @NicolaiSoeborg)
 - Fix slow tnetstring parsing in case of very large tnetstring.
   ([#7121](https://github.com/mitmproxy/mitmproxy/pull/7121), @mik1904)
-- Add `getaddrinfo`-based fallback for DNS resolution if we are unable to 
+- Add `getaddrinfo`-based fallback for DNS resolution if we are unable to
   determine the operating system's name servers.
   ([#7122](https://github.com/mitmproxy/mitmproxy/pull/7122), @mhils)
 - Improve the error message when users specify the `certs` option without a matching private key.
diff --git a/mitmproxy/tools/console/consoleaddons.py b/mitmproxy/tools/console/consoleaddons.py
index 66763a2206..ac428ffbd1 100644
--- a/mitmproxy/tools/console/consoleaddons.py
+++ b/mitmproxy/tools/console/consoleaddons.py
@@ -284,6 +284,27 @@ def console_command(self, *command_str: str) -> None:
             quoted += " "
         signals.status_prompt_command.send(partial=quoted)
 
+    @command.command("console.command.confirm")
+    def console_command_confirm(
+        self,
+        prompt: str,
+        cmd: mitmproxy.types.Cmd,
+        *args: mitmproxy.types.CmdArgs,
+    ) -> None:
+        """
+        Prompt the user before running the specified command.
+        """
+
+        def callback(opt):
+            if opt == "n":
+                return
+            try:
+                self.master.commands.call_strings(cmd, args)
+            except exceptions.CommandError as e:
+                logger.error(str(e))
+
+        self.master.prompt_for_user_choice(prompt, callback)
+
     @command.command("console.command.set")
     def console_command_set(self, option_name: str) -> None:
         """
diff --git a/mitmproxy/tools/console/defaultkeys.py b/mitmproxy/tools/console/defaultkeys.py
index 2294538c35..33a6025f55 100644
--- a/mitmproxy/tools/console/defaultkeys.py
+++ b/mitmproxy/tools/console/defaultkeys.py
@@ -139,9 +139,17 @@ def map(km: Keymap) -> None:
         "Revert changes to this flow",
     )
     km.add("X", "flow.kill @focus", ["flowlist"], "Kill this flow")
-    km.add("z", "view.flows.remove @all", ["flowlist"], "Clear flow list")
     km.add(
-        "Z", "view.flows.remove @hidden", ["flowlist"], "Purge all flows not showing"
+        "z",
+        'console.command.confirm "Delete all flows" view.flows.remove @all',
+        ["flowlist"],
+        "Clear flow list",
+    )
+    km.add(
+        "Z",
+        'console.command.confirm "Purge all hidden flows" view.flows.remove @hidden',
+        ["flowlist"],
+        "Purge all flows not showing",
     )
     km.add(
         "|",
@@ -227,7 +235,12 @@ def map(km: Keymap) -> None:
         "Save data to file as CSV",
     )
 
-    km.add("z", "eventstore.clear", ["eventlog"], "Clear")
+    km.add(
+        "z",
+        'console.command.confirm "Clear event log" eventstore.clear',
+        ["eventlog"],
+        "Clear",
+    )
 
     km.add(
         "a",
diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py
index a0a1d73d1b..358f66912d 100644
--- a/mitmproxy/tools/console/master.py
+++ b/mitmproxy/tools/console/master.py
@@ -67,16 +67,19 @@ def __setattr__(self, name, value):
     def options_error(self, exc) -> None:
         signals.status_message.send(message=str(exc), expire=1)
 
-    def prompt_for_exit(self) -> None:
+    def prompt_for_user_choice(self, prompt, callback) -> None:
         signals.status_prompt_onekey.send(
-            prompt="Quit",
+            prompt=prompt,
             keys=[
                 ("yes", "y"),
                 ("no", "n"),
             ],
-            callback=self.quit,
+            callback=callback,
         )
 
+    def prompt_for_exit(self) -> None:
+        self.prompt_for_user_choice("Quit", self.quit)
+
     def sig_add_log(self, entry: log.LogEntry):
         if log.log_tier(self.options.console_eventlog_verbosity) < log.log_tier(
             entry.level


Code review comments:
diff_hunk: @@ -284,6 +284,27 @@ def console_command(self, *command_str: str) -> None:
             quoted += " "
         signals.status_prompt_command.send(partial=quoted)
 
+    @command.command("console.command.confirm")
+    def console_command_confirm(
+        self,
+        prompt: str,
+        cmd: mitmproxy.types.Cmd,
+        *args: mitmproxy.types.CmdArgs,
+    ) -> None:
+        """
+        Prompt the user before running the specified command.
+        """
+
+        def callback(opt):
+            if opt == "n":
+                return
+            try:
+                self.master.commands.call_strings(cmd, args)
+            except exceptions.CommandError as e:
+                logger.error(str(e))
path: mitmproxy/tools/console/consoleaddons.py
text: @user1:
```suggestion
                logger.exception(str(e))
```