Skip to content

Instantly share code, notes, and snippets.

@supersym
Last active December 16, 2015 22:49
Show Gist options
  • Save supersym/5509550 to your computer and use it in GitHub Desktop.
Save supersym/5509550 to your computer and use it in GitHub Desktop.
Sublime2 Literate CoffeeScript/JavaScript/Coffeecup support and settings.

Support for Literate CoffeeScript

Sublime2

These are separate sublime-build scripts for use in Sublime2. Ensure package AAAPackageDev and BuildSwitcher are installed. To create a new build script, use one of these two ways:

  • Keyboard: Ctrl + Shift + P (command dialog) then type the following 'new bui' + RETURN
  • Mouse: click on Tools » Build System » New Build System

Step 1: .litcoffee to .js

Compiled file

From jashkenas tmbundle package, we have the following sublime-build script to compile from .litcoffee to .js but unfortunately, there is no built-in method to convert to .coffee. The (coined) term for this process, by the way, is to 'untangle' a piece of literate computer program source (or prose).

{
	"path": "$HOME/bin:/usr/local/bin:$PATH",
	"cmd": ["coffee","-c","$file"],
	"file_regex": "^(...*?):([0-9]*):?([0-9]*)",
	"selector": "source.coffee, source.litcoffee, source.coffee.md"
}

Only print result

To just print output, instead of compile the file, we could use the -p switch on the coffee executable. Note that this also depends on any user settings you may have to compile_on_save and such so your own system behaviour may differ.

{
    "cmd": ["coffee", "-p", "$file"],
    "selector": ["source.coffee", "source.litcoffee"]
}

Step 2: .js to .coffee

Finally, support untangle of Literate CoffeeScript we use this as a final part in our two-step (trans)compilation solution; from .litcoffee to .js (step 1) to now .coffee. We have to use the js2coffee package we installed using npm i -g js2coffee. This is now also available as a package if I'm not mistaken.

{
    "cmd": ["js2coffee", "$file"],
    "selector": "source.js"
}

Combining steps

UPDATE: I missed this one: https://github.com/GianlucaGuarini/SublimeText2-Parallel-Builder-Plugin

I have been looking for a 'native' way to 'untangle' the Markdown and CoffeeScript. Earlier I wrote up a quick shell script for this purpose: it uses the tools from NPM repository we already known: coffee-script and js2coffee as terminal applications we can use from the shell, plus 2 or 3 *nix built-in commands like mktemp, cp and cd.

Still, I wanted to be sure that I hadn't missed a flag somewhere so I asked in the IRC #coffeescript channel and the most obvious I had completely forgotten: awk. So the second method demonstrates this concept using the POSIX awk implementation.

You can change the value of the untangle variable to either match literal strings "md" and "cs" (two-way), depending on what you want untangled from the document. Then you can execute from the shell, the following command and arguments:

awk -f ~/patterns/lcs.awk myfile.litcoffee

Extras

Pimp my REPL

Step it up a notch, why settle for these when you can also pimp your REPL? Do a quick npm i -g nesh to get system-wide access to improved REPL with history, auto-complete, saved state, help, plugins and auto-coloring of data types and values.

⚠️ Nesh doesn't work with .litcoffee out of the box yet...

{
    "cmd": ["nesh", "-c", "$file"],
    "selector": "source.js"
}
#!/usr/bin/env bash
# vim: ft=sh:ts=4:sts=4:sw=4:et:nospell
# Robust portable bash shell script for Literate CoffeeScript
# ===========================================================
# made by Rob Jentzema (supersym) on 【ツ】 Fri 03 May 2013
# Untangles the .litcoffee file given as the only input parameter to this
# script and both creates the bare-metal `.js` and from this file, round-trip
# to `.coffee` with all text stripped and only code left.
# Syntax highlighting and other tools for Sublime2 and Vim
# https://github.com/jashkenas/coffee-script-tmbundle
# https://github.com/mintplant/vim-literate-coffeescript
# Protect subshell
set -o errexit
set -o nounset
# Some terminal color
norm=$(tput sgr0)
fail=$(tput setaf 1)
good=$(tput setaf 2)
name=$(tput setaf 3)
# More eye-candy from way back
artwork () {
x="$fail❤$norm"
cat <<EOF
__..._ _...__ ) (
_..-" \`Y\` "-.._ ( ) )
\\ Once upon | Literate / ) ( (
\\\\ a time, | $x // (_______)_
\\\\\\ two.. | Coffee /// .-'---------|
\\\\\\ _..---.|.---.._ /// ( C|S\/\\/\\/\\/|
LP\\\\\`_..---.Y.---.. \`// '-./\\/\\/\\/\\/|
'\` \`' '_________'
'-------'
EOF
}
# Helper functions
die () { printf >&2 "%s %s\n" "$fail✗$norm Failed! " "$@" && exit 1; }
show () { printf "%s %s\n" "$good ✓$norm" "Created a file $name$1$norm"; }
# Sanity checks and to limit what we accept as valid input
[ "$#" -eq 1 ] || die "1 argument required, $# provided"
# Member variables for file name can be interpolated now
filename="${1}" # safety first, escape and brace expand properly
basename=$(basename $filename) # strips only path from sanitized name
extension="${filename##*.}" # obtains file extension from the input
shortname="${basename%.*}" # stripped off path and no extension
# Pre-flight final safety checks before take-off
[[ -s "$filename" ]] || die "This file doesn't exist or is 0 bytes in size."
[[ -r "$filename" ]] || die "You don't have permissions to read this file."
[[ $extension = "litcoffee" ]] || die "You must provide a .litcoffee file"
[[ $shortname != "" ]] || die "Name can't be a empty string value"
# Showtime!
artwork
# Backup in case something goes wrong
export TMPDIR=$PWD # temporary to be made in present/current working directory
tempfiles=$(mktemp -d -t) || die "Could not make temporary directory here."
cp $filename $tempfiles && cd $tempfiles && pwd &&\
show "${filename}" # cp and cd
# All systems are go!
coffee -p -b "$tempfiles/${shortname}.litcoffee" > "$tempfiles/${shortname}.js" && show "${shortname}.js"
js2coffee "$tempfiles/${shortname}.js" > "$tempfiles/${shortname}.coffee" && show "${shortname}.coffee"
exit $?
# ~/patterns/lcs.awk
# AWK patterns and actions for Literate CoffeeScript untanglement of Markdown and CoffeeScript
BEGIN {
  RS="\n\n"
  FS="\n"
  regexMdHeader = "^\\#{1,6}+"
  regexCsIndent = "^[[:space:]]{4,} | ^[\t]"
  }
  {
# Toggle 'md' and 'cs' to alternate the untangle modi
    untangle="cs"
    if (NR!=1) {
      if (untangle == "cs" && ( $0 ~ regexCsIndent )) { print }
      if (untangle == "md" && (! ($0 ~ regexCsIndent ))) {
        print "\n";print; if ($0 ~ regexMdHeader) { print "\n" }
      }
    }
  }
@supersym
Copy link
Author

supersym commented May 3, 2013

⚠️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment