osxpeppermint / peppermint

The official bug/features tracker for Peppermint
8 stars 2 forks source link

Examples in JavaScript and CoffeeScript? #65

Closed bobrocke closed 9 years ago

bobrocke commented 9 years ago

I much prefer coding in standard JavaScript; can documentation examples be given in both JS and CS?

osxpeppermint commented 9 years ago

Well, I know CoffeeScript is not to everyone's liking... so my goal is that Plugins can be written in JavaScript as well (+ any other language that can be directly translated to JavaScript. E.g. TypeScript, Haxe, etc).

As for the documentation, I thought of it too, however I decided to postpone it until the API has taken its final form. (Right now, the API is at very good level, so I believe it might be time to start doing what you suggest :) )

osxpeppermint commented 9 years ago

Now, I've been re-thinking about the JS vs Coffee (and remembered the initial reasons that made me choose Coffee over JS).

Have a look at this example case - the Haxe Linter builtin.

This is what it looks like in CoffeeScript: https://gist.github.com/osxpeppermint/2acfee2179eb077ff2a2 And this is what it looks in JavaScript: https://gist.github.com/osxpeppermint/99f25a1e2ce8476db801

Well, the second one is undoubtedly 100% pure javascript. However, to be perfectly honest, given the way plugins are (meaning: being a "class" offering its private methods, inheriting parent methods, and all that (which is not originally supported by JS)), I doubt if I myself could even recognize or debug my code...

Don't know, perhaps it's a matter of taste. It just seems to me that the 2nd version looks much more complicated (unless I make a "simpler" model only for JS-based plugins - which I had done in the past, although it has to be revisited if we want to get this whole thing working).

P.S. Surprisingly (or not), I've never been a JavaScript guru, so any ideas are welcome! :)

bobrocke commented 9 years ago

Yes, in the end it is a matter of taste.

IMHO every other language that transpiles to JavaScript is going to generate JavaScript in the end. And if you're tracing through code with a debugger, you're going to see JavaScript.

Most developers who have learned a streamlined version of JavaScript started off with JavaScript. You can't very well have examples in every language based on JavaScript; but anyone can read JavaScript and translate that into their preferred language - whichever one that is.

So, to me, put the examples/documentation/API in JavaScript plus CoffeeScript, if that's your preference. If someone writes in Haxe, doesn't know CoffeeScript, and has to read documentation in CoffeeScript, they have a problem. But that person probably knows JavaScript - much like someone writing in LESS or SASS knows CSS,

osxpeppermint commented 9 years ago

I understand what you mean and I agree 100%.

My main concern is that - given how Peppermint plugins work - I have to find a way to make the JavaScript version (if someone chooses to directly code in JS) more... user-friendly and not as complicated as it currently should be (in order to conform to the Plugin coding standard).

To put it simply: JavaScript was not designed neither for Classes nor for inheritance. So, forcing someone who wants to write a pure JavaScript plugin, use all this "extra" code (just look at the JS version above) with "extends" and all that, doesn't sound good to me. A simpler function/object format would be a lot better. (But this would mean Peppermint would have to figure out the "extras" itself. And perhaps add them automatically. Otherwise, the plugin wouldn't be able to function as a Peppermint "plugin")

bobrocke commented 9 years ago

Hmmm. Atom uses CoffeeScript/CSON by default. But in every case, JavaScript/JSON can be substituted and Atom just uses that instead. Seamlessly.

osxpeppermint commented 9 years ago

Well, Peppermint can use JS too, right now - as long as e.g. the main script file is not a "script.coffee" but a "script.js". It will be processed correctly.

bobrocke commented 9 years ago

So you're good to go? Show the API examples in JavaScript and everything just works?

osxpeppermint commented 9 years ago

Yep, that's true.

As you said yourself, JavaScript is the core language. So, even if there is some preference for CoffeeScript (purely for reasons of readability), all CoffeeScript plugins are - quite obviously - converted to JS before being executed.

And in any case, JS was the way plugins were written at the very beginning. So, recognizing them in 100% JS is still included. (though not... showcased)

osxpeppermint commented 9 years ago

I am revisiting a bit the idea of JS plugins.

Now, here's what I believe is the simplest possible form of a JavaScript-only plugin. How readable/self-explanatory is it?

var NewPlugin = (function() {
    __extends(NewPlugin, $Plugin);

    function NewPlugin() { return NewPlugin.__super__.constructor(this, arguments); }

    NewPlugin.prototype.init = function() {
        // Initialisation
    }

    NewPlugin.prototype.run = function() {
        // Execute
    };

    NewPlugin.prototype.halt = function() {
        // Terminated
    }

    return NewPlugin;
})();
bobrocke commented 9 years ago

That looks pretty reasonable, to me. Is that how JS plugins work now, or is that a feature to come?

osxpeppermint commented 9 years ago

Well, the way JS plugins would work now is a little bit more complicated. This is what it could be - to make it as readable as possible (and automate some of the not-so-readable part, from Peppermint - during plugin processing).

I don't know. I'm still thinking about it...

osxpeppermint commented 9 years ago

Here's another way JavaScript plugins could be written in the future (this is the general idea I'm probably going to use):

function MyPlugin() {
     this.init = function() {
          // Initialization code
     }

     this.run = function() {
          // Plugin executed
     }

     this.halt = function() {
          // Plugin halted
     }
}

I think it's fairly straight-forward and as uncomplicated as possible.

bobrocke commented 9 years ago

That's very clean and clear. Who could complain? I'd say do it.

osxpeppermint commented 9 years ago

You got me thinking with your latest messages so... I've been thinking of ways to reach out to the JavaScript audience as well. And making it easy. Let's see... :)

osxpeppermint commented 9 years ago

Another thing though would be ES6 (basically the next version of javascript). It's not supported by many browsers - yet (and Safari is not in the list). However, there is already a way of making it work and getting ahead (via https://babeljs.io/docs/learn-es2015/)

bobrocke commented 9 years ago

True. And my partial understanding of ES6 suggests it brings many of the advantages of CoffeeScript to JavaScript, too.

osxpeppermint commented 9 years ago

As of 1.5 beta 20, the main CoffeeScript alternative for Plugins will be the model exactly as shown in: https://github.com/osxpeppermint/peppermint/issues/65#issuecomment-115802252 (the only thing needed is a ".js" extension for the script file, in a few words script.js instead of script.coffee)

So, let me revisit plugin creation (this time for JavaScript)...


General Plugin Structure

My Plugin Title.ppPlugin/

"My Plugin Title" is the title of the plugin as shown in the Tools menu.


info.json

{
    "name"          : "MyPlugin",
    "category"      : "",
    "author"        : "",
    "author_email"  : "",
    "last_update"   : "",
    "shortcut"      : "",
    "scope"         : "Global"
}

The only required options are: "name" (the name of the class/function as described in script.js) and "scope" (= the Spec/Language it is to be attached to. E.g. "C++", "JavaScript", "HTML", or "Global" for Spec-independent plugins).


script.js -- The absolute minimum required

  function MyPlugin() {
        this.init = function() {
              // Initialisation code to be executed once
              // the first time the plugin runs
        }

        this.run = function() {
              // This is the core function

              // Code to be executed, every time the user
              // "runs" the plugin
        }

        this.halt = function() {
              // Termination/cleanup code to be executed
              // when the plugin is terminated manually
              // or a different plugin is executed
        }
  }
osxpeppermint commented 9 years ago

And a more... complete example, showcasing the Plugin power:

  function MyPlugin() {
        this.init = function() {
              this.counter = 0; // set some private var
              $Terminal.echo("In MyPlugin::Init");
        }

        this.run = function() {
              this.counter++;   // counter = 1
              $Terminal.echo("In MyPlugin::run() - counter = " + counter);

              // Get some user input

              $Dialog.input("What's your name?", function(name){
                    $Terminal.echo("Hello " + name + "!");

                    // Call some private user functions

                    this.execScript();
                    this.getDocInfo();
              });
        }

        this.halt = function() {
              $Terminal.echo("In MyPlugin::halt()");
        }

        //-------------------------
        // User functions
        //-------------------------

        this.execScript = function() {

              // Execute command in terminal and
              // process the result asynchronously

              $Terminal.exec("ls","-la", function(result){
                    $Terminal.echo("Received results:\n"+result);
              });
        }

        this.getDocInfo = function() {

              // Get current document info

              var doc = $Document.info();

              $Terminal.echo("filename: " + doc.filename);
              $Terminal.echo("folder: " + doc.folder);
              $Terminal.echo("path: " + doc.path);
              $Terminal.echo("content: " + doc.content);
        }
  }
osxpeppermint commented 9 years ago

P.S. Regarding what I was saying about ES6, Peppermint right now can support ES6 syntax (using Babel and script.babel files). However, until it is widely adopted and more stable, it will remain mostly experimental and undocumented).

osxpeppermint commented 9 years ago

P.S. (b) I will keep this issue open, until I manage to make the documentation... bilingual... :)

osxpeppermint commented 9 years ago

Plugin creation documentation - as an experiment - in GitHub Wiki:

https://github.com/osxpeppermint/peppermint/wiki/Creating-a-Plugin


I'm also planning to migrate this to the site + convert all API examples to JS (although to be honest, most of them will be like 100% identical).

bobrocke commented 9 years ago

Looks good! Is beta 20 coming today?

osxpeppermint commented 9 years ago

:)

As for the next release, I have already done a lot of work (+ background work for core things coming at some later point), but I'm planning it for tomorrow until I iron out a few more details.