X-Git-Url: https://dreyeck.freedombox.rocks/gitweb/idiomatic.git/blobdiff_plain/96f9e23cc6e9201f27fb656588199e234901420e..1d14f8b4c3061f3bbecbbd2df4c230a9dd1fd985:/index.js?ds=inline diff --git a/index.js b/index.js index b3334a5..b1a1a24 100644 --- a/index.js +++ b/index.js @@ -1,33 +1,13 @@ -let express = require('express') -let acorn = require('acorn') -let fs = require('fs') -// let fs = require('node:fs/promises'); - -let visitor = require('./visitor.js') -let dir = '../wiki-client/lib' -let mods = [] - -const app = express() - - -// P A G E S - -app.get('/index', async (req,res,next) => { - console.log(new Date().toLocaleTimeString(), 'index') - const reductions = counter() - fs.readdir(dir, async (err, files) => { - mods = await Promise.all(files.map(load)) - const doit = branch => {reductions.count(branch.type)} - visitor.wander(mods,doit) - const result = ` -

${reductions.size()} non-terminals -
${reductions.total()} reductions -

${reductions.tally() - .map(([k,v]) => `${v} ${link(k)}`) - .join("
")}` - res.send(result); - next() - }) +const express = require('express') +const acorn = require('acorn') +const fs = require('fs') +// const fs = require('node:fs/promises'); +const visitor = require('./visitor.js') + +const dir = '../wiki-client/lib' +const mods = [] +fs.readdir(dir, async (err, files) => { + mods.push(... await Promise.all(files.map(load))) }) async function load(file) { @@ -39,6 +19,35 @@ async function load(file) { }) } + +// P A G E S + +const style = (title,here='') => ` + +

— ${title}  ${escape(here)}  —
` +const app = express() + +app.get('/index', async (req,res,next) => { + console.log(new Date().toLocaleTimeString(), 'index') + const reductions = counter() + const doit = branch => {reductions.count(branch.type)} + visitor.wander(mods,doit) + const result = ` +

${reductions.size()} non-terminals +
${reductions.total()} reductions +

${reductions.tally() + .map(([k,v]) => `
${v}${link(k)}`) + .join("\n")}
` + res.send(style('index')+result); + next() + }) + function link(key) { if(key.match(/^Ident/)) return `${key}` if(key.match(/^(As|B|L|U).*Ex/)) return `${key}` @@ -46,37 +55,63 @@ function link(key) { return key } - app.get('/terminal', (req,res) => { + const {type,field} = req.query const lits = counter() - const id = req.query.type - const field = req.query.field - const doit = branch => {if(branch.type==id) lits.count(branch[field])} + const doit = branch => {if(branch.type==type) lits.count(branch[field])} visitor.wander(mods,doit) - const result = ` + const result = style('terminal',type)+`

${lits.size()} uniques
${lits.total()} total -

${lits.tally() - .map(([k,v]) => `${v} ${escape(k)}`) - .join("
")}` +

${lits.tally() + .map(([k,v]) => `
${v}${escape(k)}`) + .join("\n")}
` res.send(result) }) app.get('/usage', (req,res) => { - const type = req.query.type - const field = req.query.field - const key = req.query.key + const {type,field,key,width,depth} = req.query const list = [] + const files = counter() const doit = (branch,stack) => { - if(branch.type==type && branch[field]==key) - list.push(`${stack.at(-1)} ${sxpr(stack[2],3)}` - // `${stack.length} - // ${stack.at(-1)}-${branch.start}-${branch.end} - // (${stack.slice(0,6).map(n => n.end-n.start).join(" ")})` - ) + if(branch.type==type && branch[field]==key)list.push(` + + ${stack.at(-1)} + ${sxpr(stack[width ?? 2], depth ?? 3)}`) } visitor.wander(mods,doit) - res.send(`

${JSON.stringify(req.query,null,2)}
${list.join("
")}`) + const vis = row => row.split(/\n/)[3].trim().replaceAll(/<.*?>/g,'').replaceAll(/\.\.+/g,'..') + 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 => ` + ` + const m = id => ` − ` + const d = id => `${id} ${p(id)} ${m(id)}` + res.send(style('usage',key)+` +

${files.total()} uses in ${files.size()} files + ${files.tally().map(([k,v]) => `
${v}${k}`).join("\n")}
+

— ${d('width')} ${d('depth')} —
+

${list.join("\n")}
`) +}) + +app.get('/nesting', (req,res) => { + const {file,type,key,start,end} = req.query + const result = [] + const doit = (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) => ` + + ${n.type}: + ${sxpr(n,3,null,stack[i-1])}`).reverse() + const hit = stack[1] + result.push(` +

${path.join("")}

+

${escape(JSON.stringify(hit,omit,2))}
`) + } + } + visitor.wander(mods,doit) + res.send(style('nesting',key)+`${result.join("
")}`) }) @@ -90,6 +125,7 @@ function counter() { counts.set(item, counts.get(item)+1) else counts.set(item,1) + return item }, size() { return counts.size @@ -119,14 +155,14 @@ function escape(text) { function sxpr(obj,deep,key,child) { const hilite = obj===child ? 'class="hi"' : '' - const link = word => obj.type == 'Identifier' ? `${word}` : word + const link = word => obj.type == 'Identifier' ? `${word}` : word if (obj) { if(deep) { const fields = Object.entries(obj) .filter(([k,v]) => !['start','end','raw','computed','optional','kind'].includes(k)) .map(([k,v]) => k=='type' ? abv(v) : - (typeof v == 'string') ? link(expand(v)) : + (typeof v == 'string') ? link(escape(v)) : Array.isArray(v) ? `[${v.map(o => sxpr(o,deep-1,k,child)).join(" ")}]` : sxpr(v, deep-1, k, child)) .join(" ") @@ -149,12 +185,4 @@ function elipsis(obj) { return `(${dots})` } -function expand(text) { - return text - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/\*(.+?)\*/g, '$1') -}; - app.listen(1954) \ No newline at end of file