add updates libs
This commit is contained in:
@@ -32,13 +32,9 @@ these would be helpful for your use case, please file an issue.
|
||||
- https://www.tcl.tk/man/tcl/TclCmd/mathop.html
|
||||
"""
|
||||
|
||||
from tclint.commands.checks import (
|
||||
CommandArgError,
|
||||
check_count,
|
||||
eval,
|
||||
)
|
||||
from tclint.commands.checks import CommandArgError, check_arg_spec, check_count, eval
|
||||
from tclint.commands.schema import commands_schema
|
||||
from tclint.syntax_tree import BareWord
|
||||
from tclint.syntax_tree import BareWord, Node
|
||||
|
||||
|
||||
def _check_code(arg):
|
||||
@@ -77,7 +73,7 @@ def _after(args, parser):
|
||||
def _after_cancel(args, parser):
|
||||
"""after id|(script...)"""
|
||||
# ref: https://www.tcl.tk/man/tcl/TclCmd/after.html
|
||||
check_count("after cancel", 1, None)
|
||||
check_count("after cancel", 1, None)(args, parser)
|
||||
|
||||
# TODO: raise warning about not checking code
|
||||
|
||||
@@ -181,20 +177,6 @@ _array = {
|
||||
}
|
||||
|
||||
|
||||
def _catch(args, parser):
|
||||
"""catch script [resultVarName] [optionsVarName]"""
|
||||
if len(args) < 1:
|
||||
raise CommandArgError(
|
||||
f"not enough args to catch: got {len(args)}, expected at least 1"
|
||||
)
|
||||
if len(args) > 3:
|
||||
raise CommandArgError(
|
||||
f"too many args to catch: got {len(args)}, expected no more than 3"
|
||||
)
|
||||
|
||||
return [parser.parse_script(args[0])] + args[1:]
|
||||
|
||||
|
||||
_chan = {
|
||||
"subcommands": {
|
||||
"blocked": {
|
||||
@@ -350,43 +332,37 @@ def _dict_filter(args, parser):
|
||||
|
||||
def _dict_map_for(cmd):
|
||||
def check(args, parser):
|
||||
if len(args) != 3:
|
||||
raise CommandArgError(
|
||||
f"wrong # of args to '{cmd}': got {len(args)}, expected 3"
|
||||
)
|
||||
|
||||
spec = {
|
||||
"positionals": [
|
||||
{"name": "keyValueList", "value": {"type": "any"}, "required": True},
|
||||
{"name": "dictionaryValue", "value": {"type": "any"}, "required": True},
|
||||
{"name": "body", "value": {"type": "script"}, "required": True},
|
||||
],
|
||||
"switches": {},
|
||||
}
|
||||
# TODO: might be worth checking that arg[0] is a pair?
|
||||
|
||||
return args[0:2] + [parser.parse_script(args[2])]
|
||||
return check_arg_spec(cmd, args, parser, spec)
|
||||
|
||||
return check
|
||||
|
||||
|
||||
def _dict_update(args, parser):
|
||||
# ref: https://www.tcl.tk/man/tcl/TclCmd/dict.html#M25
|
||||
"""dict update dictionaryVariable key varName ?key varName ...? body
|
||||
|
||||
if len(args) < 4:
|
||||
raise CommandArgError(
|
||||
f"not enough args to 'dict update': got {len(args)}, expected at least 4"
|
||||
)
|
||||
|
||||
if len(args) % 2 != 0:
|
||||
raise CommandArgError(
|
||||
"invalid # of args to 'dict update': expected an even number"
|
||||
)
|
||||
|
||||
return args[0:-1] + [parser.parse_script(args[-1])]
|
||||
|
||||
|
||||
def _dict_with(args, parser):
|
||||
# ref: https://www.tcl.tk/man/tcl/TclCmd/dict.html#M27
|
||||
|
||||
if len(args) < 2:
|
||||
raise CommandArgError(
|
||||
f"not enough args to 'dict with': got {len(args)}, expected at least 2"
|
||||
)
|
||||
|
||||
return args[0:-1] + [parser.parse_script(args[-1])]
|
||||
ref: https://www.tcl-lang.org/man/tcl8.6/TclCmd/dict.htm#M25
|
||||
"""
|
||||
spec = {
|
||||
"positionals": [
|
||||
{"name": "dictionaryVariable", "value": {"type": "any"}, "required": True},
|
||||
{"name": "key", "value": {"type": "any"}, "required": True},
|
||||
{"name": "varName", "value": {"type": "any"}, "required": True},
|
||||
{"name": "key varName", "value": {"type": "variadic"}, "required": False},
|
||||
{"name": "body", "value": {"type": "script"}, "required": True},
|
||||
],
|
||||
"switches": {},
|
||||
}
|
||||
# TODO: Check that number of variadic words is even.
|
||||
return check_arg_spec("dict update", args, parser, spec)
|
||||
|
||||
|
||||
def _eval(args, parser):
|
||||
@@ -434,53 +410,100 @@ def _fileevent(args, parser):
|
||||
)
|
||||
|
||||
|
||||
def _for(args, parser):
|
||||
# ref: https://www.tcl.tk/man/tcl/TclCmd/for.html
|
||||
if len(args) != 4:
|
||||
raise CommandArgError(f"wrong # of args to for: got {len(args)}, expected 4")
|
||||
def foreach(args, parser):
|
||||
"""
|
||||
foreach varname list ?varlist list ...? body
|
||||
|
||||
return [
|
||||
parser.parse_script(args[0]),
|
||||
parser.parse_expression(args[1]),
|
||||
parser.parse_script(args[2]),
|
||||
parser.parse_script(args[3]),
|
||||
]
|
||||
ref: https://www.tcl-lang.org/man/tcl8.6/TclCmd/foreach.htm
|
||||
"""
|
||||
spec = {
|
||||
"positionals": [
|
||||
{"name": "varname", "value": {"type": "any"}, "required": True},
|
||||
{"name": "list", "value": {"type": "any"}, "required": True},
|
||||
{"name": "varlist list", "value": {"type": "variadic"}, "required": False},
|
||||
{"name": "body", "value": {"type": "script"}, "required": True},
|
||||
],
|
||||
"switches": {},
|
||||
}
|
||||
# TODO: check that "varlist list" comes in pairs.
|
||||
return check_arg_spec("foreach", args, parser, spec)
|
||||
|
||||
|
||||
def _foreach(args, parser):
|
||||
# ref: https://www.tcl.tk/man/tcl/TclCmd/foreach.html
|
||||
if len(args) < 3:
|
||||
raise CommandArgError(
|
||||
f"insufficient args to foreach: got {len(args)}, expected at least 3"
|
||||
)
|
||||
def _if(args, parser) -> list[Node]:
|
||||
# ref: https://www.tcl-lang.org/man/tcl8.6/TclCmd/if.htm
|
||||
|
||||
# last argument is script body
|
||||
return args[0:-1] + [parser.parse_script(args[-1])]
|
||||
|
||||
|
||||
def _if(args, parser):
|
||||
# ref: https://www.tcl.tk/man/tcl/TclCmd/if.html
|
||||
# TODO: make arg checking strict
|
||||
|
||||
new_args = []
|
||||
new_args: list[Node] = []
|
||||
|
||||
# Parse if condition.
|
||||
if len(new_args) == len(args):
|
||||
raise CommandArgError("Expected condition argument in 'if'")
|
||||
new_args.append(parser.parse_expression(args[0]))
|
||||
|
||||
while len(new_args) < len(args):
|
||||
arg = args[len(new_args)]
|
||||
|
||||
if arg.contents == "then" or arg.contents == "else":
|
||||
new_args.append(arg)
|
||||
continue
|
||||
if arg.contents == "elseif":
|
||||
new_args.append(arg)
|
||||
new_args.append(parser.parse_expression(args[len(new_args)]))
|
||||
continue
|
||||
|
||||
arg = parser.parse_script(arg)
|
||||
# Parse optional noise word then.
|
||||
if len(new_args) == len(args):
|
||||
raise CommandArgError("Expected then or body argument in 'if'")
|
||||
arg = args[len(new_args)]
|
||||
if arg.contents == "then":
|
||||
new_args.append(arg)
|
||||
|
||||
return new_args
|
||||
# Parse if body.
|
||||
if len(new_args) == len(args):
|
||||
raise CommandArgError("Expected body argument in 'if'")
|
||||
new_args.append(parser.parse_script(args[len(new_args)]))
|
||||
|
||||
# Parse elseif.
|
||||
while (
|
||||
len(new_args) < len(args)
|
||||
and (arg := args[len(new_args)])
|
||||
and arg.contents == "elseif"
|
||||
):
|
||||
new_args.append(arg)
|
||||
|
||||
# Parse elseif condition.
|
||||
if len(new_args) == len(args):
|
||||
raise CommandArgError(
|
||||
"Expected condition argument in 'elseif' part of 'if'"
|
||||
)
|
||||
new_args.append(parser.parse_expression(args[len(new_args)]))
|
||||
|
||||
# Parse optional noise word then.
|
||||
if len(new_args) == len(args):
|
||||
raise CommandArgError(
|
||||
"Expected then or body argument in 'elseif' part of 'if'"
|
||||
)
|
||||
arg = args[len(new_args)]
|
||||
if arg.contents == "then":
|
||||
new_args.append(arg)
|
||||
|
||||
# Parse elseif body.
|
||||
if len(new_args) == len(args):
|
||||
raise CommandArgError("Expected body argument in 'elseif' part of 'if'")
|
||||
new_args.append(parser.parse_script(args[len(new_args)]))
|
||||
|
||||
if len(new_args) == len(args):
|
||||
# No else part, we're done.
|
||||
return new_args
|
||||
|
||||
# Parse optional noise word else.
|
||||
arg = args[len(new_args)]
|
||||
if arg.contents == "else":
|
||||
new_args.append(arg)
|
||||
|
||||
# Parse else body.
|
||||
if len(new_args) == len(args):
|
||||
raise CommandArgError("Expected body argument to 'else' part of 'if'")
|
||||
new_args.append(parser.parse_script(args[len(new_args)]))
|
||||
|
||||
if len(new_args) == len(args):
|
||||
# Else part parsed, we're done.
|
||||
return new_args
|
||||
|
||||
# Handle superfluous args.
|
||||
arg = args[len(new_args)]
|
||||
if arg.contents is None or not arg.contents:
|
||||
raise CommandArgError("Argument after complete 'if'")
|
||||
else:
|
||||
raise CommandArgError(f"Argument after complete 'if': {arg.contents}")
|
||||
|
||||
|
||||
def _interp_eval(args, parser):
|
||||
@@ -492,13 +515,22 @@ def _interp_eval(args, parser):
|
||||
|
||||
|
||||
def _lmap(args, parser):
|
||||
# ref: https://www.tcl.tk/man/tcl/TclCmd/lmap.html
|
||||
if len(args) < 3:
|
||||
raise CommandArgError(
|
||||
f"not enough args to lmap: got {len(args)}, expected at least 3"
|
||||
)
|
||||
"""
|
||||
lmap varlist1 list1 ?varlist2 list2 ...? body
|
||||
|
||||
return args[:-1] + [parser.parse_script(args[-1])]
|
||||
ref: https://www.tcl-lang.org/man/tcl8.6/TclCmd/lmap.htm
|
||||
"""
|
||||
spec = {
|
||||
"positionals": [
|
||||
{"name": "varlist1", "value": {"type": "any"}, "required": True},
|
||||
{"name": "list1", "value": {"type": "any"}, "required": True},
|
||||
{"name": "varlist list", "value": {"type": "variadic"}, "required": False},
|
||||
{"name": "body", "value": {"type": "script"}, "required": True},
|
||||
],
|
||||
"switches": {},
|
||||
}
|
||||
# TODO: Check that number of variadic words is even.
|
||||
return check_arg_spec("lmap", args, parser, spec)
|
||||
|
||||
|
||||
def _namespace_code(args, parser):
|
||||
@@ -656,6 +688,9 @@ def _switch(args, parser):
|
||||
for i, node in enumerate(pattern_and_commands):
|
||||
if i % 2 == 0:
|
||||
parsed_patterns_and_commands.append(node)
|
||||
elif node.contents == "-":
|
||||
# Detect passthrough.
|
||||
parsed_patterns_and_commands.append(node)
|
||||
else:
|
||||
parsed_patterns_and_commands.append(parser.parse_script(node))
|
||||
|
||||
@@ -795,16 +830,6 @@ def _try(args, parser):
|
||||
return new_args
|
||||
|
||||
|
||||
def _while(args, parser):
|
||||
if len(args) != 2:
|
||||
raise CommandArgError(f"wrong # of args to while: got {len(args)}, expected 2")
|
||||
|
||||
return [
|
||||
parser.parse_expression(args[0]),
|
||||
parser.parse_script(args[1]),
|
||||
]
|
||||
|
||||
|
||||
commands = commands_schema({
|
||||
"after": {
|
||||
"subcommands": {
|
||||
@@ -828,14 +853,63 @@ commands = commands_schema({
|
||||
"array": _array,
|
||||
"binary": {
|
||||
"subcommands": {
|
||||
"decode": check_count("binary decode", 2, None),
|
||||
"encode": check_count("binary encode", 2, None),
|
||||
"format": check_count("binary format", 1, None),
|
||||
"scan": check_count("binary scan", 2, None),
|
||||
"decode": {
|
||||
"positionals": [
|
||||
{"name": "format", "value": {"type": "any"}, "required": True},
|
||||
{
|
||||
"name": "options",
|
||||
"value": {"type": "variadic"},
|
||||
"required": False,
|
||||
},
|
||||
{"name": "data", "value": {"type": "any"}, "required": True},
|
||||
],
|
||||
},
|
||||
"encode": {
|
||||
"positionals": [
|
||||
{"name": "format", "value": {"type": "any"}, "required": True},
|
||||
{
|
||||
"name": "options",
|
||||
"value": {"type": "variadic"},
|
||||
"required": False,
|
||||
},
|
||||
{"name": "data", "value": {"type": "any"}, "required": True},
|
||||
],
|
||||
},
|
||||
"format": {
|
||||
"positionals": [
|
||||
{
|
||||
"name": "formatString",
|
||||
"value": {"type": "any"},
|
||||
"required": True,
|
||||
},
|
||||
{"name": "args", "value": {"type": "variadic"}, "required": False},
|
||||
],
|
||||
},
|
||||
"scan": {
|
||||
"positionals": [
|
||||
{"name": "string", "value": {"type": "any"}, "required": True},
|
||||
{
|
||||
"name": "formatString",
|
||||
"value": {"type": "any"},
|
||||
"required": True,
|
||||
},
|
||||
{
|
||||
"name": "varName",
|
||||
"value": {"type": "variadic"},
|
||||
"required": False,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
"break": check_count("break", 0, 0),
|
||||
"catch": _catch,
|
||||
"break": {},
|
||||
"catch": {
|
||||
"positionals": [
|
||||
{"name": "script", "value": {"type": "script"}, "required": True},
|
||||
{"name": "resultVarName", "value": {"type": "any"}, "required": False},
|
||||
{"name": "optionsVarName", "value": {"type": "any"}, "required": False},
|
||||
]
|
||||
},
|
||||
"cd": {
|
||||
"positionals": [
|
||||
{"name": "dirName", "value": {"type": "any"}, "required": False}
|
||||
@@ -884,7 +958,17 @@ commands = commands_schema({
|
||||
"unset": check_count("dict unset", 2, None),
|
||||
"update": _dict_update,
|
||||
"values": check_count("dict values", 1, 2),
|
||||
"with": _dict_with,
|
||||
"with": {
|
||||
"positionals": [
|
||||
{
|
||||
"name": "dictionaryVariable",
|
||||
"value": {"type": "any"},
|
||||
"required": True,
|
||||
},
|
||||
{"name": "key", "value": {"type": "variadic"}, "required": False},
|
||||
{"name": "script", "value": {"type": "script"}, "required": True},
|
||||
]
|
||||
},
|
||||
},
|
||||
},
|
||||
"encoding": {
|
||||
@@ -909,8 +993,15 @@ commands = commands_schema({
|
||||
"file": check_count("file", 1, None),
|
||||
"fileevent": _fileevent,
|
||||
"flush": check_count("flush", 1, 1),
|
||||
"for": _for,
|
||||
"foreach": _foreach,
|
||||
"for": {
|
||||
"positionals": [
|
||||
{"name": "start", "value": {"type": "script"}, "required": True},
|
||||
{"name": "test", "value": {"type": "expression"}, "required": True},
|
||||
{"name": "next", "value": {"type": "script"}, "required": True},
|
||||
{"name": "body", "value": {"type": "script"}, "required": True},
|
||||
],
|
||||
},
|
||||
"foreach": foreach,
|
||||
"format": check_count("format", 1, None),
|
||||
"gets": check_count("gets", 1, 2),
|
||||
"glob": check_count("glob"),
|
||||
@@ -974,8 +1065,28 @@ commands = commands_schema({
|
||||
"inscope": _namespace_inscope,
|
||||
"origin": check_count("namespace origin", 1, 1),
|
||||
"parent": check_count("namespace parent", 0, 1),
|
||||
"path": {
|
||||
"positionals": [
|
||||
{
|
||||
"name": "namespaceList",
|
||||
"value": {"type": "any"},
|
||||
"required": False,
|
||||
},
|
||||
]
|
||||
},
|
||||
"qualifiers": check_count("namespace qualifiers", 1, 1),
|
||||
"tail": check_count("namespace tail", 1, 1),
|
||||
"unknown": {
|
||||
"positionals": [
|
||||
{"name": "script", "value": {"type": "script"}, "required": False}
|
||||
]
|
||||
},
|
||||
"upvar": {
|
||||
"positionals": [
|
||||
{"name": "namespace", "value": {"type": "any"}, "required": True},
|
||||
{"name": "var", "value": {"type": "variadic"}, "required": False},
|
||||
]
|
||||
},
|
||||
"which": check_count("namespace which", 1, 2),
|
||||
"ensemble": {
|
||||
"subcommands": {
|
||||
@@ -1028,7 +1139,7 @@ commands = commands_schema({
|
||||
"source": check_count("source", 1, 3),
|
||||
"split": check_count("split", 1, 2),
|
||||
# TODO: check subcommands
|
||||
"string": check_count("string", 2, None),
|
||||
"string": check_count("string", 1, None),
|
||||
"subst": check_count("subst", 1, 4),
|
||||
"switch": _switch,
|
||||
"tailcall": check_count("tailcall", 1, None),
|
||||
@@ -1061,7 +1172,12 @@ commands = commands_schema({
|
||||
"upvar": check_count("upvar", 2, None),
|
||||
"variable": check_count("variable", 1, None),
|
||||
"vwait": check_count("vwait", 1, 1),
|
||||
"while": _while,
|
||||
"while": {
|
||||
"positionals": [
|
||||
{"name": "test", "value": {"type": "expression"}, "required": True},
|
||||
{"name": "body", "value": {"type": "script"}, "required": True},
|
||||
],
|
||||
},
|
||||
"yield": {
|
||||
"positionals": [
|
||||
{"name": "value", "value": {"type": "any"}, "required": False},
|
||||
@@ -1074,5 +1190,5 @@ commands = commands_schema({
|
||||
]
|
||||
},
|
||||
# TODO: check subcommands
|
||||
"zlib": check_count("zlib", 3, None),
|
||||
"zlib": check_count("zlib", 2, None),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user