anysyn
anysyn copied to clipboard
Edit javascript using any syntax
AnySyn
AnySyn is an Atom editor package that allows you to edit javascript source files with custom syntax. For example the word function could appear as -> when editing but when saved the valid javascript function keyword would be used.
AnySyn means "Any Syntax" and any javascript-compatible syntax could be developed and used by AnySyn. The syntax would be implemented as a service provider package (Atom plugin) for AnySyn to call.
The syntax conversion is not lossless but every time the javascript is saved it will be processed by a beautifier. This means a project will have to agree on beautifier preferences which every contributor follows. This solves the problem of format changes messing up the git diffs.
One included syntax (free)
The first alternate syntax Atom package will be released shortly after AnySyn. This will have features stolen from CoffeeScript. When combined with ES6 you would have a "language" that is similar to CoffeeScript but is real javascript with simple syntax substitutions. This allows one to work on someone else's javascript file using the CoffeeScript syntax and the file owner would only see javascript.
Motivation
I have used CoffeeScript exclusively for four or five years and loved it. When I originally looked at changing from CoffeeScript to ES6 I thought I could never use it because it still uses the C syntax with all the noise. Then it occured to me that something like AnySyn could fix that. You write the code mentally as real javascript but with easier writing and reading.
CoffeeScript package syntax features
This is a wish-list for the (almost) CoffeeScript syntax. Some features may not be included and I assume more will be added. Note that each feature is optional via settings. E.g, if you don't like using <- for return then you can turn off that feature.
- Significant whitespace, no more ugly pyramid of braces
- Parens are usually not needed in
for,if, or function calls - Skinny and fat arrows with almost the same semantics as CoffeeScript
- No need for empty parens before function arrows
@varreplaced withthis.var<-replaced withreturn#varreplaced withlet varx@yreplaced withx.get(y)(map access)
What AnySyn doesn't do
AnySyn makes no changes to ES6 just to be more compatible with CoffeeScript. AnySyn is only to reduce ES6 noisiness. For example these are not supported.
str = `AnySyn doesn't change #{this} to ${that}`
# this non-comment doesn't become // this comment
Atom integration out of the gate
AnySyn will be supported by Atom the same as a first-class language. When a javascript file is loaded it is automatically parsed to an AST, the plugin will convert that to text, and then AnySyn creates the editor buffer with the new syntax. It will have highlighting customized for the new syntax. Flipping the buffer between the AnySyn syntax and JS will be supported with one quick command.
Status
Just a specification at this point. There is nothing more than this readme.
Why switch from CoffeeScript
Many CoffeeScript users like me are converting to ES6. For a quick writeup comparing the two see this
Here is my personal list of reasons for changing to ES6.
- Improved debugging: Even with source maps CoffeeScript is harder to debug.
- You can't hover over a variable like
@varto see the value - You can't evaluate CoffeeScript in the console
- Stepping can be confusing because of line mismatch. I sometimes have to step many times to get past one line of CoffeeScript.
- You can't hover over a variable like
- Larger community: CoffeeScript has divided the community. I can finally publish code without people bitching they can't read it.
- Advanced features: While some CoffeeScript features are lost, like all code being expressions, there are many, if not more, features gained from ES6, like iterators.
Examples of the "CoffeeScript" syntax
//--- JS ---
let square = x => x * x;
let add = (a, b) => a + b;
let pi = () => 3.1415;
//--- AnySyn ---
#square = x => x * x // `#` changed to let
#add = (a, b) => a + b // no semicolons
#pi = => 3.1415 // no empty parens
//--- JS ---
var square = function(x) { return x * x; };
var pi = function() { return 3.1415; };
//--- AnySyn ---
var square = (x) -> <- x * x // anonymous function() becomes () ->
var pi = -> <- 3.1415 // return becomes <-
//--- JS ---
if (x == 0) {
for (let i = 0; i < 10; i++) {
y += 10;
}
}
//--- AnySyn ---
if x == 0 // parens optional
for #i = 0; i < 10; i++ // whitespace significant
y += 10
//--- JS ---
function helloWorld (a = 'hello', b = 'world') {
try {
console.log(a);
} catch(e) {
console.log(
b
);
}
//--- AnySyn ---
-> helloWorld (a = 'hello', b = 'world') // -> changed to function
try
console.log a // call doesn't need parens
catch(e)
console.log( // left paren needed for multi-line params
b
//--- JS ---
class Parrot extends Bird {
constructor(name) {
super(name);
this.name = 'Polly';
}
get name() {
return this.name;
}
}
//--- AnySyn ---
class Parrot extends Bird
constructor name // no parens needed
super name
@name = 'Polly' // @ changed to this.
get name
<- @name
//--- JS ---
function* range(start, end, step) {
while (start < end) {
yield start;
start += step;
}
}
//--- AnySyn ---
->* range (start, end, step) // ->* means generator function
while start < end
yield start
start += step
//--- JS ---
map.set(key, value)
map.get(key)
//--- AnySyn ---
map@key = value // @ replaces get and set for maps
map@key
Implementation
The following details how AnySyn would work and the interface it would expect from a syntax plugin.
-
AnySyn would be a normal Atom package that when enabled would enable an invisible conversion process. Opening javascript would just appear with the new syntax as if it was stored that way.
-
A config setting could allow specific files, maybe a regex on the path, to be linked to specific syntax plugins. That would also specify an Atom grammar. The highlighting would be implemented the standard Atom way without any interaction with AnySyn.
-
The plugin would provide two simple calls.
-
AnySyn would create a texteditor, read the file, convert the javascript to an AST, call the plugin to get the converted text, and place it in the buffer.
-
AnySyn would trap any save and do the reverse. Before the actual save it would pass the javascript through the beautifer.
-
AnySyn would also provide an Atom command to toggle the buffer between the standard javascript and the new syntax. This would be especially useful in debugging. It would do this using the same two plugin calls.
Ideas for the future
I know it is a bit premature but here are ideas that have been tossed around ...
- Adding support for icons. The lamda symbol could be used instead of
=>. - Some wild kind of editing directly on the AST instead of text.
- Adding a syntax specification language that programmatically creates new syntaxes and grammars.
- Supporting other languages than javascript
License
AnySyn is copyright Mark Hahn via the MIT license.