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.
This commit is contained in:
Kevin Ballard 2014-07-12 01:45:52 -07:00
parent 76fdfe6890
commit 2eb65b3625
3 changed files with 27 additions and 0 deletions

View file

@ -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)
{
/*

10
env.cpp
View file

@ -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<wcstring>
*/

6
env.h
View file

@ -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();