381 lines
7.4 KiB
Awk
381 lines
7.4 KiB
Awk
# ╭──────╮
|
|
# │ code │
|
|
# ╰──────╯
|
|
|
|
# ╭──────┬───────────╮
|
|
# │ code │ functions │
|
|
# ╰──────┴───────────╯
|
|
|
|
function alias_eval(new, name, type) {
|
|
text = new "() { "
|
|
if (type == "function") {
|
|
text = text name " \"${@}\""
|
|
} else if (type == "variable") {
|
|
text = text "echo \"${" name "}\""
|
|
}
|
|
print text "; }"
|
|
}
|
|
|
|
# TODO delete when useless
|
|
function extract(string, type) {
|
|
if (type == "alias") {
|
|
split(string, array, "#=")
|
|
return strip(array[2])
|
|
} else if (type == "command") {
|
|
split(string, array, "#/")
|
|
return strip(array[2])
|
|
} else if (type == "doc") {
|
|
split(string, array, "#")
|
|
return strip(array[2])
|
|
} else if (type == "function") {
|
|
split(string, array, "(")
|
|
return strip(array[1])
|
|
} else if (type == "module") {
|
|
split(string, array, "#\\.")
|
|
return strip(array[2])
|
|
} else if (type == "shebang") {
|
|
split(string, array, "#!")
|
|
return strip(array[2])
|
|
} else if ((type == "constant") || (type == "variable")) {
|
|
split(string, array, "=")
|
|
return strip(array[1])
|
|
}
|
|
}
|
|
|
|
# ╭──────┬───────────┬─────╮
|
|
# │ code │ functions │ doc │
|
|
# ╰──────┴───────────┴─────╯
|
|
|
|
function doc_append(string) {
|
|
if (doc) {
|
|
doc = doc "\n"
|
|
}
|
|
doc = doc string
|
|
}
|
|
|
|
function doc_output(name, type) {
|
|
print "↙ " type
|
|
print name
|
|
print doc
|
|
exit
|
|
}
|
|
|
|
function doc_reset() {
|
|
if (current_function == "") {
|
|
doc = ""
|
|
}
|
|
}
|
|
|
|
# ╭──────┬───────────┬───────╮
|
|
# │ code │ functions │ strip │
|
|
# ╰──────┴───────────┴───────╯
|
|
|
|
function strip(string, tmp) {
|
|
tmp = string
|
|
sub("^[\t ]*", "", tmp)
|
|
sub("[\t ]*$", "", tmp)
|
|
return tmp
|
|
}
|
|
|
|
function strip_first(string, sep, tmp) {
|
|
tmp = string
|
|
sub(sep, "", tmp)
|
|
return strip(tmp)
|
|
}
|
|
|
|
function strip_from(string, sep, tmp) {
|
|
split(string, tmp, sep)
|
|
return strip(tmp[1])
|
|
}
|
|
|
|
function strip_function(string) {
|
|
return strip_from(string, "(")
|
|
}
|
|
|
|
function strip_task(string) {
|
|
return strip_from(strip_first(string, "#"), " ")
|
|
}
|
|
|
|
function strip_value(string) {
|
|
return strip_from(string, "=")
|
|
}
|
|
|
|
# ╭──────┬───────╮
|
|
# │ code │ begin │
|
|
# ╰──────┴───────╯
|
|
|
|
BEGIN {
|
|
|
|
RE_ANY = "(.*)"
|
|
RE_BEGIN = "^"
|
|
RE_CONST = "([_A-Z][_0-9A-Z]*)"
|
|
RE_SET = "=.*"
|
|
RE_SPACE = "[[:space:]]"
|
|
RE_TSK = "(FIXME|TODO)"
|
|
RE_VAR = "([_a-z][_0-9a-z]*)"
|
|
|
|
RE_SPACES = RE_SPACE "*"
|
|
|
|
RE_END = RE_SPACES "$"
|
|
RE_FUNC = RE_SPACES "\\(" RE_SPACES "\\)" RE_SPACES "{"
|
|
|
|
re["alias"] = RE_BEGIN "#=" RE_SPACES RE_VAR RE_END
|
|
re["binary"] = RE_BEGIN "#\\|" RE_SPACES RE_VAR RE_END
|
|
RE_CLOSE = RE_BEGIN "}" RE_SPACES RE_END
|
|
re["command"] = RE_BEGIN "#/" RE_SPACES RE_VAR RE_END
|
|
RE_COMMENT = RE_BEGIN RE_SPACES "# " RE_ANY RE_END
|
|
re["constant"] = RE_BEGIN RE_CONST RE_SET RE_END
|
|
RE_DOC = RE_BEGIN "# " RE_ANY RE_END
|
|
re["function"] = RE_BEGIN RE_VAR RE_FUNC RE_END
|
|
RE_MODULE = RE_BEGIN "#\\." RE_SPACES RE_ANY RE_END
|
|
RE_SHEBANG = RE_BEGIN "#!" RE_SPACES RE_ANY RE_END
|
|
RE_TASK = RE_BEGIN RE_SPACES "#" RE_SPACES RE_TSK RE_ANY RE_END
|
|
re["variable"] = RE_BEGIN RE_VAR RE_SET RE_END
|
|
|
|
doc = ""
|
|
line = 0
|
|
module = ""
|
|
|
|
}
|
|
|
|
# ╭──────┬───────╮
|
|
# │ code │ parse │
|
|
# ╰──────┴───────╯
|
|
|
|
function parse(string) {
|
|
|
|
# module
|
|
if (match(string, RE_MODULE)) {
|
|
current_match = "module"
|
|
line = 0
|
|
module = strip_first(string, "#\\.")
|
|
doc_reset()
|
|
shebang = ""
|
|
|
|
# shebang
|
|
} else if (match(string, RE_SHEBANG)) {
|
|
current_match = "shebang"
|
|
shebang = strip_first(string, "#!")
|
|
|
|
# constant
|
|
} else if (match(string, re["constant"])) {
|
|
current_match = "constant"
|
|
constant = strip_value(string)
|
|
|
|
# variable
|
|
} else if (match(string, re["variable"])) {
|
|
current_match = "variable"
|
|
variable = strip_value(string)
|
|
|
|
# alias
|
|
} else if (match(string, re["alias"])) {
|
|
current_match = "alias"
|
|
alias = strip_first(string, "#=")
|
|
aliases[alias] = ""
|
|
doc_append("= " alias)
|
|
|
|
# command
|
|
} else if (match(string, re["command"])) {
|
|
current_match = "command"
|
|
command = strip_first(string, "#/")
|
|
commands[command] = ""
|
|
doc_append("/ " command)
|
|
|
|
# function
|
|
} else if (match(string, re["function"])) {
|
|
current_match = "function"
|
|
current_function = strip_function(string)
|
|
|
|
# task
|
|
} else if (match(string, RE_TASK)) {
|
|
current_match = "task"
|
|
task = strip_task(string)
|
|
tasks[task] = ""
|
|
doc_append(line " " string)
|
|
|
|
# doc
|
|
} else if (match(string, RE_DOC)) {
|
|
doc_append(strip_first(string, "# "))
|
|
|
|
# comment
|
|
} else if (match(string, RE_COMMENT)) {
|
|
doc_append(string)
|
|
|
|
# other
|
|
} else {
|
|
if (module == target) {
|
|
doc_output(target, "module")
|
|
} else {
|
|
doc_reset()
|
|
}
|
|
|
|
}
|
|
|
|
# close
|
|
if (match(string, RE_CLOSE)) {
|
|
current_match = "close"
|
|
}
|
|
|
|
}
|
|
|
|
# ╭──────┬──────╮
|
|
# │ code │ main │
|
|
# ╰──────┴──────╯
|
|
|
|
{
|
|
|
|
# doc
|
|
if (action == "doc") {
|
|
parse($0)
|
|
|
|
# constant
|
|
if (current_match == "constant") {
|
|
if (constant == target) {
|
|
doc_output(constant, "constant")
|
|
} else {
|
|
doc_reset()
|
|
constant = ""
|
|
}
|
|
|
|
# variable
|
|
} else if (current_match == "variable") {
|
|
if (variable == target) {
|
|
doc_output(variable, "variable")
|
|
} else {
|
|
doc_reset()
|
|
variable = ""
|
|
}
|
|
|
|
# match
|
|
}
|
|
|
|
# function
|
|
if (current_match == "close") {
|
|
if (target == current_function) {
|
|
doc_output(current_function, "function")
|
|
} else if (target in aliases) {
|
|
print "= " target
|
|
doc_output(current_function, "function")
|
|
} else if (target in commands) {
|
|
print "/ " target
|
|
doc_output(current_function, "function")
|
|
} else {
|
|
current_function = ""
|
|
doc_reset()
|
|
}
|
|
}
|
|
|
|
# tasks
|
|
} else if (action == "tasks") {
|
|
parse($0)
|
|
|
|
# module
|
|
if (current_match == "module") {
|
|
if (output_tasks) {
|
|
print ""
|
|
print ". " module
|
|
print output_tasks
|
|
output_tasks = ""
|
|
}
|
|
doc = ""
|
|
match_task = 0
|
|
|
|
# task
|
|
} else if (current_match == "task") {
|
|
if (target) {
|
|
if (target in tasks) {
|
|
match_task = 1
|
|
}
|
|
} else {
|
|
match_task = 1
|
|
}
|
|
|
|
# other
|
|
} else {
|
|
if (match_task) {
|
|
output_tasks = output_tasks "\n" doc
|
|
}
|
|
doc = ""
|
|
match_task = 0
|
|
|
|
# match
|
|
}
|
|
|
|
# function
|
|
} else if (action == "function") {
|
|
if (match($0, re["command"])) {
|
|
doc_append(extract($0, "command"))
|
|
} else if (match($0, re["function"])) {
|
|
split(doc, array, "\n")
|
|
for (item in array) {
|
|
if (array[item] == target) {
|
|
print extract($0, "function")
|
|
exit
|
|
}
|
|
}
|
|
doc_reset()
|
|
} else {
|
|
doc_reset()
|
|
}
|
|
|
|
# eval
|
|
} else if (action == "eval") {
|
|
if (match($0, re[target])) {
|
|
doc_append(extract($0, target))
|
|
} else if (match($0, re["function"])) {
|
|
split(doc, array, "\n")
|
|
for (item in array) {
|
|
alias_eval(array[item], extract($0, "function"), "function")
|
|
}
|
|
doc_reset()
|
|
} else {
|
|
doc_reset()
|
|
}
|
|
|
|
# filter
|
|
} else if (action == "filter") {
|
|
if (match($0, re[target])) {
|
|
unique[extract($0, target)] = ""
|
|
}
|
|
|
|
# lint
|
|
} else if (action == "lint") {
|
|
parse($0)
|
|
|
|
# TODO RWX_ constant
|
|
# TODO rwx_ variable
|
|
# TODO rwx_ function
|
|
|
|
# TODO unique alias
|
|
# TODO unique command
|
|
# TODO unique function
|
|
|
|
# unknown
|
|
} else {
|
|
print "unknown action: " action
|
|
exit 1
|
|
|
|
# action
|
|
}
|
|
|
|
# main
|
|
line++
|
|
}
|
|
|
|
# ╭──────┬─────╮
|
|
# │ code │ end │
|
|
# ╰──────┴─────╯
|
|
|
|
END {
|
|
|
|
# filter
|
|
if (action == "filter") {
|
|
for (item in unique) {
|
|
print item
|
|
}
|
|
|
|
# action
|
|
}
|
|
|
|
# end
|
|
}
|