|
3 | 3 | # |
4 | 4 | # axiomcode index [<repo>] [--lang java|typescript|python|javascript|csharp] [--src <subdir>] [--library <root>[,<root>…]] |
5 | 5 | # the pipeline: parser → engine → .axiomcode/out/graph.sqlite (+ index). <repo> defaults to the current directory. |
6 | | -# axiomcode context "<the task, in your own words>" [<repo>] [--in <path>[,<path>…]]… [--budget N] [--source] [--json] [--fresh] |
| 6 | +# axiomcode context "<the task, in your own words>" [<repo>] [--in <path>[,<path>…]]… [--budget N] [--source] [--json] [--fresh] [--grep] |
7 | 7 | # THE FRONT DOOR: the files and callables a task touches, from the problem statement — when there is no name |
8 | 8 | # to ask about yet. Deterministic: task terms scored against the graph's vocabulary by inverse document |
9 | 9 | # frequency, tests demoted, the closure walked from the best seed per term and ranked by nearest hop. |
|
16 | 16 | # and --library it was indexed with, never for a language the index left out; indexed first when there is none. |
17 | 17 | # Prints what it drew and the page's absolute path: <repo>/.axiomcode/graph/graph.html, or --out (a folder gets |
18 | 18 | # <folder>/<repo>.html, a .html path is used as given). The page embeds the sources, so a node opens its code. |
19 | | -# axiomcode path <from> <to> [<repo>] [--every | --paths N] [--all] [--limit N] [--in <path fragment>] [--json] [--fresh] |
| 19 | +# axiomcode path <from> <to> [<repo>] [--every | --paths N] [--all] [--limit N] [--in <path fragment>] [--json] [--fresh] [--grep] |
20 | 20 | # the shortest chain of calls from A to B per reached target, and with --every all the routes; through what? |
21 | 21 | # '*' as one endpoint: path '*' X = everything that can reach X, with the entry points among them; path X '*' = everything X reaches. Endpoints exactly as written in the code: Owner.method, |
22 | 22 | # method (free function or any owner), Type (all its methods), file.ts:123, file.py. Datalog over the graph; every |
23 | 23 | # printed hop re-checked against graph.sqlite. `axiomcode path --selftest <lang>` replays the engine's expected edges. |
24 | 24 | # Every hop carries the LINE THE CALL IS WRITTEN ON, how certain the edge is, and what kind of call it is — |
25 | 25 | # an invocation, a construction, a constructor chain, a super call, a decorator, a property access, a method |
26 | 26 | # reference — in one vocabulary across all five languages. A hop that is not a call is marked and not counted. |
27 | | -# axiomcode impact <target> [<target>…] [<repo>] [--tests] [--depth N] [--in <path>] [--limit N] [--json] [--kind k] [--fresh] |
| 27 | +# axiomcode impact <target> [<target>…] [<repo>] [--tests] [--depth N] [--in <path>] [--limit N] [--json] [--kind k] [--fresh] [--grep] |
28 | 28 | # what has to be looked at again when a declaration changes: a method, a field / constant / enum member, a type, a |
29 | 29 | # parameter (Owner.m(p)), a type parameter (Type<T>), a local (Owner.m:v), Type.<init> / Type.<clinit>. Prints what |
30 | 30 | # must change with it (overrides, subtypes), what directly touches it with WHY and how sure ([resolved] / [in scope] / |
|
36 | 36 | # name, initializer; type header; body only; removed; added) — the working tree against the commit the graph was built |
37 | 37 | # from, or a branch's commits (--range a..b reads from `git merge-base a b`) — each with the target `impact` takes; |
38 | 38 | # --impact runs impact on all of them as one change set. Without git, name the files. |
39 | | -# axiomcode test-impact [<repo>] [<file>…] [--range <a>..<b> | --staged] [--in <path>] [--limit N] [--json] [--why] |
| 39 | +# axiomcode test-impact [<repo>] [<file>…] [--range <a>..<b> | --staged] [--in <path>] [--limit N] [--json] [--why] [--grep] |
40 | 40 | # which tests actually have to run for this edit: the test files that reach any changed declaration, with the |
41 | 41 | # chain, so a selection can be checked rather than trusted. Conservative by design — a test reached only |
42 | 42 | # through an edge the graph does not encode (reflection, a service loader) will NOT appear. |
|
50 | 50 | # language's, the one with the most files, first). --lang restricts it to one language or a comma list, the first the main one; |
51 | 51 | # --src limits the analysed tree (e.g. src); --library names dependency roots. --fresh (context, path, impact) waits for |
52 | 52 | # a refresh in flight and answers from the new graph; without it an answer from a graph older than an edit marks its rows. |
| 53 | +# --grep (context, path, impact, test-impact) prints the answer's sites one per line, as grep does: `path:line: <the code |
| 54 | +# on that line> [resolved | one of a set | by name | text | hop N | test]`, the first 30 (--grep-limit N) and a count of |
| 55 | +# the rest, then whether it was verified and its bound. The MCP tools answer this way by default; full=True is the prose. |
53 | 56 | case "$0" in */*) H="${0%/*}";; *) H=.;; esac; H="$(cd "${H:-/}" && pwd)" # no `dirname`: see bin/axiomcode |
54 | 57 |
|
55 | 58 | # PYTHON UNDER ANOTHER NAME (#1331). Every verb runs `python3`, which a python.org install on Windows does not |
@@ -101,6 +104,8 @@ while [ $# -gt 0 ]; do |
101 | 104 | --src) export AXIOMCODE_SRC="$2"; shift 2 ;; |
102 | 105 | --library) export AXIOMCODE_LIBRARY="$2"; shift 2 ;; |
103 | 106 | --fresh) export AXIOMCODE_FRESH=1; shift ;; |
| 107 | + --grep) GREP=1; shift ;; |
| 108 | + --grep-limit) GREP=1; GREP_LIMIT="$2"; shift 2 ;; |
104 | 109 | *) ARGS+=("$1"); shift ;; |
105 | 110 | esac |
106 | 111 | done |
@@ -128,24 +133,29 @@ FR=.; skip=""; for a in ${ARGS[@]+"${ARGS[@]}"}; do |
128 | 133 | case "$a" in --in|--from|--budget|--seeds|--depth|--limit|--tests-in|--kind|--range|--old|--new|--file|--page|--page-budget|--out) skip=1; continue ;; esac |
129 | 134 | [ -d "$a" ] && FR="$a" |
130 | 135 | done |
| 136 | +# --grep (context, path, impact, test-impact): the answer's sites one per line, `path:line: code [tag]`, the way grep |
| 137 | +# prints them (ax_grep.py). The verb answers with --json and the sites are printed from that document, so the two |
| 138 | +# shapes are one answer. Without it the answer is the verb's own, unchanged. |
| 139 | +G=() |
| 140 | +case "$cmd" in context|path|impact|test-impact|tests) [ -n "${GREP:-}" ] && G=(python3 "$H/ax_grep.py" "$cmd" "$FR" --limit "${GREP_LIMIT:-30}" --) ;; esac |
131 | 141 | # A REPOSITORY IN SEVERAL LANGUAGES has one graph per language (.axiomcode/lang/<lang> beside the main one): a query |
132 | 142 | # asks every one of them (ax_langs.py), so no language's code is left out of an answer. A graph named in |
133 | 143 | # AXIOMCODE_GRAPH was chosen by the caller and is asked alone. |
134 | 144 | Q=""; [ -d "$FR/.axiomcode/lang" ] && [ -z "${AXIOMCODE_GRAPH:-}" ] && Q="$H/ax_langs.py" |
135 | 145 | # (-L too: a pointer whose target is gone is a graph to repair — the refresher does it — not a repository without one) |
136 | 146 | if [ -f "$FR/.axiomcode/out/graph.sqlite" ] || [ -L "$FR/.axiomcode/out/graph.sqlite" ]; then |
137 | 147 | case "$cmd" in |
138 | | - context|path|impact) exec python3 "$H/ax_fresh.py" query "$FR" "$cmd" -- python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-$cmd" ${ARGS[@]+"${ARGS[@]}"} ;; |
| 148 | + context|path|impact) exec python3 "$H/ax_fresh.py" query "$FR" "$cmd" -- ${G[@]+"${G[@]}"} python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-$cmd" ${ARGS[@]+"${ARGS[@]}"} ;; |
139 | 149 | changed|test-impact|tests) python3 "$H/ax_fresh.py" baseline "$FR" "${AXIOMCODE_BASELINE_WAIT:-30}" || true ;; |
140 | 150 | esac |
141 | 151 | fi |
142 | 152 | case "$cmd" in |
143 | 153 | index|build) exec bash "$H/axiomcode-build" ${ARGS[@]+"${ARGS[@]}"} ;; |
144 | | - context) exec python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-context" ${ARGS[@]+"${ARGS[@]}"} ;; |
145 | | - path) exec python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-path" ${ARGS[@]+"${ARGS[@]}"} ;; |
146 | | - impact) exec python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-impact" ${ARGS[@]+"${ARGS[@]}"} ;; |
| 154 | + context) exec ${G[@]+"${G[@]}"} python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-context" ${ARGS[@]+"${ARGS[@]}"} ;; |
| 155 | + path) exec ${G[@]+"${G[@]}"} python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-path" ${ARGS[@]+"${ARGS[@]}"} ;; |
| 156 | + impact) exec ${G[@]+"${G[@]}"} python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-impact" ${ARGS[@]+"${ARGS[@]}"} ;; |
147 | 157 | changed) exec python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-changed" ${ARGS[@]+"${ARGS[@]}"} ;; |
148 | | - test-impact|tests) exec python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-test-impact" ${ARGS[@]+"${ARGS[@]}"} ;; |
| 158 | + test-impact|tests) exec ${G[@]+"${G[@]}"} python3 ${Q:+"$Q" "$FR"} "$H/axiomcode-test-impact" ${ARGS[@]+"${ARGS[@]}"} ;; |
149 | 159 | graph) exec python3 "$H/axiomcode-graph" ${ARGS[@]+"${ARGS[@]}"} ;; |
150 | 160 | install) exec python3 "$H/axiomcode-install" ${ARGS[@]+"${ARGS[@]}"} ;; |
151 | 161 | --verbs) verbs ;; # what this dispatcher answers to; bin/axiomcode asks, so the two cannot drift |
|
0 commit comments