breck7 / scrollsdk

Build on top of Scroll.
https://sdk.scroll.pub
380 stars 17 forks source link

Alternative syntax for Stamp #120

Closed Sarcasm closed 1 month ago

Sarcasm commented 3 years ago

Right now the stamp language provides this syntax:

folder myProject
file myProject/index.js
 data
  console.log("Hello world")
file myProject/readme.md
 data
  # My Readme

I'm wondering if it could not be simplified like this:

myProject/
 index.js
  console.log("Hello world")
 readme.md
  # My Readme

Directories can discriminated from files thanks to the final /. Children of directories are files. Children of files, is file content.

Would that still qualify as a treenotation language?

breck7 commented 3 years ago

Love it! How would you do file permissions?

Also, you could come up with your own name. Building a tree language is cheap so could build a whole new one.

Happy to team up on a Twitch call and pair program one out.

breck7 commented 3 years ago

I guess you could add the restriction to not allow spaces in filenames, then just do index.js Writeable or something. Lots of options

Sarcasm commented 3 years ago

For permission yes, I think it could be specified after the filename. Maybe a bad idea, but could be in a chmod-like format:

foo.py +x
 #!/usr/bin/env python
 print("hello world")
breck7 commented 3 years ago

Here's a quick prototype. I just started it but gotta run to a conference

https://jtree.treenotation.org/designer/#grammar%0A%20tooling%20onsave%20jtree%20build%20produceLang%20stamp%0A%20todo%20File%20permissions%0A%20anyCell%0A%20extraCell%0A%20%20highlightScope%20invalid%0A%20anyCell%0A%20%20highlightScope%20string%0A%20promptWordsCell%0A%20%20highlightScope%20string%0A%20filepathCell%0A%20%20highlightScope%20keyword%0A%20varNameCell%0A%20%20highlightScope%20string%0A%20commentCell%0A%20%20highlightScope%20comment%0A%20inputTypeCell%0A%20%20enum%20string%20int%20any%20lowercase%0A%20keywordCell%0A%20%20highlightScope%20keyword.control%0A%20stampNode%0A%20%20root%0A%20%20description%20A%20prefix%20Tree%20Language%20for%20creating%20distributable%20text%20template%20files%20that%20expand%20to%20folders%20and%20files.%0A%20%20catchAllNodeType%20errorNode%0A%20%20javascript%0A%20%20%20async%20executeSeries(parentDir)%20%7B%0A%20%20%20%20const%20length%20%3D%20this.length%0A%20%20%20%20for%20(let%20index%20%3D%200%3B%20index%20%3C%20length%3B%20index%2B%2B)%20%7B%0A%20%20%20%20%20const%20node%20%3D%20this.nodeAt(index)%0A%20%20%20%20%20await%20node.execute(parentDir)%0A%20%20%20%20%7D%0A%20%20%20%20return%20parentDir%0A%20%20%20%7D%0A%20%20%20async%20execute(parentDir%20%3D%20process.cwd())%20%7B%0A%20%20%20%20await%20this.executeSeries(parentDir)%0A%20%20%20%7D%0A%20%20%20static%20dirToStampWithContents(absPathWithoutEndingSlash)%20%7B%0A%20%20%20%20%20return%20stampNode._dirToStampFn(absPathWithoutEndingSlash%2C%20%22content%22)%0A%20%20%20%7D%0A%20%20%20static%20dirToStamp(absPathWithoutEndingSlash)%20%7B%0A%20%20%20%20%20return%20stampNode._dirToStampFn(absPathWithoutEndingSlash%2C%20%22list%22)%0A%20%20%20%7D%0A%20%20%20static%20_dirToStampFn(absPathWithoutEndingSlash%2C%20output)%20%7B%0A%20%20%20%20const%20fs%20%3D%20require(%22fs%22)%0A%20%20%20%20%2F%2F%20todo%3A%20add%20chmod%2C%20file%20metadata%0A%20%20%20%20if%20(absPathWithoutEndingSlash.startsWith(%22.%22))%20absPathWithoutEndingSlash%20%3D%20jtree.Utils.resolvePath(absPathWithoutEndingSlash%2C%20process.cwd()%20%2B%20%22%2F%22)%0A%20%20%20%20const%20stat%20%3D%20fs.statSync(absPathWithoutEndingSlash)%0A%20%20%20%20if%20(!stat.isDirectory())%20throw%20new%20Error(%60%24%7BabsPath%7D%20is%20a%20file%20not%20a%20directory.%60)%0A%20%20%20%20const%20fns%20%3D%20%7B%0A%20%20%20%20%20list%3A%20(file%2C%20reducedPath)%20%3D%3E%20%7B%0A%20%20%20%20%20%20const%20stat%20%3D%20fs.statSync(file)%0A%20%20%20%20%20%20const%20isDir%20%3D%20stat.isDirectory()%0A%20%20%20%20%20%20if%20(isDir)%20return%20%60folder%20%60%20%2B%20reducedPath%0A%20%20%20%20%20%20return%20%60file%20%60%20%2B%20reducedPath%0A%20%20%20%20%20%7D%2C%0A%20%20%20%20%20content%3A%20(file%2C%20reducedPath)%20%3D%3E%20%7B%0A%20%20%20%20%20%20const%20stat%20%3D%20fs.statSync(file)%0A%20%20%20%20%20%20const%20isDir%20%3D%20stat.isDirectory()%0A%20%20%20%20%20%20if%20(isDir)%20return%20%60folder%20%60%20%2B%20reducedPath%0A%20%20%20%20%20%20const%20content%20%3D%20fs.readFileSync(file%2C%20%22utf8%22)%0A%20%20%20%20%20%20return%20%60file%20%24%7BreducedPath%7D%0A%20%20%20%20data%24%7Bjtree.TreeNode.nest(content%2C%202)%7D%60%0A%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20const%20fn%20%3D%20fns%5Boutput%5D%0A%20%20%20%20return%20this._dirToStamp(absPathWithoutEndingSlash%2C%20fn)%0A%20%20%20%7D%0A%20%20%20static%20_dirToStamp(absPathWithoutEndingSlash%2C%20fileFn)%20%7B%0A%20%20%20%20const%20files%20%3D%20require(%22recursive-readdir-sync%22)(absPathWithoutEndingSlash)%0A%20%20%20%20const%20folderParts%20%3D%20absPathWithoutEndingSlash.split(%22%2F%22)%0A%20%20%20%20const%20rootFolderName%20%3D%20folderParts.pop()%0A%20%20%20%20const%20rootFolderPath%20%3D%20folderParts.join(%22%2F%22)%0A%20%20%20%20const%20pathStartIndex%20%3D%20rootFolderPath.length%20%2B%201%0A%20%20%20%20return%20files.map(file%20%3D%3E%20fileFn(file%2C%20file.substr(pathStartIndex))).join(%22%5Cn%22)%0A%20%20%20%7D%0A%20%20inScope%20hashbangNode%20folderNode%20fileNode%0A%20hashbangNode%0A%20%20crux%20%23!%0A%20%20catchAllCellType%20commentCell%0A%20%20cells%20commentCell%0A%20catchAllAnyLineNode%0A%20%20catchAllCellType%20anyCell%0A%20%20catchAllNodeType%20catchAllAnyLineNode%0A%20%20cells%20anyCell%0A%20errorNode%0A%20%20baseNodeType%20errorNode%0A%20fileNode%0A%20%20cells%20filepathCell%0A%20%20javascript%0A%20%20%20compileToBash(parentDir)%20%7B%0A%20%20%20%20const%20filePath%20%3D%20this._getAbsolutePath(parentDir)%0A%20%20%20%20return%20%60touch%20%24%7BfilePath%7D%5Cnecho%20-e%20%22%24%7Bthis.childrenToString()%7D%22%20%3E%3E%20%24%7BfilePath%7D%60%0A%20%20%20%7D%0A%20%20%20_getAbsolutePath(parentDir%20%3D%20process.cwd())%20%7B%0A%20%20%20%20return%20parentDir%20%2B%20%22%2F%22%20%2B%20this.cells.filepathCell%0A%20%20%20%7D%0A%20%20%20execute(parentDir)%20%7B%0A%20%20%20%20const%20fs%20%3D%20require(%22fs%22)%0A%20%20%20%20const%20fullPath%20%3D%20this._getAbsolutePath(parentDir)%0A%20%20%20%20console.log(%60Creating%20file%20%24%7BfullPath%7D%60)%0A%20%20%20%20const%20data%20%3D%20this.getNode(%22data%22)%0A%20%20%20%20const%20content%20%3D%20data%20%3F%20data.childrenToString()%20%3A%20%22%22%0A%20%20%20%20require(%22mkdirp%22).sync(require(%22path%22).dirname(fullPath))%0A%20%20%20%20fs.writeFileSync(fullPath%2C%20content%2C%20%22utf8%22)%0A%20%20%20%20const%20isExecutable%20%3D%20this.has(%22executable%22)%20%2F%2F%20todo%3A%20allow%20for%20all%20file%20permissions%3F%0A%20%20%20%20if%20(isExecutable)%20fs.chmodSync(fullPath%2C%20%22755%22)%0A%20%20%20%7D%0A%20%20inScope%20dataNode%0A%20%20catchAllNodeType%20catchAllAnyLineNode%0A%20folderNode%0A%20%20cells%20filepathCell%0A%20%20catchAllNodeType%20fileNode%0A%20%20pattern%20%5C%2F%0A%20%20javascript%0A%20%20%20compileToBash(parentDir)%20%7B%0A%20%20%20%20return%20%60mkdir%20%24%7Bthis._getAbsolutePath(parentDir)%7D%60%0A%20%20%20%7D%0A%20%20%20_getAbsolutePath(parentDir%20%3D%20process.cwd())%20%7B%0A%20%20%20%20return%20parentDir%20%2B%20%22%2F%22%20%2B%20this.cells.filepathCell%0A%20%20%20%7D%0A%20%20%20execute(parentDir)%20%7B%0A%20%20%20%20const%20path%20%3D%20this._getAbsolutePath(parentDir)%0A%20%20%20%20console.log(%60Creating%20folder%20%24%7Bpath%7D%60)%0A%20%20%20%20require(%22mkdirp%22).sync(path)%0A%20%20%20%7D%0Asample%0A%20myProject%2F%0A%20%20index.js%0A%20%20%20console.log(%22Hello%20world%22)%0A%20%20readme.md%0A%20%20%20%23%20My%20Readme

Sarcasm commented 3 years ago

Maybe the presence of a shebang is enough to warrant the execution bit. And like now, other permissions could be omitted.

breck7 commented 3 years ago

You know what I only use that execution bit once in a blue moon. This Stamp alternative could be dead simple (expands to plain vanilla non-executable files) without file permissions.

Just playing with the demo in the Designer I like yours better than mine.

It reminds me of a better https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html

breck7 commented 3 years ago

Would you be interested in making your own repo and running with that idea?

I could contribute over there. I'd love to hear how much the experience currently sucks of building one's own Tree Language (my guess is very bad).

I think it would be worthwhile and would be a user myself.

Sarcasm commented 3 years ago

I attempted something (link at the end). Not sure I will push it further but I was happy to give it a try.

Regarding my experience.

Some nice things:

Less nice things:

https://jtree.treenotation.org/designer/#grammar%0A%20anyCell%0A%20%20highlightScope%20string%0A%20filePathCell%0A%20%20highlightScope%20keyword%0A%20stampNode%0A%20%20root%0A%20%20inScope%20directoryNode%0A%20%20catchAllNodeType%20fileNode%0A%20%20javascript%0A%20%20%20execute()%20%7B%0A%20%20%20%20return%20this.map(child%20%3D%3E%20child.execute()).join(%22%5Cn%22)%0A%20%20%20%7D%0A%20%20example%0A%20%20%20empty.txt%0A%20%20%20foo.txt%0A%20%20%20%20foo%0A%20%20%20%20bar%0A%20%20%20%20baz%0A%20%20%20executable.sh%0A%20%20%20%20%23!%2Fbin%2Fsh%0A%20%20%20%20echo%20%22Do%20you%20have%205%24%3F%22%0A%20%20%20foo%2F%0A%20%20%20%20__init__.py%0A%20%20%20%20%20__version__%20%3D%20'0.0.1'%0A%20%20%20%20bar%2F%0A%20%20%20%20%20__init__.py%0A%20directoryNode%0A%20%20cells%20filePathCell%0A%20%20catchAllCellType%20filePathCell%0A%20%20inScope%20directoryNode%0A%20%20catchAllNodeType%20fileNode%0A%20%20pattern%20%5C%2F%24%0A%20%20javascript%0A%20%20%20execute()%20%7B%0A%20%20%20%20%20const%20name%20%3D%20this.getLine()%0A%20%20%20%20%20if%20(name.indexOf('%2F')%20!%3D%20name.length%20-%201)%20%7B%0A%20%20%20%20%20%20%20throw%20%60Invalid%20directory%20name%3A%20%24%7Bname%7D%60%0A%20%20%20%20%20%7D%0A%20%20%20%20%20return%20%5B%0A%20%20%20%20%20%20%20%60mkdir%20-p%20%24%7Bname%7D%60%2C%0A%20%20%20%20%20%20%20%60pushd%20%24%7Bname%7D%60%2C%0A%20%20%20%20%20%20%20%5D.concat(%0A%20%20%20%20%20%20%20this.map(child%20%3D%3E%20child.execute())%0A%20%20%20%20%20).concat(%5B%0A%20%20%20%20%20%20%20%22popd%22%0A%20%20%20%20%20%5D).join(%22%5Cn%22)%0A%20%20%20%7D%0A%20fileNode%0A%20%20cells%20filePathCell%0A%20%20catchAllCellType%20filePathCell%0A%20%20catchAllNodeType%20catchAllAnyLineNode%0A%20%20javascript%0A%20%20%20execute()%20%7B%0A%20%20%20%20%20const%20filename%20%3D%20this.getLine()%0A%20%20%20%20%20if%20(filename.indexOf('%2F')%20!%3D%20-1)%20%7B%0A%20%20%20%20%20%20%20throw%20%60Invalid%20filename%3A%20%24%7Bfilename%7D%60%0A%20%20%20%20%20%7D%0A%20%20%20%20%20const%20lines%20%3D%20this.getLines()%0A%20%20%20%20%20if%20(lines.indexOf(%22EOF%22)%20!%3D%20-1)%20%7B%0A%20%20%20%20%20%20%20throw%20%60%24%7Bfilename%7D%3A%20Unsupported%20line%3A%20EOF%60%3B%0A%20%20%20%20%20%7D%20%0A%20%20%20%20%20if%20(lines.length%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20return%20%60touch%20%24%7Bfilename%7D%60%0A%20%20%20%20%20%7D%0A%20%20%20%20%20let%20out%20%3D%20%5B%0A%20%20%20%20%20%20%20%60%3E%24%7Bfilename%7D%20%3C%3C'EOF'%0A%20%20%20%24%7Blines.join(%22%5Cn%22)%7D%0A%20%20%20EOF%60%0A%20%20%20%20%20%5D%0A%20%20%20%20%20if%20(lines%5B0%5D.startsWith(%22%23!%22))%20%7B%0A%20%20%20%20%20%20%20out.push(%60chmod%20%2Bx%20%24%7Bfilename%7D%60)%0A%20%20%20%20%20%7D%0A%20%20%20%20%20return%20out.join(%22%5Cn%22)%0A%20%20%20%7D%0A%20catchAllAnyLineNode%0A%20%20cells%20anyCell%0A%20%20catchAllCellType%20anyCell%0A%20%20catchAllNodeType%20catchAllAnyLineNode%0A%20%20javascript%0A%20%20%20getTextContent()%20%7B%0A%20%20%20%20%20return%20this.getLine()%0A%20%20%20%7D%0Asample%0A%20empty.txt%0A%20foo.txt%0A%20%20foo%0A%20%20bar%0A%20%20baz%0A%20executable.sh%0A%20%20%23!%2Fbin%2Fsh%0A%20%20echo%20%22Do%20you%20have%205%24%3F%22%0A%20foo%2F%0A%20%20__init__.py%0A%20%20%20__version__%20%3D%20'0.0.1'%0A%20%20bar%2F%0A%20%20%20__init__.py

breck7 commented 3 years ago

@Sarcasm finally got back to this. This is awesome!

I find it way better than Stamp. Feels natural. I made a few tiny changes to your code above (just changed execute methods to compile for consistency. The other reductions in code were just to temporarily make the link shorter). Named it "Clay". Playing around with it made me think of shaping a full project fluidly.

I want to go through your feedback and address the individual points, but just wanted to say this is awesome. Better than Stamp and really as simple as possible. Kudos.

https://jtree.treenotation.org/designer/#grammar%0A%20anyCell%0A%20%20highlightScope%20string%0A%20filePathCell%0A%20%20highlightScope%20keyword%0A%20clayNode%0A%20%20description%20Edit%20an%20entire%20project%20as%20a%20single%20text%20file.%0A%20%20root%0A%20%20inScope%20directoryNode%0A%20%20catchAllNodeType%20fileNode%0A%20%20javascript%0A%20%20%20compile()%20%7B%20return%20this.map(child%20%3D%3E%20child.compile()).join(%22%5Cn%22)%7D%0A%20%20example%0A%20%20%20foo.txt%0A%20%20%20%20foo%0A%20directoryNode%0A%20%20cells%20filePathCell%0A%20%20catchAllCellType%20filePathCell%0A%20%20inScope%20directoryNode%0A%20%20catchAllNodeType%20fileNode%0A%20%20pattern%20%5C%2F%24%0A%20%20javascript%0A%20%20%20compile()%20%7B%0A%20%20%20%20%20const%20name%20%3D%20this.getLine()%0A%20%20%20%20%20return%20%5B%0A%20%20%20%20%20%20%20%60mkdir%20-p%20%24%7Bname%7D%60%2C%0A%20%20%20%20%20%20%20%60pushd%20%24%7Bname%7D%60%2C%0A%20%20%20%20%20%20%20%5D.concat(%0A%20%20%20%20%20%20%20this.map(child%20%3D%3E%20child.compile())%0A%20%20%20%20%20).concat(%5B%22popd%22%5D).join(%22%5Cn%22)%0A%20%20%20%7D%0A%20fileNode%0A%20%20cells%20filePathCell%0A%20%20catchAllCellType%20filePathCell%0A%20%20catchAllNodeType%20catchAllAnyLineNode%0A%20%20javascript%0A%20%20%20compile()%20%7B%0A%20%20%20%20%20const%20filename%20%3D%20this.getLine()%0A%20%20%20%20%20if%20(filename.indexOf('%2F')%20!%3D%20-1)%0A%20%20%20%20%20%20%20throw%20%60Invalid%20filename%3A%20%24%7Bfilename%7D%60%0A%20%20%20%20%20const%20lines%20%3D%20this.getLines()%0A%20%20%20%20%20if%20(lines.length%20%3D%3D%200)%0A%20%20%20%20%20%20%20return%20%60touch%20%24%7Bfilename%7D%60%0A%20%20%20%20%20let%20out%20%3D%20%5B%0A%20%20%20%20%20%20%20%60%3E%24%7Bfilename%7D%20%3C%3C'EOF'%0A%20%20%20%24%7Blines.join(%22%5Cn%22)%7D%0A%20%20%20EOF%60%0A%20%20%20%20%20%5D%0A%20%20%20%20%20if%20(lines%5B0%5D.startsWith(%22%23!%22))%0A%20%20%20%20%20%20%20out.push(%60chmod%20%2Bx%20%24%7Bfilename%7D%60)%0A%20%20%20%20%20return%20out.join(%22%5Cn%22)%0A%20%20%20%7D%0A%20catchAllAnyLineNode%0A%20%20cells%20anyCell%0A%20%20catchAllCellType%20anyCell%0A%20%20catchAllNodeType%20catchAllAnyLineNode%0A%20%20javascript%0A%20%20%20getTextContent()%20%7B%20return%20this.getLine()%20%7D%0Asample%0A%20readme.md%0A%20%20%23%20Click%20%22Compile%22%0A%20%20Get%20a%20bash%20script%20that%20creates%20your%20project.%0A%20%20Read%20more%3A%20https%3A%2F%2Fgithub.com%2Fpublicdomaincompany%2Fjtree%2Fissues%2F120%0A%20package.json%0A%20%20%7B%0A%20%20%20%22name%22%3A%22clay%22%0A%20%20%7D%0A%20executable.sh%0A%20%20%23!%2Fbin%2Fsh%0A%20%20echo%20%22Hello%20world%22%0A%20src%2F%0A%20%20app.js%0A%20%20%20console.log(%22Hello%20world%22)

Sarcasm commented 3 years ago

Hello,

I just try the Clay example, and it looks like there is an issue with the package.json generated content:

image

breck7 commented 3 years ago

You are right. This should work:

https://jtree.treenotation.org/designer/#grammar%0A%20anyCell%0A%20%20highlightScope%20string%0A%20filePathCell%0A%20%20highlightScope%20keyword%0A%20clayNode%0A%20%20description%20Edit%20an%20entire%20project%20as%20a%20single%20text%20file.%0A%20%20root%0A%20%20inScope%20directoryNode%0A%20%20catchAllNodeType%20fileNode%0A%20%20javascript%0A%20%20%20compile()%20%7B%20return%20this.map(child%20%3D%3E%20child.compile()).join(%22%5Cn%22)%7D%0A%20%20example%0A%20%20%20foo.txt%0A%20%20%20%20foo%0A%20directoryNode%0A%20%20cells%20filePathCell%0A%20%20catchAllCellType%20filePathCell%0A%20%20inScope%20directoryNode%0A%20%20catchAllNodeType%20fileNode%0A%20%20pattern%20%5C%2F%24%0A%20%20javascript%0A%20%20%20compile()%20%7B%0A%20%20%20%20%20const%20name%20%3D%20this.getLine()%0A%20%20%20%20%20return%20%5B%0A%20%20%20%20%20%20%20%60mkdir%20-p%20%24%7Bname%7D%60%2C%0A%20%20%20%20%20%20%20%60pushd%20%24%7Bname%7D%60%2C%0A%20%20%20%20%20%20%20%5D.concat(%0A%20%20%20%20%20%20%20this.map(child%20%3D%3E%20child.compile())%0A%20%20%20%20%20).concat(%5B%22popd%22%5D).join(%22%5Cn%22)%0A%20%20%20%7D%0A%20fileNode%0A%20%20cells%20filePathCell%0A%20%20catchAllCellType%20filePathCell%0A%20%20catchAllNodeType%20catchAllAnyLineNode%0A%20%20javascript%0A%20%20%20compile()%20%7B%0A%20%20%20%20%20const%20filename%20%3D%20this.getLine()%0A%20%20%20%20%20if%20(filename.indexOf('%2F')%20!%3D%20-1)%0A%20%20%20%20%20%20%20throw%20%60Invalid%20filename%3A%20%24%7Bfilename%7D%60%0A%20%20%20%20%20const%20contents%20%3D%20this.childrenToString()%0A%20%20%20%20%20if%20(!contents.length)%0A%20%20%20%20%20%20%20return%20%60touch%20%24%7Bfilename%7D%60%0A%20%20%20%20%20let%20out%20%3D%20%5B%0A%20%20%20%20%20%20%20%60%3E%24%7Bfilename%7D%20%3C%3C'EOF'%0A%20%20%20%24%7Bcontents%7D%0A%20%20%20EOF%60%0A%20%20%20%20%20%5D%0A%20%20%20%20%20if%20(contents.startsWith(%22%23!%22))%0A%20%20%20%20%20%20%20out.push(%60chmod%20%2Bx%20%24%7Bfilename%7D%60)%0A%20%20%20%20%20return%20out.join(%22%5Cn%22)%0A%20%20%20%7D%0A%20catchAllAnyLineNode%0A%20%20cells%20anyCell%0A%20%20catchAllCellType%20anyCell%0A%20%20catchAllNodeType%20catchAllAnyLineNode%0Asample%0A%20readme.md%0A%20%20%23%20Click%20%22Compile%22%0A%20%20Get%20a%20bash%20script%20that%20creates%20your%20project.%0A%20%20Read%20more%3A%20https%3A%2F%2Fgithub.com%2Fpublicdomaincompany%2Fjtree%2Fissues%2F120%0A%20package.json%0A%20%20%7B%0A%20%20%20%22name%22%3A%22clay%22%0A%20%20%7D%0A%20executable.sh%0A%20%20%23!%2Fbin%2Fsh%0A%20%20echo%20%22Hello%20world%22%0A%20src%2F%0A%20%20app.js%0A%20%20%20console.log(%22Hello%20world%22)

breck7 commented 3 years ago

Two reasons for this:

1) The core TreeNode methods are not great. Some methods I often make mistakes with, such as getLines. I think some subpar methods could removed, some can be better named, and some more helpful core methods could be added. Perhaps there should be fewer public methods, but the ones remaining should be fantastic and foolproof. Or maybe there's a missing pattern(s) that would make core easier to use. Not sure. All I know is that I wish the core API was better!

2) In this specific example, I changed the compilation of the parent file block to use childrenToString instead of getLines. Given a Tree like:

a
 b
  c
  d

Then "childrenToString" of "a" returns simply the text block:

b
 c
 d

I find this to be a very common pattern when embedding non-tree languages in a tree language and use it often. Using methods designed for tree languages inside "blob", non-tree language blocks can be tricky, and generally just dumping those blobs is what you want, in which case "childrenToString" works great. This situation should probably be well documented in future Grammar docs. The code currently parses non-Tree language blobs like this just like any other Tree Node, and I think there are some theoretical issues that could be resolved there. It's definitely one of the places that needs some good FAQs, as I was just having a long conversation with another dev on this very topic.

breck7 commented 3 years ago

Just for clarity, a diff of the fix:

Screen Shot 2021-08-11 at 6 36 18 AM
Sarcasm commented 3 years ago

The fix makes sense, childrenToString() looks more natural/correct than iterating over the lines, thank you.

breck7 commented 1 month ago

I finally got around to this!

https://scroll.pub/blog/stamp.html