Skip to content

Commit

Permalink
Fixes/changes to interactive history (Azure#5636)
Browse files Browse the repository at this point in the history
* fixed history persistence, logic

* version bump

* single source for history, fix clear-history
  • Loading branch information
williexu authored Feb 24, 2018
1 parent 62a137c commit 097a20b
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 51 deletions.
5 changes: 5 additions & 0 deletions src/command_modules/azure-cli-interactive/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
Release History
===============

0.3.17
++++++
* Persist history across different sessions
* Fixed history while in scope

0.3.16
++++++
* Fix issue where user is prompted to login when using interactive mode in Cloud Shell.
Expand Down
102 changes: 53 additions & 49 deletions src/command_modules/azure-cli-interactive/azclishell/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from azclishell.frequency_heuristic import DISPLAY_TIME, frequency_heuristic
from azclishell.gather_commands import add_new_lines, GatherCommands
from azclishell.key_bindings import InteractiveKeyBindings
from azclishell.layout import create_layout, create_tutorial_layout, set_scope
from azclishell.layout import create_layout, create_tutorial_layout, set_scope, get_scope
from azclishell.progress import progress_view
from azclishell.telemetry import Telemetry
from azclishell.threads import LoadCommandTableThread
Expand Down Expand Up @@ -88,8 +88,8 @@ def restart_completer(shell_ctx):
# pylint: disable=too-many-instance-attributes
class AzInteractiveShell(object):

def __init__(self, cli_ctx, style=None, completer=None, styles=None,
lexer=None, history=InMemoryHistory(),
def __init__(self, cli_ctx, style=None, completer=None,
lexer=None, history=None,
app=None, input_custom=sys.stdin, output_custom=None,
user_feedback=False, intermediate_sleep=.25, final_sleep=4):

Expand Down Expand Up @@ -142,7 +142,7 @@ def __init__(self, cli_ctx, style=None, completer=None, styles=None,
def __call__(self):

if self.cli_ctx.data["az_interactive_active"]:
logger.warning("You're in the interactive shell already.\n")
logger.warning("You're in the interactive shell already.")
return

if self.config.BOOLEAN_STATES[self.config.config.get('DEFAULT', 'firsttime')]:
Expand Down Expand Up @@ -476,60 +476,59 @@ def _special_cases(self, cmd, outside):
continue_flag = False
args = parse_quotes(cmd)
cmd_stripped = cmd.strip()
if cmd_stripped and cmd.split(' ', 1)[0].lower() == 'az':
self.telemetry.track_ssg('az', cmd)
cmd = ' '.join(cmd.split()[1:])
if self.default_command:
cmd = self.default_command + " " + cmd

if cmd_stripped == "quit" or cmd_stripped == "exit":
if not cmd_stripped and cmd:
# add scope if there are only spaces
cmd = self.default_command + " " + cmd
elif cmd_stripped == "quit" or cmd_stripped == "exit":
break_flag = True
elif cmd_stripped == "clear-history":
# clears the history, but only when you restart
outside = True
cmd = 'echo -n "" >' +\
os.path.join(
self.config.config_dir(),
self.config.get_history())
continue_flag = True
self.reset_history()
elif cmd_stripped == CLEAR_WORD:
outside = True
cmd = CLEAR_WORD
if cmd_stripped:
if cmd_stripped[0] == SELECT_SYMBOL['outside']:
cmd = cmd_stripped[1:]
outside = True
if cmd.strip() and cmd.split()[0] == 'cd':
self.handle_cd(parse_quotes(cmd))
continue_flag = True
self.telemetry.track_ssg('outside', '')
elif cmd_stripped[0] == SELECT_SYMBOL['outside']:
cmd = cmd_stripped[1:]
outside = True
if cmd.strip() and cmd.split()[0] == 'cd':
self.handle_cd(parse_quotes(cmd))
continue_flag = True
self.telemetry.track_ssg('outside', '')

elif cmd_stripped[0] == SELECT_SYMBOL['exit_code']:
meaning = "Success" if self.last_exit == 0 else "Failure"
elif cmd_stripped[0] == SELECT_SYMBOL['exit_code']:
meaning = "Success" if self.last_exit == 0 else "Failure"

print(meaning + ": " + str(self.last_exit), file=self.output)
continue_flag = True
self.telemetry.track_ssg('exit code', '')
elif SELECT_SYMBOL['query'] in cmd_stripped and self.last and self.last.result:
continue_flag = self.handle_jmespath_query(args)
self.telemetry.track_ssg('query', '')
print(meaning + ": " + str(self.last_exit), file=self.output)
continue_flag = True
self.telemetry.track_ssg('exit code', '')
elif SELECT_SYMBOL['query'] in cmd_stripped and self.last and self.last.result:
continue_flag = self.handle_jmespath_query(args)
self.telemetry.track_ssg('query', '')

elif args[0] == '--version' or args[0] == '-v':
try:
continue_flag = True
self.cli_ctx.show_version()
except SystemExit:
pass
elif "|" in cmd or ">" in cmd:
elif args[0] == '--version' or args[0] == '-v':
try:
continue_flag = True
self.cli_ctx.show_version()
except SystemExit:
pass
elif SELECT_SYMBOL['example'] in cmd:
cmd, continue_flag = self.handle_example(cmd, continue_flag)
self.telemetry.track_ssg('tutorial', cmd)
elif SELECT_SYMBOL['scope'] == cmd_stripped[0:2]:
continue_flag, cmd = self.handle_scoping_input(continue_flag, cmd, cmd_stripped)
else:
# not a special character; add scope and remove 'az'
if self.default_command:
cmd = self.default_command + " " + cmd
elif cmd.split(' ', 1)[0].lower() == 'az':
self.telemetry.track_ssg('az', cmd)
cmd = ' '.join(cmd.split()[1:])
if "|" in cmd or ">" in cmd:
# anything I don't parse, send off
outside = True
cmd = "az " + cmd

elif SELECT_SYMBOL['example'] in cmd:
cmd, continue_flag = self.handle_example(cmd, continue_flag)
self.telemetry.track_ssg('tutorial', cmd)
elif len(cmd_stripped) > 2 and SELECT_SYMBOL['scope'] == cmd_stripped[0:2]:
continue_flag, cmd = self.handle_scoping_input(continue_flag, cmd, cmd_stripped)

return break_flag, continue_flag, outside, cmd

def handle_jmespath_query(self, args):
Expand Down Expand Up @@ -604,8 +603,7 @@ def handle_scoping_input(self, continue_flag, cmd, text):
cmd = cmd.replace(SELECT_SYMBOL['scope'], '')
self.telemetry.track_ssg('scope command', value)

elif SELECT_SYMBOL['unscope'] == default_split[0] and \
len(self.default_command.split()) > 0:
elif SELECT_SYMBOL['unscope'] == default_split[0] and self.default_command.split():

value = self.default_command.split()[-1]
self.default_command = ' ' + ' '.join(self.default_command.split()[:-1])
Expand All @@ -621,6 +619,12 @@ def handle_scoping_input(self, continue_flag, cmd, text):
default_split = default_split[1:]
return continue_flag, cmd

def reset_history(self):
history_file_path = os.path.join(self.config.config_dir, self.config.get_history())
os.remove(history_file_path)
self.history = FileHistory(history_file_path)
self.cli.buffers[DEFAULT_BUFFER].history = self.history

def cli_execute(self, cmd):
""" sends the command to the CLI to be executed """

Expand Down Expand Up @@ -709,9 +713,9 @@ def run(self):
# when the user pressed Control D
break
else:
self.history.append(text)
b_flag, c_flag, outside, cmd = self._special_cases(cmd, outside)
if not self.default_command:
self.history.append(text)

if b_flag:
break
if c_flag:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ def pan_down(event):
def config_settings(event):
""" opens the configuration """
shell_ctx.telemetry.track_key('F1')

shell_ctx.is_prompting = True
config = shell_ctx.config
answer = ""
Expand Down
2 changes: 1 addition & 1 deletion src/command_modules/azure-cli-interactive/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
cmdclass = {}

# Version is also defined in azclishell.__init__.py.
VERSION = "0.3.16"
VERSION = "0.3.17"
# The full list of classifiers is available at
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
CLASSIFIERS = [
Expand Down

0 comments on commit 097a20b

Please sign in to comment.