Can someone point out what's syntactically wrong with this source filter (as documented here - https://nim-lang.org/docs/filters.html) as it refuses to compile with an "invalid indentation" error message
#? stdtmpl | standard
#proc greet(name = "world"): string =
# result = ""
<h1>Hello $name</h1>
#end proc
echo greet()
Since echo greet() is Nim code, you need to prefix it with #. Also, be aware that you may not have empty lines outside the proc, because Nim would then try to append them to a result variable, which does not exist outside the proc.
#? stdtmpl | standard
#proc greet(name = "world"): string =
# result = ""
<h1>Hello $name</h1>
#end proc
#echo greet()
Related
I've created a Live Template with IntelliJ IDEA and I'm trying to find and remove a specific String within Velocity through a variable but failed
I tried to set $moduleName variable through $NAME variable -which is giving 'File name'- with RegExp.
I'm removing View string (part of File name) during creating JS file, but failed. Code:
## Input for 'File Name' is FooView**
#set($regex = '/(View)/') ## Try to get 'View' string with regex**
#set($checkRegex = $NAME.matches($regex)) ## Checks if regex finds**
#set($moduleName = $NAME.replaceAll($regex, '')) ## Try to remove 'View' string on $NAME variable**
## So the results;**
$checkRegex ## Returns as FALSE**
$moduleName ## Still returns all input as 'FooView'**
If you want to replace View, put it as is in regex:
#set($regex = 'View')
I have variable with "origin/blahbranch" that I want to substring into "blahbranch", how to substring it? I tried with
dev newbranch = (branch1 =~ /.*)[0]
but that left me with
1. / sign included which I don't want
2. the actual git instruction returns error message when embedding the parameter ${newbranch} :
"unexpected char: '''"
Assuming branch1 is string you can use split function
List<String> list = new ArrayList<String>(Arrays.asList(branch1.split("/")));
list.remove(0);
def newbranch = String.join("/", list.toArray(new String[0]))
println newbranch
Very simple solution considering remote always remains origin you can do below
def newbranch = "origin/blahbrachwithslash/blahbranch".replace("origin/","")
println newbranch
I recently asked for help to parse out Java error stacks from a group of log files and got a very nice solution at the link below (using awk).
Pull out Java error stacks from log files
I marked the question answered and after some debugging and studying I found a few potential issues and since they are unrelated to my initial question but rather due to my limited understanding of awk and regular expressions, I thought it might be better to ask a new question.
Here is the solution:
BEGIN{ OFS="," }
/[[:space:]]+*<Error / {
split("",n2v)
while ( match($0,/[^[:space:]]+="[^"]+/) ) {
name = value = substr($0,RSTART,RLENGTH)
sub(/=.*/,"",name)
sub(/^[^=]+="/,"",value)
$0 = substr($0,RSTART+RLENGTH)
n2v[name] = value
print name value
}
code = n2v["ErrorCode"]
desc[code] = n2v["ErrorDescription"]
count[code]++
if (!seen[code,FILENAME]++) {
fnames[code] = (code in fnames ? fnames[code] ", " : "") FILENAME
}
}
END {
print "Count", "ErrorCode", "ErrorDescription", "Files"
for (code in desc) {
print count[code], code, desc[code], fnames[code]
}
}
One issue I am having with it is that not all ErrorDescriptions are being captured. For example, this error description appears in the output of this script:
ErrorDescription="Database Error."
But this error description does not appear in the results (description copied from actual log file):
ErrorDescription="Operation not allowed for reason code "7" on table "SCHEMA.TABLE".. SQLCODE=-668, SQLSTATE=57016, DRIVER=4.13.127"
Nor does this one:
ErrorDescription="Cannot Find Person For Given Order."
It seems that most error descriptions are not being returned by this script but do exist in the log file. I don't see why some error descriptions would appear and some not. Does anyone have any ideas?
EDIT 1:
Here is a sample of the XML I am parsing:
<Errors>
<Error ErrorCode="ERR_0139"
ErrorDescription="Cannot Find Person For Given Order." ErrorMoreInfo="">
...
...
</Error>
</Errors>
The pattern in the script will not match your data:
/[[:space:]]+*<Error / {
Details:
The "+" tells it to match at least one space.
The space after "Error" tells it to match another space - but your data has no space before the "=".
The "<" is unnecessary (but not part of the problem).
This would be a better pattern:
/^[[:space:]]*ErrorDescription[[:space:]]*=[[:space:]]*".*"/
This regex would only match the error description.
ErrorDescription="(.+?)"
It uses a capturing group to remember your error description.
Demo here. (Tested against a combination of your edit and your previous question error log.)
I am fiddling with some a script for Fiddler, which uses JScript.NET. I have a string of the format:
{"params":{"key1":"somevalue","key2":"someothervalue","key3":"whatevervalue", ...
I want to match and show "key2":"someothervalue" where someothervalue could be any value but the key is static.
Using good old sed and bash I can replace the part I am looking for with:
$ a='{"params":{"key1":"somevalue","key2":"someothervalue","key3":"whatevervalue", ...'
$ echo $a | sed -r 's/"key2":"[^"]+"/replaced/g'
{"params":{"key1":"somevalue",replaced,"key3":"whatevervalue", ...
Now. Instead of replacing it, I want to extract that part into a variable using JScript.NET. How can that be done?
The most graceful way is to use a JSON parser. My personal preference is to import IE's JSON parser using the htmlfile COM object.
import System;
var str:String = '{"params":{"key1":"foo","key2":"bar","key3":"baz"}}',
htmlfile = new ActiveXObject('htmlfile');
// force htmlfile COM object into IE9 compatibility
htmlfile.IHTMLDocument2_write('<meta http-equiv="x-ua-compatible" content="IE=9" />');
// clone JSON object and methods into familiar syntax
var JSON = htmlfile.parentWindow.JSON,
// deserialize your JSON-formatted string
obj = JSON.parse(str);
// access JSON values as members of a hierarchical object
Console.WriteLine("params.key2 = " + obj.params.key2);
// beautify the JSON
Console.WriteLine(JSON.stringify(obj, null, '\t'));
Compiling, linking, and running results in the following console output:
params.key2 = bar
{
"params": {
"key1": "foo",
"key2": "bar",
"key3": "baz"
}
}
Alternatively, there are also at least a couple of .NET namespaces which provide methods to serialize objects into a JSON string, and to deserialize a JSON string into objects. Can't say I'm a fan, though. The ECMAScript notation of JSON.parse() and JSON.stringify() are certainly a lot easier and profoundly less alien than whatever neckbeard madness is going on at Microsoft.
And while I certainly don't recommend scraping JSON (or any other hierarchical markup if it can be helped) as complicated text, JScript.NET will handle a lot of familiar Javascript methods and objects, including regex objects and regex replacements on strings.
sed syntax:
echo $a | sed -r 's/("key2"):"[^"]*"/\1:"replaced"/g'
JScript.NET syntax:
print(a.replace(/("key2"):"[^"]*"/, '$1:"replaced"'));
JScript.NET, just like JScript and JavaScript, also allows for calling a lambda function for the replacement.
print(
a.replace(
/"(key2)":"([^"]*)"/,
// $0 = full match; $1 = (key2); $2 = ([^"]*)
function($0, $1, $2):String {
var replace:String = $2.toUpperCase();
return '"$1":"' + replace + '"';
}
)
);
... Or to extract the value of key2 using the RegExp object's exec() method:
var extracted:String = /"key2":"([^"]*)"/.exec(a)[1];
print(extracted);
Just be careful with that, though, as retrieving element [1] of the result of exec() will cause an index-out-of-range exception if there is no match. Might either want to if (/"key2":/.test(a)) or add a try...catch. Or better yet, just do what I said earlier and deserialize your JSON into an object.
In a rather large code base with a few layers is there a way in vim or from the command line to find all classes that are derived from a base class? grep is an option but can be slow since grep does not index.
Neither cscope nor ctags allow us to deal with inheritance directly but it's relatively easy to work around that limitation because derived classes are also indexed.
cscope
In cscope, looking for "C symbol" Foobar usually lists the original class and classes inheriting from it. Since the search is done against a database, it is lightning fast.
Alternatively, you could use cscope's egrep searching capabilities with a pattern like :.*Foobar to list only classes inheriting from Foobar.
So, even if we don't have a dedicated "Find classes inheriting from this class" command, we can get the work done without much effort.
ctags
While ctags allows you to include inheritance information with --fields=+i, that information can't be used directly in Vim. The inherits field is parsed by Vim, though, so it might be possible to build a quick and dirty solution using taglist().
ack, ag
Those two programs work more or less like grep but they are targeted toward searching in source code so they are really faster than grep.
In my Vim config, :grep is set to run the ag program instead of the default grep so, searching for classes derived from the class under the cursor would look like:
:grep :.*<C-r><C-w><CR>
Here are the relevant lines from my ~/.vimrc:
if executable("ag")
set grepprg=ag\ --nogroup\ --nocolor\ --ignore-case\ --column
set grepformat=%f:%l:%c:%m,%f:%l:%m
endif
If you build your tags files with Exuberant CTags using inheritance information (see the --fields option), then the following script will work. It adds an :Inherits command which takes either the name of a class (e.g. :Inherits Foo) or a regular expression.
Like the :tag command, you indicate that you want the search with a regex by preceding it with a '\' character, e.g. :Inherits \Foo.*.
The results are put into the window's location list, which you browse with :ll, :lne, :lp, etc. VIM doesn't seem to allow scripts to modify the tag list which is what I'd prefer.
If you're wondering why I don't use taglist() for this, it's because taglist() is incredibly slow on large tag files. The original post had a version using taglist(), if you're curious you can browse the edit history.
" Parse an Exuberant Ctags record using the same format as taglist()
"
" Throws CtagsParseErr if there is a general problem parsing the record
function! ParseCtagsRec(record, tag_dir)
let tag = {}
" Parse the standard fields
let sep_pos = stridx(a:record, "\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
let tag['name'] = a:record[:sep_pos - 1]
let tail = a:record[sep_pos + 1:]
let sep_pos = stridx(tail, "\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
" '/' will work as a path separator on most OS's, but there
" should really be an OS independent way to build paths.
let tag['filename'] = a:tag_dir.'/'.tail[:sep_pos - 1]
let tail = tail[sep_pos + 1:]
let sep_pos = stridx(tail, ";\"\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
let tag['cmd'] = tail[:sep_pos - 1]
" Parse the Exuberant Ctags extension fields
let extensions = tail[sep_pos + 3:]
for extension in split(extensions, '\t')
let sep_pos = stridx(extension, ':')
if sep_pos < 1
if has_key(tag, 'kind')
throw 'CtagsParseErr'
endif
let tag['kind'] = extension
else
let tag[extension[:sep_pos - 1]] = extension[sep_pos + 1:]
endif
endfor
return tag
endfunction
" Find all classes derived from a given class, or a regex (preceded by a '/')
" The results are placed in the current windows location list.
function! Inherits(cls_or_regex)
if a:cls_or_regex[0] == '/'
let regex = a:cls_or_regex[1:]
else
let regex = '\<'.a:cls_or_regex.'\>$'
endif
let loc_list = []
let tfiles = tagfiles()
let tag_count = 0
let found_count = 0
for file in tfiles
let tag_dir = fnamemodify(file, ':p:h')
try
for line in readfile(file)
let tag_count += 1
if tag_count % 10000 == 0
echo tag_count 'tags scanned,' found_count 'matching classes found. Still searching...'
redraw
endif
if line[0] == '!'
continue
endif
let tag = ParseCtagsRec(line, tag_dir)
if has_key(tag, 'inherits')
let baselist = split(tag['inherits'], ',\s*')
for base in baselist
if match(base, regex) != -1
let location = {}
let location['filename'] = tag['filename']
let cmd = tag['cmd']
if cmd[0] == '/' || cmd[0] == '?'
let location['pattern'] = cmd[1:-2]
else
let location['lnum'] = str2nr(cmd)
endif
call add(loc_list, location)
let found_count += 1
endif
endfor
endif
endfor
catch /^OptionErr$/
echo 'Parsing error: Failed to parse an option.'
return
catch /^CtagsParseErr$/
echo 'Parsing error: Tags files does not appear to be an Exuberant Ctags file.'
return
catch
echo 'Could not read tag file:' file
return
endtry
endfor
call setloclist(0, loc_list)
echo tag_count 'tags scanned,' found_count 'matching classes found.'
endfunction
command! -nargs=1 -complete=tag Inherits call Inherits('<args>')
In lh-cpp, I define the command :Children. It relies on a ctags database, and as a consequence, it is quite limited.
It takes two optional parameters: the namespace where to look for (I haven't found a way to avoid that), and the name of the parent class -> :Children [!] {namespace} {parent-class}.
The command tries to cache as much information as possible. Hence, when pertinent information changes in the ctags database, the cache must be updated. It is done by banging the command -> :Children!
I don't think vim is the correct tool to list all child classes. Instead, we'd better use the doxygen to generate documentation for the source code. Although the doxygen needs some time, we can use the document/diagrams for all classes, which is clear and fast.