summaryrefslogtreecommitdiff
path: root/cmd2/cmd2.py
diff options
context:
space:
mode:
Diffstat (limited to 'cmd2/cmd2.py')
-rw-r--r--cmd2/cmd2.py35
1 files changed, 22 insertions, 13 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 6cd8b950..4f428d1b 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -37,6 +37,8 @@ import os
import pydoc
import re
import sys
+import tempfile
+import typing
import threading
from code import (
InteractiveConsole,
@@ -83,7 +85,6 @@ from .argparse_custom import (
CompletionItem,
)
from .clipboard import (
- can_clip,
get_paste_buffer,
write_to_paste_buffer,
)
@@ -236,6 +237,7 @@ class Cmd(cmd.Cmd):
shortcuts: Optional[Dict[str, str]] = None,
command_sets: Optional[Iterable[CommandSet]] = None,
auto_load_commands: bool = True,
+ allow_clipboard: bool = True,
) -> None:
"""An easy but powerful framework for writing line-oriented command
interpreters. Extends Python's cmd package.
@@ -283,6 +285,7 @@ class Cmd(cmd.Cmd):
that are currently loaded by Python and automatically
instantiate and register all commands. If False, CommandSets
must be manually installed with `register_command_set`.
+ :param allow_clipboard: If False, cmd2 will disable clipboard interactions
"""
# Check if py or ipy need to be disabled in this instance
if not include_py:
@@ -436,8 +439,8 @@ class Cmd(cmd.Cmd):
self.pager = 'less -RXF'
self.pager_chop = 'less -SRXF'
- # This boolean flag determines whether or not the cmd2 application can interact with the clipboard
- self._can_clip = can_clip
+ # This boolean flag stores whether cmd2 will allow clipboard related features
+ self.allow_clipboard = allow_clipboard
# This determines the value returned by cmdloop() when exiting the application
self.exit_code = 0
@@ -2734,13 +2737,9 @@ class Cmd(cmd.Cmd):
sys.stdout = self.stdout = new_stdout
elif statement.output:
- import tempfile
- if (not statement.output_to) and (not self._can_clip):
- raise RedirectionError("Cannot redirect to paste buffer; missing 'pyperclip' and/or pyperclip dependencies")
-
- # Redirecting to a file
- elif statement.output_to:
+ if statement.output_to:
+ # redirecting to a file
# statement.output can only contain REDIRECTION_APPEND or REDIRECTION_OUTPUT
mode = 'a' if statement.output == constants.REDIRECTION_APPEND else 'w'
try:
@@ -2752,14 +2751,26 @@ class Cmd(cmd.Cmd):
redir_saved_state.redirecting = True
sys.stdout = self.stdout = new_stdout
- # Redirecting to a paste buffer
else:
+ # Redirecting to a paste buffer
+ # we are going to direct output to a temporary file, then read it back in and
+ # put it in the paste buffer later
+ if not self.allow_clipboard:
+ raise RedirectionError("Clipboard access not allowed")
+
+ # attempt to get the paste buffer, this forces pyperclip to go figure
+ # out if it can actually interact with the paste buffer, and will throw exceptions
+ # if it's not gonna work. That way we throw the exception before we go
+ # run the command and queue up all the output. if this is going to fail,
+ # no point opening up the temporary file
+ current_paste_buffer = get_paste_buffer()
+ # create a temporary file to store output
new_stdout = cast(TextIO, tempfile.TemporaryFile(mode="w+"))
redir_saved_state.redirecting = True
sys.stdout = self.stdout = new_stdout
if statement.output == constants.REDIRECTION_APPEND:
- self.stdout.write(get_paste_buffer())
+ self.stdout.write(current_paste_buffer)
self.stdout.flush()
# These are updated regardless of whether the command redirected
@@ -4551,8 +4562,6 @@ class Cmd(cmd.Cmd):
self.last_result = True
return stop
elif args.edit:
- import tempfile
-
fd, fname = tempfile.mkstemp(suffix='.txt', text=True)
fobj: TextIO
with os.fdopen(fd, 'w') as fobj: