From 2eb65b362518fe3407fa6fd759927ef3136ad0a6 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Sat, 12 Jul 2014 01:45:52 -0700 Subject: [PATCH] set: Don't treat toplevel scope the same as global When using the `set` command with the -l flag, if we're at the top level, create a temporary local scope. This makes query/assignment behavior be consistent with the value-printing behavior. This works by marking the current block as needing to pop the environment if a local scope was pushed. I assume this is safe to do. I also assume the current block is the right one to modify, rather than trying to walk up the stack to the root. --- builtin_set.cpp | 11 +++++++++++ env.cpp | 10 ++++++++++ env.h | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/builtin_set.cpp b/builtin_set.cpp index 9efd12bc6..9068372f0 100644 --- a/builtin_set.cpp +++ b/builtin_set.cpp @@ -559,6 +559,17 @@ static int builtin_set(parser_t &parser, wchar_t **argv) */ scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (exportv ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER; + /* + If we're interacting with the local scope at all, ensure we actually have + one that's distinct from the global scope. If we don't have one yet, + create one and modify the current block to pop it. + */ + if ((scope & ENV_LOCAL) && env_ensure_local_scope()) + { + block_t *block = parser.current_block(); + block->wants_pop_env = true; + } + if (query) { /* diff --git a/env.cpp b/env.cpp index bdcd3960f..8dd1e0af3 100644 --- a/env.cpp +++ b/env.cpp @@ -1159,6 +1159,16 @@ void env_pop() } } +bool env_ensure_local_scope() +{ + if (top == global_env) + { + env_push(false); + return true; + } + return false; +} + /** Function used with to insert keys of one table into a set::set */ diff --git a/env.h b/env.h index d1a40f7de..e886a5b2c 100644 --- a/env.h +++ b/env.h @@ -199,6 +199,12 @@ void env_push(bool new_scope); */ void env_pop(); +/** + Push the variable stack if the current scope is the global scope. Returns + whether it pushed a scope. +*/ +bool env_ensure_local_scope(); + /** Synchronizes all universal variable changes: writes everything out, reads stuff in */ void env_universal_barrier();