+ const files = counter()
+ visitor.walk(mods,(branch,stack) => {
+ if(branch.type==type && branch[field]==key)list.push(`
+ <tr><td><a href="/nesting/?file=${files.count(stack.at(-1))}&type=${type}&key=${key}&start=${branch.start}&end=${branch.end}">
+ ${stack.at(-1)}</a>
+ <td>${sxpr(stack[width ?? 2], depth ?? 3)}`)})
+ list.sort((a,b) => vis(a)>vis(b) ? 1 : -1)
+ const q = (id,delta) => Object.entries(req.query)
+ .map(([k,v]) => k == id ? `${k}=${+v+delta}` : `${k}=${v}`)
+ .join('&')
+ const p = id => `<a href=/usage?${q(id,+1)} style="background-color:#ddd;"> + </a>`
+ const m = id => `<a href=/usage?${q(id,-1)} style="background-color:#ddd;"> − </a>`
+ const d = id => `<span title=${req.query[id]}>${id} ${p(id)} ${m(id)}</span>`
+ res.send(style('usage',key)+`
+ <p><details><summary>${files.total()} uses in ${files.size()} files</summary>
+ <table>${files.tally().map(([k,v]) => `<tr><td>${v}<td>${k}`).join("\n")}</table></details>
+ <p><section>${d('width')} ${d('depth')}</section>
+ <p><table>${list.join("\n")}</table>`)
+})
+
+app.get('/nesting', (req,res) => {
+ const {file,type,key,start,end} = req.query
+ const result = []
+ visitor.walk(mods,(branch,stack) => {
+ if(stack.at(-1)==file && branch.type==type && branch.start==start && branch.end==end) {
+ const path = stack.slice(0,-1).map((n,i) => `
+ <tr>
+ <td><a title=${file} href=/similar?${query(req.query)}&nest=${i}>${n.type}</a>:
+ <td>${sxpr(n,3,null,stack[i-1])}`).reverse()
+ const hit = stack[1]
+ result.push(`
+ <p><table>${path.join("")}</table><br>
+ <p><pre>${escape(JSON.stringify(hit,omit,2))}</pre>`)
+ }
+ })
+ res.send(style('nesting',key)+`${result.join("<hr>")}`)
+})
+
+app.get('/similar', (req,res) => {
+ const {file,type,key,start,end,nest} = req.query
+ let nested
+ visitor.walk(mods,(branch,stack) => {
+ if(stack.at(-1)==file && branch.type==type && branch.start==start && branch.end==end)
+ nested = stack[nest]})
+ const norm = node => vis(`\n\n\n${sxpr(node,3,null)}`)
+ const source = (file,node) => mods.find(mod => mod.file == file).text.substring(+node.start,+node.end)
+ const want = norm(nested)
+ const result = []
+ visitor.walk(mods,(branch,stack) => {
+ if(norm(branch) == want)
+ result.push(`<pre>${escape(source(stack.at(-1),branch))}</pre><hr>`)})
+ res.send(style('similar',key)+
+ `<p>${want}<hr>` +
+ result.join("\n")
+ )