Yes, the problem is gone! Thanks a lot for your help.
- Log in to post comments
Yes, the problem is gone! Thanks a lot for your help.
I just messaged you two snippets. Thanks again.
I will have time to prepare such a snippet tomorrow, sorry. Meanwhile, it's not necessarily one line off but up to several lines off, a few routines only. In your code, is it possible to extract text of the line for which tokens are calculated? I looked around and did not see such a possibility.
I have an odd problem. In vast majority of cases globals are defined by your code correctly. However, for some routines the lineNum as returned by GetNext is one line count off and the global with the stated token attributes is actually on the next line. I tried to slightly modify such routines and recompile, but it did not always help. Any advice?
Excellent, just excellent. It did find correctly all globals in a routine (no indirection). I populated in = ##class(%Stream.TmpCharacter).%New() with this code:
S NumLines=^ROUTINE(routineName,0,0) ; Omit extension
F n=0:1:NumLines {
S line=$T(@routineName+n^@routineName)
D in.Write(line),in.Write($c(13,10))
}
D in.Rewind()
I also added this after your Write:
Set line=$G(^ROUTINE(rtnName,0,lineNum+1))
Write $C(9),$E(line,token.p+1,token.p+token.c),!
I did not try finding globals in classes, but I assume this would be very similar. Is there any online documentation that shows that token value for globals is 18? Would be curious about other token values.
Thanks, Brett. I did try using SyntaxColor but not with JSON and did not like the HTML results. I'll give your code a try.
Thanks, Yaron. I'll skip looking for indirections for now.
Thanks, Julius
$STACK, of course. It looks like current line is represented by $st(1,"MCODE"). Did not know about $zname. Thanks!
I rebuild ^rINDEX using, as recommended, D ##class(%Library.RoutineIndex).RebuildIndex($NAMESPACE). That reduced the number of ^rINDEX entries with an empty Date Modified, the cause of the $RO error. However, this function is partially based on ^ROUTINE which in its turn had bogus entries, all of the type ^ROUTINE("ABC",0,"SIZE")=<some integer>. That’s all these routines contain. I killed these ^ROUTINE nodes and rebuilt ^rINDEX. No empty Date Modified.
I made a mistake, now corrected: it's Cache, not Ensemble. It does have this function too. I'll post results here.
That's exactly what I was looking for!
I wrote a simple function to find non-printable characters in a routine:
findNonAscii
s stream = ##class(%FileCharacterStream).%New()
s stream.Filename="C:\TestAGbackup_2024-04-15_AG.txt"
f {
q:stream.AtEnd
s line = stream.ReadLine()
; Strip all control characters, including non-processable by XML export, except for tabs and newlines
s l2=$ZSTRIP(line,"*C","",$C(9)_$C(10)_$C(13))
w:l2'=line line,!,l2,!
}
q
I am using the %File class.
This approach indeed works on a small sample file. Not sure what matters here but I have a 50 MB file created with ^%RO and while FindAt does return position, not sure if a correct one, MoveTo fails to move to it. RO files seem not to have any control characters that might have disrupted FindAt somehow.
Yes, ReadLine works, thanks,
Less verbose and more elegant
Enrico, I meant how to programmatically reproduce information on the System > Configuration > Namespaces page in Management Portal. In other words, how to extract default databases listed under Routines on this page.
Everybody, thanks for reading and Robert and Sarah for replying.
partialGlobalsSize(dir,global)
S sub="",path="C:\Cachesys\mgr\"_dir_"\",searchGlobal="^"_global,Alloc=0,Size=0
S x=##Class(%GlobalEdit).GetGlobalSize(path, global,.Alloc,.Size)
W global,",",Alloc,",",Size,! ; Alloc=1312,725 here, Size=725
S Size=0
S x=##Class(%GlobalEdit).GetGlobalSizeBySubscript(path,global,"",.Size)
W global,",",Size,! ; 1311.9 here
S totalSize=0
F {
/// Size - Maximum number of MB to count. If the size of the global exceeds this value,
/// calculation stops, and an error is returned. If undefined or set to 0, then the entire range is counted.
/// Be careful to RESET this for multiple calls to the method
S Size=0 ; Resetting!
S sub=$O(@searchGlobal@(sub)) Q:sub="" ;$D(@("^MSCG("_t_")"))
S x=##Class(%GlobalEdit).GetGlobalSizeBySubscript(path,global_"("""_sub_""")","",.Size)
S totalSize=totalSize+Size
}
W global,",",totalSize,! ; 1321.57 here
Q
Thanks, Sarah. Changing the third argument to an empty one does not make a difference. Yes, the Used/Allocated difference is clear.
Thanks, Robert. A couple of additional questions.
I was so focused on subscripts that I forgot about indirection :-) . Thanks!
That was it, invalid characters in a test method string. Thanks, @Pravin Barton and @Alex Woodhead!
@Brett Saviano @Evgeny Shvarov You listed VSCode plusses, thanks. How about what Studio does that VSCode plus free plugins still do not? One of our programmers complained about debugging as of July 2022. Is it on par now?
I'll watch it, thanks, Raj. I have to say though that I really prefer searchable text that can be visually scanned diagonally in 5 minutes as opposed to watching a 45-minute video. Oh well...
Thanks, @Brett Saviano . I'd like to assess what are plusses and minuses of migrating first.
Is there a recent and detailed article comparing VSCode plugin and the latest Studio? Something like this is what Studio still does better and this is what plugin does better.
That's the code I ended up with. Thanks for your help, everybody!
; str is parsed into two arrays, words and separators (spaces and punctuation)
; Trim leading and trailing spaces here if needed
S L=$L(str),(currWord,currSep)="",cnt=0
F i=1:1:L {
S currChar=$E(str,i,i)
I $MATCH(currChar,"\w") {
S currWord=currWord_currChar
I currSep'="" {
S sepAr(cnt)=currSep,currSep=""
}
}
ELSE {
S currSep=currSep_currChar
I currWord'="" {
S cnt=cnt+1,wordAr(cnt)=currWord,currWord=""
}
}
}
Good to know!
Very interesting, thanks!