Cyril N.
Cyril N.

Reputation: 39889

CoffeeScript compiler without node.js?

I'd like to use CoffeeScript(CS) and the CS Compiler but without having to install Node.js.

I saw that the core compiler of CS is in JavaScript, so there's no need for Node.js to be installed, but I can't find any compiler written in Python/Java or any other languages, only Node.js.

Am I missing something? Will I have to write my own implementation in Python?

Upvotes: 4

Views: 3101

Answers (4)

jgphilpott
jgphilpott

Reputation: 649

In my opinion DukPy is the best javascript interpreter written in Python! It can compile CoffeeScript, TypeScript, BabelJS and JSX. Usage is very simple:

import dukpy
dukpy.coffee_compile("CoffeeScript goes here!")

DukPy is the successor to the Python-CoffeeScript package witch is no longer maintained.

Upvotes: 0

Alien Merchant
Alien Merchant

Reputation: 149

You can use something like this: http://hovet.biz/blog/?p=27 It's a Python2 based compiler using the Js version of the CoffeScript compiler and Qt WebKit. Note, no Qt GUI is involved, it's text only.

And here's the source, as requested:

import sys, os, glob
import time, htmllib
from os.path import splitext
from PyQt5.QtCore import QUrl
from PyQt5.QtWebKitWidgets import QWebPage
from PyQt5.QtWidgets import QApplication

coffee_script_js = os.path.expanduser('~/src/coffee-monitor/coffee-script.js')

assert os.path.exists(coffee_script_js)

sleep_time = 0.05

class CoffeeMonitor(QWebPage):  
    def __init__(self, src_dir):
        self._cs_src = None
        self._div_start = '<div id="cssrc">'
        self._app = QApplication(sys.argv)  
        QWebPage.__init__(self)  
        self.loadFinished.connect(self.load_finished)

        self._cs_src_dir = src_dir

        if not self.prep_compile_file():
            exit()

        self._app.exec_()

    def prep_compile_file(self):
        while 1:
            try:
                src = self.get_cs_src()

                if src:
                    self.mainFrame().load(QUrl(src))
                    return True

                time.sleep(sleep_time)

            except KeyboardInterrupt:
                break

        return False

    def create_cs_html(self, f):
        f_html = f + '.html'

        src = open(f).read()

        fil = open(f_html, 'w')
        fil.write('''<html>
<body>
'''+ self._div_start +''' </div>
<script type="text/coffeescript">
''')

        fil.write('try\n')
        #fil.write("  src = CoffeeScript.compile '" + src.replace('\n', '\\n').replace("'", "\\'") + "', bare: on\n")
        fil.write("  src = CoffeeScript.compile '" + src.replace('\n', '\\n').replace("'", "\\'") + "', bare: off\n")

        fil.write('''  document.getElementById("cssrc").textContent = src
catch {location, message}
  if location?
    message = "'''+f+''': Error on line #{location.first_line + 1}: #{message}"
  document.getElementById("cssrc").textContent = message

</script>
<script src="''' + coffee_script_js + '''"></script>
</body>
</html>
''')
        fil.close()

        return 'file://' + f_html

    def get_cs_src(self):
        #files = []
        #for exts in [ 'coffee', 'cof', 'coffe', 'cofee', 'cofe', 'kaffe' ]:
        #    files += glob.glob(self._cs_src_dir + '/*.' + exts)
        files = glob.glob(self._cs_src_dir + '/*.coffee')

        self._cs_src = None

        for f in files:
            name,ext = splitext(f)
            js = name + '.js'
            if not os.path.exists(js):
                self._cs_src = f
                return self.create_cs_html(f)

            c_time_cof = os.stat(f).st_ctime
            c_time_js = os.stat(js).st_ctime
            if c_time_cof > c_time_js:
                self._cs_src = f
                return self.create_cs_html(f)

    def get_compiled_js_src(self):
        html = self.mainFrame().toHtml()
        js_src = ''
        error = False

        for line in html.split('\n'):
            if line.startswith(self._div_start):
                js_src = line[len(self._div_start):]
                if js_src.find('Error on line ') > 0:
                    js_src = '!'*5 + ' ' + js_src.rstrip('</div>\n')
                    js_src = 'alert("'+ js_src.replace('"', "'") +'");'
                    error = True
                    #print js_src
                    break

            elif js_src:
                js_src += line.rstrip('</div>\n')
                if line.find('</div>') >= 0:
                    break

        js_src = unescape(js_src)

        return js_src, error

    def load_finished(self, result):
        js_src, error = self.get_compiled_js_src()

        name,ext = splitext(self._cs_src)
        js = name + '.js'
        print '*** updating', js

        if error:
            print js_src

        fil = open(js, 'w')
        fil.write(js_src.replace(';',';\n'))      
        fil.close()

        if not self.prep_compile_file():
            self._app.quit()

def unescape(s):
    p = htmllib.HTMLParser(None)
    p.save_bgn()
    p.feed(s)
    return p.save_end()

if __name__ == '__main__':
    print 'This Python script comes with absolutely no warranty.'
    print 'Ctrl+C to quit'

    if len(sys.argv) == 1:
        print 'coffee-monitor.py  cs-src-dir (note: recursive search is not implemented)'
        exit()

    cs_dir = os.path.abspath(os.path.expanduser(sys.argv[1]))

    assert os.path.isdir(cs_dir)
    CoffeeMonitor(cs_dir)

Upvotes: 2

Michael Anderson
Michael Anderson

Reputation: 73590

If you don't want to install node.js, you could compile them in your web browser. Rough details of how to do that are in the docs.

If you don't want to use your browser you can run that script in anything capable of running javascript, e.g. Rhino on Java, pyv8 in python, etc.

Upvotes: 2

Esailija
Esailija

Reputation: 140236

You can run javascript in python with http://code.google.com/p/pyv8/.

You would run the javascript code for CoffeeScript compiler, and then compile CoffeeScript with that.

Upvotes: 3

Related Questions