Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

How to? SETLOCAL Level

Aug
1,949
71
In the help file, it states "SETLOCAL and ENDLOCAL may be nested up to 32 levels deep".

So, when I go beyond 32 levels, I get the following;
Code:
c:\users\jlc\utils>setlocal
TCC: Exceeded SETLOCAL nesting limit

Is there a way to determine how many SETLOCAL levels deep I am presently at?

Joe
 
There currently isn't any way to query the SETLOCAL nesting.

But the question makes me curious - I've never heard of anybody remotely approaching the maximum nesting. (Or what they would do if they knew they were about to exceed it.) What are you doing that would make this useful?
 
I quite frequently use SETLOCAL from the TCC Prompt, so as not to mess up my current environment.

I do this, because sometimes, I forget to UNSET test variables, etc.

Unfortunately, I forget to do an ENDLOCAL when I have finished testing whatever I was testing.

So, when I don't want to mess up my current environment, I do another SETLOCAL, and the cycle repeats itself.

The PROMPT has an option, $+, which will "Display one + character for each directory on the PUSHD directory stack."

When I want to know the count of the directory stack, I can see that visually, since I have one or more ++++ in my prompt at the command line.

With SETLOCAL, I have no information, visual or otherwise, to see what SETLOCAL level I am at.

Joe
 
Possible untested kludge workaround:

alias setlocal=`*setlocal & set localcount=%@inc[0%localcount%]`

Then you can query the value of %localcount%.
 
...and the corresponding;
Code:
alias endlocal=`*endlocal & if %localcount le 0 (set localcount=0) else (set localcount=%@dec[0%localcount%]`)

No doubt I will make some further tweaks. Thanks Dave!

Joe
 
I don't think you have to handle specially the case where the variable is not set.
Code:
v:\> echo %@inc[] %@dec[]
1 -1

Using @MAX instead of IF in the endlocal alias is tidier.
 
I believe that the zero preceding %localcount% in the @inc expression takes care of the case where localcount has not been set.

I've tested my own code now, and it works for me.
 
...and the corresponding;
Code:
alias endlocal=`*endlocal & if %localcount le 0 (set localcount=0) else (set localcount=%@dec[0%localcount%]`)

No doubt I will make some further tweaks. Thanks Dave!

Joe

You don't need to decrement because the old value of LOCALCOUNT is already in (and unchanged in) the previous environment which ENDLOCAL returns you to.

Here's an excerpt:
Code:
~\Work> alias setlocal=`*setlocal & set localcount=%@inc[0%localcount%]`

~\Work> alias setlocal
*setlocal & set localcount=%@inc[0%localcount%]

~\Work> setlocal

~\Work> set localcount
1

~\Work> setlocal

~\Work> set localcount
2

~\Work> endlocal

~\Work> set localcount
1

~\Work> endlocal

~\Work> set localcount
TCC: Not in environment "localcount*"
 
I believe that the zero preceding %localcount% in the @inc expression takes care of the case where localcount has not been set.
@INC gives 1 (anyway) if the variable is not set.
Code:
v:\> unset zzz

v:\> echo %@inc[%zzz]
1
 
Dave;
I removed the ENDLOCAL alias, and now have only;
Code:
setlocal=@if %_batch eq 0 (*setlocal & set localcount=%@inc[0%localcount%] & echo %localcount)

I only wanted the alias to work from the command line, not from a .BTM file, thus the @if %_batch eq 0.

So far, so good. Thanks again.

Joe
 
I created a set of 3 scripts that do pushlocal, poplocal, and locals (works like dirs). They currently save the current directories, the environment, and directory history.
pushlocal.btm
Code:
set locals=%@EVAL[%@execstr[set /v locals%_PID] + 1]
cdd /a > c:\jpsoft\drives%[locals]_%_PID.dat
cd >> c:\jpsoft\drives%[locals]_%_PID.dat
set > c:\jpsoft\env%[locals]_%_PID.dat
dirhistory > c:\jpsoft\dirhist%[locals]_%_PID.dat
set /v locals%_PID=%locals
poplocal.btm
Code:
set locals=%@execstr[set /v locals%_PID]
if "%locals" == "" .or. "%locals" == "0" (echo LOCALS stack is empty & quit)
unset *
set locals=%@execstr[set /v locals%_PID]
for %s in (@c:\JPSOFT\drives%[locals]_%_PID.dat) do cdd %s
dirhistory /r c:\JPSOFT\dirhist%[locals]_%_PID.dat
set /r c:\JPSOFT\env%[locals]_%_PID.dat
del /q c:\JPSOFT\env%[locals]_%_PID.dat c:\JPSOFT\dirhist%[locals]_%_PID.dat c:\JPSOFT\drives%[locals]_%_PID.dat
set /v locals%_PID=%@eval[locals - 1]
locals.btm
Code:
set locals=%@execstr[set /v locals%_PID]
iff "%locals" == "" .or. "%locals" == "0" then
  echo LOCALS stack is empty
else
  echo %locals
endiff
unset locals
 
Because it uses %_PID, it allows each instance of TCC to have its own LOCALS stack.
 
BTW - you could add your localcount to your prompt. I append the current Git branch to my prompt:
Code:
function gitbranch=`%@execstr[set _gb=%@execstr[git rev-parse --abbrev-ref HEAD 2>nul] & if %[_gb]. != . echo (%_gb) & unset _gb]`
PROMPT=$e[37;%@if[%@remote[%_disk] eq 0,42,41];1m[$P]$e[22;40;36m%@gitbranch[]$e[22;40;33;1m$_$$$s

That colorizes my prompt and puts the branch in parens, after the directory name. I use white on a green background for local directories and white on a red background for network directories.

1525108860444.png


You could do something like this:
Code:
function getlocalcount=`%@execstr[if %localcount. != . echo (%localcount)]`

PROMPT `[$P]$+%@getlocalcount[]$s`
 
Hi Scott,
Yepper, I have localcount added to my prompt, as such;
Code:
prompt `$e[9999E$p$g%@repeat[#,0%localcount]`

I wanted to mimic the + meta character of prompt, which is why I have %@repeat[#,0%localcount] in my prompt.

I like the LOCAL .btms, gonna tinker with them.

Joe
 
Gentlemen,

May I ask why you don't use subshells for this?
I'm under the impression that might save a lot of code, work and complexity?

Regards, DJ
 
I tend to open a new tab in TCMD. There is the "Clone Tab" command, that duplicates the environment. You can set a title to remember which tab is what.
 

Similar threads

Back
Top