diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8bfa2e2..8139589 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -- @cursorless-dev/code-owners +* @cursorless-dev/code-owners diff --git a/README.md b/README.md index 602397d..bea5207 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ foo bar baz: "foo bar baz" ```yaml repos: - repo: https://github.com/cursorless-dev/talon-tools - rev: v0.9.0 + rev: v0.10.0 hooks: - id: talon-fmt - id: snippet-fmt diff --git a/dist/lib.js b/dist/lib.js index c30c5cf..1127232 100644 --- a/dist/lib.js +++ b/dist/lib.js @@ -1,4 +1,4 @@ -function L(i){let e=i.split(/^---$/m),t={snippets:[]};for(let n of e){let o=n.match(/^-$/m),r=o!=null?n.slice(0,o.index):n,s=o!=null?n.slice(o.index+o[0].length):null,a=s?k(s):null,c=v(r);if(a!=null){c==null&&(c={variables:[]});let{variables:g,...w}=c;t.snippets.push({...w,body:a,variables:g})}else if(c!=null){if(t.header!=null||t.snippets.length!==0)throw Error("Header snippet must be first in file");t.header=c}}return t}function v(i){let e={variables:[]},t=F(i);if(Object.keys(t).length===0)return;let n={};for(let[o,r]of Object.entries(t))switch(o){case"name":e.name=r;break;case"description":e.description=r;break;case"phrase":e.phrases=h(r);break;case"insertionScope":e.insertionScopes=h(r);break;case"language":e.languages=h(r);break;default:if(!o.startsWith("$"))throw Error(`Invalid key '${o}'`);n[o]=r}return e.variables=O(n),e}function F(i){let e=i.split(/\r?\n/).map(n=>n.trim()).filter(Boolean),t={};for(let n of e){let o=n.split(":");if(o.length!==2)throw Error(`Invalid line '${n}'`);let r=o[0].trim(),s=o[1].trim();if(r.length===0||s.length===0)throw Error(`Invalid line '${n}'`);if(t[r]!=null)throw Error(`Duplicate key '${r}' in '${i}'`);t[r]=s}return t}function O(i){let e={},t=n=>(e[n]==null&&(e[n]={name:n}),e[n]);for(let[n,o]of Object.entries(i)){let r=n.split(".");if(r.length!==2)throw Error(`Invalid variable key '${n}'`);let s=r[0].slice(1);switch(r[1]){case"insertionFormatter":t(s).insertionFormatters=h(o);break;case"wrapperPhrase":t(s).wrapperPhrases=h(o);break;case"wrapperScope":t(s).wrapperScope=o;break;default:throw Error(`Invalid variable key '${n}'`)}}return Object.values(e)}function k(i){let e=i.match(/^[ \t]*\S/m);if(e?.index!=null)return i.slice(e.index).trimEnd().split(/\r?\n/).map(t=>t.trimEnd())}function h(i){return i.split("|").map(e=>e.trim())}var _=[".git",".svn",".hg","node_modules","__pycache__"],I=_.map(i=>`**/${i}/**`);function l(i){return i==="crlf"?`\r +function T(n){let e=n.split(/^---$/m),t={snippets:[]};for(let i of e){let o=i.match(/^-$/m),r=o!=null?i.slice(0,o.index):i,s=o!=null?i.slice(o.index+o[0].length):null,a=s?R(s):null,c=I(r);if(a!=null){c==null&&(c={variables:[]});let{variables:u,...O}=c;t.snippets.push({...O,body:a,variables:u})}else if(c!=null){if(t.header!=null||t.snippets.length!==0)throw Error("Header snippet must be first in file");t.header=c}}return t}function I(n){let e={variables:[]},t=k(n);if(Object.keys(t).length===0)return;let i={};for(let[o,r]of Object.entries(t))switch(o){case"name":e.name=r;break;case"description":e.description=r;break;case"phrase":e.phrases=g(r);break;case"insertionScope":e.insertionScopes=g(r);break;case"language":e.languages=g(r);break;default:if(!o.startsWith("$"))throw Error(`Invalid key '${o}'`);i[o]=r}return e.variables=j(i),e}function k(n){let e=n.split(/\r?\n/).map(i=>i.trim()).filter(Boolean),t={};for(let i of e){let o=i.split(":");if(o.length!==2)throw Error(`Invalid line '${i}'`);let r=o[0].trim(),s=o[1].trim();if(r.length===0||s.length===0)throw Error(`Invalid line '${i}'`);if(t[r]!=null)throw Error(`Duplicate key '${r}' in '${n}'`);t[r]=s}return t}function j(n){let e={},t=i=>(e[i]==null&&(e[i]={name:i}),e[i]);for(let[i,o]of Object.entries(n)){let r=i.split(".");if(r.length!==2)throw Error(`Invalid variable key '${i}'`);let s=r[0].slice(1);switch(r[1]){case"insertionFormatter":t(s).insertionFormatters=g(o);break;case"wrapperPhrase":t(s).wrapperPhrases=g(o);break;case"wrapperScope":t(s).wrapperScope=o;break;default:throw Error(`Invalid variable key '${i}'`)}}return Object.values(e)}function R(n){let e=n.match(/^[ \t]*\S/m);if(e?.index!=null)return n.slice(e.index).trimEnd().split(/\r?\n/).map(t=>t.trimEnd())}function g(n){return n.split("|").map(e=>e.trim())}var $=[".git",".svn",".hg","node_modules","__pycache__"],D=$.map(n=>`**/${n}/**`);function l(n){return n==="crlf"?`\r `:` -`}function $(i,e={}){let t=l(e.endOfLine);return new y(t,e.insertFinalNewline??!0).getText(i)}var y=class{constructor(e,t){this.eol=e;this.insertFinalNewline=t}getText(e){let n=[];e.header!=null&&n.push(this.getDocumentText(e.header)),n.push(...e.snippets.map(this.getDocumentText.bind(this)));let o=n.filter(r=>r.length>0).join(`${this.eol}---${this.eol}${this.eol}`);return o.length===0?"":this.insertFinalNewline?o+`${this.eol}---${this.eol}`:o+`${this.eol}---`}getDocumentText(e){let t=[p("name",e.name),p("description",e.description),p("language",e.languages),p("phrase",e.phrases),p("insertionScope",e.insertionScopes)].filter(Boolean);return e.variables.length>0&&(t.length>0&&t.push(""),t.push(...j(e.variables))),"body"in e&&t.push("-",...e.body),t.join(this.eol)}};function j(i){let e=i.slice();return e.sort(D),e.flatMap(t=>[p(`$${t.name}.insertionFormatter`,t.insertionFormatters),p(`$${t.name}.wrapperPhrase`,t.wrapperPhrases),p(`$${t.name}.wrapperScope`,t.wrapperScope)]).filter(t=>t.length>0)}function p(i,e){return e==null?"":Array.isArray(e)?`${i}: ${e.join(" | ")}`:`${i}: ${e}`}function D(i,e){return i.name==="0"?1:e.name==="0"?-1:i.name.localeCompare(e.name)}function Y(i,e){let t=L(i);return $(t,e)}function u(i){return{debug(e){i&&console.warn(`[debug] ${e}`)}}}function f(i){let e=i.match(/# fmt: columnWidth=(\d+)/);if(e!=null)return parseInt(e[1],10)}function m(i,e){return i?" ":" ".repeat(e??4)}function x(i){return i.length>0&&i[0]==="'"&&i[i.length-1]==="'"&&!i.includes('"')?`"${i.slice(1,-1).replaceAll("\\'","'")}"`:i}function W(i,e={},t=!1){let n=f(i.text)??e.columnWidth,o=m(e.indentTabs,e.indentSize),r=l(e.endOfLine);return new N(o,r,e.maxLineLength??80,n,e.insertFinalNewline??!0,e.preserveMultiline??!1,t).getText(i)}var N=class{constructor(e,t,n,o,r,s,a){this.indent=e;this.eol=t;this.maxLineLength=n;this.columnWidth=o;this.insertFinalNewline=r;this.preserveMultiline=s;this.logger=u(a)}lines=[];lastRow=0;logger;getText(e){this.addNode(e);let t=this.lines.join(this.eol).trimEnd();return t.length===0?"":this.insertFinalNewline?t+this.eol:t}addNL(){this.lines[this.lines.length-1]!==""&&this.lines.push("")}addNode(e,t=!1){e.startPosition.row>this.lastRow+1&&this.addNL(),this.lastRow=e.endPosition.row,this.addNodeHelper(e,t),this.lastRow=e.endPosition.row}addNodeHelper(e,t=!1){switch(e.type){case"source_file":for(let n of e.children)this.addNode(n);break;case"matches":{if(e.children.length>1||!C(e)){for(let n of e.children)this.addNode(n);this.addNL()}break}case"declarations":for(let n of e.children)this.addNode(n);break;case"block":for(let n of e.children)this.addNode(n,!0);break;case"command_declaration":case"key_binding_declaration":case"parrot_declaration":case"noise_declaration":case"face_declaration":case"gamepad_declaration":case"deck_declaration":this.addLeftRightNode(e,!1);break;case"settings_declaration":this.lines.length>0&&!this.lines[this.lines.length-1].startsWith("#")&&this.addNL(),this.addLeftRightNode(e,!0),this.addNL();break;case"comment":{let n=e.text.trimEnd(),o=t||e.startPosition.column>0?`${this.indent}${n}`:n;this.lines.push(o);break}default:{let n=this.getNodeText(e);this.lines.push(t?`${this.indent}${n}`:n)}}}getNodeText(e){switch(e.type){case"source_file":case"matches":case"declarations":case"block":case"command_declaration":case"key_binding_declaration":case"parrot_declaration":case"noise_declaration":case"face_declaration":case"gamepad_declaration":case"deck_declaration":case"settings_declaration":case"comment":throw new Error(`Node type '${e.type}' should be handled in addNode, not getNodeText`);case"parenthesized_rule":return this.pairWithChildren(e,e.parent!=null&&T(e,e.parent));case"optional":return this.pairWithChildren(e);case"expression_statement":case"assignment_statement":case"seq":case"choice":return e.children.map(t=>this.getNodeText(t)).join(" ");case"rule":case"action":case"key_action":case"sleep_action":case"argument_list":case"key_binding":case"face_binding":case"gamepad_binding":case"parrot_binding":case"noise_binding":case"deck_binding":case"tag_import_declaration":case"match":return e.children.map(t=>this.getNodeText(t)).join("");case"string":return V(e);case"match_modifier":case":":case",":return`${e.text} `;case"implicit_string":return e.text.trim();case"tag_binding":case"settings_binding":case"capture":case"list":case"key(":case"sleep(":case"gamepad(":case"face(":case"parrot(":case"noise(":case"identifier":case"variable":case"word":case"binary_operator":case"integer":case"float":case"start_anchor":case"end_anchor":case"repeat":case"deck(":case"repeat1":case"(":case")":case"=":case"-":case"|":return e.text;default:return this.logger.debug(`Unknown syntax node type '${e.type}'`),e.text}}pairWithChildren(e,t=!1){let{children:n}=e,o=n.slice(1,-1).map(a=>this.getNodeText(a)).join(" ");if(t)return o;let r=n[0].text,s=n[n.length-1].text;return`${r}${o}${s}`}addLeftRightNode(e,t){let[n,o,...r]=e.children,s=this.getNodeText(n);if(!t&&r.length===1&&(!this.preserveMultiline||A(n,r))){let a=r[0];if(a.children.length===1){let c=this.getNodeText(a.children[0]),g=this.columnWidth!=null?`${s}: `.padEnd(this.columnWidth):`${s}: `;if(g.length+c.length<=this.maxLineLength){this.lines.push(g+c);return}}}this.lines.push(`${s}:`);for(let a of r)this.addNode(a,!0)}};function A(i,e){return i.endPosition.row===e[e.length-1].startPosition.row}function T(i,e){return i.startPosition.row===e.startPosition.row&&i.startPosition.column===e.startPosition.column&&i.endPosition.row===e.endPosition.row&&i.endPosition.column===e.endPosition.column}function C(i){return i.id===i.parent?.children?.[0]?.id}function V(i){let e=x(i.text);return i.parent?.type==="expression_statement"&&i.parent.parent?.type==="block"&&T(i,i.parent)&&i.parent.parent.children.length>1?`insert(${e})`:e}function E(i){let e=i.split(/\r?\n/).map(s=>s.trim()),t=e.indexOf("-");if(t===-1)throw Error("Separator not found in talon list");let n=e.slice(0,t),o=U(e.slice(t+1)),r={headers:[],items:[]};for(let s of n){if(s.length===0)continue;if(s.startsWith("#")){r.headers.push({type:"comment",text:s});continue}let[a,c]=S(s);if(c==null)throw Error("Header value missing");r.headers.push({type:"header",key:a,value:c})}for(let s of o){if(s.length===0){r.items.push({type:"empty"});continue}if(s.startsWith("#")){r.items.push({type:"comment",text:s});continue}let[a,c]=S(s);r.items.push({type:"item",key:a,value:c})}return r}function S(i){let e=i.indexOf(":");return e===-1?[i,void 0]:[i.substring(0,e).trimEnd(),i.substring(e+1).trimStart()]}function U(i){let e=i.findIndex(n=>n.length>0);if(e<0)return[];let t=i.findLastIndex(n=>n.length>0);return i.slice(e,t+1)}function H(i,e={}){let t=f(i)??e.columnWidth,n=l(e.endOfLine),o=E(i);o.headers.sort((s,a)=>s.type==="header"&&s.key==="list"?-1:0);let r=[];for(let s of o.headers){if(s.type==="comment"){r.push(s.text);continue}r.push(`${s.key}: ${s.value}`)}r.push("-","");for(let s of o.items){if(s.type==="empty"){r.push("");continue}if(s.type==="comment"){r.push(s.text);continue}if(s.value!=null){let a=t!=null?`${s.key}: `.padEnd(t):`${s.key}: `,c=x(s.value);r.push(`${a}${c}`)}else r.push(s.key)}return r.length===0?"":((e.insertFinalNewline??!0)&&r.push(""),r.join(n))}function z(i,e={},t=!1){let n=m(e.indentTabs,e.indentSize),o=l(e.endOfLine);return new b(n,o,e.insertFinalNewline??!0,t).getText(i)}var b=class{constructor(e,t,n,o){this.indentation=e;this.eol=t;this.insertFinalNewline=n;this.logger=u(o)}lastRow=0;logger;getText(e){let t=this.getNodeText(e,0);return t.length===0?"":this.insertFinalNewline?t+this.eol:t}getNodeText(e,t){let n=e.startPosition.row>this.lastRow+1?this.eol:"";this.lastRow=e.endPosition.row;let o=this.getNodeTextInternal(e,t);return this.lastRow=e.endPosition.row,`${n}${o}`}getNamedNodeText(e,t){let n=e.children.findIndex(a=>a.type===")"),o=e.children.slice(0,2).map(a=>a.text).join(""),r=e.children.slice(n).map(a=>this.getNodeText(a,0)).join(""),s=e.children.slice(2,n).map(a=>this.getNodeText(a,t+1));return s.length===0?`${this.getIndent(t)}${o}${r}`:[`${this.getIndent(t)}${o}`,...s,`${this.getIndent(t)}${r}`].join(this.eol)}getListText(e,t){let n=e.children.findIndex(a=>a.type==="]"),o=e.children[0].text,r=e.children.slice(n).map(a=>a.text).join(" ");return[`${this.getIndent(t)}${o}`,...e.children.slice(1,n).map(a=>this.getNodeText(a,t+1)),`${this.getIndent(t)}${r}`].join(this.eol)}getPredicateText(e,t){let n=e.children[0].text,o=e.children[e.children.length-1].text,r=[e.children.slice(1,4).map(s=>s.text).join(""),...e.children[e.children.length-2].children.map(s=>s.text)];if(e.startPosition.row===e.endPosition.row){let s=`${n}${r.join(" ")}${o}`;return`${this.getIndent(t)}${s}`}return[`${this.getIndent(t)}${n}${r[0]}`,...r.slice(1).map(s=>`${this.getIndent(t+1)}${s}`),`${this.getIndent(t)}${o}`].join(this.eol)}getFieldDefinitionText(e,t){return t===0?["(_",this.getFieldDefinitionText(e,1),")"].join(this.eol):[this.getIndent(t),e.children[0].text,e.children[1].text," ",this.getNodeText(e.children[2],t).trimStart()].join("")}getNodeTextInternal(e,t){switch(e.type){case"program":return this.joinLines(e.children,0);case"grouping":return this.joinLines(e.children,t+1);case"list":return this.getListText(e,t);case"named_node":return this.getNamedNodeText(e,t);case"predicate":return this.getPredicateText(e,t);case"field_definition":return this.getFieldDefinitionText(e,t);case"anonymous_node":return this.getIndent(t)+e.children.map(n=>this.getNodeText(n,t+1)).join("");case"comment":return`${this.getIndent(t)}${e.text.trimEnd()}`;case".":case"negated_field":return`${this.getIndent(t)}${e.text}`;case"(":case")":return`${this.getIndent(t-1)}${e.text}`;case"capture":return` ${e.text}`;case"#":case"_":case"predicate_type":case"identifier":case"quantifier":case"string":return e.text;case"parameters":return` ${e.children.map(o=>o.text).join(" ")}`;default:return this.logger.debug(`Unknown syntax node type '${e.type}'`),e.text}}joinLines(e,t){if(e.length===0)return"";let n=e[e.length-1].type==="quantifier",r=(n?e.slice(0,-1):e).map(s=>this.getNodeText(s,t)).join(this.eol);return n?`${r}${e[e.length-1].text}`:r}getIndent(e){return e<1?"":new Array(e).fill(this.indentation).join("")}};export{I as GLOB_IGNORE_PATTERNS,_ as IGNORE_FOLDERS,L as parseSnippetFile,$ as serializeSnippetFile,Y as snippetFormatter,W as talonFormatter,H as talonListFormatter,z as treeSitterFormatter}; +`}function S(n,e={}){let t=l(e.endOfLine);return new b(t,e.insertFinalNewline??!0).getText(n)}var b=class{constructor(e,t){this.eol=e;this.insertFinalNewline=t}getText(e){let i=[];e.header!=null&&i.push(this.getDocumentText(e.header)),i.push(...e.snippets.map(this.getDocumentText.bind(this)));let o=i.filter(r=>r.length>0).join(`${this.eol}---${this.eol}${this.eol}`);return o.length===0?"":this.insertFinalNewline?o+`${this.eol}---${this.eol}`:o+`${this.eol}---`}getDocumentText(e){let t=[p("name",e.name),p("description",e.description),p("language",e.languages),p("phrase",e.phrases),p("insertionScope",e.insertionScopes)].filter(Boolean);return e.variables.length>0&&(t.length>0&&t.push(""),t.push(...P(e.variables))),"body"in e&&t.push("-",...e.body),t.join(this.eol)}};function P(n){let e=n.slice();return e.sort(W),e.flatMap(t=>[p(`$${t.name}.insertionFormatter`,t.insertionFormatters),p(`$${t.name}.wrapperPhrase`,t.wrapperPhrases),p(`$${t.name}.wrapperScope`,t.wrapperScope)]).filter(t=>t.length>0)}function p(n,e){return e==null?"":Array.isArray(e)?`${n}: ${e.join(" | ")}`:`${n}: ${e}`}function W(n,e){return n.name==="0"?1:e.name==="0"?-1:n.name.localeCompare(e.name)}function te(n,e){let t=T(n);return S(t,e)}function f(n){return{debug(e){n&&console.warn(`[debug] ${e}`)}}}function m(n){let e=n.match(/# fmt: columnWidth=(\d+)/);if(e!=null)return parseInt(e[1],10)}function x(n,e){return n?" ":" ".repeat(e??4)}var y=class extends Error{constructor(t){super("Syntax error.");this.location=t;this.name="SyntaxError"}getLocation(){return this.location!=null?`(${this.location.row+1}:${this.location.column+1})`:void 0}};var h=class extends y{constructor(e){super(E(e)?.startPosition),this.name="SyntaxTreeError"}};function E(n){if(n.isError||n.isMissing)return n;for(let e of n.children){if(!e.hasError)continue;let t=E(e);if(t!=null)return t}return null}function N(n){return n.length>0&&n[0]==="'"&&n[n.length-1]==="'"&&!n.includes('"')?`"${n.slice(1,-1).replaceAll("\\'","'")}"`:n}function V(n,e={},t=!1){if(n.hasError)throw new h(n);let i=m(n.text)??e.columnWidth,o=x(e.indentTabs,e.indentSize),r=l(e.endOfLine);return new L(o,r,e.maxLineLength??80,i,e.insertFinalNewline??!0,e.preserveMultiline??!1,t).getText(n)}var L=class{constructor(e,t,i,o,r,s,a){this.indent=e;this.eol=t;this.maxLineLength=i;this.columnWidth=o;this.insertFinalNewline=r;this.preserveMultiline=s;this.logger=f(a)}lines=[];lastRow=0;logger;getText(e){this.addNode(e);let t=this.lines.join(this.eol).trimEnd();return t.length===0?"":this.insertFinalNewline?t+this.eol:t}addNL(){this.lines[this.lines.length-1]!==""&&this.lines.push("")}addNode(e,t=!1){e.startPosition.row>this.lastRow+1&&this.addNL(),this.lastRow=e.endPosition.row,this.addNodeHelper(e,t),this.lastRow=e.endPosition.row}addNodeHelper(e,t=!1){switch(e.type){case"source_file":for(let i of e.children)this.addNode(i);break;case"matches":{if(e.children.length>1||!H(e)){for(let i of e.children)this.addNode(i);this.addNL()}break}case"declarations":for(let i of e.children)this.addNode(i);break;case"block":for(let i of e.children)this.addNode(i,!0);break;case"command_declaration":case"key_binding_declaration":case"parrot_declaration":case"noise_declaration":case"face_declaration":case"gamepad_declaration":case"deck_declaration":this.addLeftRightNode(e,!1);break;case"settings_declaration":this.lines.length>0&&!this.lines[this.lines.length-1].startsWith("#")&&this.addNL(),this.addLeftRightNode(e,!0),this.addNL();break;case"comment":{let i=e.text.trimEnd(),o=t||e.startPosition.column>0?`${this.indent}${i}`:i;this.lines.push(o);break}default:{let i=this.getNodeText(e);this.lines.push(t?`${this.indent}${i}`:i)}}}getNodeText(e){switch(e.type){case"source_file":case"matches":case"declarations":case"block":case"command_declaration":case"key_binding_declaration":case"parrot_declaration":case"noise_declaration":case"face_declaration":case"gamepad_declaration":case"deck_declaration":case"settings_declaration":case"comment":throw new Error(`Node type '${e.type}' should be handled in addNode, not getNodeText`);case"parenthesized_rule":return this.pairWithChildren(e,e.parent!=null&&w(e,e.parent));case"optional":return this.pairWithChildren(e);case"expression_statement":case"assignment_statement":case"seq":case"choice":return e.children.map(t=>this.getNodeText(t)).join(" ");case"rule":case"action":case"key_action":case"sleep_action":case"argument_list":case"key_binding":case"face_binding":case"gamepad_binding":case"parrot_binding":case"noise_binding":case"deck_binding":case"tag_import_declaration":case"match":return e.children.map(t=>this.getNodeText(t)).join("");case"string":return z(e);case"match_modifier":case":":case",":return`${e.text} `;case"implicit_string":return e.text.trim();case"tag_binding":case"settings_binding":case"capture":case"list":case"key(":case"sleep(":case"gamepad(":case"face(":case"parrot(":case"noise(":case"identifier":case"variable":case"word":case"binary_operator":case"integer":case"float":case"start_anchor":case"end_anchor":case"repeat":case"deck(":case"repeat1":case"(":case")":case"=":case"-":case"|":return e.text;default:return this.logger.debug(`Unknown syntax node type '${e.type}'`),e.text}}pairWithChildren(e,t=!1){let{children:i}=e,o=i.slice(1,-1).map(a=>this.getNodeText(a)).join(" ");if(t)return o;let r=i[0].text,s=i[i.length-1].text;return`${r}${o}${s}`}addLeftRightNode(e,t){let[i,o,...r]=e.children,s=this.getNodeText(i);if(!t&&r.length===1&&(!this.preserveMultiline||U(i,r))){let a=r[0];if(a.children.length===1){let c=this.getNodeText(a.children[0]),u=this.columnWidth!=null?`${s}: `.padEnd(this.columnWidth):`${s}: `;if(u.length+c.length<=this.maxLineLength){this.lines.push(u+c);return}}}this.lines.push(`${s}:`);for(let a of r)this.addNode(a,!0)}};function U(n,e){return n.endPosition.row===e[e.length-1].startPosition.row}function w(n,e){return n.startPosition.row===e.startPosition.row&&n.startPosition.column===e.startPosition.column&&n.endPosition.row===e.endPosition.row&&n.endPosition.column===e.endPosition.column}function H(n){return n.id===n.parent?.children?.[0]?.id}function z(n){let e=N(n.text);return n.parent?.type==="expression_statement"&&n.parent.parent?.type==="block"&&w(n,n.parent)&&n.parent.parent.children.length>1?`insert(${e})`:e}function F(n){let e=n.split(/\r?\n/).map(s=>s.trim()),t=e.indexOf("-");if(t===-1)throw Error("Separator not found in talon list");let i=e.slice(0,t),o=M(e.slice(t+1)),r={headers:[],items:[]};for(let s of i){if(s.length===0)continue;if(s.startsWith("#")){r.headers.push({type:"comment",text:s});continue}let[a,c]=v(s);if(c==null)throw Error("Header value missing");r.headers.push({type:"header",key:a,value:c})}for(let s of o){if(s.length===0){r.items.push({type:"empty"});continue}if(s.startsWith("#")){r.items.push({type:"comment",text:s});continue}let[a,c]=v(s);r.items.push({type:"item",key:a,value:c})}return r}function v(n){let e=n.indexOf(":");return e===-1?[n,void 0]:[n.substring(0,e).trimEnd(),n.substring(e+1).trimStart()]}function M(n){let e=n.findIndex(i=>i.length>0);if(e<0)return[];let t=n.findLastIndex(i=>i.length>0);return n.slice(e,t+1)}function G(n,e={}){let t=m(n)??e.columnWidth,i=l(e.endOfLine),o=F(n);o.headers.sort((s,a)=>s.type==="header"&&s.key==="list"?-1:0);let r=[];for(let s of o.headers){if(s.type==="comment"){r.push(s.text);continue}r.push(`${s.key}: ${s.value}`)}r.push("-","");for(let s of o.items){if(s.type==="empty"){r.push("");continue}if(s.type==="comment"){r.push(s.text);continue}if(s.value!=null){let a=t!=null?`${s.key}: `.padEnd(t):`${s.key}: `,c=N(s.value);r.push(`${a}${c}`)}else r.push(s.key)}return r.length===0?"":((e.insertFinalNewline??!0)&&r.push(""),r.join(i))}function X(n,e={},t=!1){if(n.hasError)throw new h(n);let i=x(e.indentTabs,e.indentSize),o=l(e.endOfLine);return new _(i,o,e.insertFinalNewline??!0,t).getText(n)}var _=class{constructor(e,t,i,o){this.indentation=e;this.eol=t;this.insertFinalNewline=i;this.logger=f(o)}lastRow=0;logger;getText(e){let t=this.getNodeText(e,0);return t.length===0?"":this.insertFinalNewline?t+this.eol:t}getNodeText(e,t){let i=e.startPosition.row>this.lastRow+1?this.eol:"";this.lastRow=e.endPosition.row;let o=this.getNodeTextInternal(e,t);return this.lastRow=e.endPosition.row,`${i}${o}`}getNamedNodeText(e,t){let i=e.children.findIndex(a=>a.type===")"),o=e.children.slice(0,2).map(a=>a.text).join(""),r=e.children.slice(i).map(a=>this.getNodeText(a,0)).join(""),s=e.children.slice(2,i).map(a=>this.getNodeText(a,t+1));return s.length===0?`${this.getIndent(t)}${o}${r}`:[`${this.getIndent(t)}${o}`,...s,`${this.getIndent(t)}${r}`].join(this.eol)}getListText(e,t){let i=e.children.findIndex(a=>a.type==="]"),o=e.children[0].text,r=e.children.slice(i).map(a=>a.text).join(" ");return[`${this.getIndent(t)}${o}`,...e.children.slice(1,i).map(a=>this.getNodeText(a,t+1)),`${this.getIndent(t)}${r}`].join(this.eol)}getPredicateText(e,t){let i=e.children[0].text,o=e.children[e.children.length-1].text,r=[e.children.slice(1,4).map(s=>s.text).join(""),...e.children[e.children.length-2].children.map(s=>s.text)];if(e.startPosition.row===e.endPosition.row){let s=`${i}${r.join(" ")}${o}`;return`${this.getIndent(t)}${s}`}return[`${this.getIndent(t)}${i}${r[0]}`,...r.slice(1).map(s=>`${this.getIndent(t+1)}${s}`),`${this.getIndent(t)}${o}`].join(this.eol)}getFieldDefinitionText(e,t){return t===0?["(_",this.getFieldDefinitionText(e,1),")"].join(this.eol):[this.getIndent(t),e.children[0].text,e.children[1].text," ",this.getNodeText(e.children[2],t).trimStart()].join("")}getNodeTextInternal(e,t){switch(e.type){case"program":return this.joinLines(e.children,0);case"grouping":return this.joinLines(e.children,t+1);case"list":return this.getListText(e,t);case"named_node":return this.getNamedNodeText(e,t);case"predicate":return this.getPredicateText(e,t);case"field_definition":return this.getFieldDefinitionText(e,t);case"anonymous_node":return this.getIndent(t)+e.children.map(i=>this.getNodeText(i,t+1)).join("");case"comment":return`${this.getIndent(t)}${e.text.trimEnd()}`;case".":case"negated_field":return`${this.getIndent(t)}${e.text}`;case"(":case")":return`${this.getIndent(t-1)}${e.text}`;case"capture":return` ${e.text}`;case"#":case"_":case"predicate_type":case"identifier":case"quantifier":case"string":return e.text;case"parameters":return` ${e.children.map(o=>o.text).join(" ")}`;default:return this.logger.debug(`Unknown syntax node type '${e.type}'`),e.text}}joinLines(e,t){if(e.length===0)return"";let i=e[e.length-1].type==="quantifier",r=(i?e.slice(0,-1):e).map(s=>this.getNodeText(s,t)).join(this.eol);return i?`${r}${e[e.length-1].text}`:r}getIndent(e){return e<1?"":new Array(e).fill(this.indentation).join("")}};export{D as GLOB_IGNORE_PATTERNS,$ as IGNORE_FOLDERS,T as parseSnippetFile,S as serializeSnippetFile,te as snippetFormatter,V as talonFormatter,G as talonListFormatter,X as treeSitterFormatter}; //# sourceMappingURL=lib.js.map diff --git a/dist/lib.js.map b/dist/lib.js.map index 9eae37a..cd9c9a8 100644 --- a/dist/lib.js.map +++ b/dist/lib.js.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../src/snippet/parseSnippetFile.ts", "../src/util/constants.ts", "../src/util/getEndOfLine.ts", "../src/snippet/serializeSnippetFile.ts", "../src/snippet/snippetFormatter.ts", "../src/util/createDebugLogger.ts", "../src/util/getColumnWidth.ts", "../src/util/getIndentation.ts", "../src/talon/convertQuotes.ts", "../src/talon/talonFormatter.ts", "../src/talon/parseTalonList.ts", "../src/talon/talonListFormatter.ts", "../src/treeSitterFormatter.ts"], - "sourcesContent": ["import type { Snippet, SnippetFile, SnippetVariable } from \"./snippetTypes.js\";\n\nexport function parseSnippetFile(content: string): SnippetFile {\n const documentContents = content.split(/^---$/m);\n const file: SnippetFile = { snippets: [] };\n\n for (const text of documentContents) {\n const match = text.match(/^-$/m);\n const contextText = match != null ? text.slice(0, match.index) : text;\n const bodyText =\n match != null ? text.slice(match.index! + match[0].length) : null;\n const body = bodyText ? parseBody(bodyText) : null;\n let context = parseContext(contextText);\n\n // Snippet with body\n if (body != null) {\n if (context == null) {\n context = { variables: [] };\n }\n const { variables, ...rest } = context;\n file.snippets.push({ ...rest, body, variables });\n }\n // Header without body\n else if (context != null) {\n if (file.header != null || file.snippets.length !== 0) {\n throw Error(\"Header snippet must be first in file\");\n }\n file.header = context;\n }\n }\n\n return file;\n}\n\ntype Context = Omit;\n\nfunction parseContext(text: string): Context | undefined {\n const document: Context = { variables: [] };\n const pairs = parseContextPairs(text);\n\n if (Object.keys(pairs).length === 0) {\n return undefined;\n }\n\n const variables: Record = {};\n\n for (const [key, value] of Object.entries(pairs)) {\n switch (key) {\n case \"name\":\n document.name = value;\n break;\n case \"description\":\n document.description = value;\n break;\n case \"phrase\":\n document.phrases = parseVectorValue(value);\n break;\n case \"insertionScope\":\n document.insertionScopes = parseVectorValue(value);\n break;\n case \"language\":\n document.languages = parseVectorValue(value);\n break;\n default:\n if (!key.startsWith(\"$\")) {\n throw Error(`Invalid key '${key}'`);\n }\n variables[key] = value;\n }\n }\n\n document.variables = parseVariables(variables);\n\n return document;\n}\n\nfunction parseContextPairs(text: string): Record {\n const lines = text\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter(Boolean);\n const pairs: Record = {};\n\n for (const line of lines) {\n const parts = line.split(\":\");\n if (parts.length !== 2) {\n throw Error(`Invalid line '${line}'`);\n }\n const key = parts[0].trim();\n const value = parts[1].trim();\n if (key.length === 0 || value.length === 0) {\n throw Error(`Invalid line '${line}'`);\n }\n if (pairs[key] != null) {\n throw Error(`Duplicate key '${key}' in '${text}'`);\n }\n pairs[key] = value;\n }\n\n return pairs;\n}\n\nfunction parseVariables(variables: Record): SnippetVariable[] {\n const variablesMap: Record = {};\n\n const getVariable = (name: string): SnippetVariable => {\n if (variablesMap[name] == null) {\n variablesMap[name] = { name };\n }\n return variablesMap[name];\n };\n\n for (const [key, value] of Object.entries(variables)) {\n const parts = key.split(\".\");\n if (parts.length !== 2) {\n throw Error(`Invalid variable key '${key}'`);\n }\n const name = parts[0].slice(1);\n const field = parts[1];\n switch (field) {\n case \"insertionFormatter\":\n getVariable(name).insertionFormatters = parseVectorValue(value);\n break;\n case \"wrapperPhrase\":\n getVariable(name).wrapperPhrases = parseVectorValue(value);\n break;\n case \"wrapperScope\":\n getVariable(name).wrapperScope = value;\n break;\n default:\n throw Error(`Invalid variable key '${key}'`);\n }\n }\n\n return Object.values(variablesMap);\n}\n\nfunction parseBody(text: string): string[] | undefined {\n // Find first line that is not empty. Preserve indentation.\n const matchLeading = text.match(/^[ \\t]*\\S/m);\n if (matchLeading?.index == null) {\n return undefined;\n }\n return text\n .slice(matchLeading.index)\n .trimEnd()\n .split(/\\r?\\n/)\n .map((l) => l.trimEnd());\n}\n\nfunction parseVectorValue(value: string): string[] {\n return value.split(\"|\").map((v) => v.trim());\n}\n", "// Exit code 0: Success\nexport const EXIT_OK = 0;\n// Exit code 1: Check failed\nexport const EXIT_FAIL = 1;\n// Exit code 2: Unexpected error\nexport const EXIT_ERROR = 2;\n\nexport const DEFAULT_INDENT_WIDTH = 4;\nexport const DEFAULT_MAX_LINE_LENGTH = 80;\nexport const DEFAULT_INSERT_FINAL_NEWLINE = true;\n\nexport const IGNORE_FOLDERS = [\n \".git\",\n \".svn\",\n \".hg\",\n \"node_modules\",\n \"__pycache__\",\n];\n\nexport const GLOB_IGNORE_PATTERNS = IGNORE_FOLDERS.map(\n (pattern) => `**/${pattern}/**`,\n);\n", "import type { EndOfLine } from \"../types.js\";\n\nexport function getEndOfLine(eof?: EndOfLine): string {\n return eof === \"crlf\" ? \"\\r\\n\" : \"\\n\";\n}\n", "import type { FormatterOptions } from \"../types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"../util/constants.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport type {\n Snippet,\n SnippetFile,\n SnippetHeader,\n SnippetVariable,\n} from \"./snippetTypes.js\";\n\nexport type Options = FormatterOptions<\"endOfLine\" | \"insertFinalNewline\">;\n\nexport function serializeSnippetFile(\n snippetFile: SnippetFile,\n options: Options = {},\n): string {\n const eol = getEndOfLine(options.endOfLine);\n const serializer = new SnippetSerializer(\n eol,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n );\n return serializer.getText(snippetFile);\n}\n\nclass SnippetSerializer {\n constructor(\n private eol: string,\n private insertFinalNewline: boolean,\n ) {}\n\n getText(snippetFile: SnippetFile): string {\n const docDelimiter = \"---\";\n const documents: string[] = [];\n\n if (snippetFile.header != null) {\n documents.push(this.getDocumentText(snippetFile.header));\n }\n\n documents.push(\n ...snippetFile.snippets.map(this.getDocumentText.bind(this)),\n );\n\n const result = documents\n .filter((d) => d.length > 0)\n .join(`${this.eol}${docDelimiter}${this.eol}${this.eol}`);\n\n if (result.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return result + `${this.eol}${docDelimiter}${this.eol}`;\n }\n\n return result + `${this.eol}${docDelimiter}`;\n }\n\n private getDocumentText(document: SnippetHeader | Snippet): string {\n const lines: string[] = [\n getOptionalPairString(\"name\", document.name),\n getOptionalPairString(\"description\", document.description),\n getOptionalPairString(\"language\", document.languages),\n getOptionalPairString(\"phrase\", document.phrases),\n getOptionalPairString(\"insertionScope\", document.insertionScopes),\n ].filter(Boolean);\n\n if (document.variables.length > 0) {\n if (lines.length > 0) {\n lines.push(\"\");\n }\n lines.push(...getSortedVariables(document.variables));\n }\n\n if (\"body\" in document) {\n lines.push(\"-\", ...document.body);\n }\n\n return lines.join(this.eol);\n }\n}\n\nfunction getSortedVariables(variables: SnippetVariable[]): string[] {\n const result = variables.slice();\n result.sort(compareVariables);\n return result\n .flatMap((variable) => [\n getOptionalPairString(\n `$${variable.name}.insertionFormatter`,\n variable.insertionFormatters,\n ),\n getOptionalPairString(\n `$${variable.name}.wrapperPhrase`,\n variable.wrapperPhrases,\n ),\n getOptionalPairString(\n `$${variable.name}.wrapperScope`,\n variable.wrapperScope,\n ),\n ])\n .filter((v) => v.length > 0);\n}\n\nfunction getOptionalPairString(\n key: string,\n value: string | string[] | undefined,\n): string {\n if (value == null) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return `${key}: ${value.join(\" | \")}`;\n }\n return `${key}: ${value}`;\n}\n\nfunction compareVariables(a: SnippetVariable, b: SnippetVariable): number {\n if (a.name === \"0\") {\n return 1;\n }\n if (b.name === \"0\") {\n return -1;\n }\n return a.name.localeCompare(b.name);\n}\n", "import { parseSnippetFile } from \"./parseSnippetFile.js\";\nimport { serializeSnippetFile } from \"./serializeSnippetFile.js\";\nimport type { Options } from \"./serializeSnippetFile.js\";\n\nexport function snippetFormatter(text: string, options?: Options): string {\n const snippetFile = parseSnippetFile(text);\n return serializeSnippetFile(snippetFile, options);\n}\n", "import type { DebugLogger } from \"../types.js\";\n\nexport function createDebugLogger(debug: boolean): DebugLogger {\n return {\n debug(message: string) {\n if (debug) {\n console.warn(`[debug] ${message}`);\n }\n },\n };\n}\n", "export function getColumnWidth(text: string): number | undefined {\n const match = text.match(/# fmt: columnWidth=(\\d+)/);\n\n if (match != null) {\n return parseInt(match[1], 10);\n }\n\n return undefined;\n}\n", "import { DEFAULT_INDENT_WIDTH } from \"./constants.js\";\n\nexport function getIndentation(\n indentTabs: boolean | undefined,\n indentSize: number | undefined,\n): string {\n return indentTabs ? \"\\t\" : \" \".repeat(indentSize ?? DEFAULT_INDENT_WIDTH);\n}\n", "export function convertQuotes(text: string): string {\n // Convert single quotes to double quotes\n if (\n text.length > 0 &&\n text[0] === \"'\" &&\n text[text.length - 1] === \"'\" &&\n !text.includes('\"')\n ) {\n const innerText = text.slice(1, -1).replaceAll(\"\\\\'\", \"'\");\n return `\"${innerText}\"`;\n }\n\n return text;\n}\n", "import type { DebugLogger, FormatterOptions, SyntaxNode } from \"../types.js\";\nimport {\n DEFAULT_INSERT_FINAL_NEWLINE,\n DEFAULT_MAX_LINE_LENGTH,\n} from \"../util/constants.js\";\nimport { createDebugLogger } from \"../util/createDebugLogger.js\";\nimport { getColumnWidth } from \"../util/getColumnWidth.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport { getIndentation } from \"../util/getIndentation.js\";\nimport { convertQuotes } from \"./convertQuotes.js\";\n\nexport type Options = FormatterOptions<\n | \"endOfLine\"\n | \"indentTabs\"\n | \"indentSize\"\n | \"maxLineLength\"\n | \"columnWidth\"\n | \"insertFinalNewline\"\n | \"preserveMultiline\"\n>;\n\nexport function talonFormatter(\n node: SyntaxNode,\n options: Options = {},\n debug: boolean = false,\n): string {\n const columnWidth = getColumnWidth(node.text) ?? options.columnWidth;\n const indentation = getIndentation(options.indentTabs, options.indentSize);\n const eol = getEndOfLine(options.endOfLine);\n const formatter = new TalonFormatter(\n indentation,\n eol,\n options.maxLineLength ?? DEFAULT_MAX_LINE_LENGTH,\n columnWidth,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n options.preserveMultiline ?? false,\n debug,\n );\n return formatter.getText(node);\n}\n\nclass TalonFormatter {\n private lines: string[] = [];\n private lastRow = 0;\n private logger: DebugLogger;\n\n constructor(\n private indent: string,\n private eol: string,\n private maxLineLength: number,\n private columnWidth: number | undefined,\n private insertFinalNewline: boolean,\n private preserveMultiline: boolean,\n debug: boolean,\n ) {\n this.logger = createDebugLogger(debug);\n }\n\n getText(node: SyntaxNode): string {\n this.addNode(node);\n\n const result = this.lines.join(this.eol).trimEnd();\n\n if (result.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return result + this.eol;\n }\n\n return result;\n }\n\n private addNL(): void {\n if (this.lines[this.lines.length - 1] !== \"\") {\n this.lines.push(\"\");\n }\n }\n\n private addNode(node: SyntaxNode, isIndented = false): void {\n if (node.startPosition.row > this.lastRow + 1) {\n this.addNL();\n }\n this.lastRow = node.endPosition.row;\n this.addNodeHelper(node, isIndented);\n this.lastRow = node.endPosition.row;\n }\n\n private addNodeHelper(node: SyntaxNode, isIndented = false): void {\n switch (node.type) {\n case \"source_file\":\n for (const n of node.children) {\n this.addNode(n);\n }\n break;\n\n case \"matches\": {\n // There are match nodes or there is a comment before\n if (node.children.length > 1 || !isFirstChild(node)) {\n for (const n of node.children) {\n this.addNode(n);\n }\n this.addNL();\n }\n break;\n }\n\n case \"declarations\":\n for (const n of node.children) {\n this.addNode(n);\n }\n break;\n\n case \"block\":\n for (const n of node.children) {\n this.addNode(n, true);\n }\n break;\n\n case \"command_declaration\":\n case \"key_binding_declaration\":\n case \"parrot_declaration\":\n case \"noise_declaration\":\n case \"face_declaration\":\n case \"gamepad_declaration\":\n case \"deck_declaration\":\n this.addLeftRightNode(node, false);\n break;\n\n case \"settings_declaration\":\n if (\n this.lines.length > 0 &&\n !this.lines[this.lines.length - 1].startsWith(\"#\")\n ) {\n this.addNL();\n }\n this.addLeftRightNode(node, true);\n this.addNL();\n break;\n\n case \"comment\": {\n // When using crlf eol comments have a trailing `\\r`\n const text = node.text.trimEnd();\n const nodeText =\n isIndented || node.startPosition.column > 0\n ? `${this.indent}${text}`\n : text;\n this.lines.push(nodeText);\n break;\n }\n\n default: {\n const nodeText = this.getNodeText(node);\n this.lines.push(\n isIndented ? `${this.indent}${nodeText}` : nodeText,\n );\n }\n }\n }\n\n private getNodeText(node: SyntaxNode): string {\n switch (node.type) {\n case \"source_file\":\n case \"matches\":\n case \"declarations\":\n case \"block\":\n case \"command_declaration\":\n case \"key_binding_declaration\":\n case \"parrot_declaration\":\n case \"noise_declaration\":\n case \"face_declaration\":\n case \"gamepad_declaration\":\n case \"deck_declaration\":\n case \"settings_declaration\":\n case \"comment\":\n throw new Error(\n `Node type '${node.type}' should be handled in addNode, not getNodeText`,\n );\n\n case \"parenthesized_rule\":\n return this.pairWithChildren(\n node,\n node.parent != null && rangeEqual(node, node.parent),\n );\n\n case \"optional\":\n return this.pairWithChildren(node);\n\n case \"expression_statement\":\n case \"assignment_statement\":\n case \"seq\":\n case \"choice\":\n return node.children.map((n) => this.getNodeText(n)).join(\" \");\n\n case \"rule\":\n case \"action\":\n case \"key_action\":\n case \"sleep_action\":\n case \"argument_list\":\n case \"key_binding\":\n case \"face_binding\":\n case \"gamepad_binding\":\n case \"parrot_binding\":\n case \"noise_binding\":\n case \"deck_binding\":\n case \"tag_import_declaration\":\n case \"match\":\n return node.children.map((n) => this.getNodeText(n)).join(\"\");\n\n case \"string\":\n return formatString(node);\n\n case \"match_modifier\":\n case \":\":\n case \",\":\n return `${node.text} `;\n\n case \"implicit_string\":\n return node.text.trim();\n\n case \"tag_binding\":\n case \"settings_binding\":\n case \"capture\":\n case \"list\":\n case \"key(\":\n case \"sleep(\":\n case \"gamepad(\":\n case \"face(\":\n case \"parrot(\":\n case \"noise(\":\n case \"identifier\":\n case \"variable\":\n case \"word\":\n case \"binary_operator\":\n case \"integer\":\n case \"float\":\n case \"start_anchor\":\n case \"end_anchor\":\n case \"repeat\":\n case \"deck(\":\n case \"repeat1\":\n case \"(\":\n case \")\":\n case \"=\":\n case \"-\":\n case \"|\":\n return node.text;\n\n default:\n this.logger.debug(`Unknown syntax node type '${node.type}'`);\n return node.text;\n }\n }\n\n private pairWithChildren(\n node: SyntaxNode,\n unwrap: boolean = false,\n ): string {\n const { children } = node;\n const middle = children\n .slice(1, -1)\n .map((n) => this.getNodeText(n))\n .join(\" \");\n if (unwrap) {\n return middle;\n }\n const pre = children[0].text;\n const post = children[children.length - 1].text;\n return `${pre}${middle}${post}`;\n }\n\n private addLeftRightNode(node: SyntaxNode, forceMultiline: boolean): void {\n const [leftNode, _colonNode, ...rightNodes] = node.children;\n const left = this.getNodeText(leftNode);\n\n if (!forceMultiline && rightNodes.length === 1) {\n if (\n !this.preserveMultiline ||\n isLeftRightSingleLine(leftNode, rightNodes)\n ) {\n const rightNode = rightNodes[0];\n if (rightNode.children.length === 1) {\n const right = this.getNodeText(rightNode.children[0]);\n const leftWithPadding =\n this.columnWidth != null\n ? `${left}: `.padEnd(this.columnWidth)\n : `${left}: `;\n if (\n leftWithPadding.length + right.length <=\n this.maxLineLength\n ) {\n this.lines.push(leftWithPadding + right);\n return;\n }\n }\n }\n }\n\n this.lines.push(`${left}:`);\n\n for (const n of rightNodes) {\n this.addNode(n, true);\n }\n }\n}\n\nfunction isLeftRightSingleLine(\n left: SyntaxNode,\n rights: SyntaxNode[],\n): boolean {\n return left.endPosition.row === rights[rights.length - 1].startPosition.row;\n}\n\nfunction rangeEqual(a: SyntaxNode, b: SyntaxNode): boolean {\n return (\n a.startPosition.row === b.startPosition.row &&\n a.startPosition.column === b.startPosition.column &&\n a.endPosition.row === b.endPosition.row &&\n a.endPosition.column === b.endPosition.column\n );\n}\n\nfunction isFirstChild(node: SyntaxNode): boolean {\n return node.id === node.parent?.children?.[0]?.id;\n}\n\nfunction formatString(node: SyntaxNode): string {\n // Convert single quotes to double quotes\n const text = convertQuotes(node.text);\n\n // A single string literal is allowed as syntactic sugar for the insert\n // action, but not in combination with other sibling statements.\n if (\n node.parent?.type === \"expression_statement\" &&\n node.parent.parent?.type === \"block\" &&\n rangeEqual(node, node.parent) &&\n node.parent.parent.children.length > 1\n ) {\n return `insert(${text})`;\n }\n\n return text;\n}\n", "interface TalonListHeader {\n type: \"header\";\n key: string;\n value: string;\n}\n\ninterface TalonListItem {\n type: \"item\";\n key: string;\n value?: string;\n}\n\ninterface EmptyLine {\n type: \"empty\";\n}\n\ninterface CommentLine {\n type: \"comment\";\n text: string;\n}\n\nexport interface TalonList {\n headers: (TalonListHeader | CommentLine)[];\n items: (TalonListItem | CommentLine | EmptyLine)[];\n}\n\nexport function parseTalonList(text: string): TalonList {\n const lines = text.split(/\\r?\\n/).map((l) => l.trim());\n const separatorIndex = lines.indexOf(\"-\");\n\n if (separatorIndex === -1) {\n throw Error(\"Separator not found in talon list\");\n }\n\n const headerLines = lines.slice(0, separatorIndex);\n const bodyLines = trim(lines.slice(separatorIndex + 1));\n\n const result: TalonList = {\n headers: [],\n items: [],\n };\n\n for (const line of headerLines) {\n if (line.length === 0) {\n continue;\n }\n if (line.startsWith(\"#\")) {\n result.headers.push({ type: \"comment\", text: line });\n continue;\n }\n const [key, value] = splitLine(line);\n if (value == null) {\n throw Error(\"Header value missing\");\n }\n result.headers.push({ type: \"header\", key, value });\n }\n\n for (const line of bodyLines) {\n if (line.length === 0) {\n result.items.push({ type: \"empty\" });\n continue;\n }\n if (line.startsWith(\"#\")) {\n result.items.push({ type: \"comment\", text: line });\n continue;\n }\n const [key, value] = splitLine(line);\n result.items.push({ type: \"item\", key, value });\n }\n\n return result;\n}\n\nfunction splitLine(line: string): [string, string | undefined] {\n const index = line.indexOf(\":\");\n if (index === -1) {\n return [line, undefined];\n }\n return [\n line.substring(0, index).trimEnd(),\n line.substring(index + 1).trimStart(),\n ];\n}\n\nfunction trim(list: string[]): string[] {\n const startIndex = list.findIndex((l) => l.length > 0);\n if (startIndex < 0) {\n return [];\n }\n const endIndex = list.findLastIndex((l) => l.length > 0);\n return list.slice(startIndex, endIndex + 1);\n}\n", "import type { FormatterOptions } from \"../types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"../util/constants.js\";\nimport { getColumnWidth } from \"../util/getColumnWidth.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport { convertQuotes } from \"./convertQuotes.js\";\nimport { parseTalonList } from \"./parseTalonList.js\";\n\ntype Options = FormatterOptions<\n \"endOfLine\" | \"columnWidth\" | \"insertFinalNewline\"\n>;\n\nexport function talonListFormatter(\n text: string,\n options: Options = {},\n): string {\n const columnWidth = getColumnWidth(text) ?? options.columnWidth;\n const eol = getEndOfLine(options.endOfLine);\n const talonList = parseTalonList(text);\n talonList.headers.sort((a, _b) =>\n a.type === \"header\" && a.key === \"list\" ? -1 : 0,\n );\n const lines: string[] = [];\n\n for (const header of talonList.headers) {\n if (header.type === \"comment\") {\n lines.push(header.text);\n continue;\n }\n lines.push(`${header.key}: ${header.value}`);\n }\n\n lines.push(\"-\", \"\");\n\n for (const item of talonList.items) {\n if (item.type === \"empty\") {\n lines.push(\"\");\n continue;\n }\n if (item.type === \"comment\") {\n lines.push(item.text);\n continue;\n }\n if (item.value != null) {\n const keyWithColon =\n columnWidth != null\n ? `${item.key}: `.padEnd(columnWidth)\n : `${item.key}: `;\n const value = convertQuotes(item.value);\n lines.push(`${keyWithColon}${value}`);\n } else {\n lines.push(item.key);\n }\n }\n\n if (lines.length === 0) {\n return \"\";\n }\n\n if (options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE) {\n lines.push(\"\");\n }\n\n return lines.join(eol);\n}\n", "import type { DebugLogger, FormatterOptions, SyntaxNode } from \"./types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"./util/constants.js\";\nimport { createDebugLogger } from \"./util/createDebugLogger.js\";\nimport { getEndOfLine } from \"./util/getEndOfLine.js\";\nimport { getIndentation } from \"./util/getIndentation.js\";\n\ntype Options = FormatterOptions<\n \"endOfLine\" | \"indentTabs\" | \"indentSize\" | \"insertFinalNewline\"\n>;\n\nexport function treeSitterFormatter(\n node: SyntaxNode,\n options: Options = {},\n debug: boolean = false,\n): string {\n const indentation = getIndentation(options.indentTabs, options.indentSize);\n const eol = getEndOfLine(options.endOfLine);\n const formatter = new TreeSitterFormatter(\n indentation,\n eol,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n debug,\n );\n return formatter.getText(node);\n}\n\nclass TreeSitterFormatter {\n private lastRow = 0;\n private logger: DebugLogger;\n\n constructor(\n private indentation: string,\n private eol: string,\n private insertFinalNewline: boolean,\n debug: boolean,\n ) {\n this.logger = createDebugLogger(debug);\n }\n\n getText(node: SyntaxNode): string {\n const nodeText = this.getNodeText(node, 0);\n\n if (nodeText.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return nodeText + this.eol;\n }\n\n return nodeText;\n }\n\n private getNodeText(node: SyntaxNode, numIndents: number): string {\n const nl = node.startPosition.row > this.lastRow + 1 ? this.eol : \"\";\n this.lastRow = node.endPosition.row;\n const text = this.getNodeTextInternal(node, numIndents);\n this.lastRow = node.endPosition.row;\n return `${nl}${text}`;\n }\n\n private getNamedNodeText(node: SyntaxNode, numIndents: number): string {\n const index = node.children.findIndex((n) => n.type === \")\");\n const first = node.children\n .slice(0, 2)\n .map((n) => n.text)\n .join(\"\");\n const last = node.children\n .slice(index)\n .map((n) => this.getNodeText(n, 0))\n .join(\"\");\n const interior = node.children\n .slice(2, index)\n .map((n) => this.getNodeText(n, numIndents + 1));\n // Inline node\n if (interior.length === 0) {\n return `${this.getIndent(numIndents)}${first}${last}`;\n }\n // Multiline node\n return [\n `${this.getIndent(numIndents)}${first}`,\n ...interior,\n `${this.getIndent(numIndents)}${last}`,\n ].join(this.eol);\n }\n\n private getListText(node: SyntaxNode, numIndents: number): string {\n const index = node.children.findIndex((n) => n.type === \"]\");\n const first = node.children[0].text;\n const last = node.children\n .slice(index)\n .map((n) => n.text)\n .join(\" \");\n const parts = [\n `${this.getIndent(numIndents)}${first}`,\n ...node.children\n .slice(1, index)\n .map((n) => this.getNodeText(n, numIndents + 1)),\n `${this.getIndent(numIndents)}${last}`,\n ];\n return parts.join(this.eol);\n }\n\n private getPredicateText(node: SyntaxNode, numIndents: number): string {\n const first = node.children[0].text;\n const last = node.children[node.children.length - 1].text;\n const parts = [\n node.children\n .slice(1, 4)\n .map((n) => n.text)\n .join(\"\"),\n ...node.children[node.children.length - 2].children.map(\n (n) => n.text,\n ),\n ];\n // Inline predicate\n if (node.startPosition.row === node.endPosition.row) {\n const text = `${first}${parts.join(\" \")}${last}`;\n return `${this.getIndent(numIndents)}${text}`;\n }\n // Multiline predicate\n return [\n `${this.getIndent(numIndents)}${first}${parts[0]}`,\n ...parts\n .slice(1)\n .map((s) => `${this.getIndent(numIndents + 1)}${s}`),\n `${this.getIndent(numIndents)}${last}`,\n ].join(this.eol);\n }\n\n private getFieldDefinitionText(\n node: SyntaxNode,\n numIndents: number,\n ): string {\n // Field definition directly in document root\n if (numIndents === 0) {\n return [\"(_\", this.getFieldDefinitionText(node, 1), \")\"].join(\n this.eol,\n );\n }\n // [lhs, \":\", rhs]\n return [\n this.getIndent(numIndents),\n node.children[0].text,\n node.children[1].text,\n \" \",\n this.getNodeText(node.children[2], numIndents).trimStart(),\n ].join(\"\");\n }\n\n private getNodeTextInternal(node: SyntaxNode, numIndents: number): string {\n switch (node.type) {\n case \"program\":\n return this.joinLines(node.children, 0);\n\n case \"grouping\":\n return this.joinLines(node.children, numIndents + 1);\n\n case \"list\":\n return this.getListText(node, numIndents);\n\n case \"named_node\":\n return this.getNamedNodeText(node, numIndents);\n\n case \"predicate\":\n return this.getPredicateText(node, numIndents);\n\n case \"field_definition\":\n return this.getFieldDefinitionText(node, numIndents);\n\n case \"anonymous_node\":\n return (\n this.getIndent(numIndents) +\n node.children\n .map((n) => this.getNodeText(n, numIndents + 1))\n .join(\"\")\n );\n\n case \"comment\":\n return `${this.getIndent(numIndents)}${node.text.trimEnd()}`;\n\n case \".\":\n case \"negated_field\":\n return `${this.getIndent(numIndents)}${node.text}`;\n\n case \"(\":\n case \")\":\n return `${this.getIndent(numIndents - 1)}${node.text}`;\n\n case \"capture\":\n return ` ${node.text}`;\n\n case \"#\":\n case \"_\":\n case \"predicate_type\":\n case \"identifier\":\n case \"quantifier\":\n case \"string\":\n return node.text;\n\n case \"parameters\": {\n const text = node.children.map((n) => n.text).join(\" \");\n return ` ${text}`;\n }\n\n default:\n this.logger.debug(`Unknown syntax node type '${node.type}'`);\n return node.text;\n }\n }\n\n private joinLines(nodes: SyntaxNode[], numIndents: number): string {\n if (nodes.length === 0) {\n return \"\";\n }\n const lastIsQuantifier = nodes[nodes.length - 1].type === \"quantifier\";\n const nodesToUse = lastIsQuantifier ? nodes.slice(0, -1) : nodes;\n const text = nodesToUse\n .map((n) => this.getNodeText(n, numIndents))\n .join(this.eol);\n return lastIsQuantifier\n ? `${text}${nodes[nodes.length - 1].text}`\n : text;\n }\n\n private getIndent(length: number): string {\n return length < 1\n ? \"\"\n : new Array(length).fill(this.indentation).join(\"\");\n }\n}\n"], - "mappings": "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", - "names": ["parseSnippetFile", "content", "documentContents", "file", "text", "match", "contextText", "bodyText", "body", "parseBody", "context", "parseContext", "variables", "rest", "document", "pairs", "parseContextPairs", "key", "value", "parseVectorValue", "parseVariables", "lines", "l", "line", "parts", "variablesMap", "getVariable", "name", "matchLeading", "v", "IGNORE_FOLDERS", "GLOB_IGNORE_PATTERNS", "pattern", "getEndOfLine", "eof", "serializeSnippetFile", "snippetFile", "options", "eol", "getEndOfLine", "SnippetSerializer", "insertFinalNewline", "documents", "result", "d", "document", "lines", "getOptionalPairString", "getSortedVariables", "variables", "compareVariables", "variable", "v", "key", "value", "a", "b", "snippetFormatter", "text", "options", "snippetFile", "parseSnippetFile", "serializeSnippetFile", "createDebugLogger", "debug", "message", "getColumnWidth", "text", "match", "getIndentation", "indentTabs", "indentSize", "convertQuotes", "text", "talonFormatter", "node", "options", "debug", "columnWidth", "getColumnWidth", "indentation", "getIndentation", "eol", "getEndOfLine", "TalonFormatter", "indent", "maxLineLength", "insertFinalNewline", "preserveMultiline", "createDebugLogger", "result", "isIndented", "isFirstChild", "text", "nodeText", "rangeEqual", "n", "formatString", "unwrap", "children", "middle", "pre", "post", "forceMultiline", "leftNode", "_colonNode", "rightNodes", "left", "isLeftRightSingleLine", "rightNode", "right", "leftWithPadding", "rights", "a", "b", "convertQuotes", "parseTalonList", "text", "lines", "l", "separatorIndex", "headerLines", "bodyLines", "trim", "result", "line", "key", "value", "splitLine", "index", "list", "startIndex", "endIndex", "talonListFormatter", "text", "options", "columnWidth", "getColumnWidth", "eol", "getEndOfLine", "talonList", "parseTalonList", "a", "_b", "lines", "header", "item", "keyWithColon", "value", "convertQuotes", "treeSitterFormatter", "node", "options", "debug", "indentation", "getIndentation", "eol", "getEndOfLine", "TreeSitterFormatter", "insertFinalNewline", "createDebugLogger", "nodeText", "numIndents", "nl", "text", "index", "n", "first", "last", "interior", "parts", "nodes", "lastIsQuantifier", "length"] + "sources": ["../src/snippet/parseSnippetFile.ts", "../src/util/constants.ts", "../src/util/getEndOfLine.ts", "../src/snippet/serializeSnippetFile.ts", "../src/snippet/snippetFormatter.ts", "../src/util/createDebugLogger.ts", "../src/util/getColumnWidth.ts", "../src/util/getIndentation.ts", "../src/util/SyntaxError.ts", "../src/util/SyntaxTreeError.ts", "../src/talon/convertQuotes.ts", "../src/talon/talonFormatter.ts", "../src/talon/parseTalonList.ts", "../src/talon/talonListFormatter.ts", "../src/treeSitterFormatter.ts"], + "sourcesContent": ["import type { Snippet, SnippetFile, SnippetVariable } from \"./snippetTypes.js\";\n\nexport function parseSnippetFile(content: string): SnippetFile {\n const documentContents = content.split(/^---$/m);\n const file: SnippetFile = { snippets: [] };\n\n for (const text of documentContents) {\n const match = text.match(/^-$/m);\n const contextText = match != null ? text.slice(0, match.index) : text;\n const bodyText =\n match != null ? text.slice(match.index! + match[0].length) : null;\n const body = bodyText ? parseBody(bodyText) : null;\n let context = parseContext(contextText);\n\n // Snippet with body\n if (body != null) {\n if (context == null) {\n context = { variables: [] };\n }\n const { variables, ...rest } = context;\n file.snippets.push({ ...rest, body, variables });\n }\n // Header without body\n else if (context != null) {\n if (file.header != null || file.snippets.length !== 0) {\n throw Error(\"Header snippet must be first in file\");\n }\n file.header = context;\n }\n }\n\n return file;\n}\n\ntype Context = Omit;\n\nfunction parseContext(text: string): Context | undefined {\n const document: Context = { variables: [] };\n const pairs = parseContextPairs(text);\n\n if (Object.keys(pairs).length === 0) {\n return undefined;\n }\n\n const variables: Record = {};\n\n for (const [key, value] of Object.entries(pairs)) {\n switch (key) {\n case \"name\":\n document.name = value;\n break;\n case \"description\":\n document.description = value;\n break;\n case \"phrase\":\n document.phrases = parseVectorValue(value);\n break;\n case \"insertionScope\":\n document.insertionScopes = parseVectorValue(value);\n break;\n case \"language\":\n document.languages = parseVectorValue(value);\n break;\n default:\n if (!key.startsWith(\"$\")) {\n throw Error(`Invalid key '${key}'`);\n }\n variables[key] = value;\n }\n }\n\n document.variables = parseVariables(variables);\n\n return document;\n}\n\nfunction parseContextPairs(text: string): Record {\n const lines = text\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter(Boolean);\n const pairs: Record = {};\n\n for (const line of lines) {\n const parts = line.split(\":\");\n if (parts.length !== 2) {\n throw Error(`Invalid line '${line}'`);\n }\n const key = parts[0].trim();\n const value = parts[1].trim();\n if (key.length === 0 || value.length === 0) {\n throw Error(`Invalid line '${line}'`);\n }\n if (pairs[key] != null) {\n throw Error(`Duplicate key '${key}' in '${text}'`);\n }\n pairs[key] = value;\n }\n\n return pairs;\n}\n\nfunction parseVariables(variables: Record): SnippetVariable[] {\n const variablesMap: Record = {};\n\n const getVariable = (name: string): SnippetVariable => {\n if (variablesMap[name] == null) {\n variablesMap[name] = { name };\n }\n return variablesMap[name];\n };\n\n for (const [key, value] of Object.entries(variables)) {\n const parts = key.split(\".\");\n if (parts.length !== 2) {\n throw Error(`Invalid variable key '${key}'`);\n }\n const name = parts[0].slice(1);\n const field = parts[1];\n switch (field) {\n case \"insertionFormatter\":\n getVariable(name).insertionFormatters = parseVectorValue(value);\n break;\n case \"wrapperPhrase\":\n getVariable(name).wrapperPhrases = parseVectorValue(value);\n break;\n case \"wrapperScope\":\n getVariable(name).wrapperScope = value;\n break;\n default:\n throw Error(`Invalid variable key '${key}'`);\n }\n }\n\n return Object.values(variablesMap);\n}\n\nfunction parseBody(text: string): string[] | undefined {\n // Find first line that is not empty. Preserve indentation.\n const matchLeading = text.match(/^[ \\t]*\\S/m);\n if (matchLeading?.index == null) {\n return undefined;\n }\n return text\n .slice(matchLeading.index)\n .trimEnd()\n .split(/\\r?\\n/)\n .map((l) => l.trimEnd());\n}\n\nfunction parseVectorValue(value: string): string[] {\n return value.split(\"|\").map((v) => v.trim());\n}\n", "// Exit code 0: Success\nexport const EXIT_OK = 0;\n// Exit code 1: Check failed\nexport const EXIT_FAIL = 1;\n// Exit code 2: Unexpected error\nexport const EXIT_ERROR = 2;\n\nexport type ExitCode = typeof EXIT_OK | typeof EXIT_FAIL | typeof EXIT_ERROR;\n\nexport const DEFAULT_INDENT_WIDTH = 4;\nexport const DEFAULT_MAX_LINE_LENGTH = 80;\nexport const DEFAULT_INSERT_FINAL_NEWLINE = true;\n\nexport const IGNORE_FOLDERS = [\n \".git\",\n \".svn\",\n \".hg\",\n \"node_modules\",\n \"__pycache__\",\n];\n\nexport const GLOB_IGNORE_PATTERNS = IGNORE_FOLDERS.map(\n (pattern) => `**/${pattern}/**`,\n);\n", "import type { EndOfLine } from \"../types.js\";\n\nexport function getEndOfLine(eof?: EndOfLine): string {\n return eof === \"crlf\" ? \"\\r\\n\" : \"\\n\";\n}\n", "import type { FormatterOptions } from \"../types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"../util/constants.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport type {\n Snippet,\n SnippetFile,\n SnippetHeader,\n SnippetVariable,\n} from \"./snippetTypes.js\";\n\nexport type Options = FormatterOptions<\"endOfLine\" | \"insertFinalNewline\">;\n\nexport function serializeSnippetFile(\n snippetFile: SnippetFile,\n options: Options = {},\n): string {\n const eol = getEndOfLine(options.endOfLine);\n const serializer = new SnippetSerializer(\n eol,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n );\n return serializer.getText(snippetFile);\n}\n\nclass SnippetSerializer {\n constructor(\n private eol: string,\n private insertFinalNewline: boolean,\n ) {}\n\n getText(snippetFile: SnippetFile): string {\n const docDelimiter = \"---\";\n const documents: string[] = [];\n\n if (snippetFile.header != null) {\n documents.push(this.getDocumentText(snippetFile.header));\n }\n\n documents.push(\n ...snippetFile.snippets.map(this.getDocumentText.bind(this)),\n );\n\n const result = documents\n .filter((d) => d.length > 0)\n .join(`${this.eol}${docDelimiter}${this.eol}${this.eol}`);\n\n if (result.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return result + `${this.eol}${docDelimiter}${this.eol}`;\n }\n\n return result + `${this.eol}${docDelimiter}`;\n }\n\n private getDocumentText(document: SnippetHeader | Snippet): string {\n const lines: string[] = [\n getOptionalPairString(\"name\", document.name),\n getOptionalPairString(\"description\", document.description),\n getOptionalPairString(\"language\", document.languages),\n getOptionalPairString(\"phrase\", document.phrases),\n getOptionalPairString(\"insertionScope\", document.insertionScopes),\n ].filter(Boolean);\n\n if (document.variables.length > 0) {\n if (lines.length > 0) {\n lines.push(\"\");\n }\n lines.push(...getSortedVariables(document.variables));\n }\n\n if (\"body\" in document) {\n lines.push(\"-\", ...document.body);\n }\n\n return lines.join(this.eol);\n }\n}\n\nfunction getSortedVariables(variables: SnippetVariable[]): string[] {\n const result = variables.slice();\n result.sort(compareVariables);\n return result\n .flatMap((variable) => [\n getOptionalPairString(\n `$${variable.name}.insertionFormatter`,\n variable.insertionFormatters,\n ),\n getOptionalPairString(\n `$${variable.name}.wrapperPhrase`,\n variable.wrapperPhrases,\n ),\n getOptionalPairString(\n `$${variable.name}.wrapperScope`,\n variable.wrapperScope,\n ),\n ])\n .filter((v) => v.length > 0);\n}\n\nfunction getOptionalPairString(\n key: string,\n value: string | string[] | undefined,\n): string {\n if (value == null) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return `${key}: ${value.join(\" | \")}`;\n }\n return `${key}: ${value}`;\n}\n\nfunction compareVariables(a: SnippetVariable, b: SnippetVariable): number {\n if (a.name === \"0\") {\n return 1;\n }\n if (b.name === \"0\") {\n return -1;\n }\n return a.name.localeCompare(b.name);\n}\n", "import { parseSnippetFile } from \"./parseSnippetFile.js\";\nimport { serializeSnippetFile } from \"./serializeSnippetFile.js\";\nimport type { Options } from \"./serializeSnippetFile.js\";\n\nexport function snippetFormatter(text: string, options?: Options): string {\n const snippetFile = parseSnippetFile(text);\n return serializeSnippetFile(snippetFile, options);\n}\n", "import type { DebugLogger } from \"../types.js\";\n\nexport function createDebugLogger(debug: boolean): DebugLogger {\n return {\n debug(message: string) {\n if (debug) {\n console.warn(`[debug] ${message}`);\n }\n },\n };\n}\n", "export function getColumnWidth(text: string): number | undefined {\n const match = text.match(/# fmt: columnWidth=(\\d+)/);\n\n if (match != null) {\n return parseInt(match[1], 10);\n }\n\n return undefined;\n}\n", "import { DEFAULT_INDENT_WIDTH } from \"./constants.js\";\n\nexport function getIndentation(\n indentTabs: boolean | undefined,\n indentSize: number | undefined,\n): string {\n return indentTabs ? \"\\t\" : \" \".repeat(indentSize ?? DEFAULT_INDENT_WIDTH);\n}\n", "import type { Point } from \"../types.js\";\n\nexport class SyntaxError extends Error {\n constructor(private location?: Point) {\n super(\"Syntax error.\");\n this.name = \"SyntaxError\";\n }\n\n getLocation(): string | undefined {\n return this.location != null\n ? `(${this.location.row + 1}:${this.location.column + 1})`\n : undefined;\n }\n}\n\nexport function isSyntaxError(error: unknown): error is SyntaxError {\n return error instanceof SyntaxError;\n}\n", "import type { SyntaxNode } from \"../types.js\";\nimport { SyntaxError } from \"./SyntaxError.js\";\n\nexport class SyntaxTreeError extends SyntaxError {\n constructor(rootNode: SyntaxNode) {\n super(findFirstProblemNode(rootNode)?.startPosition);\n this.name = \"SyntaxTreeError\";\n }\n}\n\nfunction findFirstProblemNode(node: SyntaxNode): SyntaxNode | null {\n if (node.isError || node.isMissing) {\n return node;\n }\n for (const child of node.children) {\n if (!child.hasError) {\n continue;\n }\n const errorNode = findFirstProblemNode(child);\n if (errorNode != null) {\n return errorNode;\n }\n }\n return null;\n}\n", "export function convertQuotes(text: string): string {\n // Convert single quotes to double quotes\n if (\n text.length > 0 &&\n text[0] === \"'\" &&\n text[text.length - 1] === \"'\" &&\n !text.includes('\"')\n ) {\n const innerText = text.slice(1, -1).replaceAll(\"\\\\'\", \"'\");\n return `\"${innerText}\"`;\n }\n\n return text;\n}\n", "import type { DebugLogger, FormatterOptions, SyntaxNode } from \"../types.js\";\nimport {\n DEFAULT_INSERT_FINAL_NEWLINE,\n DEFAULT_MAX_LINE_LENGTH,\n} from \"../util/constants.js\";\nimport { createDebugLogger } from \"../util/createDebugLogger.js\";\nimport { getColumnWidth } from \"../util/getColumnWidth.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport { getIndentation } from \"../util/getIndentation.js\";\nimport { SyntaxTreeError } from \"../util/SyntaxTreeError.js\";\nimport { convertQuotes } from \"./convertQuotes.js\";\n\nexport type Options = FormatterOptions<\n | \"endOfLine\"\n | \"indentTabs\"\n | \"indentSize\"\n | \"maxLineLength\"\n | \"columnWidth\"\n | \"insertFinalNewline\"\n | \"preserveMultiline\"\n>;\n\nexport function talonFormatter(\n node: SyntaxNode,\n options: Options = {},\n debug: boolean = false,\n): string {\n if (node.hasError) {\n throw new SyntaxTreeError(node);\n }\n\n const columnWidth = getColumnWidth(node.text) ?? options.columnWidth;\n const indentation = getIndentation(options.indentTabs, options.indentSize);\n const eol = getEndOfLine(options.endOfLine);\n const formatter = new TalonFormatter(\n indentation,\n eol,\n options.maxLineLength ?? DEFAULT_MAX_LINE_LENGTH,\n columnWidth,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n options.preserveMultiline ?? false,\n debug,\n );\n return formatter.getText(node);\n}\n\nclass TalonFormatter {\n private lines: string[] = [];\n private lastRow = 0;\n private logger: DebugLogger;\n\n constructor(\n private indent: string,\n private eol: string,\n private maxLineLength: number,\n private columnWidth: number | undefined,\n private insertFinalNewline: boolean,\n private preserveMultiline: boolean,\n debug: boolean,\n ) {\n this.logger = createDebugLogger(debug);\n }\n\n getText(node: SyntaxNode): string {\n this.addNode(node);\n\n const result = this.lines.join(this.eol).trimEnd();\n\n if (result.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return result + this.eol;\n }\n\n return result;\n }\n\n private addNL(): void {\n if (this.lines[this.lines.length - 1] !== \"\") {\n this.lines.push(\"\");\n }\n }\n\n private addNode(node: SyntaxNode, isIndented = false): void {\n if (node.startPosition.row > this.lastRow + 1) {\n this.addNL();\n }\n this.lastRow = node.endPosition.row;\n this.addNodeHelper(node, isIndented);\n this.lastRow = node.endPosition.row;\n }\n\n private addNodeHelper(node: SyntaxNode, isIndented = false): void {\n switch (node.type) {\n case \"source_file\":\n for (const n of node.children) {\n this.addNode(n);\n }\n break;\n\n case \"matches\": {\n // There are match nodes or there is a comment before\n if (node.children.length > 1 || !isFirstChild(node)) {\n for (const n of node.children) {\n this.addNode(n);\n }\n this.addNL();\n }\n break;\n }\n\n case \"declarations\":\n for (const n of node.children) {\n this.addNode(n);\n }\n break;\n\n case \"block\":\n for (const n of node.children) {\n this.addNode(n, true);\n }\n break;\n\n case \"command_declaration\":\n case \"key_binding_declaration\":\n case \"parrot_declaration\":\n case \"noise_declaration\":\n case \"face_declaration\":\n case \"gamepad_declaration\":\n case \"deck_declaration\":\n this.addLeftRightNode(node, false);\n break;\n\n case \"settings_declaration\":\n if (\n this.lines.length > 0 &&\n !this.lines[this.lines.length - 1].startsWith(\"#\")\n ) {\n this.addNL();\n }\n this.addLeftRightNode(node, true);\n this.addNL();\n break;\n\n case \"comment\": {\n // When using crlf eol comments have a trailing `\\r`\n const text = node.text.trimEnd();\n const nodeText =\n isIndented || node.startPosition.column > 0\n ? `${this.indent}${text}`\n : text;\n this.lines.push(nodeText);\n break;\n }\n\n default: {\n const nodeText = this.getNodeText(node);\n this.lines.push(\n isIndented ? `${this.indent}${nodeText}` : nodeText,\n );\n }\n }\n }\n\n private getNodeText(node: SyntaxNode): string {\n switch (node.type) {\n case \"source_file\":\n case \"matches\":\n case \"declarations\":\n case \"block\":\n case \"command_declaration\":\n case \"key_binding_declaration\":\n case \"parrot_declaration\":\n case \"noise_declaration\":\n case \"face_declaration\":\n case \"gamepad_declaration\":\n case \"deck_declaration\":\n case \"settings_declaration\":\n case \"comment\":\n throw new Error(\n `Node type '${node.type}' should be handled in addNode, not getNodeText`,\n );\n\n case \"parenthesized_rule\":\n return this.pairWithChildren(\n node,\n node.parent != null && rangeEqual(node, node.parent),\n );\n\n case \"optional\":\n return this.pairWithChildren(node);\n\n case \"expression_statement\":\n case \"assignment_statement\":\n case \"seq\":\n case \"choice\":\n return node.children.map((n) => this.getNodeText(n)).join(\" \");\n\n case \"rule\":\n case \"action\":\n case \"key_action\":\n case \"sleep_action\":\n case \"argument_list\":\n case \"key_binding\":\n case \"face_binding\":\n case \"gamepad_binding\":\n case \"parrot_binding\":\n case \"noise_binding\":\n case \"deck_binding\":\n case \"tag_import_declaration\":\n case \"match\":\n return node.children.map((n) => this.getNodeText(n)).join(\"\");\n\n case \"string\":\n return formatString(node);\n\n case \"match_modifier\":\n case \":\":\n case \",\":\n return `${node.text} `;\n\n case \"implicit_string\":\n return node.text.trim();\n\n case \"tag_binding\":\n case \"settings_binding\":\n case \"capture\":\n case \"list\":\n case \"key(\":\n case \"sleep(\":\n case \"gamepad(\":\n case \"face(\":\n case \"parrot(\":\n case \"noise(\":\n case \"identifier\":\n case \"variable\":\n case \"word\":\n case \"binary_operator\":\n case \"integer\":\n case \"float\":\n case \"start_anchor\":\n case \"end_anchor\":\n case \"repeat\":\n case \"deck(\":\n case \"repeat1\":\n case \"(\":\n case \")\":\n case \"=\":\n case \"-\":\n case \"|\":\n return node.text;\n\n default:\n this.logger.debug(`Unknown syntax node type '${node.type}'`);\n return node.text;\n }\n }\n\n private pairWithChildren(\n node: SyntaxNode,\n unwrap: boolean = false,\n ): string {\n const { children } = node;\n const middle = children\n .slice(1, -1)\n .map((n) => this.getNodeText(n))\n .join(\" \");\n if (unwrap) {\n return middle;\n }\n const pre = children[0].text;\n const post = children[children.length - 1].text;\n return `${pre}${middle}${post}`;\n }\n\n private addLeftRightNode(node: SyntaxNode, forceMultiline: boolean): void {\n const [leftNode, _colonNode, ...rightNodes] = node.children;\n const left = this.getNodeText(leftNode);\n\n if (!forceMultiline && rightNodes.length === 1) {\n if (\n !this.preserveMultiline ||\n isLeftRightSingleLine(leftNode, rightNodes)\n ) {\n const rightNode = rightNodes[0];\n if (rightNode.children.length === 1) {\n const right = this.getNodeText(rightNode.children[0]);\n const leftWithPadding =\n this.columnWidth != null\n ? `${left}: `.padEnd(this.columnWidth)\n : `${left}: `;\n if (\n leftWithPadding.length + right.length <=\n this.maxLineLength\n ) {\n this.lines.push(leftWithPadding + right);\n return;\n }\n }\n }\n }\n\n this.lines.push(`${left}:`);\n\n for (const n of rightNodes) {\n this.addNode(n, true);\n }\n }\n}\n\nfunction isLeftRightSingleLine(\n left: SyntaxNode,\n rights: SyntaxNode[],\n): boolean {\n return left.endPosition.row === rights[rights.length - 1].startPosition.row;\n}\n\nfunction rangeEqual(a: SyntaxNode, b: SyntaxNode): boolean {\n return (\n a.startPosition.row === b.startPosition.row &&\n a.startPosition.column === b.startPosition.column &&\n a.endPosition.row === b.endPosition.row &&\n a.endPosition.column === b.endPosition.column\n );\n}\n\nfunction isFirstChild(node: SyntaxNode): boolean {\n return node.id === node.parent?.children?.[0]?.id;\n}\n\nfunction formatString(node: SyntaxNode): string {\n // Convert single quotes to double quotes\n const text = convertQuotes(node.text);\n\n // A single string literal is allowed as syntactic sugar for the insert\n // action, but not in combination with other sibling statements.\n if (\n node.parent?.type === \"expression_statement\" &&\n node.parent.parent?.type === \"block\" &&\n rangeEqual(node, node.parent) &&\n node.parent.parent.children.length > 1\n ) {\n return `insert(${text})`;\n }\n\n return text;\n}\n", "interface TalonListHeader {\n type: \"header\";\n key: string;\n value: string;\n}\n\ninterface TalonListItem {\n type: \"item\";\n key: string;\n value?: string;\n}\n\ninterface EmptyLine {\n type: \"empty\";\n}\n\ninterface CommentLine {\n type: \"comment\";\n text: string;\n}\n\nexport interface TalonList {\n headers: (TalonListHeader | CommentLine)[];\n items: (TalonListItem | CommentLine | EmptyLine)[];\n}\n\nexport function parseTalonList(text: string): TalonList {\n const lines = text.split(/\\r?\\n/).map((l) => l.trim());\n const separatorIndex = lines.indexOf(\"-\");\n\n if (separatorIndex === -1) {\n throw Error(\"Separator not found in talon list\");\n }\n\n const headerLines = lines.slice(0, separatorIndex);\n const bodyLines = trim(lines.slice(separatorIndex + 1));\n\n const result: TalonList = {\n headers: [],\n items: [],\n };\n\n for (const line of headerLines) {\n if (line.length === 0) {\n continue;\n }\n if (line.startsWith(\"#\")) {\n result.headers.push({ type: \"comment\", text: line });\n continue;\n }\n const [key, value] = splitLine(line);\n if (value == null) {\n throw Error(\"Header value missing\");\n }\n result.headers.push({ type: \"header\", key, value });\n }\n\n for (const line of bodyLines) {\n if (line.length === 0) {\n result.items.push({ type: \"empty\" });\n continue;\n }\n if (line.startsWith(\"#\")) {\n result.items.push({ type: \"comment\", text: line });\n continue;\n }\n const [key, value] = splitLine(line);\n result.items.push({ type: \"item\", key, value });\n }\n\n return result;\n}\n\nfunction splitLine(line: string): [string, string | undefined] {\n const index = line.indexOf(\":\");\n if (index === -1) {\n return [line, undefined];\n }\n return [\n line.substring(0, index).trimEnd(),\n line.substring(index + 1).trimStart(),\n ];\n}\n\nfunction trim(list: string[]): string[] {\n const startIndex = list.findIndex((l) => l.length > 0);\n if (startIndex < 0) {\n return [];\n }\n const endIndex = list.findLastIndex((l) => l.length > 0);\n return list.slice(startIndex, endIndex + 1);\n}\n", "import type { FormatterOptions } from \"../types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"../util/constants.js\";\nimport { getColumnWidth } from \"../util/getColumnWidth.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport { convertQuotes } from \"./convertQuotes.js\";\nimport { parseTalonList } from \"./parseTalonList.js\";\n\ntype Options = FormatterOptions<\n \"endOfLine\" | \"columnWidth\" | \"insertFinalNewline\"\n>;\n\nexport function talonListFormatter(\n text: string,\n options: Options = {},\n): string {\n const columnWidth = getColumnWidth(text) ?? options.columnWidth;\n const eol = getEndOfLine(options.endOfLine);\n const talonList = parseTalonList(text);\n talonList.headers.sort((a, _b) =>\n a.type === \"header\" && a.key === \"list\" ? -1 : 0,\n );\n const lines: string[] = [];\n\n for (const header of talonList.headers) {\n if (header.type === \"comment\") {\n lines.push(header.text);\n continue;\n }\n lines.push(`${header.key}: ${header.value}`);\n }\n\n lines.push(\"-\", \"\");\n\n for (const item of talonList.items) {\n if (item.type === \"empty\") {\n lines.push(\"\");\n continue;\n }\n if (item.type === \"comment\") {\n lines.push(item.text);\n continue;\n }\n if (item.value != null) {\n const keyWithColon =\n columnWidth != null\n ? `${item.key}: `.padEnd(columnWidth)\n : `${item.key}: `;\n const value = convertQuotes(item.value);\n lines.push(`${keyWithColon}${value}`);\n } else {\n lines.push(item.key);\n }\n }\n\n if (lines.length === 0) {\n return \"\";\n }\n\n if (options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE) {\n lines.push(\"\");\n }\n\n return lines.join(eol);\n}\n", "import type { DebugLogger, FormatterOptions, SyntaxNode } from \"./types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"./util/constants.js\";\nimport { createDebugLogger } from \"./util/createDebugLogger.js\";\nimport { getEndOfLine } from \"./util/getEndOfLine.js\";\nimport { getIndentation } from \"./util/getIndentation.js\";\nimport { SyntaxTreeError } from \"./util/SyntaxTreeError.js\";\n\nexport type Options = FormatterOptions<\n \"endOfLine\" | \"indentTabs\" | \"indentSize\" | \"insertFinalNewline\"\n>;\n\nexport function treeSitterFormatter(\n node: SyntaxNode,\n options: Options = {},\n debug: boolean = false,\n): string {\n if (node.hasError) {\n throw new SyntaxTreeError(node);\n }\n\n const indentation = getIndentation(options.indentTabs, options.indentSize);\n const eol = getEndOfLine(options.endOfLine);\n const formatter = new TreeSitterFormatter(\n indentation,\n eol,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n debug,\n );\n return formatter.getText(node);\n}\n\nclass TreeSitterFormatter {\n private lastRow = 0;\n private logger: DebugLogger;\n\n constructor(\n private indentation: string,\n private eol: string,\n private insertFinalNewline: boolean,\n debug: boolean,\n ) {\n this.logger = createDebugLogger(debug);\n }\n\n getText(node: SyntaxNode): string {\n const nodeText = this.getNodeText(node, 0);\n\n if (nodeText.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return nodeText + this.eol;\n }\n\n return nodeText;\n }\n\n private getNodeText(node: SyntaxNode, numIndents: number): string {\n const nl = node.startPosition.row > this.lastRow + 1 ? this.eol : \"\";\n this.lastRow = node.endPosition.row;\n const text = this.getNodeTextInternal(node, numIndents);\n this.lastRow = node.endPosition.row;\n return `${nl}${text}`;\n }\n\n private getNamedNodeText(node: SyntaxNode, numIndents: number): string {\n const index = node.children.findIndex((n) => n.type === \")\");\n const first = node.children\n .slice(0, 2)\n .map((n) => n.text)\n .join(\"\");\n const last = node.children\n .slice(index)\n .map((n) => this.getNodeText(n, 0))\n .join(\"\");\n const interior = node.children\n .slice(2, index)\n .map((n) => this.getNodeText(n, numIndents + 1));\n // Inline node\n if (interior.length === 0) {\n return `${this.getIndent(numIndents)}${first}${last}`;\n }\n // Multiline node\n return [\n `${this.getIndent(numIndents)}${first}`,\n ...interior,\n `${this.getIndent(numIndents)}${last}`,\n ].join(this.eol);\n }\n\n private getListText(node: SyntaxNode, numIndents: number): string {\n const index = node.children.findIndex((n) => n.type === \"]\");\n const first = node.children[0].text;\n const last = node.children\n .slice(index)\n .map((n) => n.text)\n .join(\" \");\n const parts = [\n `${this.getIndent(numIndents)}${first}`,\n ...node.children\n .slice(1, index)\n .map((n) => this.getNodeText(n, numIndents + 1)),\n `${this.getIndent(numIndents)}${last}`,\n ];\n return parts.join(this.eol);\n }\n\n private getPredicateText(node: SyntaxNode, numIndents: number): string {\n const first = node.children[0].text;\n const last = node.children[node.children.length - 1].text;\n const parts = [\n node.children\n .slice(1, 4)\n .map((n) => n.text)\n .join(\"\"),\n ...node.children[node.children.length - 2].children.map(\n (n) => n.text,\n ),\n ];\n // Inline predicate\n if (node.startPosition.row === node.endPosition.row) {\n const text = `${first}${parts.join(\" \")}${last}`;\n return `${this.getIndent(numIndents)}${text}`;\n }\n // Multiline predicate\n return [\n `${this.getIndent(numIndents)}${first}${parts[0]}`,\n ...parts\n .slice(1)\n .map((s) => `${this.getIndent(numIndents + 1)}${s}`),\n `${this.getIndent(numIndents)}${last}`,\n ].join(this.eol);\n }\n\n private getFieldDefinitionText(\n node: SyntaxNode,\n numIndents: number,\n ): string {\n // Field definition directly in document root\n if (numIndents === 0) {\n return [\"(_\", this.getFieldDefinitionText(node, 1), \")\"].join(\n this.eol,\n );\n }\n // [lhs, \":\", rhs]\n return [\n this.getIndent(numIndents),\n node.children[0].text,\n node.children[1].text,\n \" \",\n this.getNodeText(node.children[2], numIndents).trimStart(),\n ].join(\"\");\n }\n\n private getNodeTextInternal(node: SyntaxNode, numIndents: number): string {\n switch (node.type) {\n case \"program\":\n return this.joinLines(node.children, 0);\n\n case \"grouping\":\n return this.joinLines(node.children, numIndents + 1);\n\n case \"list\":\n return this.getListText(node, numIndents);\n\n case \"named_node\":\n return this.getNamedNodeText(node, numIndents);\n\n case \"predicate\":\n return this.getPredicateText(node, numIndents);\n\n case \"field_definition\":\n return this.getFieldDefinitionText(node, numIndents);\n\n case \"anonymous_node\":\n return (\n this.getIndent(numIndents) +\n node.children\n .map((n) => this.getNodeText(n, numIndents + 1))\n .join(\"\")\n );\n\n case \"comment\":\n return `${this.getIndent(numIndents)}${node.text.trimEnd()}`;\n\n case \".\":\n case \"negated_field\":\n return `${this.getIndent(numIndents)}${node.text}`;\n\n case \"(\":\n case \")\":\n return `${this.getIndent(numIndents - 1)}${node.text}`;\n\n case \"capture\":\n return ` ${node.text}`;\n\n case \"#\":\n case \"_\":\n case \"predicate_type\":\n case \"identifier\":\n case \"quantifier\":\n case \"string\":\n return node.text;\n\n case \"parameters\": {\n const text = node.children.map((n) => n.text).join(\" \");\n return ` ${text}`;\n }\n\n default:\n this.logger.debug(`Unknown syntax node type '${node.type}'`);\n return node.text;\n }\n }\n\n private joinLines(nodes: SyntaxNode[], numIndents: number): string {\n if (nodes.length === 0) {\n return \"\";\n }\n const lastIsQuantifier = nodes[nodes.length - 1].type === \"quantifier\";\n const nodesToUse = lastIsQuantifier ? nodes.slice(0, -1) : nodes;\n const text = nodesToUse\n .map((n) => this.getNodeText(n, numIndents))\n .join(this.eol);\n return lastIsQuantifier\n ? `${text}${nodes[nodes.length - 1].text}`\n : text;\n }\n\n private getIndent(length: number): string {\n return length < 1\n ? \"\"\n : new Array(length).fill(this.indentation).join(\"\");\n }\n}\n"], + "mappings": "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", + "names": ["parseSnippetFile", "content", "documentContents", "file", "text", "match", "contextText", "bodyText", "body", "parseBody", "context", "parseContext", "variables", "rest", "document", "pairs", "parseContextPairs", "key", "value", "parseVectorValue", "parseVariables", "lines", "l", "line", "parts", "variablesMap", "getVariable", "name", "matchLeading", "v", "IGNORE_FOLDERS", "GLOB_IGNORE_PATTERNS", "pattern", "getEndOfLine", "eof", "serializeSnippetFile", "snippetFile", "options", "eol", "getEndOfLine", "SnippetSerializer", "insertFinalNewline", "documents", "result", "d", "document", "lines", "getOptionalPairString", "getSortedVariables", "variables", "compareVariables", "variable", "v", "key", "value", "a", "b", "snippetFormatter", "text", "options", "snippetFile", "parseSnippetFile", "serializeSnippetFile", "createDebugLogger", "debug", "message", "getColumnWidth", "text", "match", "getIndentation", "indentTabs", "indentSize", "SyntaxError", "location", "SyntaxTreeError", "SyntaxError", "rootNode", "findFirstProblemNode", "node", "child", "errorNode", "convertQuotes", "text", "talonFormatter", "node", "options", "debug", "SyntaxTreeError", "columnWidth", "getColumnWidth", "indentation", "getIndentation", "eol", "getEndOfLine", "TalonFormatter", "indent", "maxLineLength", "insertFinalNewline", "preserveMultiline", "createDebugLogger", "result", "isIndented", "n", "isFirstChild", "text", "nodeText", "rangeEqual", "formatString", "unwrap", "children", "middle", "pre", "post", "forceMultiline", "leftNode", "_colonNode", "rightNodes", "left", "isLeftRightSingleLine", "rightNode", "right", "leftWithPadding", "rights", "a", "b", "convertQuotes", "parseTalonList", "text", "lines", "l", "separatorIndex", "headerLines", "bodyLines", "trim", "result", "line", "key", "value", "splitLine", "index", "list", "startIndex", "endIndex", "talonListFormatter", "text", "options", "columnWidth", "getColumnWidth", "eol", "getEndOfLine", "talonList", "parseTalonList", "a", "_b", "lines", "header", "item", "keyWithColon", "value", "convertQuotes", "treeSitterFormatter", "node", "options", "debug", "SyntaxTreeError", "indentation", "getIndentation", "eol", "getEndOfLine", "TreeSitterFormatter", "insertFinalNewline", "createDebugLogger", "nodeText", "numIndents", "nl", "text", "index", "n", "first", "last", "interior", "parts", "nodes", "lastIsQuantifier", "length"] } diff --git a/dist/node/cli.d.ts b/dist/node/cli.d.ts index 38ca15c..70f5c8a 100644 --- a/dist/node/cli.d.ts +++ b/dist/node/cli.d.ts @@ -1,5 +1,6 @@ import type { Readable } from "node:stream"; import type { CLI, Logger } from "../types.js"; +import { type ExitCode } from "../util/constants.js"; export declare function main(cli: CLI): Promise; interface FormatFilesArgs { cli: CLI; @@ -8,7 +9,7 @@ interface FormatFilesArgs { debug: boolean; filePaths: string[]; } -export declare function formatFiles({ cli, logger, check, debug, filePaths, }: FormatFilesArgs): Promise; +export declare function formatFiles({ cli, logger, check, debug, filePaths, }: FormatFilesArgs): Promise<[number, boolean]>; interface FormatFileArgs { cli: CLI; logger: Logger; @@ -24,5 +25,5 @@ interface MainFormatStdinArgs { check: boolean; debug: boolean; } -export declare function mainFormatStdin({ cli, logger, stdin, check, debug, }: MainFormatStdinArgs): Promise; +export declare function mainFormatStdin({ cli, logger, stdin, check, debug, }: MainFormatStdinArgs): Promise; export {}; diff --git a/dist/node/isMissingFileError.d.ts b/dist/node/isMissingFileError.d.ts index e571516..75f1f5c 100644 --- a/dist/node/isMissingFileError.d.ts +++ b/dist/node/isMissingFileError.d.ts @@ -1 +1 @@ -export declare function isMissingFileError(error: unknown): boolean; +export declare function isMissingFileError(error: unknown): error is NodeJS.ErrnoException; diff --git a/dist/snippetFormatter.js b/dist/snippetFormatter.js index 9f06f78..f0a5c41 100644 --- a/dist/snippetFormatter.js +++ b/dist/snippetFormatter.js @@ -1,15 +1,15 @@ #!/usr/bin/env node -function N(t){let e=t.split(/^---$/m),r={snippets:[]};for(let n of e){let i=n.match(/^-$/m),o=i!=null?n.slice(0,i.index):n,s=i!=null?n.slice(i.index+i[0].length):null,a=s?Q(s):null,l=B(o);if(a!=null){l==null&&(l={variables:[]});let{variables:h,...f}=l;r.snippets.push({...f,body:a,variables:h})}else if(l!=null){if(r.header!=null||r.snippets.length!==0)throw Error("Header snippet must be first in file");r.header=l}}return r}function B(t){let e={variables:[]},r=Y(t);if(Object.keys(r).length===0)return;let n={};for(let[i,o]of Object.entries(r))switch(i){case"name":e.name=o;break;case"description":e.description=o;break;case"phrase":e.phrases=y(o);break;case"insertionScope":e.insertionScopes=y(o);break;case"language":e.languages=y(o);break;default:if(!i.startsWith("$"))throw Error(`Invalid key '${i}'`);n[i]=o}return e.variables=J(n),e}function Y(t){let e=t.split(/\r?\n/).map(n=>n.trim()).filter(Boolean),r={};for(let n of e){let i=n.split(":");if(i.length!==2)throw Error(`Invalid line '${n}'`);let o=i[0].trim(),s=i[1].trim();if(o.length===0||s.length===0)throw Error(`Invalid line '${n}'`);if(r[o]!=null)throw Error(`Duplicate key '${o}' in '${t}'`);r[o]=s}return r}function J(t){let e={},r=n=>(e[n]==null&&(e[n]={name:n}),e[n]);for(let[n,i]of Object.entries(t)){let o=n.split(".");if(o.length!==2)throw Error(`Invalid variable key '${n}'`);let s=o[0].slice(1);switch(o[1]){case"insertionFormatter":r(s).insertionFormatters=y(i);break;case"wrapperPhrase":r(s).wrapperPhrases=y(i);break;case"wrapperScope":r(s).wrapperScope=i;break;default:throw Error(`Invalid variable key '${n}'`)}}return Object.values(e)}function Q(t){let e=t.match(/^[ \t]*\S/m);if(e?.index!=null)return t.slice(e.index).trimEnd().split(/\r?\n/).map(r=>r.trimEnd())}function y(t){return t.split("|").map(e=>e.trim())}var Z=[".git",".svn",".hg","node_modules","__pycache__"],v=Z.map(t=>`**/${t}/**`);function A(t){return t==="crlf"?`\r +function N(t){let e=t.split(/^---$/m),r={snippets:[]};for(let n of e){let i=n.match(/^-$/m),o=i!=null?n.slice(0,i.index):n,s=i!=null?n.slice(i.index+i[0].length):null,a=s?re(s):null,l=Z(o);if(a!=null){l==null&&(l={variables:[]});let{variables:h,...f}=l;r.snippets.push({...f,body:a,variables:h})}else if(l!=null){if(r.header!=null||r.snippets.length!==0)throw Error("Header snippet must be first in file");r.header=l}}return r}function Z(t){let e={variables:[]},r=ee(t);if(Object.keys(r).length===0)return;let n={};for(let[i,o]of Object.entries(r))switch(i){case"name":e.name=o;break;case"description":e.description=o;break;case"phrase":e.phrases=b(o);break;case"insertionScope":e.insertionScopes=b(o);break;case"language":e.languages=b(o);break;default:if(!i.startsWith("$"))throw Error(`Invalid key '${i}'`);n[i]=o}return e.variables=te(n),e}function ee(t){let e=t.split(/\r?\n/).map(n=>n.trim()).filter(Boolean),r={};for(let n of e){let i=n.split(":");if(i.length!==2)throw Error(`Invalid line '${n}'`);let o=i[0].trim(),s=i[1].trim();if(o.length===0||s.length===0)throw Error(`Invalid line '${n}'`);if(r[o]!=null)throw Error(`Duplicate key '${o}' in '${t}'`);r[o]=s}return r}function te(t){let e={},r=n=>(e[n]==null&&(e[n]={name:n}),e[n]);for(let[n,i]of Object.entries(t)){let o=n.split(".");if(o.length!==2)throw Error(`Invalid variable key '${n}'`);let s=o[0].slice(1);switch(o[1]){case"insertionFormatter":r(s).insertionFormatters=b(i);break;case"wrapperPhrase":r(s).wrapperPhrases=b(i);break;case"wrapperScope":r(s).wrapperScope=i;break;default:throw Error(`Invalid variable key '${n}'`)}}return Object.values(e)}function re(t){let e=t.match(/^[ \t]*\S/m);if(e?.index!=null)return t.slice(e.index).trimEnd().split(/\r?\n/).map(r=>r.trimEnd())}function b(t){return t.split("|").map(e=>e.trim())}var ne=[".git",".svn",".hg","node_modules","__pycache__"],C=ne.map(t=>`**/${t}/**`);function I(t){return t==="crlf"?`\r `:` -`}function $(t,e={}){let r=A(e.endOfLine);return new S(r,e.insertFinalNewline??!0).getText(t)}var S=class{constructor(e,r){this.eol=e;this.insertFinalNewline=r}getText(e){let n=[];e.header!=null&&n.push(this.getDocumentText(e.header)),n.push(...e.snippets.map(this.getDocumentText.bind(this)));let i=n.filter(o=>o.length>0).join(`${this.eol}---${this.eol}${this.eol}`);return i.length===0?"":this.insertFinalNewline?i+`${this.eol}---${this.eol}`:i+`${this.eol}---`}getDocumentText(e){let r=[c("name",e.name),c("description",e.description),c("language",e.languages),c("phrase",e.phrases),c("insertionScope",e.insertionScopes)].filter(Boolean);return e.variables.length>0&&(r.length>0&&r.push(""),r.push(...te(e.variables))),"body"in e&&r.push("-",...e.body),r.join(this.eol)}};function te(t){let e=t.slice();return e.sort(re),e.flatMap(r=>[c(`$${r.name}.insertionFormatter`,r.insertionFormatters),c(`$${r.name}.wrapperPhrase`,r.wrapperPhrases),c(`$${r.name}.wrapperScope`,r.wrapperScope)]).filter(r=>r.length>0)}function c(t,e){return e==null?"":Array.isArray(e)?`${t}: ${e.join(" | ")}`:`${t}: ${e}`}function re(t,e){return t.name==="0"?1:e.name==="0"?-1:t.name.localeCompare(e.name)}function T(t,e){let r=N(t);return $(r,e)}import de from"get-stdin";import*as E from"node:fs/promises";import*as F from"node:path";import*as p from"node:process";var m=class extends Error{constructor(r){super(`One or more file pattern errors occurred: +`}function k(t,e={}){let r=I(e.endOfLine);return new F(r,e.insertFinalNewline??!0).getText(t)}var F=class{constructor(e,r){this.eol=e;this.insertFinalNewline=r}getText(e){let n=[];e.header!=null&&n.push(this.getDocumentText(e.header)),n.push(...e.snippets.map(this.getDocumentText.bind(this)));let i=n.filter(o=>o.length>0).join(`${this.eol}---${this.eol}${this.eol}`);return i.length===0?"":this.insertFinalNewline?i+`${this.eol}---${this.eol}`:i+`${this.eol}---`}getDocumentText(e){let r=[g("name",e.name),g("description",e.description),g("language",e.languages),g("phrase",e.phrases),g("insertionScope",e.insertionScopes)].filter(Boolean);return e.variables.length>0&&(r.length>0&&r.push(""),r.push(...oe(e.variables))),"body"in e&&r.push("-",...e.body),r.join(this.eol)}};function oe(t){let e=t.slice();return e.sort(se),e.flatMap(r=>[g(`$${r.name}.insertionFormatter`,r.insertionFormatters),g(`$${r.name}.wrapperPhrase`,r.wrapperPhrases),g(`$${r.name}.wrapperScope`,r.wrapperScope)]).filter(r=>r.length>0)}function g(t,e){return e==null?"":Array.isArray(e)?`${t}: ${e.join(" | ")}`:`${t}: ${e}`}function se(t,e){return t.name==="0"?1:e.name==="0"?-1:t.name.localeCompare(e.name)}function R(t,e){let r=N(t);return k(r,e)}import ye from"get-stdin";import*as w from"node:fs/promises";import*as S from"node:path";import*as c from"node:process";function L(t){return t instanceof Error?t.message:String(t)}var _=class extends Error{constructor(r){super("Syntax error.");this.location=r;this.name="SyntaxError"}getLocation(){return this.location!=null?`(${this.location.row+1}:${this.location.column+1})`:void 0}};function P(t){return t instanceof _}import*as u from"node:process";var ae="\x1B[0m",le="\x1B[33m",pe="\x1B[31m",ce="[warn]",fe="[error]";function O(t=!1){return ge(u.stdout,u.stderr,t)}function ge(t,e,r=!1){let n=ue(e)?(s,a)=>`${a}${s}${ae}`:(s,a)=>s,i,o;return r?(i=()=>{},o=()=>{}):(i=s=>{t.write(`${s} +`)},o=s=>{e.write(`${n(ce,le)} ${s} +`)}),{log:i,warn:o,error(s){e.write(`${n(fe,pe)} ${s} +`)}}}function ue(t){return"NO_COLOR"in u.env?!1:t.isTTY===!0}var m=class extends Error{constructor(r){super(`One or more file pattern errors occurred: ${r.join(` -`)}`);this.messages=r}name="FilePatternError"};function L(t){return t instanceof Error?t.message:String(t)}function w(t){return t instanceof Error&&"code"in t&&t.code==="ENOENT"}function _(t){Reflect.set(process,"exitCode",t)}import*as u from"node:process";var ne="\x1B[0m",ie="\x1B[33m",oe="\x1B[31m",se="[warn]",ae="[error]";function P(t=!1){return le(u.stdout,u.stderr,t)}function le(t,e,r=!1){let n=pe(e)?(s,a)=>`${a}${s}${ne}`:(s,a)=>s,i,o;return r?(i=()=>{},o=()=>{}):(i=s=>{t.write(`${s} -`)},o=s=>{e.write(`${n(se,ie)} ${s} -`)}),{log:i,warn:o,error(s){e.write(`${n(ae,oe)} ${s} -`)}}}function pe(t){return"NO_COLOR"in u.env?!1:t.isTTY===!0}import*as C from"editorconfig";async function O(t){let e=await C.parse(t),r={};return e.indent_style==="tab"?r.indentTabs=!0:e.indent_style==="space"&&(r.indentTabs=!1),typeof e.indent_size=="number"?r.indentSize=e.indent_size:e.indent_size==="tab"&&typeof e.tab_width=="number"&&(r.indentSize=e.tab_width),typeof e.max_line_length=="number"&&(r.maxLineLength=e.max_line_length),typeof e.column_width=="number"&&(r.columnWidth=e.column_width),typeof e.insert_final_newline=="boolean"&&(r.insertFinalNewline=e.insert_final_newline),typeof e.preserve_multiline=="boolean"&&(r.preserveMultiline=e.preserve_multiline),e.end_of_line!=null&&e.end_of_line!=="unset"&&(r.endOfLine=e.end_of_line),r}import*as k from"node:path";var x=k.sep==="\\"?t=>t.replaceAll("\\","/"):t=>t;function I(){return{filePatterns:[],help:!1,version:!1,quiet:!1,debug:!1,check:!1}}function R(t){let e=I();for(let r=0;rge(g,t.fileEndings));f.length===0&&i.push(`No files matching the pattern were found: ${s}`);for(let g of f)r.add(d.resolve(g))}if(i.length>0)throw new m(i);return Array.from(r).sort((s,a)=>s.localeCompare(a))}function fe(t){return t.length===1?t[0]:`{${t.join(",")}}`}function ge(t,e){let r=d.extname(t).slice(1);return e.includes(r)}var V=["--help","--version","--quiet","--check","--debug"];function W(t){process.stdout.write(`Usage: ${t.binName} [options] [file/dir/glob ...] +`)}`);this.messages=r}name="FilePatternError"};import*as j from"editorconfig";async function $(t){let e=await j.parse(t),r={};return e.indent_style==="tab"?r.indentTabs=!0:e.indent_style==="space"&&(r.indentTabs=!1),typeof e.indent_size=="number"?r.indentSize=e.indent_size:e.indent_size==="tab"&&typeof e.tab_width=="number"&&(r.indentSize=e.tab_width),typeof e.max_line_length=="number"&&(r.maxLineLength=e.max_line_length),typeof e.column_width=="number"&&(r.columnWidth=e.column_width),typeof e.insert_final_newline=="boolean"&&(r.insertFinalNewline=e.insert_final_newline),typeof e.preserve_multiline=="boolean"&&(r.preserveMultiline=e.preserve_multiline),e.end_of_line!=null&&e.end_of_line!=="unset"&&(r.endOfLine=e.end_of_line),r}function x(t){return t instanceof Error&&"code"in t&&t.code==="ENOENT"}import*as D from"node:path";var E=D.sep==="\\"?t=>t.replaceAll("\\","/"):t=>t;function M(){return{filePatterns:[],help:!1,version:!1,quiet:!1,debug:!1,check:!1}}function W(t){let e=M();for(let r=0;rhe(p,t.fileEndings));f.length===0&&i.push(`No files matching the pattern were found: ${s}`);for(let p of f)r.add(d.resolve(p))}if(i.length>0)throw new m(i);return Array.from(r).sort((s,a)=>s.localeCompare(a))}function de(t){return t.length===1?t[0]:`{${t.join(",")}}`}function he(t,e){let r=d.extname(t).slice(1);return e.includes(r)}var X=["--help","--version","--quiet","--check","--debug"];function G(t){process.stdout.write(`Usage: ${t.binName} [options] [file/dir/glob ...] `),process.stdout.write(` `),process.stdout.write(`Options: -`);for(let e of V)process.stdout.write(` ${e} -`)}var K={name:"@cursorless/talon-tools",version:"0.9.0",description:"Linting and formatting tools for Talon and Cursorless",author:"Cursorless Dev",license:"MIT",type:"module",files:["dist","!dist/test","!dist/build.*"],types:"./dist/lib.d.ts",exports:{".":{types:"./dist/lib.d.ts",default:"./dist/lib.js"},"./node":{types:"./dist/node/libNode.d.ts",default:"./dist/libNode.js"}},bin:{"snippet-fmt":"dist/snippetFormatter.js","talon-fmt":"dist/talonFormatter.js","tree-sitter-fmt":"dist/treeSitterFormatter.js"},repository:{type:"git",url:"git+https://github.com/cursorless-dev/talon-tools.git"},funding:"https://github.com/sponsors/cursorless-dev",sponsor:{url:"https://github.com/sponsors/cursorless-dev"},scripts:{build:"npm run clean && tsc -p . && tsx ./src/build.ts",clean:"rm -rf dist/*",lint:"npm run lint:ts &&npm run lint:fmt","lint:ts":"tsc -p . --noEmit && eslint src","lint:fmt":"prettier --check .",fix:"npm run fix:ts && npm run fix:fmt","fix:ts":"eslint src --fix","fix:fmt":"prettier --write --list-different .",test:"tsx src/test/runAllTests.ts","test:subset":"tsx src/test/runAllTests.ts --subset"},dependencies:{"@cursorless/tree-sitter-wasms":"^0.7.0",editorconfig:"^3.0.2","fast-glob":"^3.3.3","get-stdin":"^10.0.0","web-tree-sitter":"^0.26.7"},devDependencies:{"@eslint/js":"^9.39.4","@types/mocha":"^10.0.10","@types/node":"^24.12.0",esbuild:"^0.27.4","eslint-config-prettier":"^10.1.8","eslint-plugin-import":"^2.32.0",eslint:"^9.39.4",jiti:"^2.6.1",mocha:"^11.7.5",prettier:"^3.8.1",tsx:"^4.21.0","typescript-eslint":"^8.57.1",typescript:"^5.9.3"}};function U(){process.stdout.write(`${K.version} -`)}async function X(t){let e=P();try{let r=R(p.argv.slice(2));e=P(r.quiet);let n=await be({cli:t,args:r,logger:e});_(n)}catch(r){if(r instanceof m)for(let n of r.messages)e.error(n);else e.error(L(r));_(2)}}async function be({cli:t,args:e,logger:r}){if(e.help)return W(t),0;if(e.version)return U(),0;if(e.filePatterns.length>0)return he({cli:t,logger:r,check:e.check,debug:e.debug,filePatterns:e.filePatterns});if(!p.stdin.isTTY)return Ee({cli:t,logger:r,stdin:p.stdin,check:e.check,debug:e.debug});throw new Error("No input files specified. Use --help for usage information.")}async function he({cli:t,logger:e,check:r,debug:n,filePatterns:i}){r&&e.log("Checking formatting...");let o=await z(t,i),s=await ye({cli:t,logger:e,check:r,debug:n,filePaths:o});return r?s>0?(e.warn(`Code style issues found in ${s} file(s).`),1):(e.log("All matched files use correct code style!"),0):0}async function ye({cli:t,logger:e,check:r,debug:n,filePaths:i}){let o=0;for(let s of i)await we({cli:t,logger:e,check:r,debug:n,filePath:s})&&o++;return o}async function we({cli:t,logger:e,check:r,debug:n,filePath:i}){try{let o=await O(i),s=await E.readFile(i,"utf8"),a=await t.format(s,o,i,n);return a===s?!1:(e.log(xe(i)),r||await E.writeFile(i,a,"utf8"),!0)}catch(o){if(w(o))return!1;throw new Error(`Failed to format '${i}': ${L(o)}`,{cause:o})}}function xe(t){return x(F.relative(p.cwd(),t))}async function Ee({cli:t,logger:e,stdin:r,check:n,debug:i}){let o=await de({stdin:r}),a=`stdin.${t.getStdinFileEnding(o)}`,l=F.resolve(a),h=await O(l),f=await t.format(o,h,l,i);return n?o!==f?(e.warn("Code style issues found in stdin."),1):0:(p.stdout.write(f),0)}var H="snippet";X({binName:"snippet-fmt",fileEndings:[H],getStdinFileEnding(){return H},format:async(t,e)=>{let r=T(t,e);return Promise.resolve(r)}}); +`);for(let e of X)process.stdout.write(` ${e} +`)}var H={name:"@cursorless/talon-tools",version:"0.10.0",description:"Linting and formatting tools for Talon and Cursorless",author:"Cursorless Dev",license:"MIT",type:"module",files:["dist","!dist/test","!dist/build.*"],types:"./dist/lib.d.ts",exports:{".":{types:"./dist/lib.d.ts",default:"./dist/lib.js"},"./node":{types:"./dist/node/libNode.d.ts",default:"./dist/libNode.js"}},bin:{"snippet-fmt":"dist/snippetFormatter.js","talon-fmt":"dist/talonFormatter.js","tree-sitter-fmt":"dist/treeSitterFormatter.js"},repository:{type:"git",url:"git+https://github.com/cursorless-dev/talon-tools.git"},funding:"https://github.com/sponsors/cursorless-dev",sponsor:{url:"https://github.com/sponsors/cursorless-dev"},scripts:{build:"npm run clean && tsc -p . && tsx ./src/build.ts",clean:"rm -rf dist/*",lint:"npm run lint:ts &&npm run lint:fmt","lint:ts":"tsc -p . --noEmit && eslint src","lint:fmt":"prettier --check .",fix:"npm run fix:ts && npm run fix:fmt","fix:ts":"eslint src --fix","fix:fmt":"prettier --write --list-different .",test:"tsx src/test/runAllTests.ts","test:subset":"tsx src/test/runAllTests.ts --subset"},dependencies:{"@cursorless/tree-sitter-wasms":"^0.7.0",editorconfig:"^3.0.2","fast-glob":"^3.3.3","get-stdin":"^10.0.0","web-tree-sitter":"^0.26.7"},devDependencies:{"@eslint/js":"^9.39.4","@types/mocha":"^10.0.10","@types/node":"^24.12.0",esbuild:"^0.27.4","eslint-config-prettier":"^10.1.8","eslint-plugin-import":"^2.32.0",eslint:"^9.39.4",jiti:"^2.6.1",mocha:"^11.7.5",prettier:"^3.8.1",tsx:"^4.21.0","typescript-eslint":"^8.57.1",typescript:"^5.9.3"}};function q(){process.stdout.write(`${H.version} +`)}function T(t){Reflect.set(process,"exitCode",t)}async function J(t){let e=O();try{let r=W(c.argv.slice(2));e=O(r.quiet);let n=await xe({cli:t,args:r,logger:e});T(n)}catch(r){if(r instanceof m)for(let n of r.messages)e.error(n);else e.error(L(r));T(2)}}async function xe({cli:t,args:e,logger:r}){if(e.help)return G(t),0;if(e.version)return q(),0;if(e.filePatterns.length>0)return Ee({cli:t,logger:r,check:e.check,debug:e.debug,filePatterns:e.filePatterns});if(!c.stdin.isTTY)return Fe({cli:t,logger:r,stdin:c.stdin,check:e.check,debug:e.debug});throw new Error("No input files specified. Use --help for usage information.")}async function Ee({cli:t,logger:e,check:r,debug:n,filePatterns:i}){r&&e.log("Checking formatting...");let o=await U(t,i),[s,a]=await we({cli:t,logger:e,check:r,debug:n,filePaths:o});if(r){if(s>0&&(e.warn(`Code style issues found in ${s} file(s).`),!a))return 1;a||e.log("All matched files use correct code style!")}return a?2:0}async function we({cli:t,logger:e,check:r,debug:n,filePaths:i}){let o=0,s=!1;for(let a of i)try{await Se({cli:t,logger:e,check:r,debug:n,filePath:a})&&o++}catch(l){P(l)?e.error(`${v(a)}${l.getLocation()}: ${l.message}`):e.error(`${v(a)}: ${L(l)}`),s=!0}return[o,s]}async function Se({cli:t,logger:e,check:r,debug:n,filePath:i}){try{let o=await $(i),s=await w.readFile(i,"utf8"),a=await t.format(s,o,i,n);return a===s?!1:(e.log(v(i)),r||await w.writeFile(i,a,"utf8"),!0)}catch(o){if(x(o))return!1;throw o}}function v(t){return E(S.relative(c.cwd(),t))}async function Fe({cli:t,logger:e,stdin:r,check:n,debug:i}){let o=await ye({stdin:r}),a=`stdin.${t.getStdinFileEnding(o)}`,l=S.resolve(a),h=await $(l),f;try{f=await t.format(o,h,l,i)}catch(p){if(P(p))return e.error(`stdin${p.getLocation()}: ${p.message}`),2;throw p}return n?o!==f?(e.warn("Code style issues found in stdin."),1):0:(c.stdout.write(f),0)}var Y="snippet";J({binName:"snippet-fmt",fileEndings:[Y],getStdinFileEnding(){return Y},format:async(t,e)=>{let r=R(t,e);return Promise.resolve(r)}}); //# sourceMappingURL=snippetFormatter.js.map diff --git a/dist/snippetFormatter.js.map b/dist/snippetFormatter.js.map index 2e2271a..6c17d3f 100644 --- a/dist/snippetFormatter.js.map +++ b/dist/snippetFormatter.js.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../src/snippet/parseSnippetFile.ts", "../src/util/constants.ts", "../src/util/getEndOfLine.ts", "../src/snippet/serializeSnippetFile.ts", "../src/snippet/snippetFormatter.ts", "../src/node/cli.ts", "../src/node/FilePatternError.ts", "../src/util/getErrorMessage.ts", "../src/node/isMissingFileError.ts", "../src/node/setExitCode.ts", "../src/node/createLogger.ts", "../src/node/getOptionsFromConfig.ts", "../src/node/normalizeToPosix.ts", "../src/node/getDefaultArguments.ts", "../src/node/parseArgs.ts", "../src/node/parseFilePatterns.ts", "../src/node/lstatSafe.ts", "../src/types.ts", "../src/node/printHelp.ts", "../package.json", "../src/node/printVersion.ts", "../src/node/snippetFormatter.ts"], - "sourcesContent": ["import type { Snippet, SnippetFile, SnippetVariable } from \"./snippetTypes.js\";\n\nexport function parseSnippetFile(content: string): SnippetFile {\n const documentContents = content.split(/^---$/m);\n const file: SnippetFile = { snippets: [] };\n\n for (const text of documentContents) {\n const match = text.match(/^-$/m);\n const contextText = match != null ? text.slice(0, match.index) : text;\n const bodyText =\n match != null ? text.slice(match.index! + match[0].length) : null;\n const body = bodyText ? parseBody(bodyText) : null;\n let context = parseContext(contextText);\n\n // Snippet with body\n if (body != null) {\n if (context == null) {\n context = { variables: [] };\n }\n const { variables, ...rest } = context;\n file.snippets.push({ ...rest, body, variables });\n }\n // Header without body\n else if (context != null) {\n if (file.header != null || file.snippets.length !== 0) {\n throw Error(\"Header snippet must be first in file\");\n }\n file.header = context;\n }\n }\n\n return file;\n}\n\ntype Context = Omit;\n\nfunction parseContext(text: string): Context | undefined {\n const document: Context = { variables: [] };\n const pairs = parseContextPairs(text);\n\n if (Object.keys(pairs).length === 0) {\n return undefined;\n }\n\n const variables: Record = {};\n\n for (const [key, value] of Object.entries(pairs)) {\n switch (key) {\n case \"name\":\n document.name = value;\n break;\n case \"description\":\n document.description = value;\n break;\n case \"phrase\":\n document.phrases = parseVectorValue(value);\n break;\n case \"insertionScope\":\n document.insertionScopes = parseVectorValue(value);\n break;\n case \"language\":\n document.languages = parseVectorValue(value);\n break;\n default:\n if (!key.startsWith(\"$\")) {\n throw Error(`Invalid key '${key}'`);\n }\n variables[key] = value;\n }\n }\n\n document.variables = parseVariables(variables);\n\n return document;\n}\n\nfunction parseContextPairs(text: string): Record {\n const lines = text\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter(Boolean);\n const pairs: Record = {};\n\n for (const line of lines) {\n const parts = line.split(\":\");\n if (parts.length !== 2) {\n throw Error(`Invalid line '${line}'`);\n }\n const key = parts[0].trim();\n const value = parts[1].trim();\n if (key.length === 0 || value.length === 0) {\n throw Error(`Invalid line '${line}'`);\n }\n if (pairs[key] != null) {\n throw Error(`Duplicate key '${key}' in '${text}'`);\n }\n pairs[key] = value;\n }\n\n return pairs;\n}\n\nfunction parseVariables(variables: Record): SnippetVariable[] {\n const variablesMap: Record = {};\n\n const getVariable = (name: string): SnippetVariable => {\n if (variablesMap[name] == null) {\n variablesMap[name] = { name };\n }\n return variablesMap[name];\n };\n\n for (const [key, value] of Object.entries(variables)) {\n const parts = key.split(\".\");\n if (parts.length !== 2) {\n throw Error(`Invalid variable key '${key}'`);\n }\n const name = parts[0].slice(1);\n const field = parts[1];\n switch (field) {\n case \"insertionFormatter\":\n getVariable(name).insertionFormatters = parseVectorValue(value);\n break;\n case \"wrapperPhrase\":\n getVariable(name).wrapperPhrases = parseVectorValue(value);\n break;\n case \"wrapperScope\":\n getVariable(name).wrapperScope = value;\n break;\n default:\n throw Error(`Invalid variable key '${key}'`);\n }\n }\n\n return Object.values(variablesMap);\n}\n\nfunction parseBody(text: string): string[] | undefined {\n // Find first line that is not empty. Preserve indentation.\n const matchLeading = text.match(/^[ \\t]*\\S/m);\n if (matchLeading?.index == null) {\n return undefined;\n }\n return text\n .slice(matchLeading.index)\n .trimEnd()\n .split(/\\r?\\n/)\n .map((l) => l.trimEnd());\n}\n\nfunction parseVectorValue(value: string): string[] {\n return value.split(\"|\").map((v) => v.trim());\n}\n", "// Exit code 0: Success\nexport const EXIT_OK = 0;\n// Exit code 1: Check failed\nexport const EXIT_FAIL = 1;\n// Exit code 2: Unexpected error\nexport const EXIT_ERROR = 2;\n\nexport const DEFAULT_INDENT_WIDTH = 4;\nexport const DEFAULT_MAX_LINE_LENGTH = 80;\nexport const DEFAULT_INSERT_FINAL_NEWLINE = true;\n\nexport const IGNORE_FOLDERS = [\n \".git\",\n \".svn\",\n \".hg\",\n \"node_modules\",\n \"__pycache__\",\n];\n\nexport const GLOB_IGNORE_PATTERNS = IGNORE_FOLDERS.map(\n (pattern) => `**/${pattern}/**`,\n);\n", "import type { EndOfLine } from \"../types.js\";\n\nexport function getEndOfLine(eof?: EndOfLine): string {\n return eof === \"crlf\" ? \"\\r\\n\" : \"\\n\";\n}\n", "import type { FormatterOptions } from \"../types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"../util/constants.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport type {\n Snippet,\n SnippetFile,\n SnippetHeader,\n SnippetVariable,\n} from \"./snippetTypes.js\";\n\nexport type Options = FormatterOptions<\"endOfLine\" | \"insertFinalNewline\">;\n\nexport function serializeSnippetFile(\n snippetFile: SnippetFile,\n options: Options = {},\n): string {\n const eol = getEndOfLine(options.endOfLine);\n const serializer = new SnippetSerializer(\n eol,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n );\n return serializer.getText(snippetFile);\n}\n\nclass SnippetSerializer {\n constructor(\n private eol: string,\n private insertFinalNewline: boolean,\n ) {}\n\n getText(snippetFile: SnippetFile): string {\n const docDelimiter = \"---\";\n const documents: string[] = [];\n\n if (snippetFile.header != null) {\n documents.push(this.getDocumentText(snippetFile.header));\n }\n\n documents.push(\n ...snippetFile.snippets.map(this.getDocumentText.bind(this)),\n );\n\n const result = documents\n .filter((d) => d.length > 0)\n .join(`${this.eol}${docDelimiter}${this.eol}${this.eol}`);\n\n if (result.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return result + `${this.eol}${docDelimiter}${this.eol}`;\n }\n\n return result + `${this.eol}${docDelimiter}`;\n }\n\n private getDocumentText(document: SnippetHeader | Snippet): string {\n const lines: string[] = [\n getOptionalPairString(\"name\", document.name),\n getOptionalPairString(\"description\", document.description),\n getOptionalPairString(\"language\", document.languages),\n getOptionalPairString(\"phrase\", document.phrases),\n getOptionalPairString(\"insertionScope\", document.insertionScopes),\n ].filter(Boolean);\n\n if (document.variables.length > 0) {\n if (lines.length > 0) {\n lines.push(\"\");\n }\n lines.push(...getSortedVariables(document.variables));\n }\n\n if (\"body\" in document) {\n lines.push(\"-\", ...document.body);\n }\n\n return lines.join(this.eol);\n }\n}\n\nfunction getSortedVariables(variables: SnippetVariable[]): string[] {\n const result = variables.slice();\n result.sort(compareVariables);\n return result\n .flatMap((variable) => [\n getOptionalPairString(\n `$${variable.name}.insertionFormatter`,\n variable.insertionFormatters,\n ),\n getOptionalPairString(\n `$${variable.name}.wrapperPhrase`,\n variable.wrapperPhrases,\n ),\n getOptionalPairString(\n `$${variable.name}.wrapperScope`,\n variable.wrapperScope,\n ),\n ])\n .filter((v) => v.length > 0);\n}\n\nfunction getOptionalPairString(\n key: string,\n value: string | string[] | undefined,\n): string {\n if (value == null) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return `${key}: ${value.join(\" | \")}`;\n }\n return `${key}: ${value}`;\n}\n\nfunction compareVariables(a: SnippetVariable, b: SnippetVariable): number {\n if (a.name === \"0\") {\n return 1;\n }\n if (b.name === \"0\") {\n return -1;\n }\n return a.name.localeCompare(b.name);\n}\n", "import { parseSnippetFile } from \"./parseSnippetFile.js\";\nimport { serializeSnippetFile } from \"./serializeSnippetFile.js\";\nimport type { Options } from \"./serializeSnippetFile.js\";\n\nexport function snippetFormatter(text: string, options?: Options): string {\n const snippetFile = parseSnippetFile(text);\n return serializeSnippetFile(snippetFile, options);\n}\n", "import getStdin from \"get-stdin\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as process from \"node:process\";\nimport type { Readable } from \"node:stream\";\nimport type { CLI, Logger, ParsedArgs } from \"../types.js\";\nimport { EXIT_ERROR, EXIT_FAIL, EXIT_OK } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { getErrorMessage } from \"../util/getErrorMessage.js\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\nimport { setExitCode } from \"./setExitCode.js\";\nimport { createLogger } from \"./createLogger.js\";\nimport { getOptionsFromConfig } from \"./getOptionsFromConfig.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\nimport { parseArgs } from \"./parseArgs.js\";\nimport { parseFilePatterns } from \"./parseFilePatterns.js\";\nimport { printHelp } from \"./printHelp.js\";\nimport { printVersion } from \"./printVersion.js\";\n\nexport async function main(cli: CLI): Promise {\n let logger = createLogger();\n\n try {\n const args = parseArgs(process.argv.slice(2));\n logger = createLogger(args.quiet);\n const exitCode = await mainUnsafe({ cli, args, logger });\n setExitCode(exitCode);\n } catch (error) {\n if (error instanceof FilePatternError) {\n for (const message of error.messages) {\n logger.error(message);\n }\n } else {\n logger.error(getErrorMessage(error));\n }\n setExitCode(EXIT_ERROR);\n }\n}\n\ninterface MainUnsafeArgs {\n cli: CLI;\n args: ParsedArgs;\n logger: Logger;\n}\n\nasync function mainUnsafe({\n cli,\n args,\n logger,\n}: MainUnsafeArgs): Promise {\n if (args.help) {\n printHelp(cli);\n return EXIT_OK;\n }\n\n if (args.version) {\n printVersion();\n return EXIT_OK;\n }\n\n const hasFilePatterns = args.filePatterns.length > 0;\n\n if (hasFilePatterns) {\n return mainFormatFiles({\n cli,\n logger,\n check: args.check,\n debug: args.debug,\n filePatterns: args.filePatterns,\n });\n }\n\n // If no file patterns are provided, check if there's input from stdin.\n // If stdin TTY it's an interactive terminal, so we shouldn't read from it.\n if (!process.stdin.isTTY) {\n return mainFormatStdin({\n cli,\n logger,\n stdin: process.stdin,\n check: args.check,\n debug: args.debug,\n });\n }\n\n throw new Error(\n \"No input files specified. Use --help for usage information.\",\n );\n}\n\ninterface MainFormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePatterns: string[];\n}\n\nasync function mainFormatFiles({\n cli,\n logger,\n check,\n debug,\n filePatterns,\n}: MainFormatFilesArgs): Promise {\n if (check) {\n logger.log(\"Checking formatting...\");\n }\n\n const filePaths = await parseFilePatterns(cli, filePatterns);\n const changedFileCount = await formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n });\n\n if (check) {\n if (changedFileCount > 0) {\n logger.warn(\n `Code style issues found in ${changedFileCount} file(s).`,\n );\n return EXIT_FAIL;\n }\n\n logger.log(\"All matched files use correct code style!\");\n return EXIT_OK;\n }\n\n return EXIT_OK;\n}\n\ninterface FormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePaths: string[];\n}\n\nexport async function formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n}: FormatFilesArgs): Promise {\n let changedFileCount = 0;\n\n for (const fileName of filePaths) {\n if (\n await formatFile({\n cli,\n logger,\n check,\n debug,\n filePath: fileName,\n })\n ) {\n changedFileCount++;\n }\n }\n\n return changedFileCount;\n}\n\ninterface FormatFileArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePath: string;\n}\n\nexport async function formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n}: FormatFileArgs): Promise {\n try {\n const options = await getOptionsFromConfig(filePath);\n const content = await fs.readFile(filePath, \"utf8\");\n const formatted = await cli.format(content, options, filePath, debug);\n\n if (formatted === content) {\n return false;\n }\n\n logger.log(getDisplayPath(filePath));\n\n if (!check) {\n await fs.writeFile(filePath, formatted, \"utf8\");\n }\n\n return true;\n } catch (error) {\n if (isMissingFileError(error)) {\n return false;\n }\n\n throw new Error(\n `Failed to format '${filePath}': ${getErrorMessage(error)}`,\n {\n cause: error,\n },\n );\n }\n}\n\nfunction getDisplayPath(filePath: string): string {\n return normalizeToPosix(path.relative(process.cwd(), filePath));\n}\n\ninterface MainFormatStdinArgs {\n cli: CLI;\n logger: Logger;\n stdin: Readable;\n check: boolean;\n debug: boolean;\n}\n\nexport async function mainFormatStdin({\n cli,\n logger,\n stdin,\n check,\n debug,\n}: MainFormatStdinArgs): Promise {\n const input = await getStdin({ stdin });\n const fileEnding = cli.getStdinFileEnding(input);\n const fileName = `stdin.${fileEnding}`;\n const filePath = path.resolve(fileName);\n const options = await getOptionsFromConfig(filePath);\n const formatted = await cli.format(input, options, filePath, debug);\n\n if (check) {\n if (input !== formatted) {\n logger.warn(\"Code style issues found in stdin.\");\n return EXIT_FAIL;\n }\n\n return EXIT_OK;\n }\n\n process.stdout.write(formatted);\n\n return EXIT_OK;\n}\n", "export class FilePatternError extends Error {\n name = \"FilePatternError\";\n\n constructor(public messages: string[]) {\n super(\n `One or more file pattern errors occurred:\\n${messages.join(\"\\n\")}`,\n );\n }\n}\n", "export function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n", "export function isMissingFileError(error: unknown) {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n", "export function setExitCode(code: number): void {\n Reflect.set(process, \"exitCode\", code);\n}\n", "import * as process from \"node:process\";\nimport type { WriteStream } from \"node:tty\";\nimport type { Logger, LoggerEntry, TestLogger } from \"../types.js\";\n\ntype LogCallback = (message: string) => void;\ntype ColorizeCallback = (message: string, color: string) => string;\ntype LoggerStream = Pick & Partial;\n\nconst ANSI_RESET = \"\\u001b[0m\";\nconst ANSI_YELLOW = \"\\u001b[33m\";\nconst ANSI_RED = \"\\u001b[31m\";\nconst WARN_PREFIX = \"[warn]\";\nconst ERROR_PREFIX = \"[error]\";\n\nexport function createLogger(quiet: boolean = false): Logger {\n return createLoggerFromStreams(process.stdout, process.stderr, quiet);\n}\n\nexport function createLoggerFromStreams(\n stdout: LoggerStream,\n stderr: LoggerStream,\n quiet: boolean = false,\n): Logger {\n const colorize: ColorizeCallback = shouldUseColor(stderr)\n ? (message, color) => `${color}${message}${ANSI_RESET}`\n : (message, _color) => message;\n\n let log: LogCallback;\n let warn: LogCallback;\n\n if (quiet) {\n log = () => {};\n warn = () => {};\n } else {\n log = (message: string) => {\n stdout.write(`${message}\\n`);\n };\n warn = (message: string) => {\n stderr.write(`${colorize(WARN_PREFIX, ANSI_YELLOW)} ${message}\\n`);\n };\n }\n\n return {\n log,\n warn,\n error(message: string) {\n stderr.write(`${colorize(ERROR_PREFIX, ANSI_RED)} ${message}\\n`);\n },\n };\n}\n\nexport function createTestLogger(): TestLogger {\n const entries: LoggerEntry[] = [];\n\n return {\n log(message: string) {\n entries.push({ level: \"log\", message });\n },\n warn(message: string) {\n entries.push({ level: \"warn\", message });\n },\n error(message: string) {\n entries.push({ level: \"error\", message });\n },\n getEntries() {\n return entries;\n },\n };\n}\n\nfunction shouldUseColor(stream: LoggerStream): boolean {\n if (\"NO_COLOR\" in process.env) {\n return false;\n }\n\n return stream.isTTY === true;\n}\n", "import * as editorconfig from \"editorconfig\";\nimport type { EditorConfigOptions, Options } from \"../types.js\";\n\nexport async function getOptionsFromConfig(filePath: string): Promise {\n const config = (await editorconfig.parse(filePath)) as EditorConfigOptions;\n\n const options: Options = {};\n\n if (config.indent_style === \"tab\") {\n options.indentTabs = true;\n } else if (config.indent_style === \"space\") {\n options.indentTabs = false;\n }\n\n if (typeof config.indent_size === \"number\") {\n options.indentSize = config.indent_size;\n } else if (\n config.indent_size === \"tab\" &&\n typeof config.tab_width === \"number\"\n ) {\n options.indentSize = config.tab_width;\n }\n\n if (typeof config.max_line_length === \"number\") {\n options.maxLineLength = config.max_line_length;\n }\n\n if (typeof config.column_width === \"number\") {\n options.columnWidth = config.column_width;\n }\n\n if (typeof config.insert_final_newline === \"boolean\") {\n options.insertFinalNewline = config.insert_final_newline;\n }\n\n if (typeof config.preserve_multiline === \"boolean\") {\n options.preserveMultiline = config.preserve_multiline;\n }\n\n if (config.end_of_line != null && config.end_of_line !== \"unset\") {\n options.endOfLine = config.end_of_line;\n }\n\n return options;\n}\n", "import * as path from \"node:path\";\n\n/**\n * Replace `\\` with `/` on Windows\n * @param {string} filepath\n * @returns {string}\n */\nexport const normalizeToPosix =\n path.sep === \"\\\\\"\n ? (filepath: string) => filepath.replaceAll(\"\\\\\", \"/\")\n : (filepath: string) => filepath;\n", "import type { ParsedArgs } from \"../types.js\";\n\nexport function getDefaultArguments(): ParsedArgs {\n return {\n filePatterns: [],\n help: false,\n version: false,\n quiet: false,\n debug: false,\n check: false,\n };\n}\n", "import type { KnownArgument, ParsedArgs } from \"../types.js\";\nimport { getDefaultArguments } from \"./getDefaultArguments.js\";\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const result = getDefaultArguments();\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === \"--\") {\n // All following arguments are treated as file patterns, even if they start with \"--\"\n result.filePatterns.push(...argv.slice(i + 1));\n break;\n }\n\n if (parseKnownArgument(result, arg as KnownArgument)) {\n continue;\n }\n\n if (arg.startsWith(\"--\")) {\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n result.filePatterns.push(arg);\n }\n\n return result;\n}\n\nfunction parseKnownArgument(result: ParsedArgs, arg: KnownArgument): boolean {\n switch (arg) {\n case \"--help\":\n result.help = true;\n return true;\n case \"--version\":\n result.version = true;\n return true;\n case \"--quiet\":\n result.quiet = true;\n return true;\n case \"--check\":\n result.check = true;\n return true;\n case \"--debug\":\n result.debug = true;\n return true;\n default:\n return false;\n }\n}\n", "import type { Options } from \"fast-glob\";\nimport fastGlob from \"fast-glob\";\nimport * as path from \"node:path\";\nimport type { CLI } from \"../types.js\";\nimport { GLOB_IGNORE_PATTERNS } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { lstatSafe } from \"./lstatSafe.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\n\nexport async function parseFilePatterns(\n cli: CLI,\n filePatterns: string[],\n): Promise {\n const seen: Set = new Set();\n const globFileEndingPattern = getGlobFileEndingsPattern(cli.fileEndings);\n const errorMessages: string[] = [];\n\n const globOptions: Options = {\n dot: true,\n followSymbolicLinks: false,\n ignore: GLOB_IGNORE_PATTERNS,\n };\n\n for (const pattern of filePatterns) {\n const absolutePath = path.resolve(pattern);\n const stat = await lstatSafe(absolutePath);\n\n if (stat != null) {\n if (stat.isSymbolicLink()) {\n errorMessages.push(\n `Specified pattern is a symbolic link: ${pattern}`,\n );\n continue;\n }\n\n if (stat.isFile()) {\n seen.add(absolutePath);\n continue;\n }\n\n if (stat.isDirectory()) {\n const files = await fastGlob(`**/*.${globFileEndingPattern}`, {\n ...globOptions,\n cwd: absolutePath,\n });\n if (files.length === 0) {\n errorMessages.push(\n `No matching files were found in the directory: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(absolutePath, file));\n }\n continue;\n }\n }\n\n const glob = normalizeToPosix(pattern);\n const files = (await fastGlob(glob, globOptions)).filter((file) =>\n hasSupportedFileEnding(file, cli.fileEndings),\n );\n if (files.length === 0) {\n errorMessages.push(\n `No files matching the pattern were found: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(file));\n }\n }\n\n if (errorMessages.length > 0) {\n throw new FilePatternError(errorMessages);\n }\n\n return Array.from(seen).sort((a, b) => a.localeCompare(b));\n}\n\nfunction getGlobFileEndingsPattern(fileEndings: readonly string[]): string {\n return fileEndings.length === 1\n ? fileEndings[0]\n : `{${fileEndings.join(\",\")}}`;\n}\n\nfunction hasSupportedFileEnding(\n file: string,\n fileEndings: readonly string[],\n): boolean {\n const extension = path.extname(file).slice(1);\n return fileEndings.includes(extension);\n}\n", "import type { Stats } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\n\nexport async function lstatSafe(filePath: string): Promise {\n try {\n return await fs.lstat(filePath);\n } catch (error) {\n if (isMissingFileError(error)) {\n return undefined;\n }\n\n throw error;\n }\n}\n", "import type { KnownProps } from \"editorconfig\";\n\nexport const KNOWN_ARGUMENTS = [\n \"--help\",\n \"--version\",\n \"--quiet\",\n \"--check\",\n \"--debug\",\n] as const;\n\nexport type KnownArgument = (typeof KNOWN_ARGUMENTS)[number];\n\nexport interface CLI {\n binName: \"snippet-fmt\" | \"talon-fmt\" | \"tree-sitter-fmt\";\n fileEndings: readonly string[];\n\n getStdinFileEnding(text: string): string;\n format(\n text: string,\n options: Options,\n filePath: string,\n debug: boolean,\n ): Promise;\n}\n\nexport type EndOfLine = \"lf\" | \"crlf\";\n\nexport interface Options {\n endOfLine?: EndOfLine;\n indentTabs?: boolean;\n indentSize?: number;\n maxLineLength?: number;\n columnWidth?: number;\n insertFinalNewline?: boolean;\n preserveMultiline?: boolean;\n}\n\nexport type FormatterOptions = Pick;\n\nexport interface ParsedArgs {\n filePatterns: string[];\n help: boolean;\n version: boolean;\n check: boolean;\n quiet: boolean;\n debug: boolean;\n}\n\nexport interface LoggerEntry {\n level: \"log\" | \"warn\" | \"error\";\n message: string;\n}\n\nexport interface Logger {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\nexport interface TestLogger extends Logger {\n getEntries(): readonly LoggerEntry[];\n}\n\nexport interface DebugLogger {\n debug(message: string): void;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport interface EditorConfigOptions extends KnownProps {\n max_line_length?: number | \"unset\";\n column_width?: number | \"unset\";\n preserve_multiline?: boolean | \"unset\";\n}\n\ninterface Point {\n row: number;\n column: number;\n}\n\nexport interface SyntaxNode {\n id: number;\n text: string;\n type: string;\n startPosition: Point;\n endPosition: Point;\n parent: SyntaxNode | null;\n children: SyntaxNode[];\n}\n", "import type { CLI } from \"../types.js\";\nimport { KNOWN_ARGUMENTS } from \"../types.js\";\n\nexport function printHelp(cli: CLI) {\n process.stdout.write(\n `Usage: ${cli.binName} [options] [file/dir/glob ...]\\n`,\n );\n process.stdout.write(\"\\n\");\n process.stdout.write(\"Options:\\n\");\n\n for (const option of KNOWN_ARGUMENTS) {\n process.stdout.write(` ${option}\\n`);\n }\n}\n", "{\n \"name\": \"@cursorless/talon-tools\",\n \"version\": \"0.9.0\",\n \"description\": \"Linting and formatting tools for Talon and Cursorless\",\n \"author\": \"Cursorless Dev\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"!dist/test\",\n \"!dist/build.*\"\n ],\n \"types\": \"./dist/lib.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/lib.d.ts\",\n \"default\": \"./dist/lib.js\"\n },\n \"./node\": {\n \"types\": \"./dist/node/libNode.d.ts\",\n \"default\": \"./dist/libNode.js\"\n }\n },\n \"bin\": {\n \"snippet-fmt\": \"dist/snippetFormatter.js\",\n \"talon-fmt\": \"dist/talonFormatter.js\",\n \"tree-sitter-fmt\": \"dist/treeSitterFormatter.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/cursorless-dev/talon-tools.git\"\n },\n \"funding\": \"https://github.com/sponsors/cursorless-dev\",\n \"sponsor\": {\n \"url\": \"https://github.com/sponsors/cursorless-dev\"\n },\n \"scripts\": {\n \"build\": \"npm run clean && tsc -p . && tsx ./src/build.ts\",\n \"clean\": \"rm -rf dist/*\",\n \"lint\": \"npm run lint:ts &&npm run lint:fmt\",\n \"lint:ts\": \"tsc -p . --noEmit && eslint src\",\n \"lint:fmt\": \"prettier --check .\",\n \"fix\": \"npm run fix:ts && npm run fix:fmt\",\n \"fix:ts\": \"eslint src --fix\",\n \"fix:fmt\": \"prettier --write --list-different .\",\n \"test\": \"tsx src/test/runAllTests.ts\",\n \"test:subset\": \"tsx src/test/runAllTests.ts --subset\"\n },\n \"dependencies\": {\n \"@cursorless/tree-sitter-wasms\": \"^0.7.0\",\n \"editorconfig\": \"^3.0.2\",\n \"fast-glob\": \"^3.3.3\",\n \"get-stdin\": \"^10.0.0\",\n \"web-tree-sitter\": \"^0.26.7\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.4\",\n \"@types/mocha\": \"^10.0.10\",\n \"@types/node\": \"^24.12.0\",\n \"esbuild\": \"^0.27.4\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-import\": \"^2.32.0\",\n \"eslint\": \"^9.39.4\",\n \"jiti\": \"^2.6.1\",\n \"mocha\": \"^11.7.5\",\n \"prettier\": \"^3.8.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript-eslint\": \"^8.57.1\",\n \"typescript\": \"^5.9.3\"\n }\n}\n", "import packageJson from \"../../package.json\" with { type: \"json\" };\n\nexport function printVersion() {\n process.stdout.write(`${packageJson.version}\\n`);\n}\n", "#!/usr/bin/env node\n\nimport { snippetFormatter } from \"../snippet/snippetFormatter.js\";\nimport { main } from \"./cli.js\";\n\nconst fileEnding = \"snippet\";\n\nvoid main({\n binName: \"snippet-fmt\",\n fileEndings: [fileEnding],\n\n getStdinFileEnding() {\n return fileEnding;\n },\n\n format: async (text, options) => {\n const updated = snippetFormatter(text, options);\n return Promise.resolve(updated);\n },\n});\n"], - "mappings": "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", - "names": ["parseSnippetFile", "content", "documentContents", "file", "text", "match", "contextText", "bodyText", "body", "parseBody", "context", "parseContext", "variables", "rest", "document", "pairs", "parseContextPairs", "key", "value", "parseVectorValue", "parseVariables", "lines", "l", "line", "parts", "variablesMap", "getVariable", "name", "matchLeading", "v", "IGNORE_FOLDERS", "GLOB_IGNORE_PATTERNS", "pattern", "getEndOfLine", "eof", "serializeSnippetFile", "snippetFile", "options", "eol", "getEndOfLine", "SnippetSerializer", "insertFinalNewline", "documents", "result", "d", "document", "lines", "getOptionalPairString", "getSortedVariables", "variables", "compareVariables", "variable", "v", "key", "value", "a", "b", "snippetFormatter", "text", "options", "snippetFile", "parseSnippetFile", "serializeSnippetFile", "getStdin", "fs", "path", "process", "FilePatternError", "messages", "getErrorMessage", "error", "isMissingFileError", "error", "setExitCode", "code", "process", "ANSI_RESET", "ANSI_YELLOW", "ANSI_RED", "WARN_PREFIX", "ERROR_PREFIX", "createLogger", "quiet", "createLoggerFromStreams", "stdout", "stderr", "colorize", "shouldUseColor", "message", "color", "_color", "log", "warn", "shouldUseColor", "stream", "editorconfig", "getOptionsFromConfig", "filePath", "config", "options", "path", "normalizeToPosix", "filepath", "getDefaultArguments", "parseArgs", "argv", "result", "getDefaultArguments", "i", "arg", "parseKnownArgument", "fastGlob", "path", "fs", "lstatSafe", "filePath", "error", "isMissingFileError", "parseFilePatterns", "cli", "filePatterns", "seen", "globFileEndingPattern", "getGlobFileEndingsPattern", "errorMessages", "globOptions", "GLOB_IGNORE_PATTERNS", "pattern", "absolutePath", "stat", "lstatSafe", "files", "fastGlob", "file", "glob", "normalizeToPosix", "hasSupportedFileEnding", "FilePatternError", "a", "b", "fileEndings", "extension", "KNOWN_ARGUMENTS", "printHelp", "cli", "option", "KNOWN_ARGUMENTS", "package_default", "printVersion", "package_default", "main", "cli", "logger", "createLogger", "args", "parseArgs", "exitCode", "mainUnsafe", "setExitCode", "error", "FilePatternError", "message", "getErrorMessage", "printHelp", "printVersion", "mainFormatFiles", "mainFormatStdin", "check", "debug", "filePatterns", "filePaths", "parseFilePatterns", "changedFileCount", "formatFiles", "fileName", "formatFile", "filePath", "options", "getOptionsFromConfig", "content", "formatted", "getDisplayPath", "isMissingFileError", "normalizeToPosix", "stdin", "input", "getStdin", "fileEnding", "main", "text", "options", "updated", "snippetFormatter"] + "sources": ["../src/snippet/parseSnippetFile.ts", "../src/util/constants.ts", "../src/util/getEndOfLine.ts", "../src/snippet/serializeSnippetFile.ts", "../src/snippet/snippetFormatter.ts", "../src/node/cli.ts", "../src/util/getErrorMessage.ts", "../src/util/SyntaxError.ts", "../src/node/createLogger.ts", "../src/node/FilePatternError.ts", "../src/node/getOptionsFromConfig.ts", "../src/node/isMissingFileError.ts", "../src/node/normalizeToPosix.ts", "../src/node/getDefaultArguments.ts", "../src/node/parseArgs.ts", "../src/node/parseFilePatterns.ts", "../src/node/lstatSafe.ts", "../src/types.ts", "../src/node/printHelp.ts", "../package.json", "../src/node/printVersion.ts", "../src/node/setExitCode.ts", "../src/node/snippetFormatter.ts"], + "sourcesContent": ["import type { Snippet, SnippetFile, SnippetVariable } from \"./snippetTypes.js\";\n\nexport function parseSnippetFile(content: string): SnippetFile {\n const documentContents = content.split(/^---$/m);\n const file: SnippetFile = { snippets: [] };\n\n for (const text of documentContents) {\n const match = text.match(/^-$/m);\n const contextText = match != null ? text.slice(0, match.index) : text;\n const bodyText =\n match != null ? text.slice(match.index! + match[0].length) : null;\n const body = bodyText ? parseBody(bodyText) : null;\n let context = parseContext(contextText);\n\n // Snippet with body\n if (body != null) {\n if (context == null) {\n context = { variables: [] };\n }\n const { variables, ...rest } = context;\n file.snippets.push({ ...rest, body, variables });\n }\n // Header without body\n else if (context != null) {\n if (file.header != null || file.snippets.length !== 0) {\n throw Error(\"Header snippet must be first in file\");\n }\n file.header = context;\n }\n }\n\n return file;\n}\n\ntype Context = Omit;\n\nfunction parseContext(text: string): Context | undefined {\n const document: Context = { variables: [] };\n const pairs = parseContextPairs(text);\n\n if (Object.keys(pairs).length === 0) {\n return undefined;\n }\n\n const variables: Record = {};\n\n for (const [key, value] of Object.entries(pairs)) {\n switch (key) {\n case \"name\":\n document.name = value;\n break;\n case \"description\":\n document.description = value;\n break;\n case \"phrase\":\n document.phrases = parseVectorValue(value);\n break;\n case \"insertionScope\":\n document.insertionScopes = parseVectorValue(value);\n break;\n case \"language\":\n document.languages = parseVectorValue(value);\n break;\n default:\n if (!key.startsWith(\"$\")) {\n throw Error(`Invalid key '${key}'`);\n }\n variables[key] = value;\n }\n }\n\n document.variables = parseVariables(variables);\n\n return document;\n}\n\nfunction parseContextPairs(text: string): Record {\n const lines = text\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter(Boolean);\n const pairs: Record = {};\n\n for (const line of lines) {\n const parts = line.split(\":\");\n if (parts.length !== 2) {\n throw Error(`Invalid line '${line}'`);\n }\n const key = parts[0].trim();\n const value = parts[1].trim();\n if (key.length === 0 || value.length === 0) {\n throw Error(`Invalid line '${line}'`);\n }\n if (pairs[key] != null) {\n throw Error(`Duplicate key '${key}' in '${text}'`);\n }\n pairs[key] = value;\n }\n\n return pairs;\n}\n\nfunction parseVariables(variables: Record): SnippetVariable[] {\n const variablesMap: Record = {};\n\n const getVariable = (name: string): SnippetVariable => {\n if (variablesMap[name] == null) {\n variablesMap[name] = { name };\n }\n return variablesMap[name];\n };\n\n for (const [key, value] of Object.entries(variables)) {\n const parts = key.split(\".\");\n if (parts.length !== 2) {\n throw Error(`Invalid variable key '${key}'`);\n }\n const name = parts[0].slice(1);\n const field = parts[1];\n switch (field) {\n case \"insertionFormatter\":\n getVariable(name).insertionFormatters = parseVectorValue(value);\n break;\n case \"wrapperPhrase\":\n getVariable(name).wrapperPhrases = parseVectorValue(value);\n break;\n case \"wrapperScope\":\n getVariable(name).wrapperScope = value;\n break;\n default:\n throw Error(`Invalid variable key '${key}'`);\n }\n }\n\n return Object.values(variablesMap);\n}\n\nfunction parseBody(text: string): string[] | undefined {\n // Find first line that is not empty. Preserve indentation.\n const matchLeading = text.match(/^[ \\t]*\\S/m);\n if (matchLeading?.index == null) {\n return undefined;\n }\n return text\n .slice(matchLeading.index)\n .trimEnd()\n .split(/\\r?\\n/)\n .map((l) => l.trimEnd());\n}\n\nfunction parseVectorValue(value: string): string[] {\n return value.split(\"|\").map((v) => v.trim());\n}\n", "// Exit code 0: Success\nexport const EXIT_OK = 0;\n// Exit code 1: Check failed\nexport const EXIT_FAIL = 1;\n// Exit code 2: Unexpected error\nexport const EXIT_ERROR = 2;\n\nexport type ExitCode = typeof EXIT_OK | typeof EXIT_FAIL | typeof EXIT_ERROR;\n\nexport const DEFAULT_INDENT_WIDTH = 4;\nexport const DEFAULT_MAX_LINE_LENGTH = 80;\nexport const DEFAULT_INSERT_FINAL_NEWLINE = true;\n\nexport const IGNORE_FOLDERS = [\n \".git\",\n \".svn\",\n \".hg\",\n \"node_modules\",\n \"__pycache__\",\n];\n\nexport const GLOB_IGNORE_PATTERNS = IGNORE_FOLDERS.map(\n (pattern) => `**/${pattern}/**`,\n);\n", "import type { EndOfLine } from \"../types.js\";\n\nexport function getEndOfLine(eof?: EndOfLine): string {\n return eof === \"crlf\" ? \"\\r\\n\" : \"\\n\";\n}\n", "import type { FormatterOptions } from \"../types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"../util/constants.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport type {\n Snippet,\n SnippetFile,\n SnippetHeader,\n SnippetVariable,\n} from \"./snippetTypes.js\";\n\nexport type Options = FormatterOptions<\"endOfLine\" | \"insertFinalNewline\">;\n\nexport function serializeSnippetFile(\n snippetFile: SnippetFile,\n options: Options = {},\n): string {\n const eol = getEndOfLine(options.endOfLine);\n const serializer = new SnippetSerializer(\n eol,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n );\n return serializer.getText(snippetFile);\n}\n\nclass SnippetSerializer {\n constructor(\n private eol: string,\n private insertFinalNewline: boolean,\n ) {}\n\n getText(snippetFile: SnippetFile): string {\n const docDelimiter = \"---\";\n const documents: string[] = [];\n\n if (snippetFile.header != null) {\n documents.push(this.getDocumentText(snippetFile.header));\n }\n\n documents.push(\n ...snippetFile.snippets.map(this.getDocumentText.bind(this)),\n );\n\n const result = documents\n .filter((d) => d.length > 0)\n .join(`${this.eol}${docDelimiter}${this.eol}${this.eol}`);\n\n if (result.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return result + `${this.eol}${docDelimiter}${this.eol}`;\n }\n\n return result + `${this.eol}${docDelimiter}`;\n }\n\n private getDocumentText(document: SnippetHeader | Snippet): string {\n const lines: string[] = [\n getOptionalPairString(\"name\", document.name),\n getOptionalPairString(\"description\", document.description),\n getOptionalPairString(\"language\", document.languages),\n getOptionalPairString(\"phrase\", document.phrases),\n getOptionalPairString(\"insertionScope\", document.insertionScopes),\n ].filter(Boolean);\n\n if (document.variables.length > 0) {\n if (lines.length > 0) {\n lines.push(\"\");\n }\n lines.push(...getSortedVariables(document.variables));\n }\n\n if (\"body\" in document) {\n lines.push(\"-\", ...document.body);\n }\n\n return lines.join(this.eol);\n }\n}\n\nfunction getSortedVariables(variables: SnippetVariable[]): string[] {\n const result = variables.slice();\n result.sort(compareVariables);\n return result\n .flatMap((variable) => [\n getOptionalPairString(\n `$${variable.name}.insertionFormatter`,\n variable.insertionFormatters,\n ),\n getOptionalPairString(\n `$${variable.name}.wrapperPhrase`,\n variable.wrapperPhrases,\n ),\n getOptionalPairString(\n `$${variable.name}.wrapperScope`,\n variable.wrapperScope,\n ),\n ])\n .filter((v) => v.length > 0);\n}\n\nfunction getOptionalPairString(\n key: string,\n value: string | string[] | undefined,\n): string {\n if (value == null) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return `${key}: ${value.join(\" | \")}`;\n }\n return `${key}: ${value}`;\n}\n\nfunction compareVariables(a: SnippetVariable, b: SnippetVariable): number {\n if (a.name === \"0\") {\n return 1;\n }\n if (b.name === \"0\") {\n return -1;\n }\n return a.name.localeCompare(b.name);\n}\n", "import { parseSnippetFile } from \"./parseSnippetFile.js\";\nimport { serializeSnippetFile } from \"./serializeSnippetFile.js\";\nimport type { Options } from \"./serializeSnippetFile.js\";\n\nexport function snippetFormatter(text: string, options?: Options): string {\n const snippetFile = parseSnippetFile(text);\n return serializeSnippetFile(snippetFile, options);\n}\n", "import getStdin from \"get-stdin\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as process from \"node:process\";\nimport type { Readable } from \"node:stream\";\nimport type { CLI, Logger, ParsedArgs } from \"../types.js\";\nimport {\n EXIT_ERROR,\n EXIT_FAIL,\n EXIT_OK,\n type ExitCode,\n} from \"../util/constants.js\";\nimport { getErrorMessage } from \"../util/getErrorMessage.js\";\nimport { isSyntaxError } from \"../util/SyntaxError.js\";\nimport { createLogger } from \"./createLogger.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { getOptionsFromConfig } from \"./getOptionsFromConfig.js\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\nimport { parseArgs } from \"./parseArgs.js\";\nimport { parseFilePatterns } from \"./parseFilePatterns.js\";\nimport { printHelp } from \"./printHelp.js\";\nimport { printVersion } from \"./printVersion.js\";\nimport { setExitCode } from \"./setExitCode.js\";\n\nexport async function main(cli: CLI): Promise {\n let logger = createLogger();\n\n try {\n const args = parseArgs(process.argv.slice(2));\n logger = createLogger(args.quiet);\n const exitCode = await mainUnsafe({ cli, args, logger });\n setExitCode(exitCode);\n } catch (error) {\n if (error instanceof FilePatternError) {\n for (const message of error.messages) {\n logger.error(message);\n }\n } else {\n logger.error(getErrorMessage(error));\n }\n setExitCode(EXIT_ERROR);\n }\n}\n\ninterface MainUnsafeArgs {\n cli: CLI;\n args: ParsedArgs;\n logger: Logger;\n}\n\nasync function mainUnsafe({\n cli,\n args,\n logger,\n}: MainUnsafeArgs): Promise {\n if (args.help) {\n printHelp(cli);\n return EXIT_OK;\n }\n\n if (args.version) {\n printVersion();\n return EXIT_OK;\n }\n\n const hasFilePatterns = args.filePatterns.length > 0;\n\n if (hasFilePatterns) {\n return mainFormatFiles({\n cli,\n logger,\n check: args.check,\n debug: args.debug,\n filePatterns: args.filePatterns,\n });\n }\n\n // If no file patterns are provided, check if there's input from stdin.\n // If stdin TTY it's an interactive terminal, so we shouldn't read from it.\n if (!process.stdin.isTTY) {\n return mainFormatStdin({\n cli,\n logger,\n stdin: process.stdin,\n check: args.check,\n debug: args.debug,\n });\n }\n\n throw new Error(\n \"No input files specified. Use --help for usage information.\",\n );\n}\n\ninterface MainFormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePatterns: string[];\n}\n\nasync function mainFormatFiles({\n cli,\n logger,\n check,\n debug,\n filePatterns,\n}: MainFormatFilesArgs): Promise {\n if (check) {\n logger.log(\"Checking formatting...\");\n }\n\n const filePaths = await parseFilePatterns(cli, filePatterns);\n const [changedFileCount, hasError] = await formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n });\n\n if (check) {\n if (changedFileCount > 0) {\n logger.warn(\n `Code style issues found in ${changedFileCount} file(s).`,\n );\n if (!hasError) {\n return EXIT_FAIL;\n }\n }\n\n if (!hasError) {\n logger.log(\"All matched files use correct code style!\");\n }\n }\n\n if (hasError) {\n return EXIT_ERROR;\n }\n\n return EXIT_OK;\n}\n\ninterface FormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePaths: string[];\n}\n\nexport async function formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n}: FormatFilesArgs): Promise<[number, boolean]> {\n let changedFileCount = 0;\n let hasError = false;\n\n for (const filePath of filePaths) {\n try {\n const fileWasChanged = await formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n });\n if (fileWasChanged) {\n changedFileCount++;\n }\n } catch (error) {\n if (isSyntaxError(error)) {\n logger.error(\n `${getDisplayPath(filePath)}${error.getLocation()}: ${error.message}`,\n );\n } else {\n logger.error(\n `${getDisplayPath(filePath)}: ${getErrorMessage(error)}`,\n );\n }\n hasError = true;\n }\n }\n\n return [changedFileCount, hasError];\n}\n\ninterface FormatFileArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePath: string;\n}\n\nexport async function formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n}: FormatFileArgs): Promise {\n try {\n const options = await getOptionsFromConfig(filePath);\n const content = await fs.readFile(filePath, \"utf8\");\n const formatted = await cli.format(content, options, filePath, debug);\n\n if (formatted === content) {\n return false;\n }\n\n logger.log(getDisplayPath(filePath));\n\n if (!check) {\n await fs.writeFile(filePath, formatted, \"utf8\");\n }\n\n return true;\n } catch (error) {\n if (isMissingFileError(error)) {\n return false;\n }\n\n throw error;\n }\n}\n\nfunction getDisplayPath(filePath: string): string {\n return normalizeToPosix(path.relative(process.cwd(), filePath));\n}\n\ninterface MainFormatStdinArgs {\n cli: CLI;\n logger: Logger;\n stdin: Readable;\n check: boolean;\n debug: boolean;\n}\n\nexport async function mainFormatStdin({\n cli,\n logger,\n stdin,\n check,\n debug,\n}: MainFormatStdinArgs): Promise {\n const input = await getStdin({ stdin });\n const fileEnding = cli.getStdinFileEnding(input);\n const fauxFileName = `stdin.${fileEnding}`;\n const fauxFilePath = path.resolve(fauxFileName);\n const options = await getOptionsFromConfig(fauxFilePath);\n let formatted: string;\n\n try {\n formatted = await cli.format(input, options, fauxFilePath, debug);\n } catch (error) {\n if (isSyntaxError(error)) {\n logger.error(`stdin${error.getLocation()}: ${error.message}`);\n return EXIT_ERROR;\n }\n throw error;\n }\n\n if (check) {\n if (input !== formatted) {\n logger.warn(\"Code style issues found in stdin.\");\n return EXIT_FAIL;\n }\n\n return EXIT_OK;\n }\n\n process.stdout.write(formatted);\n\n return EXIT_OK;\n}\n", "export function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n", "import type { Point } from \"../types.js\";\n\nexport class SyntaxError extends Error {\n constructor(private location?: Point) {\n super(\"Syntax error.\");\n this.name = \"SyntaxError\";\n }\n\n getLocation(): string | undefined {\n return this.location != null\n ? `(${this.location.row + 1}:${this.location.column + 1})`\n : undefined;\n }\n}\n\nexport function isSyntaxError(error: unknown): error is SyntaxError {\n return error instanceof SyntaxError;\n}\n", "import * as process from \"node:process\";\nimport type { WriteStream } from \"node:tty\";\nimport type { Logger, LoggerEntry, TestLogger } from \"../types.js\";\n\ntype LogCallback = (message: string) => void;\ntype ColorizeCallback = (message: string, color: string) => string;\ntype LoggerStream = Pick & Partial;\n\nconst ANSI_RESET = \"\\u001b[0m\";\nconst ANSI_YELLOW = \"\\u001b[33m\";\nconst ANSI_RED = \"\\u001b[31m\";\nconst WARN_PREFIX = \"[warn]\";\nconst ERROR_PREFIX = \"[error]\";\n\nexport function createLogger(quiet: boolean = false): Logger {\n return createLoggerFromStreams(process.stdout, process.stderr, quiet);\n}\n\nexport function createLoggerFromStreams(\n stdout: LoggerStream,\n stderr: LoggerStream,\n quiet: boolean = false,\n): Logger {\n const colorize: ColorizeCallback = shouldUseColor(stderr)\n ? (message, color) => `${color}${message}${ANSI_RESET}`\n : (message, _color) => message;\n\n let log: LogCallback;\n let warn: LogCallback;\n\n if (quiet) {\n log = () => {};\n warn = () => {};\n } else {\n log = (message: string) => {\n stdout.write(`${message}\\n`);\n };\n warn = (message: string) => {\n stderr.write(`${colorize(WARN_PREFIX, ANSI_YELLOW)} ${message}\\n`);\n };\n }\n\n return {\n log,\n warn,\n error(message: string) {\n stderr.write(`${colorize(ERROR_PREFIX, ANSI_RED)} ${message}\\n`);\n },\n };\n}\n\nexport function createTestLogger(): TestLogger {\n const entries: LoggerEntry[] = [];\n\n return {\n log(message: string) {\n entries.push({ level: \"log\", message });\n },\n warn(message: string) {\n entries.push({ level: \"warn\", message });\n },\n error(message: string) {\n entries.push({ level: \"error\", message });\n },\n getEntries() {\n return entries;\n },\n };\n}\n\nfunction shouldUseColor(stream: LoggerStream): boolean {\n if (\"NO_COLOR\" in process.env) {\n return false;\n }\n\n return stream.isTTY === true;\n}\n", "export class FilePatternError extends Error {\n name = \"FilePatternError\";\n\n constructor(public messages: string[]) {\n super(\n `One or more file pattern errors occurred:\\n${messages.join(\"\\n\")}`,\n );\n }\n}\n", "import * as editorconfig from \"editorconfig\";\nimport type { EditorConfigOptions, Options } from \"../types.js\";\n\nexport async function getOptionsFromConfig(filePath: string): Promise {\n const config = (await editorconfig.parse(filePath)) as EditorConfigOptions;\n\n const options: Options = {};\n\n if (config.indent_style === \"tab\") {\n options.indentTabs = true;\n } else if (config.indent_style === \"space\") {\n options.indentTabs = false;\n }\n\n if (typeof config.indent_size === \"number\") {\n options.indentSize = config.indent_size;\n } else if (\n config.indent_size === \"tab\" &&\n typeof config.tab_width === \"number\"\n ) {\n options.indentSize = config.tab_width;\n }\n\n if (typeof config.max_line_length === \"number\") {\n options.maxLineLength = config.max_line_length;\n }\n\n if (typeof config.column_width === \"number\") {\n options.columnWidth = config.column_width;\n }\n\n if (typeof config.insert_final_newline === \"boolean\") {\n options.insertFinalNewline = config.insert_final_newline;\n }\n\n if (typeof config.preserve_multiline === \"boolean\") {\n options.preserveMultiline = config.preserve_multiline;\n }\n\n if (config.end_of_line != null && config.end_of_line !== \"unset\") {\n options.endOfLine = config.end_of_line;\n }\n\n return options;\n}\n", "export function isMissingFileError(\n error: unknown,\n): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n", "import * as path from \"node:path\";\n\n/**\n * Replace `\\` with `/` on Windows\n * @param {string} filepath\n * @returns {string}\n */\nexport const normalizeToPosix =\n path.sep === \"\\\\\"\n ? (filepath: string) => filepath.replaceAll(\"\\\\\", \"/\")\n : (filepath: string) => filepath;\n", "import type { ParsedArgs } from \"../types.js\";\n\nexport function getDefaultArguments(): ParsedArgs {\n return {\n filePatterns: [],\n help: false,\n version: false,\n quiet: false,\n debug: false,\n check: false,\n };\n}\n", "import type { KnownArgument, ParsedArgs } from \"../types.js\";\nimport { getDefaultArguments } from \"./getDefaultArguments.js\";\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const result = getDefaultArguments();\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === \"--\") {\n // All following arguments are treated as file patterns, even if they start with \"--\"\n result.filePatterns.push(...argv.slice(i + 1));\n break;\n }\n\n if (parseKnownArgument(result, arg as KnownArgument)) {\n continue;\n }\n\n if (arg.startsWith(\"--\")) {\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n result.filePatterns.push(arg);\n }\n\n return result;\n}\n\nfunction parseKnownArgument(result: ParsedArgs, arg: KnownArgument): boolean {\n switch (arg) {\n case \"--help\":\n result.help = true;\n return true;\n case \"--version\":\n result.version = true;\n return true;\n case \"--quiet\":\n result.quiet = true;\n return true;\n case \"--check\":\n result.check = true;\n return true;\n case \"--debug\":\n result.debug = true;\n return true;\n default:\n return false;\n }\n}\n", "import type { Options } from \"fast-glob\";\nimport fastGlob from \"fast-glob\";\nimport * as path from \"node:path\";\nimport type { CLI } from \"../types.js\";\nimport { GLOB_IGNORE_PATTERNS } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { lstatSafe } from \"./lstatSafe.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\n\nexport async function parseFilePatterns(\n cli: CLI,\n filePatterns: string[],\n): Promise {\n const seen: Set = new Set();\n const globFileEndingPattern = getGlobFileEndingsPattern(cli.fileEndings);\n const errorMessages: string[] = [];\n\n const globOptions: Options = {\n dot: true,\n followSymbolicLinks: false,\n ignore: GLOB_IGNORE_PATTERNS,\n };\n\n for (const pattern of filePatterns) {\n const absolutePath = path.resolve(pattern);\n const stat = await lstatSafe(absolutePath);\n\n if (stat != null) {\n if (stat.isSymbolicLink()) {\n errorMessages.push(\n `Specified pattern is a symbolic link: ${pattern}`,\n );\n continue;\n }\n\n if (stat.isFile()) {\n seen.add(absolutePath);\n continue;\n }\n\n if (stat.isDirectory()) {\n const files = await fastGlob(`**/*.${globFileEndingPattern}`, {\n ...globOptions,\n cwd: absolutePath,\n });\n if (files.length === 0) {\n errorMessages.push(\n `No matching files were found in the directory: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(absolutePath, file));\n }\n continue;\n }\n }\n\n const glob = normalizeToPosix(pattern);\n const files = (await fastGlob(glob, globOptions)).filter((file) =>\n hasSupportedFileEnding(file, cli.fileEndings),\n );\n if (files.length === 0) {\n errorMessages.push(\n `No files matching the pattern were found: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(file));\n }\n }\n\n if (errorMessages.length > 0) {\n throw new FilePatternError(errorMessages);\n }\n\n return Array.from(seen).sort((a, b) => a.localeCompare(b));\n}\n\nfunction getGlobFileEndingsPattern(fileEndings: readonly string[]): string {\n return fileEndings.length === 1\n ? fileEndings[0]\n : `{${fileEndings.join(\",\")}}`;\n}\n\nfunction hasSupportedFileEnding(\n file: string,\n fileEndings: readonly string[],\n): boolean {\n const extension = path.extname(file).slice(1);\n return fileEndings.includes(extension);\n}\n", "import type { Stats } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\n\nexport async function lstatSafe(filePath: string): Promise {\n try {\n return await fs.lstat(filePath);\n } catch (error) {\n if (isMissingFileError(error)) {\n return undefined;\n }\n\n throw error;\n }\n}\n", "import type { KnownProps } from \"editorconfig\";\n\nexport const KNOWN_ARGUMENTS = [\n \"--help\",\n \"--version\",\n \"--quiet\",\n \"--check\",\n \"--debug\",\n] as const;\n\nexport type KnownArgument = (typeof KNOWN_ARGUMENTS)[number];\n\nexport interface CLI {\n binName: \"snippet-fmt\" | \"talon-fmt\" | \"tree-sitter-fmt\";\n fileEndings: readonly string[];\n\n getStdinFileEnding(text: string): string;\n format(\n text: string,\n options: Options,\n filePath: string,\n debug: boolean,\n ): Promise;\n}\n\nexport type EndOfLine = \"lf\" | \"crlf\";\n\nexport interface Options {\n endOfLine?: EndOfLine;\n indentTabs?: boolean;\n indentSize?: number;\n maxLineLength?: number;\n columnWidth?: number;\n insertFinalNewline?: boolean;\n preserveMultiline?: boolean;\n}\n\nexport type FormatterOptions = Pick;\n\nexport interface ParsedArgs {\n filePatterns: string[];\n help: boolean;\n version: boolean;\n check: boolean;\n quiet: boolean;\n debug: boolean;\n}\n\nexport interface LoggerEntry {\n level: \"log\" | \"warn\" | \"error\";\n message: string;\n}\n\nexport interface Logger {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\nexport interface TestLogger extends Logger {\n getEntries(): readonly LoggerEntry[];\n}\n\nexport interface DebugLogger {\n debug(message: string): void;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport interface EditorConfigOptions extends KnownProps {\n max_line_length?: number | \"unset\";\n column_width?: number | \"unset\";\n preserve_multiline?: boolean | \"unset\";\n}\n\nexport interface Point {\n row: number;\n column: number;\n}\n\nexport interface SyntaxNode {\n id: number;\n text: string;\n type: string;\n startPosition: Point;\n endPosition: Point;\n hasError: boolean;\n isError: boolean;\n isMissing: boolean;\n parent: SyntaxNode | null;\n children: SyntaxNode[];\n}\n", "import type { CLI } from \"../types.js\";\nimport { KNOWN_ARGUMENTS } from \"../types.js\";\n\nexport function printHelp(cli: CLI) {\n process.stdout.write(\n `Usage: ${cli.binName} [options] [file/dir/glob ...]\\n`,\n );\n process.stdout.write(\"\\n\");\n process.stdout.write(\"Options:\\n\");\n\n for (const option of KNOWN_ARGUMENTS) {\n process.stdout.write(` ${option}\\n`);\n }\n}\n", "{\n \"name\": \"@cursorless/talon-tools\",\n \"version\": \"0.10.0\",\n \"description\": \"Linting and formatting tools for Talon and Cursorless\",\n \"author\": \"Cursorless Dev\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"!dist/test\",\n \"!dist/build.*\"\n ],\n \"types\": \"./dist/lib.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/lib.d.ts\",\n \"default\": \"./dist/lib.js\"\n },\n \"./node\": {\n \"types\": \"./dist/node/libNode.d.ts\",\n \"default\": \"./dist/libNode.js\"\n }\n },\n \"bin\": {\n \"snippet-fmt\": \"dist/snippetFormatter.js\",\n \"talon-fmt\": \"dist/talonFormatter.js\",\n \"tree-sitter-fmt\": \"dist/treeSitterFormatter.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/cursorless-dev/talon-tools.git\"\n },\n \"funding\": \"https://github.com/sponsors/cursorless-dev\",\n \"sponsor\": {\n \"url\": \"https://github.com/sponsors/cursorless-dev\"\n },\n \"scripts\": {\n \"build\": \"npm run clean && tsc -p . && tsx ./src/build.ts\",\n \"clean\": \"rm -rf dist/*\",\n \"lint\": \"npm run lint:ts &&npm run lint:fmt\",\n \"lint:ts\": \"tsc -p . --noEmit && eslint src\",\n \"lint:fmt\": \"prettier --check .\",\n \"fix\": \"npm run fix:ts && npm run fix:fmt\",\n \"fix:ts\": \"eslint src --fix\",\n \"fix:fmt\": \"prettier --write --list-different .\",\n \"test\": \"tsx src/test/runAllTests.ts\",\n \"test:subset\": \"tsx src/test/runAllTests.ts --subset\"\n },\n \"dependencies\": {\n \"@cursorless/tree-sitter-wasms\": \"^0.7.0\",\n \"editorconfig\": \"^3.0.2\",\n \"fast-glob\": \"^3.3.3\",\n \"get-stdin\": \"^10.0.0\",\n \"web-tree-sitter\": \"^0.26.7\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.4\",\n \"@types/mocha\": \"^10.0.10\",\n \"@types/node\": \"^24.12.0\",\n \"esbuild\": \"^0.27.4\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-import\": \"^2.32.0\",\n \"eslint\": \"^9.39.4\",\n \"jiti\": \"^2.6.1\",\n \"mocha\": \"^11.7.5\",\n \"prettier\": \"^3.8.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript-eslint\": \"^8.57.1\",\n \"typescript\": \"^5.9.3\"\n }\n}\n", "import packageJson from \"../../package.json\" with { type: \"json\" };\n\nexport function printVersion() {\n process.stdout.write(`${packageJson.version}\\n`);\n}\n", "export function setExitCode(code: number): void {\n Reflect.set(process, \"exitCode\", code);\n}\n", "#!/usr/bin/env node\n\nimport { snippetFormatter } from \"../snippet/snippetFormatter.js\";\nimport { main } from \"./cli.js\";\n\nconst fileEnding = \"snippet\";\n\nvoid main({\n binName: \"snippet-fmt\",\n fileEndings: [fileEnding],\n\n getStdinFileEnding() {\n return fileEnding;\n },\n\n format: async (text, options) => {\n const updated = snippetFormatter(text, options);\n return Promise.resolve(updated);\n },\n});\n"], + "mappings": "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", + "names": ["parseSnippetFile", "content", "documentContents", "file", "text", "match", "contextText", "bodyText", "body", "parseBody", "context", "parseContext", "variables", "rest", "document", "pairs", "parseContextPairs", "key", "value", "parseVectorValue", "parseVariables", "lines", "l", "line", "parts", "variablesMap", "getVariable", "name", "matchLeading", "v", "IGNORE_FOLDERS", "GLOB_IGNORE_PATTERNS", "pattern", "getEndOfLine", "eof", "serializeSnippetFile", "snippetFile", "options", "eol", "getEndOfLine", "SnippetSerializer", "insertFinalNewline", "documents", "result", "d", "document", "lines", "getOptionalPairString", "getSortedVariables", "variables", "compareVariables", "variable", "v", "key", "value", "a", "b", "snippetFormatter", "text", "options", "snippetFile", "parseSnippetFile", "serializeSnippetFile", "getStdin", "fs", "path", "process", "getErrorMessage", "error", "SyntaxError", "location", "isSyntaxError", "error", "process", "ANSI_RESET", "ANSI_YELLOW", "ANSI_RED", "WARN_PREFIX", "ERROR_PREFIX", "createLogger", "quiet", "createLoggerFromStreams", "stdout", "stderr", "colorize", "shouldUseColor", "message", "color", "_color", "log", "warn", "shouldUseColor", "stream", "FilePatternError", "messages", "editorconfig", "getOptionsFromConfig", "filePath", "config", "options", "isMissingFileError", "error", "path", "normalizeToPosix", "filepath", "getDefaultArguments", "parseArgs", "argv", "result", "getDefaultArguments", "i", "arg", "parseKnownArgument", "fastGlob", "path", "fs", "lstatSafe", "filePath", "error", "isMissingFileError", "parseFilePatterns", "cli", "filePatterns", "seen", "globFileEndingPattern", "getGlobFileEndingsPattern", "errorMessages", "globOptions", "GLOB_IGNORE_PATTERNS", "pattern", "absolutePath", "stat", "lstatSafe", "files", "fastGlob", "file", "glob", "normalizeToPosix", "hasSupportedFileEnding", "FilePatternError", "a", "b", "fileEndings", "extension", "KNOWN_ARGUMENTS", "printHelp", "cli", "option", "KNOWN_ARGUMENTS", "package_default", "printVersion", "package_default", "setExitCode", "code", "main", "cli", "logger", "createLogger", "args", "parseArgs", "exitCode", "mainUnsafe", "setExitCode", "error", "FilePatternError", "message", "getErrorMessage", "printHelp", "printVersion", "mainFormatFiles", "mainFormatStdin", "check", "debug", "filePatterns", "filePaths", "parseFilePatterns", "changedFileCount", "hasError", "formatFiles", "filePath", "formatFile", "isSyntaxError", "getDisplayPath", "options", "getOptionsFromConfig", "content", "formatted", "isMissingFileError", "normalizeToPosix", "stdin", "input", "getStdin", "fauxFileName", "fauxFilePath", "fileEnding", "main", "text", "options", "updated", "snippetFormatter"] } diff --git a/dist/talonFormatter.js b/dist/talonFormatter.js index e69f73e..891642f 100644 --- a/dist/talonFormatter.js +++ b/dist/talonFormatter.js @@ -1,15 +1,15 @@ #!/usr/bin/env node -var C=[".git",".svn",".hg","node_modules","__pycache__"],F=C.map(t=>`**/${t}/**`);function g(t){return t==="crlf"?`\r +var U=[".git",".svn",".hg","node_modules","__pycache__"],$=U.map(t=>`**/${t}/**`);function g(t){return t==="crlf"?`\r `:` -`}function T(t){return{debug(e){t&&console.warn(`[debug] ${e}`)}}}function L(t){let e=t.match(/# fmt: columnWidth=(\d+)/);if(e!=null)return parseInt(e[1],10)}function $(t,e){return t?" ":" ".repeat(e??4)}function N(t){return t.length>0&&t[0]==="'"&&t[t.length-1]==="'"&&!t.includes('"')?`"${t.slice(1,-1).replaceAll("\\'","'")}"`:t}function P(t,e={},r=!1){let n=L(t.text)??e.columnWidth,o=$(e.indentTabs,e.indentSize),s=g(e.endOfLine);return new v(o,s,e.maxLineLength??80,n,e.insertFinalNewline??!0,e.preserveMultiline??!1,r).getText(t)}var v=class{constructor(e,r,n,o,s,i,a){this.indent=e;this.eol=r;this.maxLineLength=n;this.columnWidth=o;this.insertFinalNewline=s;this.preserveMultiline=i;this.logger=T(a)}lines=[];lastRow=0;logger;getText(e){this.addNode(e);let r=this.lines.join(this.eol).trimEnd();return r.length===0?"":this.insertFinalNewline?r+this.eol:r}addNL(){this.lines[this.lines.length-1]!==""&&this.lines.push("")}addNode(e,r=!1){e.startPosition.row>this.lastRow+1&&this.addNL(),this.lastRow=e.endPosition.row,this.addNodeHelper(e,r),this.lastRow=e.endPosition.row}addNodeHelper(e,r=!1){switch(e.type){case"source_file":for(let n of e.children)this.addNode(n);break;case"matches":{if(e.children.length>1||!de(e)){for(let n of e.children)this.addNode(n);this.addNL()}break}case"declarations":for(let n of e.children)this.addNode(n);break;case"block":for(let n of e.children)this.addNode(n,!0);break;case"command_declaration":case"key_binding_declaration":case"parrot_declaration":case"noise_declaration":case"face_declaration":case"gamepad_declaration":case"deck_declaration":this.addLeftRightNode(e,!1);break;case"settings_declaration":this.lines.length>0&&!this.lines[this.lines.length-1].startsWith("#")&&this.addNL(),this.addLeftRightNode(e,!0),this.addNL();break;case"comment":{let n=e.text.trimEnd(),o=r||e.startPosition.column>0?`${this.indent}${n}`:n;this.lines.push(o);break}default:{let n=this.getNodeText(e);this.lines.push(r?`${this.indent}${n}`:n)}}}getNodeText(e){switch(e.type){case"source_file":case"matches":case"declarations":case"block":case"command_declaration":case"key_binding_declaration":case"parrot_declaration":case"noise_declaration":case"face_declaration":case"gamepad_declaration":case"deck_declaration":case"settings_declaration":case"comment":throw new Error(`Node type '${e.type}' should be handled in addNode, not getNodeText`);case"parenthesized_rule":return this.pairWithChildren(e,e.parent!=null&&R(e,e.parent));case"optional":return this.pairWithChildren(e);case"expression_statement":case"assignment_statement":case"seq":case"choice":return e.children.map(r=>this.getNodeText(r)).join(" ");case"rule":case"action":case"key_action":case"sleep_action":case"argument_list":case"key_binding":case"face_binding":case"gamepad_binding":case"parrot_binding":case"noise_binding":case"deck_binding":case"tag_import_declaration":case"match":return e.children.map(r=>this.getNodeText(r)).join("");case"string":return ue(e);case"match_modifier":case":":case",":return`${e.text} `;case"implicit_string":return e.text.trim();case"tag_binding":case"settings_binding":case"capture":case"list":case"key(":case"sleep(":case"gamepad(":case"face(":case"parrot(":case"noise(":case"identifier":case"variable":case"word":case"binary_operator":case"integer":case"float":case"start_anchor":case"end_anchor":case"repeat":case"deck(":case"repeat1":case"(":case")":case"=":case"-":case"|":return e.text;default:return this.logger.debug(`Unknown syntax node type '${e.type}'`),e.text}}pairWithChildren(e,r=!1){let{children:n}=e,o=n.slice(1,-1).map(a=>this.getNodeText(a)).join(" ");if(r)return o;let s=n[0].text,i=n[n.length-1].text;return`${s}${o}${i}`}addLeftRightNode(e,r){let[n,o,...s]=e.children,i=this.getNodeText(n);if(!r&&s.length===1&&(!this.preserveMultiline||ge(n,s))){let a=s[0];if(a.children.length===1){let l=this.getNodeText(a.children[0]),p=this.columnWidth!=null?`${i}: `.padEnd(this.columnWidth):`${i}: `;if(p.length+l.length<=this.maxLineLength){this.lines.push(p+l);return}}}this.lines.push(`${i}:`);for(let a of s)this.addNode(a,!0)}};function ge(t,e){return t.endPosition.row===e[e.length-1].startPosition.row}function R(t,e){return t.startPosition.row===e.startPosition.row&&t.startPosition.column===e.startPosition.column&&t.endPosition.row===e.endPosition.row&&t.endPosition.column===e.endPosition.column}function de(t){return t.id===t.parent?.children?.[0]?.id}function ue(t){let e=N(t.text);return t.parent?.type==="expression_statement"&&t.parent.parent?.type==="block"&&R(t,t.parent)&&t.parent.parent.children.length>1?`insert(${e})`:e}function W(t){let e=t.split(/\r?\n/).map(i=>i.trim()),r=e.indexOf("-");if(r===-1)throw Error("Separator not found in talon list");let n=e.slice(0,r),o=me(e.slice(r+1)),s={headers:[],items:[]};for(let i of n){if(i.length===0)continue;if(i.startsWith("#")){s.headers.push({type:"comment",text:i});continue}let[a,l]=D(i);if(l==null)throw Error("Header value missing");s.headers.push({type:"header",key:a,value:l})}for(let i of o){if(i.length===0){s.items.push({type:"empty"});continue}if(i.startsWith("#")){s.items.push({type:"comment",text:i});continue}let[a,l]=D(i);s.items.push({type:"item",key:a,value:l})}return s}function D(t){let e=t.indexOf(":");return e===-1?[t,void 0]:[t.substring(0,e).trimEnd(),t.substring(e+1).trimStart()]}function me(t){let e=t.findIndex(n=>n.length>0);if(e<0)return[];let r=t.findLastIndex(n=>n.length>0);return t.slice(e,r+1)}function O(t,e={}){let r=L(t)??e.columnWidth,n=g(e.endOfLine),o=W(t);o.headers.sort((i,a)=>i.type==="header"&&i.key==="list"?-1:0);let s=[];for(let i of o.headers){if(i.type==="comment"){s.push(i.text);continue}s.push(`${i.key}: ${i.value}`)}s.push("-","");for(let i of o.items){if(i.type==="empty"){s.push("");continue}if(i.type==="comment"){s.push(i.text);continue}if(i.value!=null){let a=r!=null?`${i.key}: `.padEnd(r):`${i.key}: `,l=N(i.value);s.push(`${a}${l}`)}else s.push(i.key)}return s.length===0?"":((e.insertFinalNewline??!0)&&s.push(""),s.join(n))}import*as V from"node:fs";import*as y from"node:path";import{fileURLToPath as he}from"node:url";import{Language as xe,Parser as G}from"web-tree-sitter";var M,U=new Map,z=y.dirname(he(import.meta.url));function be(){return M??=G.init(),M}function ye(t){let e=U.get(t);if(e==null){let r=Le(t);e=xe.load(r),U.set(t,e)}return e}function Le(t){let e=`${t}.wasm`,r=[y.join(z,"../../node_modules/@cursorless/tree-sitter-wasms/out",e),y.join(z,"../node_modules/@cursorless/tree-sitter-wasms/out",e)].find(n=>V.existsSync(n));if(r==null)throw new Error(`Could not find ${e}`);return r}async function H(t,e){await be();let r=await ye(e),n=new G;n.setLanguage(r);let o=n.parse(t);if(o==null)throw new Error("Failed to parse text");return o.rootNode}import Ie from"get-stdin";import*as E from"node:fs/promises";import*as S from"node:path";import*as c from"node:process";var d=class extends Error{constructor(r){super(`One or more file pattern errors occurred: +`}function v(t){return{debug(e){t&&console.warn(`[debug] ${e}`)}}}function w(t){let e=t.match(/# fmt: columnWidth=(\d+)/);if(e!=null)return parseInt(e[1],10)}function P(t,e){return t?" ":" ".repeat(e??4)}var y=class extends Error{constructor(r){super("Syntax error.");this.location=r;this.name="SyntaxError"}getLocation(){return this.location!=null?`(${this.location.row+1}:${this.location.column+1})`:void 0}};function O(t){return t instanceof y}var b=class extends y{constructor(e){super(z(e)?.startPosition),this.name="SyntaxTreeError"}};function z(t){if(t.isError||t.isMissing)return t;for(let e of t.children){if(!e.hasError)continue;let r=z(e);if(r!=null)return r}return null}function E(t){return t.length>0&&t[0]==="'"&&t[t.length-1]==="'"&&!t.includes('"')?`"${t.slice(1,-1).replaceAll("\\'","'")}"`:t}function I(t,e={},r=!1){if(t.hasError)throw new b(t);let i=w(t.text)??e.columnWidth,s=P(e.indentTabs,e.indentSize),o=g(e.endOfLine);return new k(s,o,e.maxLineLength??80,i,e.insertFinalNewline??!0,e.preserveMultiline??!1,r).getText(t)}var k=class{constructor(e,r,i,s,o,n,a){this.indent=e;this.eol=r;this.maxLineLength=i;this.columnWidth=s;this.insertFinalNewline=o;this.preserveMultiline=n;this.logger=v(a)}lines=[];lastRow=0;logger;getText(e){this.addNode(e);let r=this.lines.join(this.eol).trimEnd();return r.length===0?"":this.insertFinalNewline?r+this.eol:r}addNL(){this.lines[this.lines.length-1]!==""&&this.lines.push("")}addNode(e,r=!1){e.startPosition.row>this.lastRow+1&&this.addNL(),this.lastRow=e.endPosition.row,this.addNodeHelper(e,r),this.lastRow=e.endPosition.row}addNodeHelper(e,r=!1){switch(e.type){case"source_file":for(let i of e.children)this.addNode(i);break;case"matches":{if(e.children.length>1||!be(e)){for(let i of e.children)this.addNode(i);this.addNL()}break}case"declarations":for(let i of e.children)this.addNode(i);break;case"block":for(let i of e.children)this.addNode(i,!0);break;case"command_declaration":case"key_binding_declaration":case"parrot_declaration":case"noise_declaration":case"face_declaration":case"gamepad_declaration":case"deck_declaration":this.addLeftRightNode(e,!1);break;case"settings_declaration":this.lines.length>0&&!this.lines[this.lines.length-1].startsWith("#")&&this.addNL(),this.addLeftRightNode(e,!0),this.addNL();break;case"comment":{let i=e.text.trimEnd(),s=r||e.startPosition.column>0?`${this.indent}${i}`:i;this.lines.push(s);break}default:{let i=this.getNodeText(e);this.lines.push(r?`${this.indent}${i}`:i)}}}getNodeText(e){switch(e.type){case"source_file":case"matches":case"declarations":case"block":case"command_declaration":case"key_binding_declaration":case"parrot_declaration":case"noise_declaration":case"face_declaration":case"gamepad_declaration":case"deck_declaration":case"settings_declaration":case"comment":throw new Error(`Node type '${e.type}' should be handled in addNode, not getNodeText`);case"parenthesized_rule":return this.pairWithChildren(e,e.parent!=null&&V(e,e.parent));case"optional":return this.pairWithChildren(e);case"expression_statement":case"assignment_statement":case"seq":case"choice":return e.children.map(r=>this.getNodeText(r)).join(" ");case"rule":case"action":case"key_action":case"sleep_action":case"argument_list":case"key_binding":case"face_binding":case"gamepad_binding":case"parrot_binding":case"noise_binding":case"deck_binding":case"tag_import_declaration":case"match":return e.children.map(r=>this.getNodeText(r)).join("");case"string":return Le(e);case"match_modifier":case":":case",":return`${e.text} `;case"implicit_string":return e.text.trim();case"tag_binding":case"settings_binding":case"capture":case"list":case"key(":case"sleep(":case"gamepad(":case"face(":case"parrot(":case"noise(":case"identifier":case"variable":case"word":case"binary_operator":case"integer":case"float":case"start_anchor":case"end_anchor":case"repeat":case"deck(":case"repeat1":case"(":case")":case"=":case"-":case"|":return e.text;default:return this.logger.debug(`Unknown syntax node type '${e.type}'`),e.text}}pairWithChildren(e,r=!1){let{children:i}=e,s=i.slice(1,-1).map(a=>this.getNodeText(a)).join(" ");if(r)return s;let o=i[0].text,n=i[i.length-1].text;return`${o}${s}${n}`}addLeftRightNode(e,r){let[i,s,...o]=e.children,n=this.getNodeText(i);if(!r&&o.length===1&&(!this.preserveMultiline||ye(i,o))){let a=o[0];if(a.children.length===1){let l=this.getNodeText(a.children[0]),f=this.columnWidth!=null?`${n}: `.padEnd(this.columnWidth):`${n}: `;if(f.length+l.length<=this.maxLineLength){this.lines.push(f+l);return}}}this.lines.push(`${n}:`);for(let a of o)this.addNode(a,!0)}};function ye(t,e){return t.endPosition.row===e[e.length-1].startPosition.row}function V(t,e){return t.startPosition.row===e.startPosition.row&&t.startPosition.column===e.startPosition.column&&t.endPosition.row===e.endPosition.row&&t.endPosition.column===e.endPosition.column}function be(t){return t.id===t.parent?.children?.[0]?.id}function Le(t){let e=E(t.text);return t.parent?.type==="expression_statement"&&t.parent.parent?.type==="block"&&V(t,t.parent)&&t.parent.parent.children.length>1?`insert(${e})`:e}function K(t){let e=t.split(/\r?\n/).map(n=>n.trim()),r=e.indexOf("-");if(r===-1)throw Error("Separator not found in talon list");let i=e.slice(0,r),s=Ne(e.slice(r+1)),o={headers:[],items:[]};for(let n of i){if(n.length===0)continue;if(n.startsWith("#")){o.headers.push({type:"comment",text:n});continue}let[a,l]=G(n);if(l==null)throw Error("Header value missing");o.headers.push({type:"header",key:a,value:l})}for(let n of s){if(n.length===0){o.items.push({type:"empty"});continue}if(n.startsWith("#")){o.items.push({type:"comment",text:n});continue}let[a,l]=G(n);o.items.push({type:"item",key:a,value:l})}return o}function G(t){let e=t.indexOf(":");return e===-1?[t,void 0]:[t.substring(0,e).trimEnd(),t.substring(e+1).trimStart()]}function Ne(t){let e=t.findIndex(i=>i.length>0);if(e<0)return[];let r=t.findLastIndex(i=>i.length>0);return t.slice(e,r+1)}function A(t,e={}){let r=w(t)??e.columnWidth,i=g(e.endOfLine),s=K(t);s.headers.sort((n,a)=>n.type==="header"&&n.key==="list"?-1:0);let o=[];for(let n of s.headers){if(n.type==="comment"){o.push(n.text);continue}o.push(`${n.key}: ${n.value}`)}o.push("-","");for(let n of s.items){if(n.type==="empty"){o.push("");continue}if(n.type==="comment"){o.push(n.text);continue}if(n.value!=null){let a=r!=null?`${n.key}: `.padEnd(r):`${n.key}: `,l=E(n.value);o.push(`${a}${l}`)}else o.push(n.key)}return o.length===0?"":((e.insertFinalNewline??!0)&&o.push(""),o.join(i))}import*as B from"node:fs";import*as L from"node:path";import{fileURLToPath as we}from"node:url";import{Language as Ee,Parser as Q}from"web-tree-sitter";var H,X=new Map,q=L.dirname(we(import.meta.url));function _e(){return H??=Q.init(),H}function Se(t){let e=X.get(t);if(e==null){let r=Fe(t);e=Ee.load(r),X.set(t,e)}return e}function Fe(t){let e=`${t}.wasm`,r=[L.join(q,"../../node_modules/@cursorless/tree-sitter-wasms/out",e),L.join(q,"../node_modules/@cursorless/tree-sitter-wasms/out",e)].find(i=>B.existsSync(i));if(r==null)throw new Error(`Could not find ${e}`);return r}async function J(t,e){await _e();let r=await Se(e),i=new Q;i.setLanguage(r);let s=i.parse(t);if(s==null)throw new Error("Failed to parse text");return s.rootNode}import We from"get-stdin";import*as F from"node:fs/promises";import*as T from"node:path";import*as p from"node:process";function C(t){return t instanceof Error?t.message:String(t)}import*as u from"node:process";var Te="\x1B[0m",$e="\x1B[33m",ve="\x1B[31m",Pe="[warn]",Oe="[error]";function j(t=!1){return ke(u.stdout,u.stderr,t)}function ke(t,e,r=!1){let i=Ie(e)?(n,a)=>`${a}${n}${Te}`:(n,a)=>n,s,o;return r?(s=()=>{},o=()=>{}):(s=n=>{t.write(`${n} +`)},o=n=>{e.write(`${i(Pe,$e)} ${n} +`)}),{log:s,warn:o,error(n){e.write(`${i(Oe,ve)} ${n} +`)}}}function Ie(t){return"NO_COLOR"in u.env?!1:t.isTTY===!0}var m=class extends Error{constructor(r){super(`One or more file pattern errors occurred: ${r.join(` -`)}`);this.messages=r}name="FilePatternError"};function k(t){return t instanceof Error?t.message:String(t)}function w(t){return t instanceof Error&&"code"in t&&t.code==="ENOENT"}function I(t){Reflect.set(process,"exitCode",t)}import*as u from"node:process";var Ne="\x1B[0m",we="\x1B[33m",_e="\x1B[31m",Ee="[warn]",Se="[error]";function A(t=!1){return Fe(u.stdout,u.stderr,t)}function Fe(t,e,r=!1){let n=Te(e)?(i,a)=>`${a}${i}${Ne}`:(i,a)=>i,o,s;return r?(o=()=>{},s=()=>{}):(o=i=>{t.write(`${i} -`)},s=i=>{e.write(`${n(Ee,we)} ${i} -`)}),{log:o,warn:s,error(i){e.write(`${n(Se,_e)} ${i} -`)}}}function Te(t){return"NO_COLOR"in u.env?!1:t.isTTY===!0}import*as K from"editorconfig";async function j(t){let e=await K.parse(t),r={};return e.indent_style==="tab"?r.indentTabs=!0:e.indent_style==="space"&&(r.indentTabs=!1),typeof e.indent_size=="number"?r.indentSize=e.indent_size:e.indent_size==="tab"&&typeof e.tab_width=="number"&&(r.indentSize=e.tab_width),typeof e.max_line_length=="number"&&(r.maxLineLength=e.max_line_length),typeof e.column_width=="number"&&(r.columnWidth=e.column_width),typeof e.insert_final_newline=="boolean"&&(r.insertFinalNewline=e.insert_final_newline),typeof e.preserve_multiline=="boolean"&&(r.preserveMultiline=e.preserve_multiline),e.end_of_line!=null&&e.end_of_line!=="unset"&&(r.endOfLine=e.end_of_line),r}import*as q from"node:path";var _=q.sep==="\\"?t=>t.replaceAll("\\","/"):t=>t;function X(){return{filePatterns:[],help:!1,version:!1,quiet:!1,debug:!1,check:!1}}function B(t){let e=X();for(let r=0;rPe(f,t.fileEndings));x.length===0&&o.push(`No files matching the pattern were found: ${i}`);for(let f of x)r.add(m.resolve(f))}if(o.length>0)throw new d(o);return Array.from(r).sort((i,a)=>i.localeCompare(a))}function ve(t){return t.length===1?t[0]:`{${t.join(",")}}`}function Pe(t,e){let r=m.extname(t).slice(1);return e.includes(r)}var ee=["--help","--version","--quiet","--check","--debug"];function te(t){process.stdout.write(`Usage: ${t.binName} [options] [file/dir/glob ...] +`)}`);this.messages=r}name="FilePatternError"};import*as Y from"editorconfig";async function R(t){let e=await Y.parse(t),r={};return e.indent_style==="tab"?r.indentTabs=!0:e.indent_style==="space"&&(r.indentTabs=!1),typeof e.indent_size=="number"?r.indentSize=e.indent_size:e.indent_size==="tab"&&typeof e.tab_width=="number"&&(r.indentSize=e.tab_width),typeof e.max_line_length=="number"&&(r.maxLineLength=e.max_line_length),typeof e.column_width=="number"&&(r.columnWidth=e.column_width),typeof e.insert_final_newline=="boolean"&&(r.insertFinalNewline=e.insert_final_newline),typeof e.preserve_multiline=="boolean"&&(r.preserveMultiline=e.preserve_multiline),e.end_of_line!=null&&e.end_of_line!=="unset"&&(r.endOfLine=e.end_of_line),r}function _(t){return t instanceof Error&&"code"in t&&t.code==="ENOENT"}import*as Z from"node:path";var S=Z.sep==="\\"?t=>t.replaceAll("\\","/"):t=>t;function ee(){return{filePatterns:[],help:!1,version:!1,quiet:!1,debug:!1,check:!1}}function te(t){let e=ee();for(let r=0;rje(c,t.fileEndings));d.length===0&&s.push(`No files matching the pattern were found: ${n}`);for(let c of d)r.add(h.resolve(c))}if(s.length>0)throw new m(s);return Array.from(r).sort((n,a)=>n.localeCompare(a))}function Ce(t){return t.length===1?t[0]:`{${t.join(",")}}`}function je(t,e){let r=h.extname(t).slice(1);return e.includes(r)}var se=["--help","--version","--quiet","--check","--debug"];function ae(t){process.stdout.write(`Usage: ${t.binName} [options] [file/dir/glob ...] `),process.stdout.write(` `),process.stdout.write(`Options: -`);for(let e of ee)process.stdout.write(` ${e} -`)}var re={name:"@cursorless/talon-tools",version:"0.9.0",description:"Linting and formatting tools for Talon and Cursorless",author:"Cursorless Dev",license:"MIT",type:"module",files:["dist","!dist/test","!dist/build.*"],types:"./dist/lib.d.ts",exports:{".":{types:"./dist/lib.d.ts",default:"./dist/lib.js"},"./node":{types:"./dist/node/libNode.d.ts",default:"./dist/libNode.js"}},bin:{"snippet-fmt":"dist/snippetFormatter.js","talon-fmt":"dist/talonFormatter.js","tree-sitter-fmt":"dist/treeSitterFormatter.js"},repository:{type:"git",url:"git+https://github.com/cursorless-dev/talon-tools.git"},funding:"https://github.com/sponsors/cursorless-dev",sponsor:{url:"https://github.com/sponsors/cursorless-dev"},scripts:{build:"npm run clean && tsc -p . && tsx ./src/build.ts",clean:"rm -rf dist/*",lint:"npm run lint:ts &&npm run lint:fmt","lint:ts":"tsc -p . --noEmit && eslint src","lint:fmt":"prettier --check .",fix:"npm run fix:ts && npm run fix:fmt","fix:ts":"eslint src --fix","fix:fmt":"prettier --write --list-different .",test:"tsx src/test/runAllTests.ts","test:subset":"tsx src/test/runAllTests.ts --subset"},dependencies:{"@cursorless/tree-sitter-wasms":"^0.7.0",editorconfig:"^3.0.2","fast-glob":"^3.3.3","get-stdin":"^10.0.0","web-tree-sitter":"^0.26.7"},devDependencies:{"@eslint/js":"^9.39.4","@types/mocha":"^10.0.10","@types/node":"^24.12.0",esbuild:"^0.27.4","eslint-config-prettier":"^10.1.8","eslint-plugin-import":"^2.32.0",eslint:"^9.39.4",jiti:"^2.6.1",mocha:"^11.7.5",prettier:"^3.8.1",tsx:"^4.21.0","typescript-eslint":"^8.57.1",typescript:"^5.9.3"}};function ne(){process.stdout.write(`${re.version} -`)}async function se(t){let e=A();try{let r=B(c.argv.slice(2));e=A(r.quiet);let n=await Ae({cli:t,args:r,logger:e});I(n)}catch(r){if(r instanceof d)for(let n of r.messages)e.error(n);else e.error(k(r));I(2)}}async function Ae({cli:t,args:e,logger:r}){if(e.help)return te(t),0;if(e.version)return ne(),0;if(e.filePatterns.length>0)return je({cli:t,logger:r,check:e.check,debug:e.debug,filePatterns:e.filePatterns});if(!c.stdin.isTTY)return We({cli:t,logger:r,stdin:c.stdin,check:e.check,debug:e.debug});throw new Error("No input files specified. Use --help for usage information.")}async function je({cli:t,logger:e,check:r,debug:n,filePatterns:o}){r&&e.log("Checking formatting...");let s=await Z(t,o),i=await Ce({cli:t,logger:e,check:r,debug:n,filePaths:s});return r?i>0?(e.warn(`Code style issues found in ${i} file(s).`),1):(e.log("All matched files use correct code style!"),0):0}async function Ce({cli:t,logger:e,check:r,debug:n,filePaths:o}){let s=0;for(let i of o)await Re({cli:t,logger:e,check:r,debug:n,filePath:i})&&s++;return s}async function Re({cli:t,logger:e,check:r,debug:n,filePath:o}){try{let s=await j(o),i=await E.readFile(o,"utf8"),a=await t.format(i,s,o,n);return a===i?!1:(e.log(De(o)),r||await E.writeFile(o,a,"utf8"),!0)}catch(s){if(w(s))return!1;throw new Error(`Failed to format '${o}': ${k(s)}`,{cause:s})}}function De(t){return _(S.relative(c.cwd(),t))}async function We({cli:t,logger:e,stdin:r,check:n,debug:o}){let s=await Ie({stdin:r}),a=`stdin.${t.getStdinFileEnding(s)}`,l=S.resolve(a),p=await j(l),x=await t.format(s,p,l,o);return n?s!==x?(e.warn("Code style issues found in stdin."),1):0:(c.stdout.write(x),0)}var oe="talon",ae="talon-list";se({binName:"talon-fmt",fileEndings:[oe,ae],getStdinFileEnding(t){return le(t)?ae:oe},format:async(t,e,r,n)=>{if(Me(t,r)){let s=O(t,e);return Promise.resolve(s)}let o=await H(t,"tree-sitter-talon");return P(o,e,n)}});function Me(t,e){return e.endsWith(".talon")?!1:e.endsWith(".talon-list")?!0:le(t)}function le(t){return t.trimStart().startsWith("list:")} +`);for(let e of se)process.stdout.write(` ${e} +`)}var le={name:"@cursorless/talon-tools",version:"0.10.0",description:"Linting and formatting tools for Talon and Cursorless",author:"Cursorless Dev",license:"MIT",type:"module",files:["dist","!dist/test","!dist/build.*"],types:"./dist/lib.d.ts",exports:{".":{types:"./dist/lib.d.ts",default:"./dist/lib.js"},"./node":{types:"./dist/node/libNode.d.ts",default:"./dist/libNode.js"}},bin:{"snippet-fmt":"dist/snippetFormatter.js","talon-fmt":"dist/talonFormatter.js","tree-sitter-fmt":"dist/treeSitterFormatter.js"},repository:{type:"git",url:"git+https://github.com/cursorless-dev/talon-tools.git"},funding:"https://github.com/sponsors/cursorless-dev",sponsor:{url:"https://github.com/sponsors/cursorless-dev"},scripts:{build:"npm run clean && tsc -p . && tsx ./src/build.ts",clean:"rm -rf dist/*",lint:"npm run lint:ts &&npm run lint:fmt","lint:ts":"tsc -p . --noEmit && eslint src","lint:fmt":"prettier --check .",fix:"npm run fix:ts && npm run fix:fmt","fix:ts":"eslint src --fix","fix:fmt":"prettier --write --list-different .",test:"tsx src/test/runAllTests.ts","test:subset":"tsx src/test/runAllTests.ts --subset"},dependencies:{"@cursorless/tree-sitter-wasms":"^0.7.0",editorconfig:"^3.0.2","fast-glob":"^3.3.3","get-stdin":"^10.0.0","web-tree-sitter":"^0.26.7"},devDependencies:{"@eslint/js":"^9.39.4","@types/mocha":"^10.0.10","@types/node":"^24.12.0",esbuild:"^0.27.4","eslint-config-prettier":"^10.1.8","eslint-plugin-import":"^2.32.0",eslint:"^9.39.4",jiti:"^2.6.1",mocha:"^11.7.5",prettier:"^3.8.1",tsx:"^4.21.0","typescript-eslint":"^8.57.1",typescript:"^5.9.3"}};function ce(){process.stdout.write(`${le.version} +`)}function W(t){Reflect.set(process,"exitCode",t)}async function fe(t){let e=j();try{let r=te(p.argv.slice(2));e=j(r.quiet);let i=await De({cli:t,args:r,logger:e});W(i)}catch(r){if(r instanceof m)for(let i of r.messages)e.error(i);else e.error(C(r));W(2)}}async function De({cli:t,args:e,logger:r}){if(e.help)return ae(t),0;if(e.version)return ce(),0;if(e.filePatterns.length>0)return Me({cli:t,logger:r,check:e.check,debug:e.debug,filePatterns:e.filePatterns});if(!p.stdin.isTTY)return Ve({cli:t,logger:r,stdin:p.stdin,check:e.check,debug:e.debug});throw new Error("No input files specified. Use --help for usage information.")}async function Me({cli:t,logger:e,check:r,debug:i,filePatterns:s}){r&&e.log("Checking formatting...");let o=await oe(t,s),[n,a]=await Ue({cli:t,logger:e,check:r,debug:i,filePaths:o});if(r){if(n>0&&(e.warn(`Code style issues found in ${n} file(s).`),!a))return 1;a||e.log("All matched files use correct code style!")}return a?2:0}async function Ue({cli:t,logger:e,check:r,debug:i,filePaths:s}){let o=0,n=!1;for(let a of s)try{await ze({cli:t,logger:e,check:r,debug:i,filePath:a})&&o++}catch(l){O(l)?e.error(`${D(a)}${l.getLocation()}: ${l.message}`):e.error(`${D(a)}: ${C(l)}`),n=!0}return[o,n]}async function ze({cli:t,logger:e,check:r,debug:i,filePath:s}){try{let o=await R(s),n=await F.readFile(s,"utf8"),a=await t.format(n,o,s,i);return a===n?!1:(e.log(D(s)),r||await F.writeFile(s,a,"utf8"),!0)}catch(o){if(_(o))return!1;throw o}}function D(t){return S(T.relative(p.cwd(),t))}async function Ve({cli:t,logger:e,stdin:r,check:i,debug:s}){let o=await We({stdin:r}),a=`stdin.${t.getStdinFileEnding(o)}`,l=T.resolve(a),f=await R(l),d;try{d=await t.format(o,f,l,s)}catch(c){if(O(c))return e.error(`stdin${c.getLocation()}: ${c.message}`),2;throw c}return i?o!==d?(e.warn("Code style issues found in stdin."),1):0:(p.stdout.write(d),0)}var de="talon",ge="talon-list";fe({binName:"talon-fmt",fileEndings:[de,ge],getStdinFileEnding(t){return ue(t)?ge:de},format:async(t,e,r,i)=>{if(Ge(t,r)){let o=A(t,e);return Promise.resolve(o)}let s=await J(t,"tree-sitter-talon");return I(s,e,i)}});function Ge(t,e){return e.endsWith(".talon")?!1:e.endsWith(".talon-list")?!0:ue(t)}function ue(t){return t.trimStart().startsWith("list:")} //# sourceMappingURL=talonFormatter.js.map diff --git a/dist/talonFormatter.js.map b/dist/talonFormatter.js.map index b870319..647c776 100644 --- a/dist/talonFormatter.js.map +++ b/dist/talonFormatter.js.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../src/util/constants.ts", "../src/util/getEndOfLine.ts", "../src/util/createDebugLogger.ts", "../src/util/getColumnWidth.ts", "../src/util/getIndentation.ts", "../src/talon/convertQuotes.ts", "../src/talon/talonFormatter.ts", "../src/talon/parseTalonList.ts", "../src/talon/talonListFormatter.ts", "../src/node/parseText.ts", "../src/node/cli.ts", "../src/node/FilePatternError.ts", "../src/util/getErrorMessage.ts", "../src/node/isMissingFileError.ts", "../src/node/setExitCode.ts", "../src/node/createLogger.ts", "../src/node/getOptionsFromConfig.ts", "../src/node/normalizeToPosix.ts", "../src/node/getDefaultArguments.ts", "../src/node/parseArgs.ts", "../src/node/parseFilePatterns.ts", "../src/node/lstatSafe.ts", "../src/types.ts", "../src/node/printHelp.ts", "../package.json", "../src/node/printVersion.ts", "../src/node/talonFormatter.ts"], - "sourcesContent": ["// Exit code 0: Success\nexport const EXIT_OK = 0;\n// Exit code 1: Check failed\nexport const EXIT_FAIL = 1;\n// Exit code 2: Unexpected error\nexport const EXIT_ERROR = 2;\n\nexport const DEFAULT_INDENT_WIDTH = 4;\nexport const DEFAULT_MAX_LINE_LENGTH = 80;\nexport const DEFAULT_INSERT_FINAL_NEWLINE = true;\n\nexport const IGNORE_FOLDERS = [\n \".git\",\n \".svn\",\n \".hg\",\n \"node_modules\",\n \"__pycache__\",\n];\n\nexport const GLOB_IGNORE_PATTERNS = IGNORE_FOLDERS.map(\n (pattern) => `**/${pattern}/**`,\n);\n", "import type { EndOfLine } from \"../types.js\";\n\nexport function getEndOfLine(eof?: EndOfLine): string {\n return eof === \"crlf\" ? \"\\r\\n\" : \"\\n\";\n}\n", "import type { DebugLogger } from \"../types.js\";\n\nexport function createDebugLogger(debug: boolean): DebugLogger {\n return {\n debug(message: string) {\n if (debug) {\n console.warn(`[debug] ${message}`);\n }\n },\n };\n}\n", "export function getColumnWidth(text: string): number | undefined {\n const match = text.match(/# fmt: columnWidth=(\\d+)/);\n\n if (match != null) {\n return parseInt(match[1], 10);\n }\n\n return undefined;\n}\n", "import { DEFAULT_INDENT_WIDTH } from \"./constants.js\";\n\nexport function getIndentation(\n indentTabs: boolean | undefined,\n indentSize: number | undefined,\n): string {\n return indentTabs ? \"\\t\" : \" \".repeat(indentSize ?? DEFAULT_INDENT_WIDTH);\n}\n", "export function convertQuotes(text: string): string {\n // Convert single quotes to double quotes\n if (\n text.length > 0 &&\n text[0] === \"'\" &&\n text[text.length - 1] === \"'\" &&\n !text.includes('\"')\n ) {\n const innerText = text.slice(1, -1).replaceAll(\"\\\\'\", \"'\");\n return `\"${innerText}\"`;\n }\n\n return text;\n}\n", "import type { DebugLogger, FormatterOptions, SyntaxNode } from \"../types.js\";\nimport {\n DEFAULT_INSERT_FINAL_NEWLINE,\n DEFAULT_MAX_LINE_LENGTH,\n} from \"../util/constants.js\";\nimport { createDebugLogger } from \"../util/createDebugLogger.js\";\nimport { getColumnWidth } from \"../util/getColumnWidth.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport { getIndentation } from \"../util/getIndentation.js\";\nimport { convertQuotes } from \"./convertQuotes.js\";\n\nexport type Options = FormatterOptions<\n | \"endOfLine\"\n | \"indentTabs\"\n | \"indentSize\"\n | \"maxLineLength\"\n | \"columnWidth\"\n | \"insertFinalNewline\"\n | \"preserveMultiline\"\n>;\n\nexport function talonFormatter(\n node: SyntaxNode,\n options: Options = {},\n debug: boolean = false,\n): string {\n const columnWidth = getColumnWidth(node.text) ?? options.columnWidth;\n const indentation = getIndentation(options.indentTabs, options.indentSize);\n const eol = getEndOfLine(options.endOfLine);\n const formatter = new TalonFormatter(\n indentation,\n eol,\n options.maxLineLength ?? DEFAULT_MAX_LINE_LENGTH,\n columnWidth,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n options.preserveMultiline ?? false,\n debug,\n );\n return formatter.getText(node);\n}\n\nclass TalonFormatter {\n private lines: string[] = [];\n private lastRow = 0;\n private logger: DebugLogger;\n\n constructor(\n private indent: string,\n private eol: string,\n private maxLineLength: number,\n private columnWidth: number | undefined,\n private insertFinalNewline: boolean,\n private preserveMultiline: boolean,\n debug: boolean,\n ) {\n this.logger = createDebugLogger(debug);\n }\n\n getText(node: SyntaxNode): string {\n this.addNode(node);\n\n const result = this.lines.join(this.eol).trimEnd();\n\n if (result.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return result + this.eol;\n }\n\n return result;\n }\n\n private addNL(): void {\n if (this.lines[this.lines.length - 1] !== \"\") {\n this.lines.push(\"\");\n }\n }\n\n private addNode(node: SyntaxNode, isIndented = false): void {\n if (node.startPosition.row > this.lastRow + 1) {\n this.addNL();\n }\n this.lastRow = node.endPosition.row;\n this.addNodeHelper(node, isIndented);\n this.lastRow = node.endPosition.row;\n }\n\n private addNodeHelper(node: SyntaxNode, isIndented = false): void {\n switch (node.type) {\n case \"source_file\":\n for (const n of node.children) {\n this.addNode(n);\n }\n break;\n\n case \"matches\": {\n // There are match nodes or there is a comment before\n if (node.children.length > 1 || !isFirstChild(node)) {\n for (const n of node.children) {\n this.addNode(n);\n }\n this.addNL();\n }\n break;\n }\n\n case \"declarations\":\n for (const n of node.children) {\n this.addNode(n);\n }\n break;\n\n case \"block\":\n for (const n of node.children) {\n this.addNode(n, true);\n }\n break;\n\n case \"command_declaration\":\n case \"key_binding_declaration\":\n case \"parrot_declaration\":\n case \"noise_declaration\":\n case \"face_declaration\":\n case \"gamepad_declaration\":\n case \"deck_declaration\":\n this.addLeftRightNode(node, false);\n break;\n\n case \"settings_declaration\":\n if (\n this.lines.length > 0 &&\n !this.lines[this.lines.length - 1].startsWith(\"#\")\n ) {\n this.addNL();\n }\n this.addLeftRightNode(node, true);\n this.addNL();\n break;\n\n case \"comment\": {\n // When using crlf eol comments have a trailing `\\r`\n const text = node.text.trimEnd();\n const nodeText =\n isIndented || node.startPosition.column > 0\n ? `${this.indent}${text}`\n : text;\n this.lines.push(nodeText);\n break;\n }\n\n default: {\n const nodeText = this.getNodeText(node);\n this.lines.push(\n isIndented ? `${this.indent}${nodeText}` : nodeText,\n );\n }\n }\n }\n\n private getNodeText(node: SyntaxNode): string {\n switch (node.type) {\n case \"source_file\":\n case \"matches\":\n case \"declarations\":\n case \"block\":\n case \"command_declaration\":\n case \"key_binding_declaration\":\n case \"parrot_declaration\":\n case \"noise_declaration\":\n case \"face_declaration\":\n case \"gamepad_declaration\":\n case \"deck_declaration\":\n case \"settings_declaration\":\n case \"comment\":\n throw new Error(\n `Node type '${node.type}' should be handled in addNode, not getNodeText`,\n );\n\n case \"parenthesized_rule\":\n return this.pairWithChildren(\n node,\n node.parent != null && rangeEqual(node, node.parent),\n );\n\n case \"optional\":\n return this.pairWithChildren(node);\n\n case \"expression_statement\":\n case \"assignment_statement\":\n case \"seq\":\n case \"choice\":\n return node.children.map((n) => this.getNodeText(n)).join(\" \");\n\n case \"rule\":\n case \"action\":\n case \"key_action\":\n case \"sleep_action\":\n case \"argument_list\":\n case \"key_binding\":\n case \"face_binding\":\n case \"gamepad_binding\":\n case \"parrot_binding\":\n case \"noise_binding\":\n case \"deck_binding\":\n case \"tag_import_declaration\":\n case \"match\":\n return node.children.map((n) => this.getNodeText(n)).join(\"\");\n\n case \"string\":\n return formatString(node);\n\n case \"match_modifier\":\n case \":\":\n case \",\":\n return `${node.text} `;\n\n case \"implicit_string\":\n return node.text.trim();\n\n case \"tag_binding\":\n case \"settings_binding\":\n case \"capture\":\n case \"list\":\n case \"key(\":\n case \"sleep(\":\n case \"gamepad(\":\n case \"face(\":\n case \"parrot(\":\n case \"noise(\":\n case \"identifier\":\n case \"variable\":\n case \"word\":\n case \"binary_operator\":\n case \"integer\":\n case \"float\":\n case \"start_anchor\":\n case \"end_anchor\":\n case \"repeat\":\n case \"deck(\":\n case \"repeat1\":\n case \"(\":\n case \")\":\n case \"=\":\n case \"-\":\n case \"|\":\n return node.text;\n\n default:\n this.logger.debug(`Unknown syntax node type '${node.type}'`);\n return node.text;\n }\n }\n\n private pairWithChildren(\n node: SyntaxNode,\n unwrap: boolean = false,\n ): string {\n const { children } = node;\n const middle = children\n .slice(1, -1)\n .map((n) => this.getNodeText(n))\n .join(\" \");\n if (unwrap) {\n return middle;\n }\n const pre = children[0].text;\n const post = children[children.length - 1].text;\n return `${pre}${middle}${post}`;\n }\n\n private addLeftRightNode(node: SyntaxNode, forceMultiline: boolean): void {\n const [leftNode, _colonNode, ...rightNodes] = node.children;\n const left = this.getNodeText(leftNode);\n\n if (!forceMultiline && rightNodes.length === 1) {\n if (\n !this.preserveMultiline ||\n isLeftRightSingleLine(leftNode, rightNodes)\n ) {\n const rightNode = rightNodes[0];\n if (rightNode.children.length === 1) {\n const right = this.getNodeText(rightNode.children[0]);\n const leftWithPadding =\n this.columnWidth != null\n ? `${left}: `.padEnd(this.columnWidth)\n : `${left}: `;\n if (\n leftWithPadding.length + right.length <=\n this.maxLineLength\n ) {\n this.lines.push(leftWithPadding + right);\n return;\n }\n }\n }\n }\n\n this.lines.push(`${left}:`);\n\n for (const n of rightNodes) {\n this.addNode(n, true);\n }\n }\n}\n\nfunction isLeftRightSingleLine(\n left: SyntaxNode,\n rights: SyntaxNode[],\n): boolean {\n return left.endPosition.row === rights[rights.length - 1].startPosition.row;\n}\n\nfunction rangeEqual(a: SyntaxNode, b: SyntaxNode): boolean {\n return (\n a.startPosition.row === b.startPosition.row &&\n a.startPosition.column === b.startPosition.column &&\n a.endPosition.row === b.endPosition.row &&\n a.endPosition.column === b.endPosition.column\n );\n}\n\nfunction isFirstChild(node: SyntaxNode): boolean {\n return node.id === node.parent?.children?.[0]?.id;\n}\n\nfunction formatString(node: SyntaxNode): string {\n // Convert single quotes to double quotes\n const text = convertQuotes(node.text);\n\n // A single string literal is allowed as syntactic sugar for the insert\n // action, but not in combination with other sibling statements.\n if (\n node.parent?.type === \"expression_statement\" &&\n node.parent.parent?.type === \"block\" &&\n rangeEqual(node, node.parent) &&\n node.parent.parent.children.length > 1\n ) {\n return `insert(${text})`;\n }\n\n return text;\n}\n", "interface TalonListHeader {\n type: \"header\";\n key: string;\n value: string;\n}\n\ninterface TalonListItem {\n type: \"item\";\n key: string;\n value?: string;\n}\n\ninterface EmptyLine {\n type: \"empty\";\n}\n\ninterface CommentLine {\n type: \"comment\";\n text: string;\n}\n\nexport interface TalonList {\n headers: (TalonListHeader | CommentLine)[];\n items: (TalonListItem | CommentLine | EmptyLine)[];\n}\n\nexport function parseTalonList(text: string): TalonList {\n const lines = text.split(/\\r?\\n/).map((l) => l.trim());\n const separatorIndex = lines.indexOf(\"-\");\n\n if (separatorIndex === -1) {\n throw Error(\"Separator not found in talon list\");\n }\n\n const headerLines = lines.slice(0, separatorIndex);\n const bodyLines = trim(lines.slice(separatorIndex + 1));\n\n const result: TalonList = {\n headers: [],\n items: [],\n };\n\n for (const line of headerLines) {\n if (line.length === 0) {\n continue;\n }\n if (line.startsWith(\"#\")) {\n result.headers.push({ type: \"comment\", text: line });\n continue;\n }\n const [key, value] = splitLine(line);\n if (value == null) {\n throw Error(\"Header value missing\");\n }\n result.headers.push({ type: \"header\", key, value });\n }\n\n for (const line of bodyLines) {\n if (line.length === 0) {\n result.items.push({ type: \"empty\" });\n continue;\n }\n if (line.startsWith(\"#\")) {\n result.items.push({ type: \"comment\", text: line });\n continue;\n }\n const [key, value] = splitLine(line);\n result.items.push({ type: \"item\", key, value });\n }\n\n return result;\n}\n\nfunction splitLine(line: string): [string, string | undefined] {\n const index = line.indexOf(\":\");\n if (index === -1) {\n return [line, undefined];\n }\n return [\n line.substring(0, index).trimEnd(),\n line.substring(index + 1).trimStart(),\n ];\n}\n\nfunction trim(list: string[]): string[] {\n const startIndex = list.findIndex((l) => l.length > 0);\n if (startIndex < 0) {\n return [];\n }\n const endIndex = list.findLastIndex((l) => l.length > 0);\n return list.slice(startIndex, endIndex + 1);\n}\n", "import type { FormatterOptions } from \"../types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"../util/constants.js\";\nimport { getColumnWidth } from \"../util/getColumnWidth.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport { convertQuotes } from \"./convertQuotes.js\";\nimport { parseTalonList } from \"./parseTalonList.js\";\n\ntype Options = FormatterOptions<\n \"endOfLine\" | \"columnWidth\" | \"insertFinalNewline\"\n>;\n\nexport function talonListFormatter(\n text: string,\n options: Options = {},\n): string {\n const columnWidth = getColumnWidth(text) ?? options.columnWidth;\n const eol = getEndOfLine(options.endOfLine);\n const talonList = parseTalonList(text);\n talonList.headers.sort((a, _b) =>\n a.type === \"header\" && a.key === \"list\" ? -1 : 0,\n );\n const lines: string[] = [];\n\n for (const header of talonList.headers) {\n if (header.type === \"comment\") {\n lines.push(header.text);\n continue;\n }\n lines.push(`${header.key}: ${header.value}`);\n }\n\n lines.push(\"-\", \"\");\n\n for (const item of talonList.items) {\n if (item.type === \"empty\") {\n lines.push(\"\");\n continue;\n }\n if (item.type === \"comment\") {\n lines.push(item.text);\n continue;\n }\n if (item.value != null) {\n const keyWithColon =\n columnWidth != null\n ? `${item.key}: `.padEnd(columnWidth)\n : `${item.key}: `;\n const value = convertQuotes(item.value);\n lines.push(`${keyWithColon}${value}`);\n } else {\n lines.push(item.key);\n }\n }\n\n if (lines.length === 0) {\n return \"\";\n }\n\n if (options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE) {\n lines.push(\"\");\n }\n\n return lines.join(eol);\n}\n", "import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Node } from \"web-tree-sitter\";\nimport { Language, Parser } from \"web-tree-sitter\";\n\ntype ParserName = \"tree-sitter-talon\" | \"tree-sitter-query\";\n\nlet initPromise: Promise | undefined;\nconst languageCache = new Map>();\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\nfunction initTreeSitter() {\n initPromise ??= Parser.init();\n return initPromise;\n}\n\nfunction loadLanguage(parserName: ParserName) {\n let promise = languageCache.get(parserName);\n\n if (promise == null) {\n const wasmFilePath = getWasmFilePath(parserName);\n promise = Language.load(wasmFilePath);\n languageCache.set(parserName, promise);\n }\n\n return promise;\n}\n\nfunction getWasmFilePath(parserName: ParserName) {\n const fileName = `${parserName}.wasm`;\n const wasmFilePath = [\n path.join(\n moduleDir,\n \"../../node_modules/@cursorless/tree-sitter-wasms/out\",\n fileName,\n ),\n path.join(\n moduleDir,\n \"../node_modules/@cursorless/tree-sitter-wasms/out\",\n fileName,\n ),\n ].find((candidate) => fs.existsSync(candidate));\n\n if (wasmFilePath == null) {\n throw new Error(`Could not find ${fileName}`);\n }\n\n return wasmFilePath;\n}\n\nexport async function parseText(\n text: string,\n parserName: ParserName,\n): Promise {\n await initTreeSitter();\n\n const language = await loadLanguage(parserName);\n\n const parser = new Parser();\n parser.setLanguage(language);\n\n const tree = parser.parse(text);\n\n if (tree == null) {\n throw new Error(\"Failed to parse text\");\n }\n\n return tree.rootNode;\n}\n", "import getStdin from \"get-stdin\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as process from \"node:process\";\nimport type { Readable } from \"node:stream\";\nimport type { CLI, Logger, ParsedArgs } from \"../types.js\";\nimport { EXIT_ERROR, EXIT_FAIL, EXIT_OK } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { getErrorMessage } from \"../util/getErrorMessage.js\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\nimport { setExitCode } from \"./setExitCode.js\";\nimport { createLogger } from \"./createLogger.js\";\nimport { getOptionsFromConfig } from \"./getOptionsFromConfig.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\nimport { parseArgs } from \"./parseArgs.js\";\nimport { parseFilePatterns } from \"./parseFilePatterns.js\";\nimport { printHelp } from \"./printHelp.js\";\nimport { printVersion } from \"./printVersion.js\";\n\nexport async function main(cli: CLI): Promise {\n let logger = createLogger();\n\n try {\n const args = parseArgs(process.argv.slice(2));\n logger = createLogger(args.quiet);\n const exitCode = await mainUnsafe({ cli, args, logger });\n setExitCode(exitCode);\n } catch (error) {\n if (error instanceof FilePatternError) {\n for (const message of error.messages) {\n logger.error(message);\n }\n } else {\n logger.error(getErrorMessage(error));\n }\n setExitCode(EXIT_ERROR);\n }\n}\n\ninterface MainUnsafeArgs {\n cli: CLI;\n args: ParsedArgs;\n logger: Logger;\n}\n\nasync function mainUnsafe({\n cli,\n args,\n logger,\n}: MainUnsafeArgs): Promise {\n if (args.help) {\n printHelp(cli);\n return EXIT_OK;\n }\n\n if (args.version) {\n printVersion();\n return EXIT_OK;\n }\n\n const hasFilePatterns = args.filePatterns.length > 0;\n\n if (hasFilePatterns) {\n return mainFormatFiles({\n cli,\n logger,\n check: args.check,\n debug: args.debug,\n filePatterns: args.filePatterns,\n });\n }\n\n // If no file patterns are provided, check if there's input from stdin.\n // If stdin TTY it's an interactive terminal, so we shouldn't read from it.\n if (!process.stdin.isTTY) {\n return mainFormatStdin({\n cli,\n logger,\n stdin: process.stdin,\n check: args.check,\n debug: args.debug,\n });\n }\n\n throw new Error(\n \"No input files specified. Use --help for usage information.\",\n );\n}\n\ninterface MainFormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePatterns: string[];\n}\n\nasync function mainFormatFiles({\n cli,\n logger,\n check,\n debug,\n filePatterns,\n}: MainFormatFilesArgs): Promise {\n if (check) {\n logger.log(\"Checking formatting...\");\n }\n\n const filePaths = await parseFilePatterns(cli, filePatterns);\n const changedFileCount = await formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n });\n\n if (check) {\n if (changedFileCount > 0) {\n logger.warn(\n `Code style issues found in ${changedFileCount} file(s).`,\n );\n return EXIT_FAIL;\n }\n\n logger.log(\"All matched files use correct code style!\");\n return EXIT_OK;\n }\n\n return EXIT_OK;\n}\n\ninterface FormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePaths: string[];\n}\n\nexport async function formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n}: FormatFilesArgs): Promise {\n let changedFileCount = 0;\n\n for (const fileName of filePaths) {\n if (\n await formatFile({\n cli,\n logger,\n check,\n debug,\n filePath: fileName,\n })\n ) {\n changedFileCount++;\n }\n }\n\n return changedFileCount;\n}\n\ninterface FormatFileArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePath: string;\n}\n\nexport async function formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n}: FormatFileArgs): Promise {\n try {\n const options = await getOptionsFromConfig(filePath);\n const content = await fs.readFile(filePath, \"utf8\");\n const formatted = await cli.format(content, options, filePath, debug);\n\n if (formatted === content) {\n return false;\n }\n\n logger.log(getDisplayPath(filePath));\n\n if (!check) {\n await fs.writeFile(filePath, formatted, \"utf8\");\n }\n\n return true;\n } catch (error) {\n if (isMissingFileError(error)) {\n return false;\n }\n\n throw new Error(\n `Failed to format '${filePath}': ${getErrorMessage(error)}`,\n {\n cause: error,\n },\n );\n }\n}\n\nfunction getDisplayPath(filePath: string): string {\n return normalizeToPosix(path.relative(process.cwd(), filePath));\n}\n\ninterface MainFormatStdinArgs {\n cli: CLI;\n logger: Logger;\n stdin: Readable;\n check: boolean;\n debug: boolean;\n}\n\nexport async function mainFormatStdin({\n cli,\n logger,\n stdin,\n check,\n debug,\n}: MainFormatStdinArgs): Promise {\n const input = await getStdin({ stdin });\n const fileEnding = cli.getStdinFileEnding(input);\n const fileName = `stdin.${fileEnding}`;\n const filePath = path.resolve(fileName);\n const options = await getOptionsFromConfig(filePath);\n const formatted = await cli.format(input, options, filePath, debug);\n\n if (check) {\n if (input !== formatted) {\n logger.warn(\"Code style issues found in stdin.\");\n return EXIT_FAIL;\n }\n\n return EXIT_OK;\n }\n\n process.stdout.write(formatted);\n\n return EXIT_OK;\n}\n", "export class FilePatternError extends Error {\n name = \"FilePatternError\";\n\n constructor(public messages: string[]) {\n super(\n `One or more file pattern errors occurred:\\n${messages.join(\"\\n\")}`,\n );\n }\n}\n", "export function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n", "export function isMissingFileError(error: unknown) {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n", "export function setExitCode(code: number): void {\n Reflect.set(process, \"exitCode\", code);\n}\n", "import * as process from \"node:process\";\nimport type { WriteStream } from \"node:tty\";\nimport type { Logger, LoggerEntry, TestLogger } from \"../types.js\";\n\ntype LogCallback = (message: string) => void;\ntype ColorizeCallback = (message: string, color: string) => string;\ntype LoggerStream = Pick & Partial;\n\nconst ANSI_RESET = \"\\u001b[0m\";\nconst ANSI_YELLOW = \"\\u001b[33m\";\nconst ANSI_RED = \"\\u001b[31m\";\nconst WARN_PREFIX = \"[warn]\";\nconst ERROR_PREFIX = \"[error]\";\n\nexport function createLogger(quiet: boolean = false): Logger {\n return createLoggerFromStreams(process.stdout, process.stderr, quiet);\n}\n\nexport function createLoggerFromStreams(\n stdout: LoggerStream,\n stderr: LoggerStream,\n quiet: boolean = false,\n): Logger {\n const colorize: ColorizeCallback = shouldUseColor(stderr)\n ? (message, color) => `${color}${message}${ANSI_RESET}`\n : (message, _color) => message;\n\n let log: LogCallback;\n let warn: LogCallback;\n\n if (quiet) {\n log = () => {};\n warn = () => {};\n } else {\n log = (message: string) => {\n stdout.write(`${message}\\n`);\n };\n warn = (message: string) => {\n stderr.write(`${colorize(WARN_PREFIX, ANSI_YELLOW)} ${message}\\n`);\n };\n }\n\n return {\n log,\n warn,\n error(message: string) {\n stderr.write(`${colorize(ERROR_PREFIX, ANSI_RED)} ${message}\\n`);\n },\n };\n}\n\nexport function createTestLogger(): TestLogger {\n const entries: LoggerEntry[] = [];\n\n return {\n log(message: string) {\n entries.push({ level: \"log\", message });\n },\n warn(message: string) {\n entries.push({ level: \"warn\", message });\n },\n error(message: string) {\n entries.push({ level: \"error\", message });\n },\n getEntries() {\n return entries;\n },\n };\n}\n\nfunction shouldUseColor(stream: LoggerStream): boolean {\n if (\"NO_COLOR\" in process.env) {\n return false;\n }\n\n return stream.isTTY === true;\n}\n", "import * as editorconfig from \"editorconfig\";\nimport type { EditorConfigOptions, Options } from \"../types.js\";\n\nexport async function getOptionsFromConfig(filePath: string): Promise {\n const config = (await editorconfig.parse(filePath)) as EditorConfigOptions;\n\n const options: Options = {};\n\n if (config.indent_style === \"tab\") {\n options.indentTabs = true;\n } else if (config.indent_style === \"space\") {\n options.indentTabs = false;\n }\n\n if (typeof config.indent_size === \"number\") {\n options.indentSize = config.indent_size;\n } else if (\n config.indent_size === \"tab\" &&\n typeof config.tab_width === \"number\"\n ) {\n options.indentSize = config.tab_width;\n }\n\n if (typeof config.max_line_length === \"number\") {\n options.maxLineLength = config.max_line_length;\n }\n\n if (typeof config.column_width === \"number\") {\n options.columnWidth = config.column_width;\n }\n\n if (typeof config.insert_final_newline === \"boolean\") {\n options.insertFinalNewline = config.insert_final_newline;\n }\n\n if (typeof config.preserve_multiline === \"boolean\") {\n options.preserveMultiline = config.preserve_multiline;\n }\n\n if (config.end_of_line != null && config.end_of_line !== \"unset\") {\n options.endOfLine = config.end_of_line;\n }\n\n return options;\n}\n", "import * as path from \"node:path\";\n\n/**\n * Replace `\\` with `/` on Windows\n * @param {string} filepath\n * @returns {string}\n */\nexport const normalizeToPosix =\n path.sep === \"\\\\\"\n ? (filepath: string) => filepath.replaceAll(\"\\\\\", \"/\")\n : (filepath: string) => filepath;\n", "import type { ParsedArgs } from \"../types.js\";\n\nexport function getDefaultArguments(): ParsedArgs {\n return {\n filePatterns: [],\n help: false,\n version: false,\n quiet: false,\n debug: false,\n check: false,\n };\n}\n", "import type { KnownArgument, ParsedArgs } from \"../types.js\";\nimport { getDefaultArguments } from \"./getDefaultArguments.js\";\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const result = getDefaultArguments();\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === \"--\") {\n // All following arguments are treated as file patterns, even if they start with \"--\"\n result.filePatterns.push(...argv.slice(i + 1));\n break;\n }\n\n if (parseKnownArgument(result, arg as KnownArgument)) {\n continue;\n }\n\n if (arg.startsWith(\"--\")) {\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n result.filePatterns.push(arg);\n }\n\n return result;\n}\n\nfunction parseKnownArgument(result: ParsedArgs, arg: KnownArgument): boolean {\n switch (arg) {\n case \"--help\":\n result.help = true;\n return true;\n case \"--version\":\n result.version = true;\n return true;\n case \"--quiet\":\n result.quiet = true;\n return true;\n case \"--check\":\n result.check = true;\n return true;\n case \"--debug\":\n result.debug = true;\n return true;\n default:\n return false;\n }\n}\n", "import type { Options } from \"fast-glob\";\nimport fastGlob from \"fast-glob\";\nimport * as path from \"node:path\";\nimport type { CLI } from \"../types.js\";\nimport { GLOB_IGNORE_PATTERNS } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { lstatSafe } from \"./lstatSafe.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\n\nexport async function parseFilePatterns(\n cli: CLI,\n filePatterns: string[],\n): Promise {\n const seen: Set = new Set();\n const globFileEndingPattern = getGlobFileEndingsPattern(cli.fileEndings);\n const errorMessages: string[] = [];\n\n const globOptions: Options = {\n dot: true,\n followSymbolicLinks: false,\n ignore: GLOB_IGNORE_PATTERNS,\n };\n\n for (const pattern of filePatterns) {\n const absolutePath = path.resolve(pattern);\n const stat = await lstatSafe(absolutePath);\n\n if (stat != null) {\n if (stat.isSymbolicLink()) {\n errorMessages.push(\n `Specified pattern is a symbolic link: ${pattern}`,\n );\n continue;\n }\n\n if (stat.isFile()) {\n seen.add(absolutePath);\n continue;\n }\n\n if (stat.isDirectory()) {\n const files = await fastGlob(`**/*.${globFileEndingPattern}`, {\n ...globOptions,\n cwd: absolutePath,\n });\n if (files.length === 0) {\n errorMessages.push(\n `No matching files were found in the directory: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(absolutePath, file));\n }\n continue;\n }\n }\n\n const glob = normalizeToPosix(pattern);\n const files = (await fastGlob(glob, globOptions)).filter((file) =>\n hasSupportedFileEnding(file, cli.fileEndings),\n );\n if (files.length === 0) {\n errorMessages.push(\n `No files matching the pattern were found: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(file));\n }\n }\n\n if (errorMessages.length > 0) {\n throw new FilePatternError(errorMessages);\n }\n\n return Array.from(seen).sort((a, b) => a.localeCompare(b));\n}\n\nfunction getGlobFileEndingsPattern(fileEndings: readonly string[]): string {\n return fileEndings.length === 1\n ? fileEndings[0]\n : `{${fileEndings.join(\",\")}}`;\n}\n\nfunction hasSupportedFileEnding(\n file: string,\n fileEndings: readonly string[],\n): boolean {\n const extension = path.extname(file).slice(1);\n return fileEndings.includes(extension);\n}\n", "import type { Stats } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\n\nexport async function lstatSafe(filePath: string): Promise {\n try {\n return await fs.lstat(filePath);\n } catch (error) {\n if (isMissingFileError(error)) {\n return undefined;\n }\n\n throw error;\n }\n}\n", "import type { KnownProps } from \"editorconfig\";\n\nexport const KNOWN_ARGUMENTS = [\n \"--help\",\n \"--version\",\n \"--quiet\",\n \"--check\",\n \"--debug\",\n] as const;\n\nexport type KnownArgument = (typeof KNOWN_ARGUMENTS)[number];\n\nexport interface CLI {\n binName: \"snippet-fmt\" | \"talon-fmt\" | \"tree-sitter-fmt\";\n fileEndings: readonly string[];\n\n getStdinFileEnding(text: string): string;\n format(\n text: string,\n options: Options,\n filePath: string,\n debug: boolean,\n ): Promise;\n}\n\nexport type EndOfLine = \"lf\" | \"crlf\";\n\nexport interface Options {\n endOfLine?: EndOfLine;\n indentTabs?: boolean;\n indentSize?: number;\n maxLineLength?: number;\n columnWidth?: number;\n insertFinalNewline?: boolean;\n preserveMultiline?: boolean;\n}\n\nexport type FormatterOptions = Pick;\n\nexport interface ParsedArgs {\n filePatterns: string[];\n help: boolean;\n version: boolean;\n check: boolean;\n quiet: boolean;\n debug: boolean;\n}\n\nexport interface LoggerEntry {\n level: \"log\" | \"warn\" | \"error\";\n message: string;\n}\n\nexport interface Logger {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\nexport interface TestLogger extends Logger {\n getEntries(): readonly LoggerEntry[];\n}\n\nexport interface DebugLogger {\n debug(message: string): void;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport interface EditorConfigOptions extends KnownProps {\n max_line_length?: number | \"unset\";\n column_width?: number | \"unset\";\n preserve_multiline?: boolean | \"unset\";\n}\n\ninterface Point {\n row: number;\n column: number;\n}\n\nexport interface SyntaxNode {\n id: number;\n text: string;\n type: string;\n startPosition: Point;\n endPosition: Point;\n parent: SyntaxNode | null;\n children: SyntaxNode[];\n}\n", "import type { CLI } from \"../types.js\";\nimport { KNOWN_ARGUMENTS } from \"../types.js\";\n\nexport function printHelp(cli: CLI) {\n process.stdout.write(\n `Usage: ${cli.binName} [options] [file/dir/glob ...]\\n`,\n );\n process.stdout.write(\"\\n\");\n process.stdout.write(\"Options:\\n\");\n\n for (const option of KNOWN_ARGUMENTS) {\n process.stdout.write(` ${option}\\n`);\n }\n}\n", "{\n \"name\": \"@cursorless/talon-tools\",\n \"version\": \"0.9.0\",\n \"description\": \"Linting and formatting tools for Talon and Cursorless\",\n \"author\": \"Cursorless Dev\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"!dist/test\",\n \"!dist/build.*\"\n ],\n \"types\": \"./dist/lib.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/lib.d.ts\",\n \"default\": \"./dist/lib.js\"\n },\n \"./node\": {\n \"types\": \"./dist/node/libNode.d.ts\",\n \"default\": \"./dist/libNode.js\"\n }\n },\n \"bin\": {\n \"snippet-fmt\": \"dist/snippetFormatter.js\",\n \"talon-fmt\": \"dist/talonFormatter.js\",\n \"tree-sitter-fmt\": \"dist/treeSitterFormatter.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/cursorless-dev/talon-tools.git\"\n },\n \"funding\": \"https://github.com/sponsors/cursorless-dev\",\n \"sponsor\": {\n \"url\": \"https://github.com/sponsors/cursorless-dev\"\n },\n \"scripts\": {\n \"build\": \"npm run clean && tsc -p . && tsx ./src/build.ts\",\n \"clean\": \"rm -rf dist/*\",\n \"lint\": \"npm run lint:ts &&npm run lint:fmt\",\n \"lint:ts\": \"tsc -p . --noEmit && eslint src\",\n \"lint:fmt\": \"prettier --check .\",\n \"fix\": \"npm run fix:ts && npm run fix:fmt\",\n \"fix:ts\": \"eslint src --fix\",\n \"fix:fmt\": \"prettier --write --list-different .\",\n \"test\": \"tsx src/test/runAllTests.ts\",\n \"test:subset\": \"tsx src/test/runAllTests.ts --subset\"\n },\n \"dependencies\": {\n \"@cursorless/tree-sitter-wasms\": \"^0.7.0\",\n \"editorconfig\": \"^3.0.2\",\n \"fast-glob\": \"^3.3.3\",\n \"get-stdin\": \"^10.0.0\",\n \"web-tree-sitter\": \"^0.26.7\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.4\",\n \"@types/mocha\": \"^10.0.10\",\n \"@types/node\": \"^24.12.0\",\n \"esbuild\": \"^0.27.4\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-import\": \"^2.32.0\",\n \"eslint\": \"^9.39.4\",\n \"jiti\": \"^2.6.1\",\n \"mocha\": \"^11.7.5\",\n \"prettier\": \"^3.8.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript-eslint\": \"^8.57.1\",\n \"typescript\": \"^5.9.3\"\n }\n}\n", "import packageJson from \"../../package.json\" with { type: \"json\" };\n\nexport function printVersion() {\n process.stdout.write(`${packageJson.version}\\n`);\n}\n", "#!/usr/bin/env node\n\nimport { talonListFormatter } from \"../lib.js\";\nimport { talonFormatter } from \"../talon/talonFormatter.js\";\nimport { parseText } from \"./parseText.js\";\nimport { main } from \"./cli.js\";\n\nconst fileEndingTalon = \"talon\";\nconst fileEndingTalonList = \"talon-list\";\n\nvoid main({\n binName: \"talon-fmt\",\n fileEndings: [fileEndingTalon, fileEndingTalonList],\n\n getStdinFileEnding(text) {\n return textIsList(text) ? fileEndingTalonList : fileEndingTalon;\n },\n\n format: async (text, options, filePath, debug) => {\n if (isListFile(text, filePath)) {\n const updated = talonListFormatter(text, options);\n return Promise.resolve(updated);\n }\n\n const node = await parseText(text, \"tree-sitter-talon\");\n return talonFormatter(node, options, debug);\n },\n});\n\nfunction isListFile(text: string, filePath: string): boolean {\n if (filePath.endsWith(\".talon\")) {\n return false;\n }\n if (filePath.endsWith(\".talon-list\")) {\n return true;\n }\n return textIsList(text);\n}\n\nfunction textIsList(text: string): boolean {\n return text.trimStart().startsWith(\"list:\");\n}\n"], - "mappings": "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", - "names": ["IGNORE_FOLDERS", "GLOB_IGNORE_PATTERNS", "pattern", "getEndOfLine", "eof", "createDebugLogger", "debug", "message", "getColumnWidth", "text", "match", "getIndentation", "indentTabs", "indentSize", "convertQuotes", "text", "talonFormatter", "node", "options", "debug", "columnWidth", "getColumnWidth", "indentation", "getIndentation", "eol", "getEndOfLine", "TalonFormatter", "indent", "maxLineLength", "insertFinalNewline", "preserveMultiline", "createDebugLogger", "result", "isIndented", "isFirstChild", "text", "nodeText", "rangeEqual", "n", "formatString", "unwrap", "children", "middle", "pre", "post", "forceMultiline", "leftNode", "_colonNode", "rightNodes", "left", "isLeftRightSingleLine", "rightNode", "right", "leftWithPadding", "rights", "a", "b", "convertQuotes", "parseTalonList", "text", "lines", "l", "separatorIndex", "headerLines", "bodyLines", "trim", "result", "line", "key", "value", "splitLine", "index", "list", "startIndex", "endIndex", "talonListFormatter", "text", "options", "columnWidth", "getColumnWidth", "eol", "getEndOfLine", "talonList", "parseTalonList", "a", "_b", "lines", "header", "item", "keyWithColon", "value", "convertQuotes", "fs", "path", "fileURLToPath", "Language", "Parser", "initPromise", "languageCache", "moduleDir", "initTreeSitter", "loadLanguage", "parserName", "promise", "wasmFilePath", "getWasmFilePath", "fileName", "candidate", "parseText", "text", "language", "parser", "tree", "getStdin", "fs", "path", "process", "FilePatternError", "messages", "getErrorMessage", "error", "isMissingFileError", "error", "setExitCode", "code", "process", "ANSI_RESET", "ANSI_YELLOW", "ANSI_RED", "WARN_PREFIX", "ERROR_PREFIX", "createLogger", "quiet", "createLoggerFromStreams", "stdout", "stderr", "colorize", "shouldUseColor", "message", "color", "_color", "log", "warn", "shouldUseColor", "stream", "editorconfig", "getOptionsFromConfig", "filePath", "config", "options", "path", "normalizeToPosix", "filepath", "getDefaultArguments", "parseArgs", "argv", "result", "getDefaultArguments", "i", "arg", "parseKnownArgument", "fastGlob", "path", "fs", "lstatSafe", "filePath", "error", "isMissingFileError", "parseFilePatterns", "cli", "filePatterns", "seen", "globFileEndingPattern", "getGlobFileEndingsPattern", "errorMessages", "globOptions", "GLOB_IGNORE_PATTERNS", "pattern", "absolutePath", "stat", "lstatSafe", "files", "fastGlob", "file", "glob", "normalizeToPosix", "hasSupportedFileEnding", "FilePatternError", "a", "b", "fileEndings", "extension", "KNOWN_ARGUMENTS", "printHelp", "cli", "option", "KNOWN_ARGUMENTS", "package_default", "printVersion", "package_default", "main", "cli", "logger", "createLogger", "args", "parseArgs", "exitCode", "mainUnsafe", "setExitCode", "error", "FilePatternError", "message", "getErrorMessage", "printHelp", "printVersion", "mainFormatFiles", "mainFormatStdin", "check", "debug", "filePatterns", "filePaths", "parseFilePatterns", "changedFileCount", "formatFiles", "fileName", "formatFile", "filePath", "options", "getOptionsFromConfig", "content", "formatted", "getDisplayPath", "isMissingFileError", "normalizeToPosix", "stdin", "input", "getStdin", "fileEndingTalon", "fileEndingTalonList", "main", "text", "textIsList", "options", "filePath", "debug", "isListFile", "updated", "talonListFormatter", "node", "parseText", "talonFormatter"] + "sources": ["../src/util/constants.ts", "../src/util/getEndOfLine.ts", "../src/util/createDebugLogger.ts", "../src/util/getColumnWidth.ts", "../src/util/getIndentation.ts", "../src/util/SyntaxError.ts", "../src/util/SyntaxTreeError.ts", "../src/talon/convertQuotes.ts", "../src/talon/talonFormatter.ts", "../src/talon/parseTalonList.ts", "../src/talon/talonListFormatter.ts", "../src/node/parseText.ts", "../src/node/cli.ts", "../src/util/getErrorMessage.ts", "../src/node/createLogger.ts", "../src/node/FilePatternError.ts", "../src/node/getOptionsFromConfig.ts", "../src/node/isMissingFileError.ts", "../src/node/normalizeToPosix.ts", "../src/node/getDefaultArguments.ts", "../src/node/parseArgs.ts", "../src/node/parseFilePatterns.ts", "../src/node/lstatSafe.ts", "../src/types.ts", "../src/node/printHelp.ts", "../package.json", "../src/node/printVersion.ts", "../src/node/setExitCode.ts", "../src/node/talonFormatter.ts"], + "sourcesContent": ["// Exit code 0: Success\nexport const EXIT_OK = 0;\n// Exit code 1: Check failed\nexport const EXIT_FAIL = 1;\n// Exit code 2: Unexpected error\nexport const EXIT_ERROR = 2;\n\nexport type ExitCode = typeof EXIT_OK | typeof EXIT_FAIL | typeof EXIT_ERROR;\n\nexport const DEFAULT_INDENT_WIDTH = 4;\nexport const DEFAULT_MAX_LINE_LENGTH = 80;\nexport const DEFAULT_INSERT_FINAL_NEWLINE = true;\n\nexport const IGNORE_FOLDERS = [\n \".git\",\n \".svn\",\n \".hg\",\n \"node_modules\",\n \"__pycache__\",\n];\n\nexport const GLOB_IGNORE_PATTERNS = IGNORE_FOLDERS.map(\n (pattern) => `**/${pattern}/**`,\n);\n", "import type { EndOfLine } from \"../types.js\";\n\nexport function getEndOfLine(eof?: EndOfLine): string {\n return eof === \"crlf\" ? \"\\r\\n\" : \"\\n\";\n}\n", "import type { DebugLogger } from \"../types.js\";\n\nexport function createDebugLogger(debug: boolean): DebugLogger {\n return {\n debug(message: string) {\n if (debug) {\n console.warn(`[debug] ${message}`);\n }\n },\n };\n}\n", "export function getColumnWidth(text: string): number | undefined {\n const match = text.match(/# fmt: columnWidth=(\\d+)/);\n\n if (match != null) {\n return parseInt(match[1], 10);\n }\n\n return undefined;\n}\n", "import { DEFAULT_INDENT_WIDTH } from \"./constants.js\";\n\nexport function getIndentation(\n indentTabs: boolean | undefined,\n indentSize: number | undefined,\n): string {\n return indentTabs ? \"\\t\" : \" \".repeat(indentSize ?? DEFAULT_INDENT_WIDTH);\n}\n", "import type { Point } from \"../types.js\";\n\nexport class SyntaxError extends Error {\n constructor(private location?: Point) {\n super(\"Syntax error.\");\n this.name = \"SyntaxError\";\n }\n\n getLocation(): string | undefined {\n return this.location != null\n ? `(${this.location.row + 1}:${this.location.column + 1})`\n : undefined;\n }\n}\n\nexport function isSyntaxError(error: unknown): error is SyntaxError {\n return error instanceof SyntaxError;\n}\n", "import type { SyntaxNode } from \"../types.js\";\nimport { SyntaxError } from \"./SyntaxError.js\";\n\nexport class SyntaxTreeError extends SyntaxError {\n constructor(rootNode: SyntaxNode) {\n super(findFirstProblemNode(rootNode)?.startPosition);\n this.name = \"SyntaxTreeError\";\n }\n}\n\nfunction findFirstProblemNode(node: SyntaxNode): SyntaxNode | null {\n if (node.isError || node.isMissing) {\n return node;\n }\n for (const child of node.children) {\n if (!child.hasError) {\n continue;\n }\n const errorNode = findFirstProblemNode(child);\n if (errorNode != null) {\n return errorNode;\n }\n }\n return null;\n}\n", "export function convertQuotes(text: string): string {\n // Convert single quotes to double quotes\n if (\n text.length > 0 &&\n text[0] === \"'\" &&\n text[text.length - 1] === \"'\" &&\n !text.includes('\"')\n ) {\n const innerText = text.slice(1, -1).replaceAll(\"\\\\'\", \"'\");\n return `\"${innerText}\"`;\n }\n\n return text;\n}\n", "import type { DebugLogger, FormatterOptions, SyntaxNode } from \"../types.js\";\nimport {\n DEFAULT_INSERT_FINAL_NEWLINE,\n DEFAULT_MAX_LINE_LENGTH,\n} from \"../util/constants.js\";\nimport { createDebugLogger } from \"../util/createDebugLogger.js\";\nimport { getColumnWidth } from \"../util/getColumnWidth.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport { getIndentation } from \"../util/getIndentation.js\";\nimport { SyntaxTreeError } from \"../util/SyntaxTreeError.js\";\nimport { convertQuotes } from \"./convertQuotes.js\";\n\nexport type Options = FormatterOptions<\n | \"endOfLine\"\n | \"indentTabs\"\n | \"indentSize\"\n | \"maxLineLength\"\n | \"columnWidth\"\n | \"insertFinalNewline\"\n | \"preserveMultiline\"\n>;\n\nexport function talonFormatter(\n node: SyntaxNode,\n options: Options = {},\n debug: boolean = false,\n): string {\n if (node.hasError) {\n throw new SyntaxTreeError(node);\n }\n\n const columnWidth = getColumnWidth(node.text) ?? options.columnWidth;\n const indentation = getIndentation(options.indentTabs, options.indentSize);\n const eol = getEndOfLine(options.endOfLine);\n const formatter = new TalonFormatter(\n indentation,\n eol,\n options.maxLineLength ?? DEFAULT_MAX_LINE_LENGTH,\n columnWidth,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n options.preserveMultiline ?? false,\n debug,\n );\n return formatter.getText(node);\n}\n\nclass TalonFormatter {\n private lines: string[] = [];\n private lastRow = 0;\n private logger: DebugLogger;\n\n constructor(\n private indent: string,\n private eol: string,\n private maxLineLength: number,\n private columnWidth: number | undefined,\n private insertFinalNewline: boolean,\n private preserveMultiline: boolean,\n debug: boolean,\n ) {\n this.logger = createDebugLogger(debug);\n }\n\n getText(node: SyntaxNode): string {\n this.addNode(node);\n\n const result = this.lines.join(this.eol).trimEnd();\n\n if (result.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return result + this.eol;\n }\n\n return result;\n }\n\n private addNL(): void {\n if (this.lines[this.lines.length - 1] !== \"\") {\n this.lines.push(\"\");\n }\n }\n\n private addNode(node: SyntaxNode, isIndented = false): void {\n if (node.startPosition.row > this.lastRow + 1) {\n this.addNL();\n }\n this.lastRow = node.endPosition.row;\n this.addNodeHelper(node, isIndented);\n this.lastRow = node.endPosition.row;\n }\n\n private addNodeHelper(node: SyntaxNode, isIndented = false): void {\n switch (node.type) {\n case \"source_file\":\n for (const n of node.children) {\n this.addNode(n);\n }\n break;\n\n case \"matches\": {\n // There are match nodes or there is a comment before\n if (node.children.length > 1 || !isFirstChild(node)) {\n for (const n of node.children) {\n this.addNode(n);\n }\n this.addNL();\n }\n break;\n }\n\n case \"declarations\":\n for (const n of node.children) {\n this.addNode(n);\n }\n break;\n\n case \"block\":\n for (const n of node.children) {\n this.addNode(n, true);\n }\n break;\n\n case \"command_declaration\":\n case \"key_binding_declaration\":\n case \"parrot_declaration\":\n case \"noise_declaration\":\n case \"face_declaration\":\n case \"gamepad_declaration\":\n case \"deck_declaration\":\n this.addLeftRightNode(node, false);\n break;\n\n case \"settings_declaration\":\n if (\n this.lines.length > 0 &&\n !this.lines[this.lines.length - 1].startsWith(\"#\")\n ) {\n this.addNL();\n }\n this.addLeftRightNode(node, true);\n this.addNL();\n break;\n\n case \"comment\": {\n // When using crlf eol comments have a trailing `\\r`\n const text = node.text.trimEnd();\n const nodeText =\n isIndented || node.startPosition.column > 0\n ? `${this.indent}${text}`\n : text;\n this.lines.push(nodeText);\n break;\n }\n\n default: {\n const nodeText = this.getNodeText(node);\n this.lines.push(\n isIndented ? `${this.indent}${nodeText}` : nodeText,\n );\n }\n }\n }\n\n private getNodeText(node: SyntaxNode): string {\n switch (node.type) {\n case \"source_file\":\n case \"matches\":\n case \"declarations\":\n case \"block\":\n case \"command_declaration\":\n case \"key_binding_declaration\":\n case \"parrot_declaration\":\n case \"noise_declaration\":\n case \"face_declaration\":\n case \"gamepad_declaration\":\n case \"deck_declaration\":\n case \"settings_declaration\":\n case \"comment\":\n throw new Error(\n `Node type '${node.type}' should be handled in addNode, not getNodeText`,\n );\n\n case \"parenthesized_rule\":\n return this.pairWithChildren(\n node,\n node.parent != null && rangeEqual(node, node.parent),\n );\n\n case \"optional\":\n return this.pairWithChildren(node);\n\n case \"expression_statement\":\n case \"assignment_statement\":\n case \"seq\":\n case \"choice\":\n return node.children.map((n) => this.getNodeText(n)).join(\" \");\n\n case \"rule\":\n case \"action\":\n case \"key_action\":\n case \"sleep_action\":\n case \"argument_list\":\n case \"key_binding\":\n case \"face_binding\":\n case \"gamepad_binding\":\n case \"parrot_binding\":\n case \"noise_binding\":\n case \"deck_binding\":\n case \"tag_import_declaration\":\n case \"match\":\n return node.children.map((n) => this.getNodeText(n)).join(\"\");\n\n case \"string\":\n return formatString(node);\n\n case \"match_modifier\":\n case \":\":\n case \",\":\n return `${node.text} `;\n\n case \"implicit_string\":\n return node.text.trim();\n\n case \"tag_binding\":\n case \"settings_binding\":\n case \"capture\":\n case \"list\":\n case \"key(\":\n case \"sleep(\":\n case \"gamepad(\":\n case \"face(\":\n case \"parrot(\":\n case \"noise(\":\n case \"identifier\":\n case \"variable\":\n case \"word\":\n case \"binary_operator\":\n case \"integer\":\n case \"float\":\n case \"start_anchor\":\n case \"end_anchor\":\n case \"repeat\":\n case \"deck(\":\n case \"repeat1\":\n case \"(\":\n case \")\":\n case \"=\":\n case \"-\":\n case \"|\":\n return node.text;\n\n default:\n this.logger.debug(`Unknown syntax node type '${node.type}'`);\n return node.text;\n }\n }\n\n private pairWithChildren(\n node: SyntaxNode,\n unwrap: boolean = false,\n ): string {\n const { children } = node;\n const middle = children\n .slice(1, -1)\n .map((n) => this.getNodeText(n))\n .join(\" \");\n if (unwrap) {\n return middle;\n }\n const pre = children[0].text;\n const post = children[children.length - 1].text;\n return `${pre}${middle}${post}`;\n }\n\n private addLeftRightNode(node: SyntaxNode, forceMultiline: boolean): void {\n const [leftNode, _colonNode, ...rightNodes] = node.children;\n const left = this.getNodeText(leftNode);\n\n if (!forceMultiline && rightNodes.length === 1) {\n if (\n !this.preserveMultiline ||\n isLeftRightSingleLine(leftNode, rightNodes)\n ) {\n const rightNode = rightNodes[0];\n if (rightNode.children.length === 1) {\n const right = this.getNodeText(rightNode.children[0]);\n const leftWithPadding =\n this.columnWidth != null\n ? `${left}: `.padEnd(this.columnWidth)\n : `${left}: `;\n if (\n leftWithPadding.length + right.length <=\n this.maxLineLength\n ) {\n this.lines.push(leftWithPadding + right);\n return;\n }\n }\n }\n }\n\n this.lines.push(`${left}:`);\n\n for (const n of rightNodes) {\n this.addNode(n, true);\n }\n }\n}\n\nfunction isLeftRightSingleLine(\n left: SyntaxNode,\n rights: SyntaxNode[],\n): boolean {\n return left.endPosition.row === rights[rights.length - 1].startPosition.row;\n}\n\nfunction rangeEqual(a: SyntaxNode, b: SyntaxNode): boolean {\n return (\n a.startPosition.row === b.startPosition.row &&\n a.startPosition.column === b.startPosition.column &&\n a.endPosition.row === b.endPosition.row &&\n a.endPosition.column === b.endPosition.column\n );\n}\n\nfunction isFirstChild(node: SyntaxNode): boolean {\n return node.id === node.parent?.children?.[0]?.id;\n}\n\nfunction formatString(node: SyntaxNode): string {\n // Convert single quotes to double quotes\n const text = convertQuotes(node.text);\n\n // A single string literal is allowed as syntactic sugar for the insert\n // action, but not in combination with other sibling statements.\n if (\n node.parent?.type === \"expression_statement\" &&\n node.parent.parent?.type === \"block\" &&\n rangeEqual(node, node.parent) &&\n node.parent.parent.children.length > 1\n ) {\n return `insert(${text})`;\n }\n\n return text;\n}\n", "interface TalonListHeader {\n type: \"header\";\n key: string;\n value: string;\n}\n\ninterface TalonListItem {\n type: \"item\";\n key: string;\n value?: string;\n}\n\ninterface EmptyLine {\n type: \"empty\";\n}\n\ninterface CommentLine {\n type: \"comment\";\n text: string;\n}\n\nexport interface TalonList {\n headers: (TalonListHeader | CommentLine)[];\n items: (TalonListItem | CommentLine | EmptyLine)[];\n}\n\nexport function parseTalonList(text: string): TalonList {\n const lines = text.split(/\\r?\\n/).map((l) => l.trim());\n const separatorIndex = lines.indexOf(\"-\");\n\n if (separatorIndex === -1) {\n throw Error(\"Separator not found in talon list\");\n }\n\n const headerLines = lines.slice(0, separatorIndex);\n const bodyLines = trim(lines.slice(separatorIndex + 1));\n\n const result: TalonList = {\n headers: [],\n items: [],\n };\n\n for (const line of headerLines) {\n if (line.length === 0) {\n continue;\n }\n if (line.startsWith(\"#\")) {\n result.headers.push({ type: \"comment\", text: line });\n continue;\n }\n const [key, value] = splitLine(line);\n if (value == null) {\n throw Error(\"Header value missing\");\n }\n result.headers.push({ type: \"header\", key, value });\n }\n\n for (const line of bodyLines) {\n if (line.length === 0) {\n result.items.push({ type: \"empty\" });\n continue;\n }\n if (line.startsWith(\"#\")) {\n result.items.push({ type: \"comment\", text: line });\n continue;\n }\n const [key, value] = splitLine(line);\n result.items.push({ type: \"item\", key, value });\n }\n\n return result;\n}\n\nfunction splitLine(line: string): [string, string | undefined] {\n const index = line.indexOf(\":\");\n if (index === -1) {\n return [line, undefined];\n }\n return [\n line.substring(0, index).trimEnd(),\n line.substring(index + 1).trimStart(),\n ];\n}\n\nfunction trim(list: string[]): string[] {\n const startIndex = list.findIndex((l) => l.length > 0);\n if (startIndex < 0) {\n return [];\n }\n const endIndex = list.findLastIndex((l) => l.length > 0);\n return list.slice(startIndex, endIndex + 1);\n}\n", "import type { FormatterOptions } from \"../types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"../util/constants.js\";\nimport { getColumnWidth } from \"../util/getColumnWidth.js\";\nimport { getEndOfLine } from \"../util/getEndOfLine.js\";\nimport { convertQuotes } from \"./convertQuotes.js\";\nimport { parseTalonList } from \"./parseTalonList.js\";\n\ntype Options = FormatterOptions<\n \"endOfLine\" | \"columnWidth\" | \"insertFinalNewline\"\n>;\n\nexport function talonListFormatter(\n text: string,\n options: Options = {},\n): string {\n const columnWidth = getColumnWidth(text) ?? options.columnWidth;\n const eol = getEndOfLine(options.endOfLine);\n const talonList = parseTalonList(text);\n talonList.headers.sort((a, _b) =>\n a.type === \"header\" && a.key === \"list\" ? -1 : 0,\n );\n const lines: string[] = [];\n\n for (const header of talonList.headers) {\n if (header.type === \"comment\") {\n lines.push(header.text);\n continue;\n }\n lines.push(`${header.key}: ${header.value}`);\n }\n\n lines.push(\"-\", \"\");\n\n for (const item of talonList.items) {\n if (item.type === \"empty\") {\n lines.push(\"\");\n continue;\n }\n if (item.type === \"comment\") {\n lines.push(item.text);\n continue;\n }\n if (item.value != null) {\n const keyWithColon =\n columnWidth != null\n ? `${item.key}: `.padEnd(columnWidth)\n : `${item.key}: `;\n const value = convertQuotes(item.value);\n lines.push(`${keyWithColon}${value}`);\n } else {\n lines.push(item.key);\n }\n }\n\n if (lines.length === 0) {\n return \"\";\n }\n\n if (options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE) {\n lines.push(\"\");\n }\n\n return lines.join(eol);\n}\n", "import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Node } from \"web-tree-sitter\";\nimport { Language, Parser } from \"web-tree-sitter\";\n\ntype ParserName = \"tree-sitter-talon\" | \"tree-sitter-query\";\n\nlet initPromise: Promise | undefined;\nconst languageCache = new Map>();\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\nfunction initTreeSitter() {\n initPromise ??= Parser.init();\n return initPromise;\n}\n\nfunction loadLanguage(parserName: ParserName) {\n let promise = languageCache.get(parserName);\n\n if (promise == null) {\n const wasmFilePath = getWasmFilePath(parserName);\n promise = Language.load(wasmFilePath);\n languageCache.set(parserName, promise);\n }\n\n return promise;\n}\n\nfunction getWasmFilePath(parserName: ParserName) {\n const fileName = `${parserName}.wasm`;\n const wasmFilePath = [\n path.join(\n moduleDir,\n \"../../node_modules/@cursorless/tree-sitter-wasms/out\",\n fileName,\n ),\n path.join(\n moduleDir,\n \"../node_modules/@cursorless/tree-sitter-wasms/out\",\n fileName,\n ),\n ].find((candidate) => fs.existsSync(candidate));\n\n if (wasmFilePath == null) {\n throw new Error(`Could not find ${fileName}`);\n }\n\n return wasmFilePath;\n}\n\nexport async function parseText(\n text: string,\n parserName: ParserName,\n): Promise {\n await initTreeSitter();\n\n const language = await loadLanguage(parserName);\n\n const parser = new Parser();\n parser.setLanguage(language);\n\n const tree = parser.parse(text);\n\n if (tree == null) {\n throw new Error(\"Failed to parse text\");\n }\n\n return tree.rootNode;\n}\n", "import getStdin from \"get-stdin\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as process from \"node:process\";\nimport type { Readable } from \"node:stream\";\nimport type { CLI, Logger, ParsedArgs } from \"../types.js\";\nimport {\n EXIT_ERROR,\n EXIT_FAIL,\n EXIT_OK,\n type ExitCode,\n} from \"../util/constants.js\";\nimport { getErrorMessage } from \"../util/getErrorMessage.js\";\nimport { isSyntaxError } from \"../util/SyntaxError.js\";\nimport { createLogger } from \"./createLogger.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { getOptionsFromConfig } from \"./getOptionsFromConfig.js\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\nimport { parseArgs } from \"./parseArgs.js\";\nimport { parseFilePatterns } from \"./parseFilePatterns.js\";\nimport { printHelp } from \"./printHelp.js\";\nimport { printVersion } from \"./printVersion.js\";\nimport { setExitCode } from \"./setExitCode.js\";\n\nexport async function main(cli: CLI): Promise {\n let logger = createLogger();\n\n try {\n const args = parseArgs(process.argv.slice(2));\n logger = createLogger(args.quiet);\n const exitCode = await mainUnsafe({ cli, args, logger });\n setExitCode(exitCode);\n } catch (error) {\n if (error instanceof FilePatternError) {\n for (const message of error.messages) {\n logger.error(message);\n }\n } else {\n logger.error(getErrorMessage(error));\n }\n setExitCode(EXIT_ERROR);\n }\n}\n\ninterface MainUnsafeArgs {\n cli: CLI;\n args: ParsedArgs;\n logger: Logger;\n}\n\nasync function mainUnsafe({\n cli,\n args,\n logger,\n}: MainUnsafeArgs): Promise {\n if (args.help) {\n printHelp(cli);\n return EXIT_OK;\n }\n\n if (args.version) {\n printVersion();\n return EXIT_OK;\n }\n\n const hasFilePatterns = args.filePatterns.length > 0;\n\n if (hasFilePatterns) {\n return mainFormatFiles({\n cli,\n logger,\n check: args.check,\n debug: args.debug,\n filePatterns: args.filePatterns,\n });\n }\n\n // If no file patterns are provided, check if there's input from stdin.\n // If stdin TTY it's an interactive terminal, so we shouldn't read from it.\n if (!process.stdin.isTTY) {\n return mainFormatStdin({\n cli,\n logger,\n stdin: process.stdin,\n check: args.check,\n debug: args.debug,\n });\n }\n\n throw new Error(\n \"No input files specified. Use --help for usage information.\",\n );\n}\n\ninterface MainFormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePatterns: string[];\n}\n\nasync function mainFormatFiles({\n cli,\n logger,\n check,\n debug,\n filePatterns,\n}: MainFormatFilesArgs): Promise {\n if (check) {\n logger.log(\"Checking formatting...\");\n }\n\n const filePaths = await parseFilePatterns(cli, filePatterns);\n const [changedFileCount, hasError] = await formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n });\n\n if (check) {\n if (changedFileCount > 0) {\n logger.warn(\n `Code style issues found in ${changedFileCount} file(s).`,\n );\n if (!hasError) {\n return EXIT_FAIL;\n }\n }\n\n if (!hasError) {\n logger.log(\"All matched files use correct code style!\");\n }\n }\n\n if (hasError) {\n return EXIT_ERROR;\n }\n\n return EXIT_OK;\n}\n\ninterface FormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePaths: string[];\n}\n\nexport async function formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n}: FormatFilesArgs): Promise<[number, boolean]> {\n let changedFileCount = 0;\n let hasError = false;\n\n for (const filePath of filePaths) {\n try {\n const fileWasChanged = await formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n });\n if (fileWasChanged) {\n changedFileCount++;\n }\n } catch (error) {\n if (isSyntaxError(error)) {\n logger.error(\n `${getDisplayPath(filePath)}${error.getLocation()}: ${error.message}`,\n );\n } else {\n logger.error(\n `${getDisplayPath(filePath)}: ${getErrorMessage(error)}`,\n );\n }\n hasError = true;\n }\n }\n\n return [changedFileCount, hasError];\n}\n\ninterface FormatFileArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePath: string;\n}\n\nexport async function formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n}: FormatFileArgs): Promise {\n try {\n const options = await getOptionsFromConfig(filePath);\n const content = await fs.readFile(filePath, \"utf8\");\n const formatted = await cli.format(content, options, filePath, debug);\n\n if (formatted === content) {\n return false;\n }\n\n logger.log(getDisplayPath(filePath));\n\n if (!check) {\n await fs.writeFile(filePath, formatted, \"utf8\");\n }\n\n return true;\n } catch (error) {\n if (isMissingFileError(error)) {\n return false;\n }\n\n throw error;\n }\n}\n\nfunction getDisplayPath(filePath: string): string {\n return normalizeToPosix(path.relative(process.cwd(), filePath));\n}\n\ninterface MainFormatStdinArgs {\n cli: CLI;\n logger: Logger;\n stdin: Readable;\n check: boolean;\n debug: boolean;\n}\n\nexport async function mainFormatStdin({\n cli,\n logger,\n stdin,\n check,\n debug,\n}: MainFormatStdinArgs): Promise {\n const input = await getStdin({ stdin });\n const fileEnding = cli.getStdinFileEnding(input);\n const fauxFileName = `stdin.${fileEnding}`;\n const fauxFilePath = path.resolve(fauxFileName);\n const options = await getOptionsFromConfig(fauxFilePath);\n let formatted: string;\n\n try {\n formatted = await cli.format(input, options, fauxFilePath, debug);\n } catch (error) {\n if (isSyntaxError(error)) {\n logger.error(`stdin${error.getLocation()}: ${error.message}`);\n return EXIT_ERROR;\n }\n throw error;\n }\n\n if (check) {\n if (input !== formatted) {\n logger.warn(\"Code style issues found in stdin.\");\n return EXIT_FAIL;\n }\n\n return EXIT_OK;\n }\n\n process.stdout.write(formatted);\n\n return EXIT_OK;\n}\n", "export function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n", "import * as process from \"node:process\";\nimport type { WriteStream } from \"node:tty\";\nimport type { Logger, LoggerEntry, TestLogger } from \"../types.js\";\n\ntype LogCallback = (message: string) => void;\ntype ColorizeCallback = (message: string, color: string) => string;\ntype LoggerStream = Pick & Partial;\n\nconst ANSI_RESET = \"\\u001b[0m\";\nconst ANSI_YELLOW = \"\\u001b[33m\";\nconst ANSI_RED = \"\\u001b[31m\";\nconst WARN_PREFIX = \"[warn]\";\nconst ERROR_PREFIX = \"[error]\";\n\nexport function createLogger(quiet: boolean = false): Logger {\n return createLoggerFromStreams(process.stdout, process.stderr, quiet);\n}\n\nexport function createLoggerFromStreams(\n stdout: LoggerStream,\n stderr: LoggerStream,\n quiet: boolean = false,\n): Logger {\n const colorize: ColorizeCallback = shouldUseColor(stderr)\n ? (message, color) => `${color}${message}${ANSI_RESET}`\n : (message, _color) => message;\n\n let log: LogCallback;\n let warn: LogCallback;\n\n if (quiet) {\n log = () => {};\n warn = () => {};\n } else {\n log = (message: string) => {\n stdout.write(`${message}\\n`);\n };\n warn = (message: string) => {\n stderr.write(`${colorize(WARN_PREFIX, ANSI_YELLOW)} ${message}\\n`);\n };\n }\n\n return {\n log,\n warn,\n error(message: string) {\n stderr.write(`${colorize(ERROR_PREFIX, ANSI_RED)} ${message}\\n`);\n },\n };\n}\n\nexport function createTestLogger(): TestLogger {\n const entries: LoggerEntry[] = [];\n\n return {\n log(message: string) {\n entries.push({ level: \"log\", message });\n },\n warn(message: string) {\n entries.push({ level: \"warn\", message });\n },\n error(message: string) {\n entries.push({ level: \"error\", message });\n },\n getEntries() {\n return entries;\n },\n };\n}\n\nfunction shouldUseColor(stream: LoggerStream): boolean {\n if (\"NO_COLOR\" in process.env) {\n return false;\n }\n\n return stream.isTTY === true;\n}\n", "export class FilePatternError extends Error {\n name = \"FilePatternError\";\n\n constructor(public messages: string[]) {\n super(\n `One or more file pattern errors occurred:\\n${messages.join(\"\\n\")}`,\n );\n }\n}\n", "import * as editorconfig from \"editorconfig\";\nimport type { EditorConfigOptions, Options } from \"../types.js\";\n\nexport async function getOptionsFromConfig(filePath: string): Promise {\n const config = (await editorconfig.parse(filePath)) as EditorConfigOptions;\n\n const options: Options = {};\n\n if (config.indent_style === \"tab\") {\n options.indentTabs = true;\n } else if (config.indent_style === \"space\") {\n options.indentTabs = false;\n }\n\n if (typeof config.indent_size === \"number\") {\n options.indentSize = config.indent_size;\n } else if (\n config.indent_size === \"tab\" &&\n typeof config.tab_width === \"number\"\n ) {\n options.indentSize = config.tab_width;\n }\n\n if (typeof config.max_line_length === \"number\") {\n options.maxLineLength = config.max_line_length;\n }\n\n if (typeof config.column_width === \"number\") {\n options.columnWidth = config.column_width;\n }\n\n if (typeof config.insert_final_newline === \"boolean\") {\n options.insertFinalNewline = config.insert_final_newline;\n }\n\n if (typeof config.preserve_multiline === \"boolean\") {\n options.preserveMultiline = config.preserve_multiline;\n }\n\n if (config.end_of_line != null && config.end_of_line !== \"unset\") {\n options.endOfLine = config.end_of_line;\n }\n\n return options;\n}\n", "export function isMissingFileError(\n error: unknown,\n): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n", "import * as path from \"node:path\";\n\n/**\n * Replace `\\` with `/` on Windows\n * @param {string} filepath\n * @returns {string}\n */\nexport const normalizeToPosix =\n path.sep === \"\\\\\"\n ? (filepath: string) => filepath.replaceAll(\"\\\\\", \"/\")\n : (filepath: string) => filepath;\n", "import type { ParsedArgs } from \"../types.js\";\n\nexport function getDefaultArguments(): ParsedArgs {\n return {\n filePatterns: [],\n help: false,\n version: false,\n quiet: false,\n debug: false,\n check: false,\n };\n}\n", "import type { KnownArgument, ParsedArgs } from \"../types.js\";\nimport { getDefaultArguments } from \"./getDefaultArguments.js\";\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const result = getDefaultArguments();\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === \"--\") {\n // All following arguments are treated as file patterns, even if they start with \"--\"\n result.filePatterns.push(...argv.slice(i + 1));\n break;\n }\n\n if (parseKnownArgument(result, arg as KnownArgument)) {\n continue;\n }\n\n if (arg.startsWith(\"--\")) {\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n result.filePatterns.push(arg);\n }\n\n return result;\n}\n\nfunction parseKnownArgument(result: ParsedArgs, arg: KnownArgument): boolean {\n switch (arg) {\n case \"--help\":\n result.help = true;\n return true;\n case \"--version\":\n result.version = true;\n return true;\n case \"--quiet\":\n result.quiet = true;\n return true;\n case \"--check\":\n result.check = true;\n return true;\n case \"--debug\":\n result.debug = true;\n return true;\n default:\n return false;\n }\n}\n", "import type { Options } from \"fast-glob\";\nimport fastGlob from \"fast-glob\";\nimport * as path from \"node:path\";\nimport type { CLI } from \"../types.js\";\nimport { GLOB_IGNORE_PATTERNS } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { lstatSafe } from \"./lstatSafe.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\n\nexport async function parseFilePatterns(\n cli: CLI,\n filePatterns: string[],\n): Promise {\n const seen: Set = new Set();\n const globFileEndingPattern = getGlobFileEndingsPattern(cli.fileEndings);\n const errorMessages: string[] = [];\n\n const globOptions: Options = {\n dot: true,\n followSymbolicLinks: false,\n ignore: GLOB_IGNORE_PATTERNS,\n };\n\n for (const pattern of filePatterns) {\n const absolutePath = path.resolve(pattern);\n const stat = await lstatSafe(absolutePath);\n\n if (stat != null) {\n if (stat.isSymbolicLink()) {\n errorMessages.push(\n `Specified pattern is a symbolic link: ${pattern}`,\n );\n continue;\n }\n\n if (stat.isFile()) {\n seen.add(absolutePath);\n continue;\n }\n\n if (stat.isDirectory()) {\n const files = await fastGlob(`**/*.${globFileEndingPattern}`, {\n ...globOptions,\n cwd: absolutePath,\n });\n if (files.length === 0) {\n errorMessages.push(\n `No matching files were found in the directory: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(absolutePath, file));\n }\n continue;\n }\n }\n\n const glob = normalizeToPosix(pattern);\n const files = (await fastGlob(glob, globOptions)).filter((file) =>\n hasSupportedFileEnding(file, cli.fileEndings),\n );\n if (files.length === 0) {\n errorMessages.push(\n `No files matching the pattern were found: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(file));\n }\n }\n\n if (errorMessages.length > 0) {\n throw new FilePatternError(errorMessages);\n }\n\n return Array.from(seen).sort((a, b) => a.localeCompare(b));\n}\n\nfunction getGlobFileEndingsPattern(fileEndings: readonly string[]): string {\n return fileEndings.length === 1\n ? fileEndings[0]\n : `{${fileEndings.join(\",\")}}`;\n}\n\nfunction hasSupportedFileEnding(\n file: string,\n fileEndings: readonly string[],\n): boolean {\n const extension = path.extname(file).slice(1);\n return fileEndings.includes(extension);\n}\n", "import type { Stats } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\n\nexport async function lstatSafe(filePath: string): Promise {\n try {\n return await fs.lstat(filePath);\n } catch (error) {\n if (isMissingFileError(error)) {\n return undefined;\n }\n\n throw error;\n }\n}\n", "import type { KnownProps } from \"editorconfig\";\n\nexport const KNOWN_ARGUMENTS = [\n \"--help\",\n \"--version\",\n \"--quiet\",\n \"--check\",\n \"--debug\",\n] as const;\n\nexport type KnownArgument = (typeof KNOWN_ARGUMENTS)[number];\n\nexport interface CLI {\n binName: \"snippet-fmt\" | \"talon-fmt\" | \"tree-sitter-fmt\";\n fileEndings: readonly string[];\n\n getStdinFileEnding(text: string): string;\n format(\n text: string,\n options: Options,\n filePath: string,\n debug: boolean,\n ): Promise;\n}\n\nexport type EndOfLine = \"lf\" | \"crlf\";\n\nexport interface Options {\n endOfLine?: EndOfLine;\n indentTabs?: boolean;\n indentSize?: number;\n maxLineLength?: number;\n columnWidth?: number;\n insertFinalNewline?: boolean;\n preserveMultiline?: boolean;\n}\n\nexport type FormatterOptions = Pick;\n\nexport interface ParsedArgs {\n filePatterns: string[];\n help: boolean;\n version: boolean;\n check: boolean;\n quiet: boolean;\n debug: boolean;\n}\n\nexport interface LoggerEntry {\n level: \"log\" | \"warn\" | \"error\";\n message: string;\n}\n\nexport interface Logger {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\nexport interface TestLogger extends Logger {\n getEntries(): readonly LoggerEntry[];\n}\n\nexport interface DebugLogger {\n debug(message: string): void;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport interface EditorConfigOptions extends KnownProps {\n max_line_length?: number | \"unset\";\n column_width?: number | \"unset\";\n preserve_multiline?: boolean | \"unset\";\n}\n\nexport interface Point {\n row: number;\n column: number;\n}\n\nexport interface SyntaxNode {\n id: number;\n text: string;\n type: string;\n startPosition: Point;\n endPosition: Point;\n hasError: boolean;\n isError: boolean;\n isMissing: boolean;\n parent: SyntaxNode | null;\n children: SyntaxNode[];\n}\n", "import type { CLI } from \"../types.js\";\nimport { KNOWN_ARGUMENTS } from \"../types.js\";\n\nexport function printHelp(cli: CLI) {\n process.stdout.write(\n `Usage: ${cli.binName} [options] [file/dir/glob ...]\\n`,\n );\n process.stdout.write(\"\\n\");\n process.stdout.write(\"Options:\\n\");\n\n for (const option of KNOWN_ARGUMENTS) {\n process.stdout.write(` ${option}\\n`);\n }\n}\n", "{\n \"name\": \"@cursorless/talon-tools\",\n \"version\": \"0.10.0\",\n \"description\": \"Linting and formatting tools for Talon and Cursorless\",\n \"author\": \"Cursorless Dev\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"!dist/test\",\n \"!dist/build.*\"\n ],\n \"types\": \"./dist/lib.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/lib.d.ts\",\n \"default\": \"./dist/lib.js\"\n },\n \"./node\": {\n \"types\": \"./dist/node/libNode.d.ts\",\n \"default\": \"./dist/libNode.js\"\n }\n },\n \"bin\": {\n \"snippet-fmt\": \"dist/snippetFormatter.js\",\n \"talon-fmt\": \"dist/talonFormatter.js\",\n \"tree-sitter-fmt\": \"dist/treeSitterFormatter.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/cursorless-dev/talon-tools.git\"\n },\n \"funding\": \"https://github.com/sponsors/cursorless-dev\",\n \"sponsor\": {\n \"url\": \"https://github.com/sponsors/cursorless-dev\"\n },\n \"scripts\": {\n \"build\": \"npm run clean && tsc -p . && tsx ./src/build.ts\",\n \"clean\": \"rm -rf dist/*\",\n \"lint\": \"npm run lint:ts &&npm run lint:fmt\",\n \"lint:ts\": \"tsc -p . --noEmit && eslint src\",\n \"lint:fmt\": \"prettier --check .\",\n \"fix\": \"npm run fix:ts && npm run fix:fmt\",\n \"fix:ts\": \"eslint src --fix\",\n \"fix:fmt\": \"prettier --write --list-different .\",\n \"test\": \"tsx src/test/runAllTests.ts\",\n \"test:subset\": \"tsx src/test/runAllTests.ts --subset\"\n },\n \"dependencies\": {\n \"@cursorless/tree-sitter-wasms\": \"^0.7.0\",\n \"editorconfig\": \"^3.0.2\",\n \"fast-glob\": \"^3.3.3\",\n \"get-stdin\": \"^10.0.0\",\n \"web-tree-sitter\": \"^0.26.7\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.4\",\n \"@types/mocha\": \"^10.0.10\",\n \"@types/node\": \"^24.12.0\",\n \"esbuild\": \"^0.27.4\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-import\": \"^2.32.0\",\n \"eslint\": \"^9.39.4\",\n \"jiti\": \"^2.6.1\",\n \"mocha\": \"^11.7.5\",\n \"prettier\": \"^3.8.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript-eslint\": \"^8.57.1\",\n \"typescript\": \"^5.9.3\"\n }\n}\n", "import packageJson from \"../../package.json\" with { type: \"json\" };\n\nexport function printVersion() {\n process.stdout.write(`${packageJson.version}\\n`);\n}\n", "export function setExitCode(code: number): void {\n Reflect.set(process, \"exitCode\", code);\n}\n", "#!/usr/bin/env node\n\nimport { talonListFormatter } from \"../lib.js\";\nimport { talonFormatter } from \"../talon/talonFormatter.js\";\nimport { parseText } from \"./parseText.js\";\nimport { main } from \"./cli.js\";\n\nconst fileEndingTalon = \"talon\";\nconst fileEndingTalonList = \"talon-list\";\n\nvoid main({\n binName: \"talon-fmt\",\n fileEndings: [fileEndingTalon, fileEndingTalonList],\n\n getStdinFileEnding(text) {\n return textIsList(text) ? fileEndingTalonList : fileEndingTalon;\n },\n\n format: async (text, options, filePath, debug) => {\n if (isListFile(text, filePath)) {\n const updated = talonListFormatter(text, options);\n return Promise.resolve(updated);\n }\n\n const node = await parseText(text, \"tree-sitter-talon\");\n return talonFormatter(node, options, debug);\n },\n});\n\nfunction isListFile(text: string, filePath: string): boolean {\n if (filePath.endsWith(\".talon\")) {\n return false;\n }\n if (filePath.endsWith(\".talon-list\")) {\n return true;\n }\n return textIsList(text);\n}\n\nfunction textIsList(text: string): boolean {\n return text.trimStart().startsWith(\"list:\");\n}\n"], + "mappings": "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", + "names": ["IGNORE_FOLDERS", "GLOB_IGNORE_PATTERNS", "pattern", "getEndOfLine", "eof", "createDebugLogger", "debug", "message", "getColumnWidth", "text", "match", "getIndentation", "indentTabs", "indentSize", "SyntaxError", "location", "isSyntaxError", "error", "SyntaxTreeError", "SyntaxError", "rootNode", "findFirstProblemNode", "node", "child", "errorNode", "convertQuotes", "text", "talonFormatter", "node", "options", "debug", "SyntaxTreeError", "columnWidth", "getColumnWidth", "indentation", "getIndentation", "eol", "getEndOfLine", "TalonFormatter", "indent", "maxLineLength", "insertFinalNewline", "preserveMultiline", "createDebugLogger", "result", "isIndented", "n", "isFirstChild", "text", "nodeText", "rangeEqual", "formatString", "unwrap", "children", "middle", "pre", "post", "forceMultiline", "leftNode", "_colonNode", "rightNodes", "left", "isLeftRightSingleLine", "rightNode", "right", "leftWithPadding", "rights", "a", "b", "convertQuotes", "parseTalonList", "text", "lines", "l", "separatorIndex", "headerLines", "bodyLines", "trim", "result", "line", "key", "value", "splitLine", "index", "list", "startIndex", "endIndex", "talonListFormatter", "text", "options", "columnWidth", "getColumnWidth", "eol", "getEndOfLine", "talonList", "parseTalonList", "a", "_b", "lines", "header", "item", "keyWithColon", "value", "convertQuotes", "fs", "path", "fileURLToPath", "Language", "Parser", "initPromise", "languageCache", "moduleDir", "initTreeSitter", "loadLanguage", "parserName", "promise", "wasmFilePath", "getWasmFilePath", "fileName", "candidate", "parseText", "text", "language", "parser", "tree", "getStdin", "fs", "path", "process", "getErrorMessage", "error", "process", "ANSI_RESET", "ANSI_YELLOW", "ANSI_RED", "WARN_PREFIX", "ERROR_PREFIX", "createLogger", "quiet", "createLoggerFromStreams", "stdout", "stderr", "colorize", "shouldUseColor", "message", "color", "_color", "log", "warn", "shouldUseColor", "stream", "FilePatternError", "messages", "editorconfig", "getOptionsFromConfig", "filePath", "config", "options", "isMissingFileError", "error", "path", "normalizeToPosix", "filepath", "getDefaultArguments", "parseArgs", "argv", "result", "getDefaultArguments", "i", "arg", "parseKnownArgument", "fastGlob", "path", "fs", "lstatSafe", "filePath", "error", "isMissingFileError", "parseFilePatterns", "cli", "filePatterns", "seen", "globFileEndingPattern", "getGlobFileEndingsPattern", "errorMessages", "globOptions", "GLOB_IGNORE_PATTERNS", "pattern", "absolutePath", "stat", "lstatSafe", "files", "fastGlob", "file", "glob", "normalizeToPosix", "hasSupportedFileEnding", "FilePatternError", "a", "b", "fileEndings", "extension", "KNOWN_ARGUMENTS", "printHelp", "cli", "option", "KNOWN_ARGUMENTS", "package_default", "printVersion", "package_default", "setExitCode", "code", "main", "cli", "logger", "createLogger", "args", "parseArgs", "exitCode", "mainUnsafe", "setExitCode", "error", "FilePatternError", "message", "getErrorMessage", "printHelp", "printVersion", "mainFormatFiles", "mainFormatStdin", "check", "debug", "filePatterns", "filePaths", "parseFilePatterns", "changedFileCount", "hasError", "formatFiles", "filePath", "formatFile", "isSyntaxError", "getDisplayPath", "options", "getOptionsFromConfig", "content", "formatted", "isMissingFileError", "normalizeToPosix", "stdin", "input", "getStdin", "fauxFileName", "fauxFilePath", "fileEndingTalon", "fileEndingTalonList", "main", "text", "textIsList", "options", "filePath", "debug", "isListFile", "updated", "talonListFormatter", "node", "parseText", "talonFormatter"] } diff --git a/dist/treeSitterFormatter.d.ts b/dist/treeSitterFormatter.d.ts index 81677d1..c18afbd 100644 --- a/dist/treeSitterFormatter.d.ts +++ b/dist/treeSitterFormatter.d.ts @@ -1,4 +1,3 @@ import type { FormatterOptions, SyntaxNode } from "./types.js"; -type Options = FormatterOptions<"endOfLine" | "indentTabs" | "indentSize" | "insertFinalNewline">; +export type Options = FormatterOptions<"endOfLine" | "indentTabs" | "indentSize" | "insertFinalNewline">; export declare function treeSitterFormatter(node: SyntaxNode, options?: Options, debug?: boolean): string; -export {}; diff --git a/dist/treeSitterFormatter.js b/dist/treeSitterFormatter.js index adc8b03..cda5870 100644 --- a/dist/treeSitterFormatter.js +++ b/dist/treeSitterFormatter.js @@ -1,15 +1,15 @@ #!/usr/bin/env node -var ee=[".git",".svn",".hg","node_modules","__pycache__"],T=ee.map(r=>`**/${r}/**`);function S(r){return{debug(e){r&&console.warn(`[debug] ${e}`)}}}function $(r){return r==="crlf"?`\r +var st=[".git",".svn",".hg","node_modules","__pycache__"],v=st.map(r=>`**/${r}/**`);function C(r){return{debug(t){r&&console.warn(`[debug] ${t}`)}}}function I(r){return r==="crlf"?`\r `:` -`}function A(r,e){return r?" ":" ".repeat(e??4)}function v(r,e={},t=!1){let n=A(e.indentTabs,e.indentSize),i=$(e.endOfLine);return new E(n,i,e.insertFinalNewline??!0,t).getText(r)}var E=class{constructor(e,t,n,i){this.indentation=e;this.eol=t;this.insertFinalNewline=n;this.logger=S(i)}lastRow=0;logger;getText(e){let t=this.getNodeText(e,0);return t.length===0?"":this.insertFinalNewline?t+this.eol:t}getNodeText(e,t){let n=e.startPosition.row>this.lastRow+1?this.eol:"";this.lastRow=e.endPosition.row;let i=this.getNodeTextInternal(e,t);return this.lastRow=e.endPosition.row,`${n}${i}`}getNamedNodeText(e,t){let n=e.children.findIndex(a=>a.type===")"),i=e.children.slice(0,2).map(a=>a.text).join(""),s=e.children.slice(n).map(a=>this.getNodeText(a,0)).join(""),o=e.children.slice(2,n).map(a=>this.getNodeText(a,t+1));return o.length===0?`${this.getIndent(t)}${i}${s}`:[`${this.getIndent(t)}${i}`,...o,`${this.getIndent(t)}${s}`].join(this.eol)}getListText(e,t){let n=e.children.findIndex(a=>a.type==="]"),i=e.children[0].text,s=e.children.slice(n).map(a=>a.text).join(" ");return[`${this.getIndent(t)}${i}`,...e.children.slice(1,n).map(a=>this.getNodeText(a,t+1)),`${this.getIndent(t)}${s}`].join(this.eol)}getPredicateText(e,t){let n=e.children[0].text,i=e.children[e.children.length-1].text,s=[e.children.slice(1,4).map(o=>o.text).join(""),...e.children[e.children.length-2].children.map(o=>o.text)];if(e.startPosition.row===e.endPosition.row){let o=`${n}${s.join(" ")}${i}`;return`${this.getIndent(t)}${o}`}return[`${this.getIndent(t)}${n}${s[0]}`,...s.slice(1).map(o=>`${this.getIndent(t+1)}${o}`),`${this.getIndent(t)}${i}`].join(this.eol)}getFieldDefinitionText(e,t){return t===0?["(_",this.getFieldDefinitionText(e,1),")"].join(this.eol):[this.getIndent(t),e.children[0].text,e.children[1].text," ",this.getNodeText(e.children[2],t).trimStart()].join("")}getNodeTextInternal(e,t){switch(e.type){case"program":return this.joinLines(e.children,0);case"grouping":return this.joinLines(e.children,t+1);case"list":return this.getListText(e,t);case"named_node":return this.getNamedNodeText(e,t);case"predicate":return this.getPredicateText(e,t);case"field_definition":return this.getFieldDefinitionText(e,t);case"anonymous_node":return this.getIndent(t)+e.children.map(n=>this.getNodeText(n,t+1)).join("");case"comment":return`${this.getIndent(t)}${e.text.trimEnd()}`;case".":case"negated_field":return`${this.getIndent(t)}${e.text}`;case"(":case")":return`${this.getIndent(t-1)}${e.text}`;case"capture":return` ${e.text}`;case"#":case"_":case"predicate_type":case"identifier":case"quantifier":case"string":return e.text;case"parameters":return` ${e.children.map(i=>i.text).join(" ")}`;default:return this.logger.debug(`Unknown syntax node type '${e.type}'`),e.text}}joinLines(e,t){if(e.length===0)return"";let n=e[e.length-1].type==="quantifier",s=(n?e.slice(0,-1):e).map(o=>this.getNodeText(o,t)).join(this.eol);return n?`${s}${e[e.length-1].text}`:s}getIndent(e){return e<1?"":new Array(e).fill(this.indentation).join("")}};import*as j from"node:fs";import*as h from"node:path";import{fileURLToPath as ne}from"node:url";import{Language as ie,Parser as R}from"web-tree-sitter";var O,I=new Map,C=h.dirname(ne(import.meta.url));function oe(){return O??=R.init(),O}function se(r){let e=I.get(r);if(e==null){let t=ae(r);e=ie.load(t),I.set(r,e)}return e}function ae(r){let e=`${r}.wasm`,t=[h.join(C,"../../node_modules/@cursorless/tree-sitter-wasms/out",e),h.join(C,"../node_modules/@cursorless/tree-sitter-wasms/out",e)].find(n=>j.existsSync(n));if(t==null)throw new Error(`Could not find ${e}`);return t}async function k(r,e){await oe();let t=await se(e),n=new R;n.setLanguage(t);let i=n.parse(r);if(i==null)throw new Error("Failed to parse text");return i.rootNode}import we from"get-stdin";import*as y from"node:fs/promises";import*as w from"node:path";import*as l from"node:process";var p=class extends Error{constructor(t){super(`One or more file pattern errors occurred: -${t.join(` -`)}`);this.messages=t}name="FilePatternError"};function N(r){return r instanceof Error?r.message:String(r)}function x(r){return r instanceof Error&&"code"in r&&r.code==="ENOENT"}function _(r){Reflect.set(process,"exitCode",r)}import*as f from"node:process";var le="\x1B[0m",ce="\x1B[33m",ge="\x1B[31m",pe="[warn]",fe="[error]";function P(r=!1){return me(f.stdout,f.stderr,r)}function me(r,e,t=!1){let n=ue(e)?(o,a)=>`${a}${o}${le}`:(o,a)=>o,i,s;return t?(i=()=>{},s=()=>{}):(i=o=>{r.write(`${o} -`)},s=o=>{e.write(`${n(pe,ce)} ${o} -`)}),{log:i,warn:s,error(o){e.write(`${n(fe,ge)} ${o} -`)}}}function ue(r){return"NO_COLOR"in f.env?!1:r.isTTY===!0}import*as D from"editorconfig";async function F(r){let e=await D.parse(r),t={};return e.indent_style==="tab"?t.indentTabs=!0:e.indent_style==="space"&&(t.indentTabs=!1),typeof e.indent_size=="number"?t.indentSize=e.indent_size:e.indent_size==="tab"&&typeof e.tab_width=="number"&&(t.indentSize=e.tab_width),typeof e.max_line_length=="number"&&(t.maxLineLength=e.max_line_length),typeof e.column_width=="number"&&(t.columnWidth=e.column_width),typeof e.insert_final_newline=="boolean"&&(t.insertFinalNewline=e.insert_final_newline),typeof e.preserve_multiline=="boolean"&&(t.preserveMultiline=e.preserve_multiline),e.end_of_line!=null&&e.end_of_line!=="unset"&&(t.endOfLine=e.end_of_line),t}import*as M from"node:path";var b=M.sep==="\\"?r=>r.replaceAll("\\","/"):r=>r;function U(){return{filePatterns:[],help:!1,version:!1,quiet:!1,debug:!1,check:!1}}function W(r){let e=U();for(let t=0;txe(g,r.fileEndings));d.length===0&&i.push(`No files matching the pattern were found: ${o}`);for(let g of d)t.add(m.resolve(g))}if(i.length>0)throw new p(i);return Array.from(t).sort((o,a)=>o.localeCompare(a))}function he(r){return r.length===1?r[0]:`{${r.join(",")}}`}function xe(r,e){let t=m.extname(r).slice(1);return e.includes(t)}var X=["--help","--version","--quiet","--check","--debug"];function H(r){process.stdout.write(`Usage: ${r.binName} [options] [file/dir/glob ...] +`}function j(r,t){return r?" ":" ".repeat(t??4)}var d=class extends Error{constructor(e){super("Syntax error.");this.location=e;this.name="SyntaxError"}getLocation(){return this.location!=null?`(${this.location.row+1}:${this.location.column+1})`:void 0}};function P(r){return r instanceof d}var b=class extends d{constructor(t){super(R(t)?.startPosition),this.name="SyntaxTreeError"}};function R(r){if(r.isError||r.isMissing)return r;for(let t of r.children){if(!t.hasError)continue;let e=R(t);if(e!=null)return e}return null}function k(r,t={},e=!1){if(r.hasError)throw new b(r);let n=j(t.indentTabs,t.indentSize),i=I(t.endOfLine);return new _(n,i,t.insertFinalNewline??!0,e).getText(r)}var _=class{constructor(t,e,n,i){this.indentation=t;this.eol=e;this.insertFinalNewline=n;this.logger=C(i)}lastRow=0;logger;getText(t){let e=this.getNodeText(t,0);return e.length===0?"":this.insertFinalNewline?e+this.eol:e}getNodeText(t,e){let n=t.startPosition.row>this.lastRow+1?this.eol:"";this.lastRow=t.endPosition.row;let i=this.getNodeTextInternal(t,e);return this.lastRow=t.endPosition.row,`${n}${i}`}getNamedNodeText(t,e){let n=t.children.findIndex(s=>s.type===")"),i=t.children.slice(0,2).map(s=>s.text).join(""),a=t.children.slice(n).map(s=>this.getNodeText(s,0)).join(""),o=t.children.slice(2,n).map(s=>this.getNodeText(s,e+1));return o.length===0?`${this.getIndent(e)}${i}${a}`:[`${this.getIndent(e)}${i}`,...o,`${this.getIndent(e)}${a}`].join(this.eol)}getListText(t,e){let n=t.children.findIndex(s=>s.type==="]"),i=t.children[0].text,a=t.children.slice(n).map(s=>s.text).join(" ");return[`${this.getIndent(e)}${i}`,...t.children.slice(1,n).map(s=>this.getNodeText(s,e+1)),`${this.getIndent(e)}${a}`].join(this.eol)}getPredicateText(t,e){let n=t.children[0].text,i=t.children[t.children.length-1].text,a=[t.children.slice(1,4).map(o=>o.text).join(""),...t.children[t.children.length-2].children.map(o=>o.text)];if(t.startPosition.row===t.endPosition.row){let o=`${n}${a.join(" ")}${i}`;return`${this.getIndent(e)}${o}`}return[`${this.getIndent(e)}${n}${a[0]}`,...a.slice(1).map(o=>`${this.getIndent(e+1)}${o}`),`${this.getIndent(e)}${i}`].join(this.eol)}getFieldDefinitionText(t,e){return e===0?["(_",this.getFieldDefinitionText(t,1),")"].join(this.eol):[this.getIndent(e),t.children[0].text,t.children[1].text," ",this.getNodeText(t.children[2],e).trimStart()].join("")}getNodeTextInternal(t,e){switch(t.type){case"program":return this.joinLines(t.children,0);case"grouping":return this.joinLines(t.children,e+1);case"list":return this.getListText(t,e);case"named_node":return this.getNamedNodeText(t,e);case"predicate":return this.getPredicateText(t,e);case"field_definition":return this.getFieldDefinitionText(t,e);case"anonymous_node":return this.getIndent(e)+t.children.map(n=>this.getNodeText(n,e+1)).join("");case"comment":return`${this.getIndent(e)}${t.text.trimEnd()}`;case".":case"negated_field":return`${this.getIndent(e)}${t.text}`;case"(":case")":return`${this.getIndent(e-1)}${t.text}`;case"capture":return` ${t.text}`;case"#":case"_":case"predicate_type":case"identifier":case"quantifier":case"string":return t.text;case"parameters":return` ${t.children.map(i=>i.text).join(" ")}`;default:return this.logger.debug(`Unknown syntax node type '${t.type}'`),t.text}}joinLines(t,e){if(t.length===0)return"";let n=t[t.length-1].type==="quantifier",a=(n?t.slice(0,-1):t).map(o=>this.getNodeText(o,e)).join(this.eol);return n?`${a}${t[t.length-1].text}`:a}getIndent(t){return t<1?"":new Array(t).fill(this.indentation).join("")}};import*as W from"node:fs";import*as h from"node:path";import{fileURLToPath as ct}from"node:url";import{Language as ft,Parser as K}from"web-tree-sitter";var D,M=new Map,U=h.dirname(ct(import.meta.url));function pt(){return D??=K.init(),D}function gt(r){let t=M.get(r);if(t==null){let e=ut(r);t=ft.load(e),M.set(r,t)}return t}function ut(r){let t=`${r}.wasm`,e=[h.join(U,"../../node_modules/@cursorless/tree-sitter-wasms/out",t),h.join(U,"../node_modules/@cursorless/tree-sitter-wasms/out",t)].find(n=>W.existsSync(n));if(e==null)throw new Error(`Could not find ${t}`);return e}async function z(r,t){await pt();let e=await gt(t),n=new K;n.setLanguage(e);let i=n.parse(r);if(i==null)throw new Error("Failed to parse text");return i.rootNode}import _t from"get-stdin";import*as E from"node:fs/promises";import*as L from"node:path";import*as f from"node:process";function F(r){return r instanceof Error?r.message:String(r)}import*as g from"node:process";var mt="\x1B[0m",dt="\x1B[33m",ht="\x1B[31m",xt="[warn]",bt="[error]";function T(r=!1){return yt(g.stdout,g.stderr,r)}function yt(r,t,e=!1){let n=wt(t)?(o,s)=>`${s}${o}${mt}`:(o,s)=>o,i,a;return e?(i=()=>{},a=()=>{}):(i=o=>{r.write(`${o} +`)},a=o=>{t.write(`${n(xt,dt)} ${o} +`)}),{log:i,warn:a,error(o){t.write(`${n(bt,ht)} ${o} +`)}}}function wt(r){return"NO_COLOR"in g.env?!1:r.isTTY===!0}var u=class extends Error{constructor(e){super(`One or more file pattern errors occurred: +${e.join(` +`)}`);this.messages=e}name="FilePatternError"};import*as X from"editorconfig";async function S(r){let t=await X.parse(r),e={};return t.indent_style==="tab"?e.indentTabs=!0:t.indent_style==="space"&&(e.indentTabs=!1),typeof t.indent_size=="number"?e.indentSize=t.indent_size:t.indent_size==="tab"&&typeof t.tab_width=="number"&&(e.indentSize=t.tab_width),typeof t.max_line_length=="number"&&(e.maxLineLength=t.max_line_length),typeof t.column_width=="number"&&(e.columnWidth=t.column_width),typeof t.insert_final_newline=="boolean"&&(e.insertFinalNewline=t.insert_final_newline),typeof t.preserve_multiline=="boolean"&&(e.preserveMultiline=t.preserve_multiline),t.end_of_line!=null&&t.end_of_line!=="unset"&&(e.endOfLine=t.end_of_line),e}function y(r){return r instanceof Error&&"code"in r&&r.code==="ENOENT"}import*as G from"node:path";var w=G.sep==="\\"?r=>r.replaceAll("\\","/"):r=>r;function q(){return{filePatterns:[],help:!1,version:!1,quiet:!1,debug:!1,check:!1}}function H(r){let t=q();for(let e=0;eNt(c,r.fileEndings));p.length===0&&i.push(`No files matching the pattern were found: ${o}`);for(let c of p)e.add(m.resolve(c))}if(i.length>0)throw new u(i);return Array.from(e).sort((o,s)=>o.localeCompare(s))}function Lt(r){return r.length===1?r[0]:`{${r.join(",")}}`}function Nt(r,t){let e=m.extname(r).slice(1);return t.includes(e)}var Q=["--help","--version","--quiet","--check","--debug"];function Z(r){process.stdout.write(`Usage: ${r.binName} [options] [file/dir/glob ...] `),process.stdout.write(` `),process.stdout.write(`Options: -`);for(let e of X)process.stdout.write(` ${e} -`)}var Y={name:"@cursorless/talon-tools",version:"0.9.0",description:"Linting and formatting tools for Talon and Cursorless",author:"Cursorless Dev",license:"MIT",type:"module",files:["dist","!dist/test","!dist/build.*"],types:"./dist/lib.d.ts",exports:{".":{types:"./dist/lib.d.ts",default:"./dist/lib.js"},"./node":{types:"./dist/node/libNode.d.ts",default:"./dist/libNode.js"}},bin:{"snippet-fmt":"dist/snippetFormatter.js","talon-fmt":"dist/talonFormatter.js","tree-sitter-fmt":"dist/treeSitterFormatter.js"},repository:{type:"git",url:"git+https://github.com/cursorless-dev/talon-tools.git"},funding:"https://github.com/sponsors/cursorless-dev",sponsor:{url:"https://github.com/sponsors/cursorless-dev"},scripts:{build:"npm run clean && tsc -p . && tsx ./src/build.ts",clean:"rm -rf dist/*",lint:"npm run lint:ts &&npm run lint:fmt","lint:ts":"tsc -p . --noEmit && eslint src","lint:fmt":"prettier --check .",fix:"npm run fix:ts && npm run fix:fmt","fix:ts":"eslint src --fix","fix:fmt":"prettier --write --list-different .",test:"tsx src/test/runAllTests.ts","test:subset":"tsx src/test/runAllTests.ts --subset"},dependencies:{"@cursorless/tree-sitter-wasms":"^0.7.0",editorconfig:"^3.0.2","fast-glob":"^3.3.3","get-stdin":"^10.0.0","web-tree-sitter":"^0.26.7"},devDependencies:{"@eslint/js":"^9.39.4","@types/mocha":"^10.0.10","@types/node":"^24.12.0",esbuild:"^0.27.4","eslint-config-prettier":"^10.1.8","eslint-plugin-import":"^2.32.0",eslint:"^9.39.4",jiti:"^2.6.1",mocha:"^11.7.5",prettier:"^3.8.1",tsx:"^4.21.0","typescript-eslint":"^8.57.1",typescript:"^5.9.3"}};function B(){process.stdout.write(`${Y.version} -`)}async function V(r){let e=P();try{let t=W(l.argv.slice(2));e=P(t.quiet);let n=await Le({cli:r,args:t,logger:e});_(n)}catch(t){if(t instanceof p)for(let n of t.messages)e.error(n);else e.error(N(t));_(2)}}async function Le({cli:r,args:e,logger:t}){if(e.help)return H(r),0;if(e.version)return B(),0;if(e.filePatterns.length>0)return Ee({cli:r,logger:t,check:e.check,debug:e.debug,filePatterns:e.filePatterns});if(!l.stdin.isTTY)return Fe({cli:r,logger:t,stdin:l.stdin,check:e.check,debug:e.debug});throw new Error("No input files specified. Use --help for usage information.")}async function Ee({cli:r,logger:e,check:t,debug:n,filePatterns:i}){t&&e.log("Checking formatting...");let s=await q(r,i),o=await Ne({cli:r,logger:e,check:t,debug:n,filePaths:s});return t?o>0?(e.warn(`Code style issues found in ${o} file(s).`),1):(e.log("All matched files use correct code style!"),0):0}async function Ne({cli:r,logger:e,check:t,debug:n,filePaths:i}){let s=0;for(let o of i)await _e({cli:r,logger:e,check:t,debug:n,filePath:o})&&s++;return s}async function _e({cli:r,logger:e,check:t,debug:n,filePath:i}){try{let s=await F(i),o=await y.readFile(i,"utf8"),a=await r.format(o,s,i,n);return a===o?!1:(e.log(Pe(i)),t||await y.writeFile(i,a,"utf8"),!0)}catch(s){if(x(s))return!1;throw new Error(`Failed to format '${i}': ${N(s)}`,{cause:s})}}function Pe(r){return b(w.relative(l.cwd(),r))}async function Fe({cli:r,logger:e,stdin:t,check:n,debug:i}){let s=await we({stdin:t}),a=`stdin.${r.getStdinFileEnding(s)}`,c=w.resolve(a),L=await F(c),d=await r.format(s,L,c,i);return n?s!==d?(e.warn("Code style issues found in stdin."),1):0:(l.stdout.write(d),0)}var Q="scm";V({binName:"tree-sitter-fmt",fileEndings:[Q],getStdinFileEnding(){return Q},format:async(r,e,t,n)=>{let i=await k(r,"tree-sitter-query");return v(i,e,n)}}); +`);for(let t of Q)process.stdout.write(` ${t} +`)}var tt={name:"@cursorless/talon-tools",version:"0.10.0",description:"Linting and formatting tools for Talon and Cursorless",author:"Cursorless Dev",license:"MIT",type:"module",files:["dist","!dist/test","!dist/build.*"],types:"./dist/lib.d.ts",exports:{".":{types:"./dist/lib.d.ts",default:"./dist/lib.js"},"./node":{types:"./dist/node/libNode.d.ts",default:"./dist/libNode.js"}},bin:{"snippet-fmt":"dist/snippetFormatter.js","talon-fmt":"dist/talonFormatter.js","tree-sitter-fmt":"dist/treeSitterFormatter.js"},repository:{type:"git",url:"git+https://github.com/cursorless-dev/talon-tools.git"},funding:"https://github.com/sponsors/cursorless-dev",sponsor:{url:"https://github.com/sponsors/cursorless-dev"},scripts:{build:"npm run clean && tsc -p . && tsx ./src/build.ts",clean:"rm -rf dist/*",lint:"npm run lint:ts &&npm run lint:fmt","lint:ts":"tsc -p . --noEmit && eslint src","lint:fmt":"prettier --check .",fix:"npm run fix:ts && npm run fix:fmt","fix:ts":"eslint src --fix","fix:fmt":"prettier --write --list-different .",test:"tsx src/test/runAllTests.ts","test:subset":"tsx src/test/runAllTests.ts --subset"},dependencies:{"@cursorless/tree-sitter-wasms":"^0.7.0",editorconfig:"^3.0.2","fast-glob":"^3.3.3","get-stdin":"^10.0.0","web-tree-sitter":"^0.26.7"},devDependencies:{"@eslint/js":"^9.39.4","@types/mocha":"^10.0.10","@types/node":"^24.12.0",esbuild:"^0.27.4","eslint-config-prettier":"^10.1.8","eslint-plugin-import":"^2.32.0",eslint:"^9.39.4",jiti:"^2.6.1",mocha:"^11.7.5",prettier:"^3.8.1",tsx:"^4.21.0","typescript-eslint":"^8.57.1",typescript:"^5.9.3"}};function et(){process.stdout.write(`${tt.version} +`)}function $(r){Reflect.set(process,"exitCode",r)}async function nt(r){let t=T();try{let e=H(f.argv.slice(2));t=T(e.quiet);let n=await Ft({cli:r,args:e,logger:t});$(n)}catch(e){if(e instanceof u)for(let n of e.messages)t.error(n);else t.error(F(e));$(2)}}async function Ft({cli:r,args:t,logger:e}){if(t.help)return Z(r),0;if(t.version)return et(),0;if(t.filePatterns.length>0)return Tt({cli:r,logger:e,check:t.check,debug:t.debug,filePatterns:t.filePatterns});if(!f.stdin.isTTY)return At({cli:r,logger:e,stdin:f.stdin,check:t.check,debug:t.debug});throw new Error("No input files specified. Use --help for usage information.")}async function Tt({cli:r,logger:t,check:e,debug:n,filePatterns:i}){e&&t.log("Checking formatting...");let a=await V(r,i),[o,s]=await St({cli:r,logger:t,check:e,debug:n,filePaths:a});if(e){if(o>0&&(t.warn(`Code style issues found in ${o} file(s).`),!s))return 1;s||t.log("All matched files use correct code style!")}return s?2:0}async function St({cli:r,logger:t,check:e,debug:n,filePaths:i}){let a=0,o=!1;for(let s of i)try{await $t({cli:r,logger:t,check:e,debug:n,filePath:s})&&a++}catch(l){P(l)?t.error(`${A(s)}${l.getLocation()}: ${l.message}`):t.error(`${A(s)}: ${F(l)}`),o=!0}return[a,o]}async function $t({cli:r,logger:t,check:e,debug:n,filePath:i}){try{let a=await S(i),o=await E.readFile(i,"utf8"),s=await r.format(o,a,i,n);return s===o?!1:(t.log(A(i)),e||await E.writeFile(i,s,"utf8"),!0)}catch(a){if(y(a))return!1;throw a}}function A(r){return w(L.relative(f.cwd(),r))}async function At({cli:r,logger:t,stdin:e,check:n,debug:i}){let a=await _t({stdin:e}),s=`stdin.${r.getStdinFileEnding(a)}`,l=L.resolve(s),N=await S(l),p;try{p=await r.format(a,N,l,i)}catch(c){if(P(c))return t.error(`stdin${c.getLocation()}: ${c.message}`),2;throw c}return n?a!==p?(t.warn("Code style issues found in stdin."),1):0:(f.stdout.write(p),0)}var it="scm";nt({binName:"tree-sitter-fmt",fileEndings:[it],getStdinFileEnding(){return it},format:async(r,t,e,n)=>{let i=await z(r,"tree-sitter-query");return k(i,t,n)}}); //# sourceMappingURL=treeSitterFormatter.js.map diff --git a/dist/treeSitterFormatter.js.map b/dist/treeSitterFormatter.js.map index 33d3cf7..fcdd855 100644 --- a/dist/treeSitterFormatter.js.map +++ b/dist/treeSitterFormatter.js.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../src/util/constants.ts", "../src/util/createDebugLogger.ts", "../src/util/getEndOfLine.ts", "../src/util/getIndentation.ts", "../src/treeSitterFormatter.ts", "../src/node/parseText.ts", "../src/node/cli.ts", "../src/node/FilePatternError.ts", "../src/util/getErrorMessage.ts", "../src/node/isMissingFileError.ts", "../src/node/setExitCode.ts", "../src/node/createLogger.ts", "../src/node/getOptionsFromConfig.ts", "../src/node/normalizeToPosix.ts", "../src/node/getDefaultArguments.ts", "../src/node/parseArgs.ts", "../src/node/parseFilePatterns.ts", "../src/node/lstatSafe.ts", "../src/types.ts", "../src/node/printHelp.ts", "../package.json", "../src/node/printVersion.ts", "../src/node/treeSitterFormatter.ts"], - "sourcesContent": ["// Exit code 0: Success\nexport const EXIT_OK = 0;\n// Exit code 1: Check failed\nexport const EXIT_FAIL = 1;\n// Exit code 2: Unexpected error\nexport const EXIT_ERROR = 2;\n\nexport const DEFAULT_INDENT_WIDTH = 4;\nexport const DEFAULT_MAX_LINE_LENGTH = 80;\nexport const DEFAULT_INSERT_FINAL_NEWLINE = true;\n\nexport const IGNORE_FOLDERS = [\n \".git\",\n \".svn\",\n \".hg\",\n \"node_modules\",\n \"__pycache__\",\n];\n\nexport const GLOB_IGNORE_PATTERNS = IGNORE_FOLDERS.map(\n (pattern) => `**/${pattern}/**`,\n);\n", "import type { DebugLogger } from \"../types.js\";\n\nexport function createDebugLogger(debug: boolean): DebugLogger {\n return {\n debug(message: string) {\n if (debug) {\n console.warn(`[debug] ${message}`);\n }\n },\n };\n}\n", "import type { EndOfLine } from \"../types.js\";\n\nexport function getEndOfLine(eof?: EndOfLine): string {\n return eof === \"crlf\" ? \"\\r\\n\" : \"\\n\";\n}\n", "import { DEFAULT_INDENT_WIDTH } from \"./constants.js\";\n\nexport function getIndentation(\n indentTabs: boolean | undefined,\n indentSize: number | undefined,\n): string {\n return indentTabs ? \"\\t\" : \" \".repeat(indentSize ?? DEFAULT_INDENT_WIDTH);\n}\n", "import type { DebugLogger, FormatterOptions, SyntaxNode } from \"./types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"./util/constants.js\";\nimport { createDebugLogger } from \"./util/createDebugLogger.js\";\nimport { getEndOfLine } from \"./util/getEndOfLine.js\";\nimport { getIndentation } from \"./util/getIndentation.js\";\n\ntype Options = FormatterOptions<\n \"endOfLine\" | \"indentTabs\" | \"indentSize\" | \"insertFinalNewline\"\n>;\n\nexport function treeSitterFormatter(\n node: SyntaxNode,\n options: Options = {},\n debug: boolean = false,\n): string {\n const indentation = getIndentation(options.indentTabs, options.indentSize);\n const eol = getEndOfLine(options.endOfLine);\n const formatter = new TreeSitterFormatter(\n indentation,\n eol,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n debug,\n );\n return formatter.getText(node);\n}\n\nclass TreeSitterFormatter {\n private lastRow = 0;\n private logger: DebugLogger;\n\n constructor(\n private indentation: string,\n private eol: string,\n private insertFinalNewline: boolean,\n debug: boolean,\n ) {\n this.logger = createDebugLogger(debug);\n }\n\n getText(node: SyntaxNode): string {\n const nodeText = this.getNodeText(node, 0);\n\n if (nodeText.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return nodeText + this.eol;\n }\n\n return nodeText;\n }\n\n private getNodeText(node: SyntaxNode, numIndents: number): string {\n const nl = node.startPosition.row > this.lastRow + 1 ? this.eol : \"\";\n this.lastRow = node.endPosition.row;\n const text = this.getNodeTextInternal(node, numIndents);\n this.lastRow = node.endPosition.row;\n return `${nl}${text}`;\n }\n\n private getNamedNodeText(node: SyntaxNode, numIndents: number): string {\n const index = node.children.findIndex((n) => n.type === \")\");\n const first = node.children\n .slice(0, 2)\n .map((n) => n.text)\n .join(\"\");\n const last = node.children\n .slice(index)\n .map((n) => this.getNodeText(n, 0))\n .join(\"\");\n const interior = node.children\n .slice(2, index)\n .map((n) => this.getNodeText(n, numIndents + 1));\n // Inline node\n if (interior.length === 0) {\n return `${this.getIndent(numIndents)}${first}${last}`;\n }\n // Multiline node\n return [\n `${this.getIndent(numIndents)}${first}`,\n ...interior,\n `${this.getIndent(numIndents)}${last}`,\n ].join(this.eol);\n }\n\n private getListText(node: SyntaxNode, numIndents: number): string {\n const index = node.children.findIndex((n) => n.type === \"]\");\n const first = node.children[0].text;\n const last = node.children\n .slice(index)\n .map((n) => n.text)\n .join(\" \");\n const parts = [\n `${this.getIndent(numIndents)}${first}`,\n ...node.children\n .slice(1, index)\n .map((n) => this.getNodeText(n, numIndents + 1)),\n `${this.getIndent(numIndents)}${last}`,\n ];\n return parts.join(this.eol);\n }\n\n private getPredicateText(node: SyntaxNode, numIndents: number): string {\n const first = node.children[0].text;\n const last = node.children[node.children.length - 1].text;\n const parts = [\n node.children\n .slice(1, 4)\n .map((n) => n.text)\n .join(\"\"),\n ...node.children[node.children.length - 2].children.map(\n (n) => n.text,\n ),\n ];\n // Inline predicate\n if (node.startPosition.row === node.endPosition.row) {\n const text = `${first}${parts.join(\" \")}${last}`;\n return `${this.getIndent(numIndents)}${text}`;\n }\n // Multiline predicate\n return [\n `${this.getIndent(numIndents)}${first}${parts[0]}`,\n ...parts\n .slice(1)\n .map((s) => `${this.getIndent(numIndents + 1)}${s}`),\n `${this.getIndent(numIndents)}${last}`,\n ].join(this.eol);\n }\n\n private getFieldDefinitionText(\n node: SyntaxNode,\n numIndents: number,\n ): string {\n // Field definition directly in document root\n if (numIndents === 0) {\n return [\"(_\", this.getFieldDefinitionText(node, 1), \")\"].join(\n this.eol,\n );\n }\n // [lhs, \":\", rhs]\n return [\n this.getIndent(numIndents),\n node.children[0].text,\n node.children[1].text,\n \" \",\n this.getNodeText(node.children[2], numIndents).trimStart(),\n ].join(\"\");\n }\n\n private getNodeTextInternal(node: SyntaxNode, numIndents: number): string {\n switch (node.type) {\n case \"program\":\n return this.joinLines(node.children, 0);\n\n case \"grouping\":\n return this.joinLines(node.children, numIndents + 1);\n\n case \"list\":\n return this.getListText(node, numIndents);\n\n case \"named_node\":\n return this.getNamedNodeText(node, numIndents);\n\n case \"predicate\":\n return this.getPredicateText(node, numIndents);\n\n case \"field_definition\":\n return this.getFieldDefinitionText(node, numIndents);\n\n case \"anonymous_node\":\n return (\n this.getIndent(numIndents) +\n node.children\n .map((n) => this.getNodeText(n, numIndents + 1))\n .join(\"\")\n );\n\n case \"comment\":\n return `${this.getIndent(numIndents)}${node.text.trimEnd()}`;\n\n case \".\":\n case \"negated_field\":\n return `${this.getIndent(numIndents)}${node.text}`;\n\n case \"(\":\n case \")\":\n return `${this.getIndent(numIndents - 1)}${node.text}`;\n\n case \"capture\":\n return ` ${node.text}`;\n\n case \"#\":\n case \"_\":\n case \"predicate_type\":\n case \"identifier\":\n case \"quantifier\":\n case \"string\":\n return node.text;\n\n case \"parameters\": {\n const text = node.children.map((n) => n.text).join(\" \");\n return ` ${text}`;\n }\n\n default:\n this.logger.debug(`Unknown syntax node type '${node.type}'`);\n return node.text;\n }\n }\n\n private joinLines(nodes: SyntaxNode[], numIndents: number): string {\n if (nodes.length === 0) {\n return \"\";\n }\n const lastIsQuantifier = nodes[nodes.length - 1].type === \"quantifier\";\n const nodesToUse = lastIsQuantifier ? nodes.slice(0, -1) : nodes;\n const text = nodesToUse\n .map((n) => this.getNodeText(n, numIndents))\n .join(this.eol);\n return lastIsQuantifier\n ? `${text}${nodes[nodes.length - 1].text}`\n : text;\n }\n\n private getIndent(length: number): string {\n return length < 1\n ? \"\"\n : new Array(length).fill(this.indentation).join(\"\");\n }\n}\n", "import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Node } from \"web-tree-sitter\";\nimport { Language, Parser } from \"web-tree-sitter\";\n\ntype ParserName = \"tree-sitter-talon\" | \"tree-sitter-query\";\n\nlet initPromise: Promise | undefined;\nconst languageCache = new Map>();\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\nfunction initTreeSitter() {\n initPromise ??= Parser.init();\n return initPromise;\n}\n\nfunction loadLanguage(parserName: ParserName) {\n let promise = languageCache.get(parserName);\n\n if (promise == null) {\n const wasmFilePath = getWasmFilePath(parserName);\n promise = Language.load(wasmFilePath);\n languageCache.set(parserName, promise);\n }\n\n return promise;\n}\n\nfunction getWasmFilePath(parserName: ParserName) {\n const fileName = `${parserName}.wasm`;\n const wasmFilePath = [\n path.join(\n moduleDir,\n \"../../node_modules/@cursorless/tree-sitter-wasms/out\",\n fileName,\n ),\n path.join(\n moduleDir,\n \"../node_modules/@cursorless/tree-sitter-wasms/out\",\n fileName,\n ),\n ].find((candidate) => fs.existsSync(candidate));\n\n if (wasmFilePath == null) {\n throw new Error(`Could not find ${fileName}`);\n }\n\n return wasmFilePath;\n}\n\nexport async function parseText(\n text: string,\n parserName: ParserName,\n): Promise {\n await initTreeSitter();\n\n const language = await loadLanguage(parserName);\n\n const parser = new Parser();\n parser.setLanguage(language);\n\n const tree = parser.parse(text);\n\n if (tree == null) {\n throw new Error(\"Failed to parse text\");\n }\n\n return tree.rootNode;\n}\n", "import getStdin from \"get-stdin\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as process from \"node:process\";\nimport type { Readable } from \"node:stream\";\nimport type { CLI, Logger, ParsedArgs } from \"../types.js\";\nimport { EXIT_ERROR, EXIT_FAIL, EXIT_OK } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { getErrorMessage } from \"../util/getErrorMessage.js\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\nimport { setExitCode } from \"./setExitCode.js\";\nimport { createLogger } from \"./createLogger.js\";\nimport { getOptionsFromConfig } from \"./getOptionsFromConfig.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\nimport { parseArgs } from \"./parseArgs.js\";\nimport { parseFilePatterns } from \"./parseFilePatterns.js\";\nimport { printHelp } from \"./printHelp.js\";\nimport { printVersion } from \"./printVersion.js\";\n\nexport async function main(cli: CLI): Promise {\n let logger = createLogger();\n\n try {\n const args = parseArgs(process.argv.slice(2));\n logger = createLogger(args.quiet);\n const exitCode = await mainUnsafe({ cli, args, logger });\n setExitCode(exitCode);\n } catch (error) {\n if (error instanceof FilePatternError) {\n for (const message of error.messages) {\n logger.error(message);\n }\n } else {\n logger.error(getErrorMessage(error));\n }\n setExitCode(EXIT_ERROR);\n }\n}\n\ninterface MainUnsafeArgs {\n cli: CLI;\n args: ParsedArgs;\n logger: Logger;\n}\n\nasync function mainUnsafe({\n cli,\n args,\n logger,\n}: MainUnsafeArgs): Promise {\n if (args.help) {\n printHelp(cli);\n return EXIT_OK;\n }\n\n if (args.version) {\n printVersion();\n return EXIT_OK;\n }\n\n const hasFilePatterns = args.filePatterns.length > 0;\n\n if (hasFilePatterns) {\n return mainFormatFiles({\n cli,\n logger,\n check: args.check,\n debug: args.debug,\n filePatterns: args.filePatterns,\n });\n }\n\n // If no file patterns are provided, check if there's input from stdin.\n // If stdin TTY it's an interactive terminal, so we shouldn't read from it.\n if (!process.stdin.isTTY) {\n return mainFormatStdin({\n cli,\n logger,\n stdin: process.stdin,\n check: args.check,\n debug: args.debug,\n });\n }\n\n throw new Error(\n \"No input files specified. Use --help for usage information.\",\n );\n}\n\ninterface MainFormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePatterns: string[];\n}\n\nasync function mainFormatFiles({\n cli,\n logger,\n check,\n debug,\n filePatterns,\n}: MainFormatFilesArgs): Promise {\n if (check) {\n logger.log(\"Checking formatting...\");\n }\n\n const filePaths = await parseFilePatterns(cli, filePatterns);\n const changedFileCount = await formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n });\n\n if (check) {\n if (changedFileCount > 0) {\n logger.warn(\n `Code style issues found in ${changedFileCount} file(s).`,\n );\n return EXIT_FAIL;\n }\n\n logger.log(\"All matched files use correct code style!\");\n return EXIT_OK;\n }\n\n return EXIT_OK;\n}\n\ninterface FormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePaths: string[];\n}\n\nexport async function formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n}: FormatFilesArgs): Promise {\n let changedFileCount = 0;\n\n for (const fileName of filePaths) {\n if (\n await formatFile({\n cli,\n logger,\n check,\n debug,\n filePath: fileName,\n })\n ) {\n changedFileCount++;\n }\n }\n\n return changedFileCount;\n}\n\ninterface FormatFileArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePath: string;\n}\n\nexport async function formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n}: FormatFileArgs): Promise {\n try {\n const options = await getOptionsFromConfig(filePath);\n const content = await fs.readFile(filePath, \"utf8\");\n const formatted = await cli.format(content, options, filePath, debug);\n\n if (formatted === content) {\n return false;\n }\n\n logger.log(getDisplayPath(filePath));\n\n if (!check) {\n await fs.writeFile(filePath, formatted, \"utf8\");\n }\n\n return true;\n } catch (error) {\n if (isMissingFileError(error)) {\n return false;\n }\n\n throw new Error(\n `Failed to format '${filePath}': ${getErrorMessage(error)}`,\n {\n cause: error,\n },\n );\n }\n}\n\nfunction getDisplayPath(filePath: string): string {\n return normalizeToPosix(path.relative(process.cwd(), filePath));\n}\n\ninterface MainFormatStdinArgs {\n cli: CLI;\n logger: Logger;\n stdin: Readable;\n check: boolean;\n debug: boolean;\n}\n\nexport async function mainFormatStdin({\n cli,\n logger,\n stdin,\n check,\n debug,\n}: MainFormatStdinArgs): Promise {\n const input = await getStdin({ stdin });\n const fileEnding = cli.getStdinFileEnding(input);\n const fileName = `stdin.${fileEnding}`;\n const filePath = path.resolve(fileName);\n const options = await getOptionsFromConfig(filePath);\n const formatted = await cli.format(input, options, filePath, debug);\n\n if (check) {\n if (input !== formatted) {\n logger.warn(\"Code style issues found in stdin.\");\n return EXIT_FAIL;\n }\n\n return EXIT_OK;\n }\n\n process.stdout.write(formatted);\n\n return EXIT_OK;\n}\n", "export class FilePatternError extends Error {\n name = \"FilePatternError\";\n\n constructor(public messages: string[]) {\n super(\n `One or more file pattern errors occurred:\\n${messages.join(\"\\n\")}`,\n );\n }\n}\n", "export function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n", "export function isMissingFileError(error: unknown) {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n", "export function setExitCode(code: number): void {\n Reflect.set(process, \"exitCode\", code);\n}\n", "import * as process from \"node:process\";\nimport type { WriteStream } from \"node:tty\";\nimport type { Logger, LoggerEntry, TestLogger } from \"../types.js\";\n\ntype LogCallback = (message: string) => void;\ntype ColorizeCallback = (message: string, color: string) => string;\ntype LoggerStream = Pick & Partial;\n\nconst ANSI_RESET = \"\\u001b[0m\";\nconst ANSI_YELLOW = \"\\u001b[33m\";\nconst ANSI_RED = \"\\u001b[31m\";\nconst WARN_PREFIX = \"[warn]\";\nconst ERROR_PREFIX = \"[error]\";\n\nexport function createLogger(quiet: boolean = false): Logger {\n return createLoggerFromStreams(process.stdout, process.stderr, quiet);\n}\n\nexport function createLoggerFromStreams(\n stdout: LoggerStream,\n stderr: LoggerStream,\n quiet: boolean = false,\n): Logger {\n const colorize: ColorizeCallback = shouldUseColor(stderr)\n ? (message, color) => `${color}${message}${ANSI_RESET}`\n : (message, _color) => message;\n\n let log: LogCallback;\n let warn: LogCallback;\n\n if (quiet) {\n log = () => {};\n warn = () => {};\n } else {\n log = (message: string) => {\n stdout.write(`${message}\\n`);\n };\n warn = (message: string) => {\n stderr.write(`${colorize(WARN_PREFIX, ANSI_YELLOW)} ${message}\\n`);\n };\n }\n\n return {\n log,\n warn,\n error(message: string) {\n stderr.write(`${colorize(ERROR_PREFIX, ANSI_RED)} ${message}\\n`);\n },\n };\n}\n\nexport function createTestLogger(): TestLogger {\n const entries: LoggerEntry[] = [];\n\n return {\n log(message: string) {\n entries.push({ level: \"log\", message });\n },\n warn(message: string) {\n entries.push({ level: \"warn\", message });\n },\n error(message: string) {\n entries.push({ level: \"error\", message });\n },\n getEntries() {\n return entries;\n },\n };\n}\n\nfunction shouldUseColor(stream: LoggerStream): boolean {\n if (\"NO_COLOR\" in process.env) {\n return false;\n }\n\n return stream.isTTY === true;\n}\n", "import * as editorconfig from \"editorconfig\";\nimport type { EditorConfigOptions, Options } from \"../types.js\";\n\nexport async function getOptionsFromConfig(filePath: string): Promise {\n const config = (await editorconfig.parse(filePath)) as EditorConfigOptions;\n\n const options: Options = {};\n\n if (config.indent_style === \"tab\") {\n options.indentTabs = true;\n } else if (config.indent_style === \"space\") {\n options.indentTabs = false;\n }\n\n if (typeof config.indent_size === \"number\") {\n options.indentSize = config.indent_size;\n } else if (\n config.indent_size === \"tab\" &&\n typeof config.tab_width === \"number\"\n ) {\n options.indentSize = config.tab_width;\n }\n\n if (typeof config.max_line_length === \"number\") {\n options.maxLineLength = config.max_line_length;\n }\n\n if (typeof config.column_width === \"number\") {\n options.columnWidth = config.column_width;\n }\n\n if (typeof config.insert_final_newline === \"boolean\") {\n options.insertFinalNewline = config.insert_final_newline;\n }\n\n if (typeof config.preserve_multiline === \"boolean\") {\n options.preserveMultiline = config.preserve_multiline;\n }\n\n if (config.end_of_line != null && config.end_of_line !== \"unset\") {\n options.endOfLine = config.end_of_line;\n }\n\n return options;\n}\n", "import * as path from \"node:path\";\n\n/**\n * Replace `\\` with `/` on Windows\n * @param {string} filepath\n * @returns {string}\n */\nexport const normalizeToPosix =\n path.sep === \"\\\\\"\n ? (filepath: string) => filepath.replaceAll(\"\\\\\", \"/\")\n : (filepath: string) => filepath;\n", "import type { ParsedArgs } from \"../types.js\";\n\nexport function getDefaultArguments(): ParsedArgs {\n return {\n filePatterns: [],\n help: false,\n version: false,\n quiet: false,\n debug: false,\n check: false,\n };\n}\n", "import type { KnownArgument, ParsedArgs } from \"../types.js\";\nimport { getDefaultArguments } from \"./getDefaultArguments.js\";\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const result = getDefaultArguments();\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === \"--\") {\n // All following arguments are treated as file patterns, even if they start with \"--\"\n result.filePatterns.push(...argv.slice(i + 1));\n break;\n }\n\n if (parseKnownArgument(result, arg as KnownArgument)) {\n continue;\n }\n\n if (arg.startsWith(\"--\")) {\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n result.filePatterns.push(arg);\n }\n\n return result;\n}\n\nfunction parseKnownArgument(result: ParsedArgs, arg: KnownArgument): boolean {\n switch (arg) {\n case \"--help\":\n result.help = true;\n return true;\n case \"--version\":\n result.version = true;\n return true;\n case \"--quiet\":\n result.quiet = true;\n return true;\n case \"--check\":\n result.check = true;\n return true;\n case \"--debug\":\n result.debug = true;\n return true;\n default:\n return false;\n }\n}\n", "import type { Options } from \"fast-glob\";\nimport fastGlob from \"fast-glob\";\nimport * as path from \"node:path\";\nimport type { CLI } from \"../types.js\";\nimport { GLOB_IGNORE_PATTERNS } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { lstatSafe } from \"./lstatSafe.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\n\nexport async function parseFilePatterns(\n cli: CLI,\n filePatterns: string[],\n): Promise {\n const seen: Set = new Set();\n const globFileEndingPattern = getGlobFileEndingsPattern(cli.fileEndings);\n const errorMessages: string[] = [];\n\n const globOptions: Options = {\n dot: true,\n followSymbolicLinks: false,\n ignore: GLOB_IGNORE_PATTERNS,\n };\n\n for (const pattern of filePatterns) {\n const absolutePath = path.resolve(pattern);\n const stat = await lstatSafe(absolutePath);\n\n if (stat != null) {\n if (stat.isSymbolicLink()) {\n errorMessages.push(\n `Specified pattern is a symbolic link: ${pattern}`,\n );\n continue;\n }\n\n if (stat.isFile()) {\n seen.add(absolutePath);\n continue;\n }\n\n if (stat.isDirectory()) {\n const files = await fastGlob(`**/*.${globFileEndingPattern}`, {\n ...globOptions,\n cwd: absolutePath,\n });\n if (files.length === 0) {\n errorMessages.push(\n `No matching files were found in the directory: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(absolutePath, file));\n }\n continue;\n }\n }\n\n const glob = normalizeToPosix(pattern);\n const files = (await fastGlob(glob, globOptions)).filter((file) =>\n hasSupportedFileEnding(file, cli.fileEndings),\n );\n if (files.length === 0) {\n errorMessages.push(\n `No files matching the pattern were found: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(file));\n }\n }\n\n if (errorMessages.length > 0) {\n throw new FilePatternError(errorMessages);\n }\n\n return Array.from(seen).sort((a, b) => a.localeCompare(b));\n}\n\nfunction getGlobFileEndingsPattern(fileEndings: readonly string[]): string {\n return fileEndings.length === 1\n ? fileEndings[0]\n : `{${fileEndings.join(\",\")}}`;\n}\n\nfunction hasSupportedFileEnding(\n file: string,\n fileEndings: readonly string[],\n): boolean {\n const extension = path.extname(file).slice(1);\n return fileEndings.includes(extension);\n}\n", "import type { Stats } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\n\nexport async function lstatSafe(filePath: string): Promise {\n try {\n return await fs.lstat(filePath);\n } catch (error) {\n if (isMissingFileError(error)) {\n return undefined;\n }\n\n throw error;\n }\n}\n", "import type { KnownProps } from \"editorconfig\";\n\nexport const KNOWN_ARGUMENTS = [\n \"--help\",\n \"--version\",\n \"--quiet\",\n \"--check\",\n \"--debug\",\n] as const;\n\nexport type KnownArgument = (typeof KNOWN_ARGUMENTS)[number];\n\nexport interface CLI {\n binName: \"snippet-fmt\" | \"talon-fmt\" | \"tree-sitter-fmt\";\n fileEndings: readonly string[];\n\n getStdinFileEnding(text: string): string;\n format(\n text: string,\n options: Options,\n filePath: string,\n debug: boolean,\n ): Promise;\n}\n\nexport type EndOfLine = \"lf\" | \"crlf\";\n\nexport interface Options {\n endOfLine?: EndOfLine;\n indentTabs?: boolean;\n indentSize?: number;\n maxLineLength?: number;\n columnWidth?: number;\n insertFinalNewline?: boolean;\n preserveMultiline?: boolean;\n}\n\nexport type FormatterOptions = Pick;\n\nexport interface ParsedArgs {\n filePatterns: string[];\n help: boolean;\n version: boolean;\n check: boolean;\n quiet: boolean;\n debug: boolean;\n}\n\nexport interface LoggerEntry {\n level: \"log\" | \"warn\" | \"error\";\n message: string;\n}\n\nexport interface Logger {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\nexport interface TestLogger extends Logger {\n getEntries(): readonly LoggerEntry[];\n}\n\nexport interface DebugLogger {\n debug(message: string): void;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport interface EditorConfigOptions extends KnownProps {\n max_line_length?: number | \"unset\";\n column_width?: number | \"unset\";\n preserve_multiline?: boolean | \"unset\";\n}\n\ninterface Point {\n row: number;\n column: number;\n}\n\nexport interface SyntaxNode {\n id: number;\n text: string;\n type: string;\n startPosition: Point;\n endPosition: Point;\n parent: SyntaxNode | null;\n children: SyntaxNode[];\n}\n", "import type { CLI } from \"../types.js\";\nimport { KNOWN_ARGUMENTS } from \"../types.js\";\n\nexport function printHelp(cli: CLI) {\n process.stdout.write(\n `Usage: ${cli.binName} [options] [file/dir/glob ...]\\n`,\n );\n process.stdout.write(\"\\n\");\n process.stdout.write(\"Options:\\n\");\n\n for (const option of KNOWN_ARGUMENTS) {\n process.stdout.write(` ${option}\\n`);\n }\n}\n", "{\n \"name\": \"@cursorless/talon-tools\",\n \"version\": \"0.9.0\",\n \"description\": \"Linting and formatting tools for Talon and Cursorless\",\n \"author\": \"Cursorless Dev\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"!dist/test\",\n \"!dist/build.*\"\n ],\n \"types\": \"./dist/lib.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/lib.d.ts\",\n \"default\": \"./dist/lib.js\"\n },\n \"./node\": {\n \"types\": \"./dist/node/libNode.d.ts\",\n \"default\": \"./dist/libNode.js\"\n }\n },\n \"bin\": {\n \"snippet-fmt\": \"dist/snippetFormatter.js\",\n \"talon-fmt\": \"dist/talonFormatter.js\",\n \"tree-sitter-fmt\": \"dist/treeSitterFormatter.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/cursorless-dev/talon-tools.git\"\n },\n \"funding\": \"https://github.com/sponsors/cursorless-dev\",\n \"sponsor\": {\n \"url\": \"https://github.com/sponsors/cursorless-dev\"\n },\n \"scripts\": {\n \"build\": \"npm run clean && tsc -p . && tsx ./src/build.ts\",\n \"clean\": \"rm -rf dist/*\",\n \"lint\": \"npm run lint:ts &&npm run lint:fmt\",\n \"lint:ts\": \"tsc -p . --noEmit && eslint src\",\n \"lint:fmt\": \"prettier --check .\",\n \"fix\": \"npm run fix:ts && npm run fix:fmt\",\n \"fix:ts\": \"eslint src --fix\",\n \"fix:fmt\": \"prettier --write --list-different .\",\n \"test\": \"tsx src/test/runAllTests.ts\",\n \"test:subset\": \"tsx src/test/runAllTests.ts --subset\"\n },\n \"dependencies\": {\n \"@cursorless/tree-sitter-wasms\": \"^0.7.0\",\n \"editorconfig\": \"^3.0.2\",\n \"fast-glob\": \"^3.3.3\",\n \"get-stdin\": \"^10.0.0\",\n \"web-tree-sitter\": \"^0.26.7\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.4\",\n \"@types/mocha\": \"^10.0.10\",\n \"@types/node\": \"^24.12.0\",\n \"esbuild\": \"^0.27.4\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-import\": \"^2.32.0\",\n \"eslint\": \"^9.39.4\",\n \"jiti\": \"^2.6.1\",\n \"mocha\": \"^11.7.5\",\n \"prettier\": \"^3.8.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript-eslint\": \"^8.57.1\",\n \"typescript\": \"^5.9.3\"\n }\n}\n", "import packageJson from \"../../package.json\" with { type: \"json\" };\n\nexport function printVersion() {\n process.stdout.write(`${packageJson.version}\\n`);\n}\n", "#!/usr/bin/env node\n\nimport { treeSitterFormatter } from \"../treeSitterFormatter.js\";\nimport { parseText } from \"./parseText.js\";\nimport { main } from \"./cli.js\";\n\nconst fileEnding = \"scm\";\n\nvoid main({\n binName: \"tree-sitter-fmt\",\n fileEndings: [fileEnding],\n\n getStdinFileEnding() {\n return fileEnding;\n },\n\n format: async (text, options, _filePath, debug) => {\n const node = await parseText(text, \"tree-sitter-query\");\n return treeSitterFormatter(node, options, debug);\n },\n});\n"], - "mappings": "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", - "names": ["IGNORE_FOLDERS", "GLOB_IGNORE_PATTERNS", "pattern", "createDebugLogger", "debug", "message", "getEndOfLine", "eof", "getIndentation", "indentTabs", "indentSize", "treeSitterFormatter", "node", "options", "debug", "indentation", "getIndentation", "eol", "getEndOfLine", "TreeSitterFormatter", "insertFinalNewline", "createDebugLogger", "nodeText", "numIndents", "nl", "text", "index", "n", "first", "last", "interior", "parts", "s", "nodes", "lastIsQuantifier", "length", "fs", "path", "fileURLToPath", "Language", "Parser", "initPromise", "languageCache", "moduleDir", "initTreeSitter", "loadLanguage", "parserName", "promise", "wasmFilePath", "getWasmFilePath", "fileName", "candidate", "parseText", "text", "language", "parser", "tree", "getStdin", "fs", "path", "process", "FilePatternError", "messages", "getErrorMessage", "error", "isMissingFileError", "error", "setExitCode", "code", "process", "ANSI_RESET", "ANSI_YELLOW", "ANSI_RED", "WARN_PREFIX", "ERROR_PREFIX", "createLogger", "quiet", "createLoggerFromStreams", "stdout", "stderr", "colorize", "shouldUseColor", "message", "color", "_color", "log", "warn", "shouldUseColor", "stream", "editorconfig", "getOptionsFromConfig", "filePath", "config", "options", "path", "normalizeToPosix", "filepath", "getDefaultArguments", "parseArgs", "argv", "result", "getDefaultArguments", "i", "arg", "parseKnownArgument", "fastGlob", "path", "fs", "lstatSafe", "filePath", "error", "isMissingFileError", "parseFilePatterns", "cli", "filePatterns", "seen", "globFileEndingPattern", "getGlobFileEndingsPattern", "errorMessages", "globOptions", "GLOB_IGNORE_PATTERNS", "pattern", "absolutePath", "stat", "lstatSafe", "files", "fastGlob", "file", "glob", "normalizeToPosix", "hasSupportedFileEnding", "FilePatternError", "a", "b", "fileEndings", "extension", "KNOWN_ARGUMENTS", "printHelp", "cli", "option", "KNOWN_ARGUMENTS", "package_default", "printVersion", "package_default", "main", "cli", "logger", "createLogger", "args", "parseArgs", "exitCode", "mainUnsafe", "setExitCode", "error", "FilePatternError", "message", "getErrorMessage", "printHelp", "printVersion", "mainFormatFiles", "mainFormatStdin", "check", "debug", "filePatterns", "filePaths", "parseFilePatterns", "changedFileCount", "formatFiles", "fileName", "formatFile", "filePath", "options", "getOptionsFromConfig", "content", "formatted", "getDisplayPath", "isMissingFileError", "normalizeToPosix", "stdin", "input", "getStdin", "fileEnding", "main", "text", "options", "_filePath", "debug", "node", "parseText", "treeSitterFormatter"] + "sources": ["../src/util/constants.ts", "../src/util/createDebugLogger.ts", "../src/util/getEndOfLine.ts", "../src/util/getIndentation.ts", "../src/util/SyntaxError.ts", "../src/util/SyntaxTreeError.ts", "../src/treeSitterFormatter.ts", "../src/node/parseText.ts", "../src/node/cli.ts", "../src/util/getErrorMessage.ts", "../src/node/createLogger.ts", "../src/node/FilePatternError.ts", "../src/node/getOptionsFromConfig.ts", "../src/node/isMissingFileError.ts", "../src/node/normalizeToPosix.ts", "../src/node/getDefaultArguments.ts", "../src/node/parseArgs.ts", "../src/node/parseFilePatterns.ts", "../src/node/lstatSafe.ts", "../src/types.ts", "../src/node/printHelp.ts", "../package.json", "../src/node/printVersion.ts", "../src/node/setExitCode.ts", "../src/node/treeSitterFormatter.ts"], + "sourcesContent": ["// Exit code 0: Success\nexport const EXIT_OK = 0;\n// Exit code 1: Check failed\nexport const EXIT_FAIL = 1;\n// Exit code 2: Unexpected error\nexport const EXIT_ERROR = 2;\n\nexport type ExitCode = typeof EXIT_OK | typeof EXIT_FAIL | typeof EXIT_ERROR;\n\nexport const DEFAULT_INDENT_WIDTH = 4;\nexport const DEFAULT_MAX_LINE_LENGTH = 80;\nexport const DEFAULT_INSERT_FINAL_NEWLINE = true;\n\nexport const IGNORE_FOLDERS = [\n \".git\",\n \".svn\",\n \".hg\",\n \"node_modules\",\n \"__pycache__\",\n];\n\nexport const GLOB_IGNORE_PATTERNS = IGNORE_FOLDERS.map(\n (pattern) => `**/${pattern}/**`,\n);\n", "import type { DebugLogger } from \"../types.js\";\n\nexport function createDebugLogger(debug: boolean): DebugLogger {\n return {\n debug(message: string) {\n if (debug) {\n console.warn(`[debug] ${message}`);\n }\n },\n };\n}\n", "import type { EndOfLine } from \"../types.js\";\n\nexport function getEndOfLine(eof?: EndOfLine): string {\n return eof === \"crlf\" ? \"\\r\\n\" : \"\\n\";\n}\n", "import { DEFAULT_INDENT_WIDTH } from \"./constants.js\";\n\nexport function getIndentation(\n indentTabs: boolean | undefined,\n indentSize: number | undefined,\n): string {\n return indentTabs ? \"\\t\" : \" \".repeat(indentSize ?? DEFAULT_INDENT_WIDTH);\n}\n", "import type { Point } from \"../types.js\";\n\nexport class SyntaxError extends Error {\n constructor(private location?: Point) {\n super(\"Syntax error.\");\n this.name = \"SyntaxError\";\n }\n\n getLocation(): string | undefined {\n return this.location != null\n ? `(${this.location.row + 1}:${this.location.column + 1})`\n : undefined;\n }\n}\n\nexport function isSyntaxError(error: unknown): error is SyntaxError {\n return error instanceof SyntaxError;\n}\n", "import type { SyntaxNode } from \"../types.js\";\nimport { SyntaxError } from \"./SyntaxError.js\";\n\nexport class SyntaxTreeError extends SyntaxError {\n constructor(rootNode: SyntaxNode) {\n super(findFirstProblemNode(rootNode)?.startPosition);\n this.name = \"SyntaxTreeError\";\n }\n}\n\nfunction findFirstProblemNode(node: SyntaxNode): SyntaxNode | null {\n if (node.isError || node.isMissing) {\n return node;\n }\n for (const child of node.children) {\n if (!child.hasError) {\n continue;\n }\n const errorNode = findFirstProblemNode(child);\n if (errorNode != null) {\n return errorNode;\n }\n }\n return null;\n}\n", "import type { DebugLogger, FormatterOptions, SyntaxNode } from \"./types.js\";\nimport { DEFAULT_INSERT_FINAL_NEWLINE } from \"./util/constants.js\";\nimport { createDebugLogger } from \"./util/createDebugLogger.js\";\nimport { getEndOfLine } from \"./util/getEndOfLine.js\";\nimport { getIndentation } from \"./util/getIndentation.js\";\nimport { SyntaxTreeError } from \"./util/SyntaxTreeError.js\";\n\nexport type Options = FormatterOptions<\n \"endOfLine\" | \"indentTabs\" | \"indentSize\" | \"insertFinalNewline\"\n>;\n\nexport function treeSitterFormatter(\n node: SyntaxNode,\n options: Options = {},\n debug: boolean = false,\n): string {\n if (node.hasError) {\n throw new SyntaxTreeError(node);\n }\n\n const indentation = getIndentation(options.indentTabs, options.indentSize);\n const eol = getEndOfLine(options.endOfLine);\n const formatter = new TreeSitterFormatter(\n indentation,\n eol,\n options.insertFinalNewline ?? DEFAULT_INSERT_FINAL_NEWLINE,\n debug,\n );\n return formatter.getText(node);\n}\n\nclass TreeSitterFormatter {\n private lastRow = 0;\n private logger: DebugLogger;\n\n constructor(\n private indentation: string,\n private eol: string,\n private insertFinalNewline: boolean,\n debug: boolean,\n ) {\n this.logger = createDebugLogger(debug);\n }\n\n getText(node: SyntaxNode): string {\n const nodeText = this.getNodeText(node, 0);\n\n if (nodeText.length === 0) {\n return \"\";\n }\n\n if (this.insertFinalNewline) {\n return nodeText + this.eol;\n }\n\n return nodeText;\n }\n\n private getNodeText(node: SyntaxNode, numIndents: number): string {\n const nl = node.startPosition.row > this.lastRow + 1 ? this.eol : \"\";\n this.lastRow = node.endPosition.row;\n const text = this.getNodeTextInternal(node, numIndents);\n this.lastRow = node.endPosition.row;\n return `${nl}${text}`;\n }\n\n private getNamedNodeText(node: SyntaxNode, numIndents: number): string {\n const index = node.children.findIndex((n) => n.type === \")\");\n const first = node.children\n .slice(0, 2)\n .map((n) => n.text)\n .join(\"\");\n const last = node.children\n .slice(index)\n .map((n) => this.getNodeText(n, 0))\n .join(\"\");\n const interior = node.children\n .slice(2, index)\n .map((n) => this.getNodeText(n, numIndents + 1));\n // Inline node\n if (interior.length === 0) {\n return `${this.getIndent(numIndents)}${first}${last}`;\n }\n // Multiline node\n return [\n `${this.getIndent(numIndents)}${first}`,\n ...interior,\n `${this.getIndent(numIndents)}${last}`,\n ].join(this.eol);\n }\n\n private getListText(node: SyntaxNode, numIndents: number): string {\n const index = node.children.findIndex((n) => n.type === \"]\");\n const first = node.children[0].text;\n const last = node.children\n .slice(index)\n .map((n) => n.text)\n .join(\" \");\n const parts = [\n `${this.getIndent(numIndents)}${first}`,\n ...node.children\n .slice(1, index)\n .map((n) => this.getNodeText(n, numIndents + 1)),\n `${this.getIndent(numIndents)}${last}`,\n ];\n return parts.join(this.eol);\n }\n\n private getPredicateText(node: SyntaxNode, numIndents: number): string {\n const first = node.children[0].text;\n const last = node.children[node.children.length - 1].text;\n const parts = [\n node.children\n .slice(1, 4)\n .map((n) => n.text)\n .join(\"\"),\n ...node.children[node.children.length - 2].children.map(\n (n) => n.text,\n ),\n ];\n // Inline predicate\n if (node.startPosition.row === node.endPosition.row) {\n const text = `${first}${parts.join(\" \")}${last}`;\n return `${this.getIndent(numIndents)}${text}`;\n }\n // Multiline predicate\n return [\n `${this.getIndent(numIndents)}${first}${parts[0]}`,\n ...parts\n .slice(1)\n .map((s) => `${this.getIndent(numIndents + 1)}${s}`),\n `${this.getIndent(numIndents)}${last}`,\n ].join(this.eol);\n }\n\n private getFieldDefinitionText(\n node: SyntaxNode,\n numIndents: number,\n ): string {\n // Field definition directly in document root\n if (numIndents === 0) {\n return [\"(_\", this.getFieldDefinitionText(node, 1), \")\"].join(\n this.eol,\n );\n }\n // [lhs, \":\", rhs]\n return [\n this.getIndent(numIndents),\n node.children[0].text,\n node.children[1].text,\n \" \",\n this.getNodeText(node.children[2], numIndents).trimStart(),\n ].join(\"\");\n }\n\n private getNodeTextInternal(node: SyntaxNode, numIndents: number): string {\n switch (node.type) {\n case \"program\":\n return this.joinLines(node.children, 0);\n\n case \"grouping\":\n return this.joinLines(node.children, numIndents + 1);\n\n case \"list\":\n return this.getListText(node, numIndents);\n\n case \"named_node\":\n return this.getNamedNodeText(node, numIndents);\n\n case \"predicate\":\n return this.getPredicateText(node, numIndents);\n\n case \"field_definition\":\n return this.getFieldDefinitionText(node, numIndents);\n\n case \"anonymous_node\":\n return (\n this.getIndent(numIndents) +\n node.children\n .map((n) => this.getNodeText(n, numIndents + 1))\n .join(\"\")\n );\n\n case \"comment\":\n return `${this.getIndent(numIndents)}${node.text.trimEnd()}`;\n\n case \".\":\n case \"negated_field\":\n return `${this.getIndent(numIndents)}${node.text}`;\n\n case \"(\":\n case \")\":\n return `${this.getIndent(numIndents - 1)}${node.text}`;\n\n case \"capture\":\n return ` ${node.text}`;\n\n case \"#\":\n case \"_\":\n case \"predicate_type\":\n case \"identifier\":\n case \"quantifier\":\n case \"string\":\n return node.text;\n\n case \"parameters\": {\n const text = node.children.map((n) => n.text).join(\" \");\n return ` ${text}`;\n }\n\n default:\n this.logger.debug(`Unknown syntax node type '${node.type}'`);\n return node.text;\n }\n }\n\n private joinLines(nodes: SyntaxNode[], numIndents: number): string {\n if (nodes.length === 0) {\n return \"\";\n }\n const lastIsQuantifier = nodes[nodes.length - 1].type === \"quantifier\";\n const nodesToUse = lastIsQuantifier ? nodes.slice(0, -1) : nodes;\n const text = nodesToUse\n .map((n) => this.getNodeText(n, numIndents))\n .join(this.eol);\n return lastIsQuantifier\n ? `${text}${nodes[nodes.length - 1].text}`\n : text;\n }\n\n private getIndent(length: number): string {\n return length < 1\n ? \"\"\n : new Array(length).fill(this.indentation).join(\"\");\n }\n}\n", "import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Node } from \"web-tree-sitter\";\nimport { Language, Parser } from \"web-tree-sitter\";\n\ntype ParserName = \"tree-sitter-talon\" | \"tree-sitter-query\";\n\nlet initPromise: Promise | undefined;\nconst languageCache = new Map>();\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\nfunction initTreeSitter() {\n initPromise ??= Parser.init();\n return initPromise;\n}\n\nfunction loadLanguage(parserName: ParserName) {\n let promise = languageCache.get(parserName);\n\n if (promise == null) {\n const wasmFilePath = getWasmFilePath(parserName);\n promise = Language.load(wasmFilePath);\n languageCache.set(parserName, promise);\n }\n\n return promise;\n}\n\nfunction getWasmFilePath(parserName: ParserName) {\n const fileName = `${parserName}.wasm`;\n const wasmFilePath = [\n path.join(\n moduleDir,\n \"../../node_modules/@cursorless/tree-sitter-wasms/out\",\n fileName,\n ),\n path.join(\n moduleDir,\n \"../node_modules/@cursorless/tree-sitter-wasms/out\",\n fileName,\n ),\n ].find((candidate) => fs.existsSync(candidate));\n\n if (wasmFilePath == null) {\n throw new Error(`Could not find ${fileName}`);\n }\n\n return wasmFilePath;\n}\n\nexport async function parseText(\n text: string,\n parserName: ParserName,\n): Promise {\n await initTreeSitter();\n\n const language = await loadLanguage(parserName);\n\n const parser = new Parser();\n parser.setLanguage(language);\n\n const tree = parser.parse(text);\n\n if (tree == null) {\n throw new Error(\"Failed to parse text\");\n }\n\n return tree.rootNode;\n}\n", "import getStdin from \"get-stdin\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as process from \"node:process\";\nimport type { Readable } from \"node:stream\";\nimport type { CLI, Logger, ParsedArgs } from \"../types.js\";\nimport {\n EXIT_ERROR,\n EXIT_FAIL,\n EXIT_OK,\n type ExitCode,\n} from \"../util/constants.js\";\nimport { getErrorMessage } from \"../util/getErrorMessage.js\";\nimport { isSyntaxError } from \"../util/SyntaxError.js\";\nimport { createLogger } from \"./createLogger.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { getOptionsFromConfig } from \"./getOptionsFromConfig.js\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\nimport { parseArgs } from \"./parseArgs.js\";\nimport { parseFilePatterns } from \"./parseFilePatterns.js\";\nimport { printHelp } from \"./printHelp.js\";\nimport { printVersion } from \"./printVersion.js\";\nimport { setExitCode } from \"./setExitCode.js\";\n\nexport async function main(cli: CLI): Promise {\n let logger = createLogger();\n\n try {\n const args = parseArgs(process.argv.slice(2));\n logger = createLogger(args.quiet);\n const exitCode = await mainUnsafe({ cli, args, logger });\n setExitCode(exitCode);\n } catch (error) {\n if (error instanceof FilePatternError) {\n for (const message of error.messages) {\n logger.error(message);\n }\n } else {\n logger.error(getErrorMessage(error));\n }\n setExitCode(EXIT_ERROR);\n }\n}\n\ninterface MainUnsafeArgs {\n cli: CLI;\n args: ParsedArgs;\n logger: Logger;\n}\n\nasync function mainUnsafe({\n cli,\n args,\n logger,\n}: MainUnsafeArgs): Promise {\n if (args.help) {\n printHelp(cli);\n return EXIT_OK;\n }\n\n if (args.version) {\n printVersion();\n return EXIT_OK;\n }\n\n const hasFilePatterns = args.filePatterns.length > 0;\n\n if (hasFilePatterns) {\n return mainFormatFiles({\n cli,\n logger,\n check: args.check,\n debug: args.debug,\n filePatterns: args.filePatterns,\n });\n }\n\n // If no file patterns are provided, check if there's input from stdin.\n // If stdin TTY it's an interactive terminal, so we shouldn't read from it.\n if (!process.stdin.isTTY) {\n return mainFormatStdin({\n cli,\n logger,\n stdin: process.stdin,\n check: args.check,\n debug: args.debug,\n });\n }\n\n throw new Error(\n \"No input files specified. Use --help for usage information.\",\n );\n}\n\ninterface MainFormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePatterns: string[];\n}\n\nasync function mainFormatFiles({\n cli,\n logger,\n check,\n debug,\n filePatterns,\n}: MainFormatFilesArgs): Promise {\n if (check) {\n logger.log(\"Checking formatting...\");\n }\n\n const filePaths = await parseFilePatterns(cli, filePatterns);\n const [changedFileCount, hasError] = await formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n });\n\n if (check) {\n if (changedFileCount > 0) {\n logger.warn(\n `Code style issues found in ${changedFileCount} file(s).`,\n );\n if (!hasError) {\n return EXIT_FAIL;\n }\n }\n\n if (!hasError) {\n logger.log(\"All matched files use correct code style!\");\n }\n }\n\n if (hasError) {\n return EXIT_ERROR;\n }\n\n return EXIT_OK;\n}\n\ninterface FormatFilesArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePaths: string[];\n}\n\nexport async function formatFiles({\n cli,\n logger,\n check,\n debug,\n filePaths,\n}: FormatFilesArgs): Promise<[number, boolean]> {\n let changedFileCount = 0;\n let hasError = false;\n\n for (const filePath of filePaths) {\n try {\n const fileWasChanged = await formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n });\n if (fileWasChanged) {\n changedFileCount++;\n }\n } catch (error) {\n if (isSyntaxError(error)) {\n logger.error(\n `${getDisplayPath(filePath)}${error.getLocation()}: ${error.message}`,\n );\n } else {\n logger.error(\n `${getDisplayPath(filePath)}: ${getErrorMessage(error)}`,\n );\n }\n hasError = true;\n }\n }\n\n return [changedFileCount, hasError];\n}\n\ninterface FormatFileArgs {\n cli: CLI;\n logger: Logger;\n check: boolean;\n debug: boolean;\n filePath: string;\n}\n\nexport async function formatFile({\n cli,\n logger,\n check,\n debug,\n filePath,\n}: FormatFileArgs): Promise {\n try {\n const options = await getOptionsFromConfig(filePath);\n const content = await fs.readFile(filePath, \"utf8\");\n const formatted = await cli.format(content, options, filePath, debug);\n\n if (formatted === content) {\n return false;\n }\n\n logger.log(getDisplayPath(filePath));\n\n if (!check) {\n await fs.writeFile(filePath, formatted, \"utf8\");\n }\n\n return true;\n } catch (error) {\n if (isMissingFileError(error)) {\n return false;\n }\n\n throw error;\n }\n}\n\nfunction getDisplayPath(filePath: string): string {\n return normalizeToPosix(path.relative(process.cwd(), filePath));\n}\n\ninterface MainFormatStdinArgs {\n cli: CLI;\n logger: Logger;\n stdin: Readable;\n check: boolean;\n debug: boolean;\n}\n\nexport async function mainFormatStdin({\n cli,\n logger,\n stdin,\n check,\n debug,\n}: MainFormatStdinArgs): Promise {\n const input = await getStdin({ stdin });\n const fileEnding = cli.getStdinFileEnding(input);\n const fauxFileName = `stdin.${fileEnding}`;\n const fauxFilePath = path.resolve(fauxFileName);\n const options = await getOptionsFromConfig(fauxFilePath);\n let formatted: string;\n\n try {\n formatted = await cli.format(input, options, fauxFilePath, debug);\n } catch (error) {\n if (isSyntaxError(error)) {\n logger.error(`stdin${error.getLocation()}: ${error.message}`);\n return EXIT_ERROR;\n }\n throw error;\n }\n\n if (check) {\n if (input !== formatted) {\n logger.warn(\"Code style issues found in stdin.\");\n return EXIT_FAIL;\n }\n\n return EXIT_OK;\n }\n\n process.stdout.write(formatted);\n\n return EXIT_OK;\n}\n", "export function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n", "import * as process from \"node:process\";\nimport type { WriteStream } from \"node:tty\";\nimport type { Logger, LoggerEntry, TestLogger } from \"../types.js\";\n\ntype LogCallback = (message: string) => void;\ntype ColorizeCallback = (message: string, color: string) => string;\ntype LoggerStream = Pick & Partial;\n\nconst ANSI_RESET = \"\\u001b[0m\";\nconst ANSI_YELLOW = \"\\u001b[33m\";\nconst ANSI_RED = \"\\u001b[31m\";\nconst WARN_PREFIX = \"[warn]\";\nconst ERROR_PREFIX = \"[error]\";\n\nexport function createLogger(quiet: boolean = false): Logger {\n return createLoggerFromStreams(process.stdout, process.stderr, quiet);\n}\n\nexport function createLoggerFromStreams(\n stdout: LoggerStream,\n stderr: LoggerStream,\n quiet: boolean = false,\n): Logger {\n const colorize: ColorizeCallback = shouldUseColor(stderr)\n ? (message, color) => `${color}${message}${ANSI_RESET}`\n : (message, _color) => message;\n\n let log: LogCallback;\n let warn: LogCallback;\n\n if (quiet) {\n log = () => {};\n warn = () => {};\n } else {\n log = (message: string) => {\n stdout.write(`${message}\\n`);\n };\n warn = (message: string) => {\n stderr.write(`${colorize(WARN_PREFIX, ANSI_YELLOW)} ${message}\\n`);\n };\n }\n\n return {\n log,\n warn,\n error(message: string) {\n stderr.write(`${colorize(ERROR_PREFIX, ANSI_RED)} ${message}\\n`);\n },\n };\n}\n\nexport function createTestLogger(): TestLogger {\n const entries: LoggerEntry[] = [];\n\n return {\n log(message: string) {\n entries.push({ level: \"log\", message });\n },\n warn(message: string) {\n entries.push({ level: \"warn\", message });\n },\n error(message: string) {\n entries.push({ level: \"error\", message });\n },\n getEntries() {\n return entries;\n },\n };\n}\n\nfunction shouldUseColor(stream: LoggerStream): boolean {\n if (\"NO_COLOR\" in process.env) {\n return false;\n }\n\n return stream.isTTY === true;\n}\n", "export class FilePatternError extends Error {\n name = \"FilePatternError\";\n\n constructor(public messages: string[]) {\n super(\n `One or more file pattern errors occurred:\\n${messages.join(\"\\n\")}`,\n );\n }\n}\n", "import * as editorconfig from \"editorconfig\";\nimport type { EditorConfigOptions, Options } from \"../types.js\";\n\nexport async function getOptionsFromConfig(filePath: string): Promise {\n const config = (await editorconfig.parse(filePath)) as EditorConfigOptions;\n\n const options: Options = {};\n\n if (config.indent_style === \"tab\") {\n options.indentTabs = true;\n } else if (config.indent_style === \"space\") {\n options.indentTabs = false;\n }\n\n if (typeof config.indent_size === \"number\") {\n options.indentSize = config.indent_size;\n } else if (\n config.indent_size === \"tab\" &&\n typeof config.tab_width === \"number\"\n ) {\n options.indentSize = config.tab_width;\n }\n\n if (typeof config.max_line_length === \"number\") {\n options.maxLineLength = config.max_line_length;\n }\n\n if (typeof config.column_width === \"number\") {\n options.columnWidth = config.column_width;\n }\n\n if (typeof config.insert_final_newline === \"boolean\") {\n options.insertFinalNewline = config.insert_final_newline;\n }\n\n if (typeof config.preserve_multiline === \"boolean\") {\n options.preserveMultiline = config.preserve_multiline;\n }\n\n if (config.end_of_line != null && config.end_of_line !== \"unset\") {\n options.endOfLine = config.end_of_line;\n }\n\n return options;\n}\n", "export function isMissingFileError(\n error: unknown,\n): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n", "import * as path from \"node:path\";\n\n/**\n * Replace `\\` with `/` on Windows\n * @param {string} filepath\n * @returns {string}\n */\nexport const normalizeToPosix =\n path.sep === \"\\\\\"\n ? (filepath: string) => filepath.replaceAll(\"\\\\\", \"/\")\n : (filepath: string) => filepath;\n", "import type { ParsedArgs } from \"../types.js\";\n\nexport function getDefaultArguments(): ParsedArgs {\n return {\n filePatterns: [],\n help: false,\n version: false,\n quiet: false,\n debug: false,\n check: false,\n };\n}\n", "import type { KnownArgument, ParsedArgs } from \"../types.js\";\nimport { getDefaultArguments } from \"./getDefaultArguments.js\";\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const result = getDefaultArguments();\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === \"--\") {\n // All following arguments are treated as file patterns, even if they start with \"--\"\n result.filePatterns.push(...argv.slice(i + 1));\n break;\n }\n\n if (parseKnownArgument(result, arg as KnownArgument)) {\n continue;\n }\n\n if (arg.startsWith(\"--\")) {\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n result.filePatterns.push(arg);\n }\n\n return result;\n}\n\nfunction parseKnownArgument(result: ParsedArgs, arg: KnownArgument): boolean {\n switch (arg) {\n case \"--help\":\n result.help = true;\n return true;\n case \"--version\":\n result.version = true;\n return true;\n case \"--quiet\":\n result.quiet = true;\n return true;\n case \"--check\":\n result.check = true;\n return true;\n case \"--debug\":\n result.debug = true;\n return true;\n default:\n return false;\n }\n}\n", "import type { Options } from \"fast-glob\";\nimport fastGlob from \"fast-glob\";\nimport * as path from \"node:path\";\nimport type { CLI } from \"../types.js\";\nimport { GLOB_IGNORE_PATTERNS } from \"../util/constants.js\";\nimport { FilePatternError } from \"./FilePatternError.js\";\nimport { lstatSafe } from \"./lstatSafe.js\";\nimport { normalizeToPosix } from \"./normalizeToPosix.js\";\n\nexport async function parseFilePatterns(\n cli: CLI,\n filePatterns: string[],\n): Promise {\n const seen: Set = new Set();\n const globFileEndingPattern = getGlobFileEndingsPattern(cli.fileEndings);\n const errorMessages: string[] = [];\n\n const globOptions: Options = {\n dot: true,\n followSymbolicLinks: false,\n ignore: GLOB_IGNORE_PATTERNS,\n };\n\n for (const pattern of filePatterns) {\n const absolutePath = path.resolve(pattern);\n const stat = await lstatSafe(absolutePath);\n\n if (stat != null) {\n if (stat.isSymbolicLink()) {\n errorMessages.push(\n `Specified pattern is a symbolic link: ${pattern}`,\n );\n continue;\n }\n\n if (stat.isFile()) {\n seen.add(absolutePath);\n continue;\n }\n\n if (stat.isDirectory()) {\n const files = await fastGlob(`**/*.${globFileEndingPattern}`, {\n ...globOptions,\n cwd: absolutePath,\n });\n if (files.length === 0) {\n errorMessages.push(\n `No matching files were found in the directory: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(absolutePath, file));\n }\n continue;\n }\n }\n\n const glob = normalizeToPosix(pattern);\n const files = (await fastGlob(glob, globOptions)).filter((file) =>\n hasSupportedFileEnding(file, cli.fileEndings),\n );\n if (files.length === 0) {\n errorMessages.push(\n `No files matching the pattern were found: ${pattern}`,\n );\n }\n for (const file of files) {\n seen.add(path.resolve(file));\n }\n }\n\n if (errorMessages.length > 0) {\n throw new FilePatternError(errorMessages);\n }\n\n return Array.from(seen).sort((a, b) => a.localeCompare(b));\n}\n\nfunction getGlobFileEndingsPattern(fileEndings: readonly string[]): string {\n return fileEndings.length === 1\n ? fileEndings[0]\n : `{${fileEndings.join(\",\")}}`;\n}\n\nfunction hasSupportedFileEnding(\n file: string,\n fileEndings: readonly string[],\n): boolean {\n const extension = path.extname(file).slice(1);\n return fileEndings.includes(extension);\n}\n", "import type { Stats } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport { isMissingFileError } from \"./isMissingFileError.js\";\n\nexport async function lstatSafe(filePath: string): Promise {\n try {\n return await fs.lstat(filePath);\n } catch (error) {\n if (isMissingFileError(error)) {\n return undefined;\n }\n\n throw error;\n }\n}\n", "import type { KnownProps } from \"editorconfig\";\n\nexport const KNOWN_ARGUMENTS = [\n \"--help\",\n \"--version\",\n \"--quiet\",\n \"--check\",\n \"--debug\",\n] as const;\n\nexport type KnownArgument = (typeof KNOWN_ARGUMENTS)[number];\n\nexport interface CLI {\n binName: \"snippet-fmt\" | \"talon-fmt\" | \"tree-sitter-fmt\";\n fileEndings: readonly string[];\n\n getStdinFileEnding(text: string): string;\n format(\n text: string,\n options: Options,\n filePath: string,\n debug: boolean,\n ): Promise;\n}\n\nexport type EndOfLine = \"lf\" | \"crlf\";\n\nexport interface Options {\n endOfLine?: EndOfLine;\n indentTabs?: boolean;\n indentSize?: number;\n maxLineLength?: number;\n columnWidth?: number;\n insertFinalNewline?: boolean;\n preserveMultiline?: boolean;\n}\n\nexport type FormatterOptions = Pick;\n\nexport interface ParsedArgs {\n filePatterns: string[];\n help: boolean;\n version: boolean;\n check: boolean;\n quiet: boolean;\n debug: boolean;\n}\n\nexport interface LoggerEntry {\n level: \"log\" | \"warn\" | \"error\";\n message: string;\n}\n\nexport interface Logger {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\nexport interface TestLogger extends Logger {\n getEntries(): readonly LoggerEntry[];\n}\n\nexport interface DebugLogger {\n debug(message: string): void;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport interface EditorConfigOptions extends KnownProps {\n max_line_length?: number | \"unset\";\n column_width?: number | \"unset\";\n preserve_multiline?: boolean | \"unset\";\n}\n\nexport interface Point {\n row: number;\n column: number;\n}\n\nexport interface SyntaxNode {\n id: number;\n text: string;\n type: string;\n startPosition: Point;\n endPosition: Point;\n hasError: boolean;\n isError: boolean;\n isMissing: boolean;\n parent: SyntaxNode | null;\n children: SyntaxNode[];\n}\n", "import type { CLI } from \"../types.js\";\nimport { KNOWN_ARGUMENTS } from \"../types.js\";\n\nexport function printHelp(cli: CLI) {\n process.stdout.write(\n `Usage: ${cli.binName} [options] [file/dir/glob ...]\\n`,\n );\n process.stdout.write(\"\\n\");\n process.stdout.write(\"Options:\\n\");\n\n for (const option of KNOWN_ARGUMENTS) {\n process.stdout.write(` ${option}\\n`);\n }\n}\n", "{\n \"name\": \"@cursorless/talon-tools\",\n \"version\": \"0.10.0\",\n \"description\": \"Linting and formatting tools for Talon and Cursorless\",\n \"author\": \"Cursorless Dev\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"!dist/test\",\n \"!dist/build.*\"\n ],\n \"types\": \"./dist/lib.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/lib.d.ts\",\n \"default\": \"./dist/lib.js\"\n },\n \"./node\": {\n \"types\": \"./dist/node/libNode.d.ts\",\n \"default\": \"./dist/libNode.js\"\n }\n },\n \"bin\": {\n \"snippet-fmt\": \"dist/snippetFormatter.js\",\n \"talon-fmt\": \"dist/talonFormatter.js\",\n \"tree-sitter-fmt\": \"dist/treeSitterFormatter.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/cursorless-dev/talon-tools.git\"\n },\n \"funding\": \"https://github.com/sponsors/cursorless-dev\",\n \"sponsor\": {\n \"url\": \"https://github.com/sponsors/cursorless-dev\"\n },\n \"scripts\": {\n \"build\": \"npm run clean && tsc -p . && tsx ./src/build.ts\",\n \"clean\": \"rm -rf dist/*\",\n \"lint\": \"npm run lint:ts &&npm run lint:fmt\",\n \"lint:ts\": \"tsc -p . --noEmit && eslint src\",\n \"lint:fmt\": \"prettier --check .\",\n \"fix\": \"npm run fix:ts && npm run fix:fmt\",\n \"fix:ts\": \"eslint src --fix\",\n \"fix:fmt\": \"prettier --write --list-different .\",\n \"test\": \"tsx src/test/runAllTests.ts\",\n \"test:subset\": \"tsx src/test/runAllTests.ts --subset\"\n },\n \"dependencies\": {\n \"@cursorless/tree-sitter-wasms\": \"^0.7.0\",\n \"editorconfig\": \"^3.0.2\",\n \"fast-glob\": \"^3.3.3\",\n \"get-stdin\": \"^10.0.0\",\n \"web-tree-sitter\": \"^0.26.7\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.4\",\n \"@types/mocha\": \"^10.0.10\",\n \"@types/node\": \"^24.12.0\",\n \"esbuild\": \"^0.27.4\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-import\": \"^2.32.0\",\n \"eslint\": \"^9.39.4\",\n \"jiti\": \"^2.6.1\",\n \"mocha\": \"^11.7.5\",\n \"prettier\": \"^3.8.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript-eslint\": \"^8.57.1\",\n \"typescript\": \"^5.9.3\"\n }\n}\n", "import packageJson from \"../../package.json\" with { type: \"json\" };\n\nexport function printVersion() {\n process.stdout.write(`${packageJson.version}\\n`);\n}\n", "export function setExitCode(code: number): void {\n Reflect.set(process, \"exitCode\", code);\n}\n", "#!/usr/bin/env node\n\nimport { treeSitterFormatter } from \"../treeSitterFormatter.js\";\nimport { parseText } from \"./parseText.js\";\nimport { main } from \"./cli.js\";\n\nconst fileEnding = \"scm\";\n\nvoid main({\n binName: \"tree-sitter-fmt\",\n fileEndings: [fileEnding],\n\n getStdinFileEnding() {\n return fileEnding;\n },\n\n format: async (text, options, _filePath, debug) => {\n const node = await parseText(text, \"tree-sitter-query\");\n return treeSitterFormatter(node, options, debug);\n },\n});\n"], + "mappings": "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", + "names": ["IGNORE_FOLDERS", "GLOB_IGNORE_PATTERNS", "pattern", "createDebugLogger", "debug", "message", "getEndOfLine", "eof", "getIndentation", "indentTabs", "indentSize", "SyntaxError", "location", "isSyntaxError", "error", "SyntaxTreeError", "SyntaxError", "rootNode", "findFirstProblemNode", "node", "child", "errorNode", "treeSitterFormatter", "node", "options", "debug", "SyntaxTreeError", "indentation", "getIndentation", "eol", "getEndOfLine", "TreeSitterFormatter", "insertFinalNewline", "createDebugLogger", "nodeText", "numIndents", "nl", "text", "index", "n", "first", "last", "interior", "parts", "s", "nodes", "lastIsQuantifier", "length", "fs", "path", "fileURLToPath", "Language", "Parser", "initPromise", "languageCache", "moduleDir", "initTreeSitter", "loadLanguage", "parserName", "promise", "wasmFilePath", "getWasmFilePath", "fileName", "candidate", "parseText", "text", "language", "parser", "tree", "getStdin", "fs", "path", "process", "getErrorMessage", "error", "process", "ANSI_RESET", "ANSI_YELLOW", "ANSI_RED", "WARN_PREFIX", "ERROR_PREFIX", "createLogger", "quiet", "createLoggerFromStreams", "stdout", "stderr", "colorize", "shouldUseColor", "message", "color", "_color", "log", "warn", "shouldUseColor", "stream", "FilePatternError", "messages", "editorconfig", "getOptionsFromConfig", "filePath", "config", "options", "isMissingFileError", "error", "path", "normalizeToPosix", "filepath", "getDefaultArguments", "parseArgs", "argv", "result", "getDefaultArguments", "i", "arg", "parseKnownArgument", "fastGlob", "path", "fs", "lstatSafe", "filePath", "error", "isMissingFileError", "parseFilePatterns", "cli", "filePatterns", "seen", "globFileEndingPattern", "getGlobFileEndingsPattern", "errorMessages", "globOptions", "GLOB_IGNORE_PATTERNS", "pattern", "absolutePath", "stat", "lstatSafe", "files", "fastGlob", "file", "glob", "normalizeToPosix", "hasSupportedFileEnding", "FilePatternError", "a", "b", "fileEndings", "extension", "KNOWN_ARGUMENTS", "printHelp", "cli", "option", "KNOWN_ARGUMENTS", "package_default", "printVersion", "package_default", "setExitCode", "code", "main", "cli", "logger", "createLogger", "args", "parseArgs", "exitCode", "mainUnsafe", "setExitCode", "error", "FilePatternError", "message", "getErrorMessage", "printHelp", "printVersion", "mainFormatFiles", "mainFormatStdin", "check", "debug", "filePatterns", "filePaths", "parseFilePatterns", "changedFileCount", "hasError", "formatFiles", "filePath", "formatFile", "isSyntaxError", "getDisplayPath", "options", "getOptionsFromConfig", "content", "formatted", "isMissingFileError", "normalizeToPosix", "stdin", "input", "getStdin", "fauxFileName", "fauxFilePath", "fileEnding", "main", "text", "options", "_filePath", "debug", "node", "parseText", "treeSitterFormatter"] } diff --git a/dist/types.d.ts b/dist/types.d.ts index 4d8a91d..1cbf5ec 100644 --- a/dist/types.d.ts +++ b/dist/types.d.ts @@ -46,7 +46,7 @@ export interface EditorConfigOptions extends KnownProps { column_width?: number | "unset"; preserve_multiline?: boolean | "unset"; } -interface Point { +export interface Point { row: number; column: number; } @@ -56,7 +56,9 @@ export interface SyntaxNode { type: string; startPosition: Point; endPosition: Point; + hasError: boolean; + isError: boolean; + isMissing: boolean; parent: SyntaxNode | null; children: SyntaxNode[]; } -export {}; diff --git a/dist/util/SyntaxError.d.ts b/dist/util/SyntaxError.d.ts new file mode 100644 index 0000000..766db50 --- /dev/null +++ b/dist/util/SyntaxError.d.ts @@ -0,0 +1,7 @@ +import type { Point } from "../types.js"; +export declare class SyntaxError extends Error { + private location?; + constructor(location?: Point | undefined); + getLocation(): string | undefined; +} +export declare function isSyntaxError(error: unknown): error is SyntaxError; diff --git a/dist/util/SyntaxTreeError.d.ts b/dist/util/SyntaxTreeError.d.ts new file mode 100644 index 0000000..aff64df --- /dev/null +++ b/dist/util/SyntaxTreeError.d.ts @@ -0,0 +1,5 @@ +import type { SyntaxNode } from "../types.js"; +import { SyntaxError } from "./SyntaxError.js"; +export declare class SyntaxTreeError extends SyntaxError { + constructor(rootNode: SyntaxNode); +} diff --git a/dist/util/constants.d.ts b/dist/util/constants.d.ts index ea4eb6e..1b15214 100644 --- a/dist/util/constants.d.ts +++ b/dist/util/constants.d.ts @@ -1,6 +1,7 @@ export declare const EXIT_OK = 0; export declare const EXIT_FAIL = 1; export declare const EXIT_ERROR = 2; +export type ExitCode = typeof EXIT_OK | typeof EXIT_FAIL | typeof EXIT_ERROR; export declare const DEFAULT_INDENT_WIDTH = 4; export declare const DEFAULT_MAX_LINE_LENGTH = 80; export declare const DEFAULT_INSERT_FINAL_NEWLINE = true; diff --git a/package-lock.json b/package-lock.json index 7f5d2b9..96e5da1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@cursorless/talon-tools", - "version": "0.9.0", + "version": "0.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cursorless/talon-tools", - "version": "0.9.0", + "version": "0.10.0", "license": "MIT", "dependencies": { "@cursorless/tree-sitter-wasms": "^0.7.0", diff --git a/package.json b/package.json index c41793b..8c182eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cursorless/talon-tools", - "version": "0.9.0", + "version": "0.10.0", "description": "Linting and formatting tools for Talon and Cursorless", "author": "Cursorless Dev", "license": "MIT", diff --git a/src/node/cli.ts b/src/node/cli.ts index 2de9bf1..4723b7d 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -4,18 +4,24 @@ import * as path from "node:path"; import * as process from "node:process"; import type { Readable } from "node:stream"; import type { CLI, Logger, ParsedArgs } from "../types.js"; -import { EXIT_ERROR, EXIT_FAIL, EXIT_OK } from "../util/constants.js"; -import { FilePatternError } from "./FilePatternError.js"; +import { + EXIT_ERROR, + EXIT_FAIL, + EXIT_OK, + type ExitCode, +} from "../util/constants.js"; import { getErrorMessage } from "../util/getErrorMessage.js"; -import { isMissingFileError } from "./isMissingFileError.js"; -import { setExitCode } from "./setExitCode.js"; +import { isSyntaxError } from "../util/SyntaxError.js"; import { createLogger } from "./createLogger.js"; +import { FilePatternError } from "./FilePatternError.js"; import { getOptionsFromConfig } from "./getOptionsFromConfig.js"; +import { isMissingFileError } from "./isMissingFileError.js"; import { normalizeToPosix } from "./normalizeToPosix.js"; import { parseArgs } from "./parseArgs.js"; import { parseFilePatterns } from "./parseFilePatterns.js"; import { printHelp } from "./printHelp.js"; import { printVersion } from "./printVersion.js"; +import { setExitCode } from "./setExitCode.js"; export async function main(cli: CLI): Promise { let logger = createLogger(); @@ -47,7 +53,7 @@ async function mainUnsafe({ cli, args, logger, -}: MainUnsafeArgs): Promise { +}: MainUnsafeArgs): Promise { if (args.help) { printHelp(cli); return EXIT_OK; @@ -101,13 +107,13 @@ async function mainFormatFiles({ check, debug, filePatterns, -}: MainFormatFilesArgs): Promise { +}: MainFormatFilesArgs): Promise { if (check) { logger.log("Checking formatting..."); } const filePaths = await parseFilePatterns(cli, filePatterns); - const changedFileCount = await formatFiles({ + const [changedFileCount, hasError] = await formatFiles({ cli, logger, check, @@ -120,11 +126,18 @@ async function mainFormatFiles({ logger.warn( `Code style issues found in ${changedFileCount} file(s).`, ); - return EXIT_FAIL; + if (!hasError) { + return EXIT_FAIL; + } } - logger.log("All matched files use correct code style!"); - return EXIT_OK; + if (!hasError) { + logger.log("All matched files use correct code style!"); + } + } + + if (hasError) { + return EXIT_ERROR; } return EXIT_OK; @@ -144,24 +157,37 @@ export async function formatFiles({ check, debug, filePaths, -}: FormatFilesArgs): Promise { +}: FormatFilesArgs): Promise<[number, boolean]> { let changedFileCount = 0; + let hasError = false; - for (const fileName of filePaths) { - if ( - await formatFile({ + for (const filePath of filePaths) { + try { + const fileWasChanged = await formatFile({ cli, logger, check, debug, - filePath: fileName, - }) - ) { - changedFileCount++; + filePath, + }); + if (fileWasChanged) { + changedFileCount++; + } + } catch (error) { + if (isSyntaxError(error)) { + logger.error( + `${getDisplayPath(filePath)}${error.getLocation()}: ${error.message}`, + ); + } else { + logger.error( + `${getDisplayPath(filePath)}: ${getErrorMessage(error)}`, + ); + } + hasError = true; } } - return changedFileCount; + return [changedFileCount, hasError]; } interface FormatFileArgs { @@ -200,12 +226,7 @@ export async function formatFile({ return false; } - throw new Error( - `Failed to format '${filePath}': ${getErrorMessage(error)}`, - { - cause: error, - }, - ); + throw error; } } @@ -227,13 +248,23 @@ export async function mainFormatStdin({ stdin, check, debug, -}: MainFormatStdinArgs): Promise { +}: MainFormatStdinArgs): Promise { const input = await getStdin({ stdin }); const fileEnding = cli.getStdinFileEnding(input); - const fileName = `stdin.${fileEnding}`; - const filePath = path.resolve(fileName); - const options = await getOptionsFromConfig(filePath); - const formatted = await cli.format(input, options, filePath, debug); + const fauxFileName = `stdin.${fileEnding}`; + const fauxFilePath = path.resolve(fauxFileName); + const options = await getOptionsFromConfig(fauxFilePath); + let formatted: string; + + try { + formatted = await cli.format(input, options, fauxFilePath, debug); + } catch (error) { + if (isSyntaxError(error)) { + logger.error(`stdin${error.getLocation()}: ${error.message}`); + return EXIT_ERROR; + } + throw error; + } if (check) { if (input !== formatted) { diff --git a/src/node/isMissingFileError.ts b/src/node/isMissingFileError.ts index 5bee612..63c1acc 100644 --- a/src/node/isMissingFileError.ts +++ b/src/node/isMissingFileError.ts @@ -1,3 +1,5 @@ -export function isMissingFileError(error: unknown) { +export function isMissingFileError( + error: unknown, +): error is NodeJS.ErrnoException { return error instanceof Error && "code" in error && error.code === "ENOENT"; } diff --git a/src/talon/talonFormatter.ts b/src/talon/talonFormatter.ts index f3ac20a..70cdccb 100644 --- a/src/talon/talonFormatter.ts +++ b/src/talon/talonFormatter.ts @@ -7,6 +7,7 @@ import { createDebugLogger } from "../util/createDebugLogger.js"; import { getColumnWidth } from "../util/getColumnWidth.js"; import { getEndOfLine } from "../util/getEndOfLine.js"; import { getIndentation } from "../util/getIndentation.js"; +import { SyntaxTreeError } from "../util/SyntaxTreeError.js"; import { convertQuotes } from "./convertQuotes.js"; export type Options = FormatterOptions< @@ -24,6 +25,10 @@ export function talonFormatter( options: Options = {}, debug: boolean = false, ): string { + if (node.hasError) { + throw new SyntaxTreeError(node); + } + const columnWidth = getColumnWidth(node.text) ?? options.columnWidth; const indentation = getIndentation(options.indentTabs, options.indentSize); const eol = getEndOfLine(options.endOfLine); diff --git a/src/test/cli.test.ts b/src/test/cli.test.ts index 93361bc..34387e2 100644 --- a/src/test/cli.test.ts +++ b/src/test/cli.test.ts @@ -93,7 +93,7 @@ suite("CLI", () => { await fs.writeFile(unchangedFileName, "unchanged", "utf8"); await fs.writeFile(changedFileName, "changed", "utf8"); - const changedFileCount = await formatFiles({ + const [changedFileCount] = await formatFiles({ cli, logger, check: false, @@ -280,7 +280,7 @@ suite("CLI", () => { debug: false, filePath: fileName, }), - /Failed to format '.*example\.txt': boom/, + /boom/, ); } finally { await cleanupTempFile(fileName); diff --git a/src/test/talonFormatter.test.ts b/src/test/talonFormatter.test.ts index 57c5a0b..3fba813 100644 --- a/src/test/talonFormatter.test.ts +++ b/src/test/talonFormatter.test.ts @@ -85,6 +85,21 @@ suite("Talon formatter", () => { assert.equal(actual, "aaa: bbb\n"); }); + test("Syntax tree error", async () => { + const content = [ + "^test []$:", + 'if ini: insert("{ini}")', + ].join("\n"); + await assert.rejects( + () => talonFormatter(content), + (error) => { + assert.ok(error instanceof Error); + assert.equal(error.name, "SyntaxTreeError"); + return true; + }, + ); + }); + test("Debug logs unknown syntax node types", async () => { const rootNode = createNode("mystery", "value"); const output = await captureStreamWrite(process.stderr, () => diff --git a/src/test/testUtils.ts b/src/test/testUtils.ts index f74d1a5..9c24887 100644 --- a/src/test/testUtils.ts +++ b/src/test/testUtils.ts @@ -15,6 +15,9 @@ export function createNode(type: string, text: string): SyntaxNode { startPosition: { row: 0, column: 0 }, endPosition: { row: 0, column: text.length }, parent: null, + hasError: false, + isError: false, + isMissing: false, children: [], }; } diff --git a/src/test/treeSitterFormatter.test.ts b/src/test/treeSitterFormatter.test.ts index 7aa8cd0..b766b46 100644 --- a/src/test/treeSitterFormatter.test.ts +++ b/src/test/treeSitterFormatter.test.ts @@ -1,5 +1,8 @@ import * as assert from "node:assert"; -import { treeSitterFormatter } from "../treeSitterFormatter.js"; +import { + treeSitterFormatter as originalTreeSitterFormatter, + type Options, +} from "../treeSitterFormatter.js"; import { parseText } from "../node/parseText.js"; import { captureStreamWrite, @@ -12,48 +15,54 @@ suite("Tree-sitter formatter", () => { for (const fixture of getFixtures("treeSitterFixtures")) { test(fixture.title, async () => { const { input, expected } = getFixture(fixture.file); - const rootNode = await parseText(input, "tree-sitter-query"); - const actual = treeSitterFormatter(rootNode, {}); + const actual = await treeSitterFormatter(input, {}); assert.equal(actual, expected); }); } test("endOfLine: CRLF", async () => { - const rootNode = await parseText("(aaa (bbb))", "tree-sitter-query"); - const actual = treeSitterFormatter(rootNode, { + const actual = await treeSitterFormatter("(aaa (bbb))", { endOfLine: "crlf", }); assert.equal(actual, "(aaa\r\n (bbb)\r\n)\r\n"); }); test("indentTabs: true", async () => { - const rootNode = await parseText("(aaa (bbb))", "tree-sitter-query"); - const actual = treeSitterFormatter(rootNode, { + const actual = await treeSitterFormatter("(aaa (bbb))", { indentTabs: true, }); assert.equal(actual, "(aaa\n\t(bbb)\n)\n"); }); test("indentSize: 2", async () => { - const rootNode = await parseText("(aaa (bbb))", "tree-sitter-query"); - const actual = treeSitterFormatter(rootNode, { + const actual = await treeSitterFormatter("(aaa (bbb))", { indentSize: 2, }); assert.equal(actual, "(aaa\n (bbb)\n)\n"); }); test("insertFinalNewline: false", async () => { - const rootNode = await parseText("(aaa (bbb))", "tree-sitter-query"); - const actual = treeSitterFormatter(rootNode, { + const actual = await treeSitterFormatter("(aaa (bbb))", { insertFinalNewline: false, }); assert.equal(actual, "(aaa\n (bbb)\n)"); }); + test("Syntax tree error", async () => { + await assert.rejects( + () => treeSitterFormatter("(aaa!)"), + (error) => { + assert.ok(error instanceof Error); + assert.equal(error.name, "SyntaxTreeError"); + return true; + }, + ); + }); + test("Debug logs unknown syntax node types", async () => { const rootNode = createNode("mystery", "value"); const output = await captureStreamWrite(process.stderr, () => - treeSitterFormatter(rootNode, {}, true), + originalTreeSitterFormatter(rootNode, {}, true), ); assert.equal(output.result, "value\n"); assert.equal( @@ -62,3 +71,11 @@ suite("Tree-sitter formatter", () => { ); }); }); + +async function treeSitterFormatter( + content: string, + options: Options = {}, +): Promise { + const node = await parseText(content, "tree-sitter-query"); + return originalTreeSitterFormatter(node, options, true); +} diff --git a/src/treeSitterFormatter.ts b/src/treeSitterFormatter.ts index 397edc2..28c1e3f 100644 --- a/src/treeSitterFormatter.ts +++ b/src/treeSitterFormatter.ts @@ -3,8 +3,9 @@ import { DEFAULT_INSERT_FINAL_NEWLINE } from "./util/constants.js"; import { createDebugLogger } from "./util/createDebugLogger.js"; import { getEndOfLine } from "./util/getEndOfLine.js"; import { getIndentation } from "./util/getIndentation.js"; +import { SyntaxTreeError } from "./util/SyntaxTreeError.js"; -type Options = FormatterOptions< +export type Options = FormatterOptions< "endOfLine" | "indentTabs" | "indentSize" | "insertFinalNewline" >; @@ -13,6 +14,10 @@ export function treeSitterFormatter( options: Options = {}, debug: boolean = false, ): string { + if (node.hasError) { + throw new SyntaxTreeError(node); + } + const indentation = getIndentation(options.indentTabs, options.indentSize); const eol = getEndOfLine(options.endOfLine); const formatter = new TreeSitterFormatter( diff --git a/src/types.ts b/src/types.ts index 78a25e7..1590cca 100644 --- a/src/types.ts +++ b/src/types.ts @@ -72,7 +72,7 @@ export interface EditorConfigOptions extends KnownProps { preserve_multiline?: boolean | "unset"; } -interface Point { +export interface Point { row: number; column: number; } @@ -83,6 +83,9 @@ export interface SyntaxNode { type: string; startPosition: Point; endPosition: Point; + hasError: boolean; + isError: boolean; + isMissing: boolean; parent: SyntaxNode | null; children: SyntaxNode[]; } diff --git a/src/util/SyntaxError.ts b/src/util/SyntaxError.ts new file mode 100644 index 0000000..5aa5047 --- /dev/null +++ b/src/util/SyntaxError.ts @@ -0,0 +1,18 @@ +import type { Point } from "../types.js"; + +export class SyntaxError extends Error { + constructor(private location?: Point) { + super("Syntax error."); + this.name = "SyntaxError"; + } + + getLocation(): string | undefined { + return this.location != null + ? `(${this.location.row + 1}:${this.location.column + 1})` + : undefined; + } +} + +export function isSyntaxError(error: unknown): error is SyntaxError { + return error instanceof SyntaxError; +} diff --git a/src/util/SyntaxTreeError.ts b/src/util/SyntaxTreeError.ts new file mode 100644 index 0000000..97bacff --- /dev/null +++ b/src/util/SyntaxTreeError.ts @@ -0,0 +1,25 @@ +import type { SyntaxNode } from "../types.js"; +import { SyntaxError } from "./SyntaxError.js"; + +export class SyntaxTreeError extends SyntaxError { + constructor(rootNode: SyntaxNode) { + super(findFirstProblemNode(rootNode)?.startPosition); + this.name = "SyntaxTreeError"; + } +} + +function findFirstProblemNode(node: SyntaxNode): SyntaxNode | null { + if (node.isError || node.isMissing) { + return node; + } + for (const child of node.children) { + if (!child.hasError) { + continue; + } + const errorNode = findFirstProblemNode(child); + if (errorNode != null) { + return errorNode; + } + } + return null; +} diff --git a/src/util/constants.ts b/src/util/constants.ts index 1b80390..036b3c9 100644 --- a/src/util/constants.ts +++ b/src/util/constants.ts @@ -5,6 +5,8 @@ export const EXIT_FAIL = 1; // Exit code 2: Unexpected error export const EXIT_ERROR = 2; +export type ExitCode = typeof EXIT_OK | typeof EXIT_FAIL | typeof EXIT_ERROR; + export const DEFAULT_INDENT_WIDTH = 4; export const DEFAULT_MAX_LINE_LENGTH = 80; export const DEFAULT_INSERT_FINAL_NEWLINE = true;