How to? SETLOCAL Level

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
 

rconn

Administrator
Staff member
May 14, 2008
12,161
140
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
 
May 29, 2008
562
4
Groton, CT
Possible untested kludge workaround:

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

Then you can query the value of %localcount%.
 
May 20, 2008
11,019
88
Syracuse, NY, USA
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.
 
May 29, 2008
562
4
Groton, CT
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.
 
May 29, 2008
562
4
Groton, CT
...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*"
 
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
 
  • Like
Reactions: dcantor

samintz

Scott Mintz
May 20, 2008
1,465
15
Solon, OH, USA
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
 

samintz

Scott Mintz
May 20, 2008
1,465
15
Solon, OH, USA
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`
 
Apr 13, 2010
301
7
60
The Hague
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