Ctrl+P again to print, arrows/tab to navigate results, enter to confirm

    The tricks from the JS wiki apply to Civet as well.

    Special variables

    #

    # by itself is an alias to this.length. It's useful as a variable pre-initialized to undefined, as well as a loop variable (as explained below).

    # is more generally a shortcut to .length

    string#
    array#
    //instead of
    string.length
    array.length
    

    & and .

    & and . can be used as argument placeholders, allowing short syntax for creating functions. They differ in that . lifts outside a function call while & does not.

    [99..1].map console.log .,"beers on the wall"
    [99..1].map &+" beers on the wall"
    //instead of
    [99..1].map (x)=>console.log x,"beers on the wall"
    [99..1].map (x)=>x+" beers on the wall"
    

    If you want to access a property of ., you can't follow it with ., as it fails to parse. Instead, ? (which compiles to ?. in JS) or ! (which compiles to . in JS) can be used:

    args.map console.log ..X   //fails
    args.map console.log .?X   //okay
    args.map console.log .!X   //okay
    

    @

    @ is shorthand for this and @X is shorthand for this.X.

    Looping

    The traditional for-loop

    for(i=0;i++<10;)console.log i
    

    can be shortened in Civet to

    for$=0;$++<10;console.log $
    for$ of[1..10]console.log $
    for[i=1..10]console.log i++
    for;#^10;console.log #=-~#
    [1..10].map console.log .
    

    These are not always interchangeable, so which is shortest will depend on the rest of the code. Note that # can also be used in place of $.

    Also try postfix loop, sometimes it could be shorter.

    This is a bit cursed, but if you are using eval, you can access the loop variable without ever assigning it directly:

    for[0..9]eval "console.log(i)"
    

    Late Assignment

    a&&(b=3)
    a&&b=3   //-2 bytes
    
    i=1/(i+3)
    i=1/i+=3 //-1 byte
    

    Multiple Assignment

    c=c*2+1
    c++*=2   //-1 byte
    

    Operators

    Civet introduces a number of new operators that can help shorten your code.

    Pipe operator

    Sometimes using |> can avoid an intermediate variable to save a byte.

    s=a+b,console.log s*s
    a+b|>console.log .*.  //-1 byte
    

    It can also be used to help lift the placeholder variable . through multiple function calls.

    args.map console.log f .      //fails
    console.log f $ for$ of args  //use a for-loop
    args.map console.log(.|>f)    //or pipe into the inner function
    

    Concat operator

    The ++ operator is a shorter alternative to the concat method.

    [1,2,3]++[4,5,6] // [1,2,3,4,5,6]
    

    Modulo operator

    %% always returns positive values.

    -5%3  // -2 (remainder)
    -5%%3 // 1 (modulo)
    

    Other operators

    "abc"<?"string"  // typeof "abc" === "string"
    "abc"!<?"string" // typeof "abc" !== "string"
    
    a^^b // a xor b
    a!^b // a xnor b
    
    a^^=b // a = a xor b
    a!^=b // a = a xnor b
    
    a?=b // a??=b
    
    a%/b // floor division: Math.floor(a/b)
    
    a∈b // b.contains(a)
    
    a?b   //a?.b   (optional chaining property access)
    a?(b) //a?.(b) (optional chaining function call)
    a? b  //a?.(b), same as above
    

    Chained comparisons

    s<2&&console.log i
    s<2<console.log i   // -1 byte
    

    Node.js features

    Civet runs on Node.js, which makes additional functions available compared to pure JavaScript.

    Buffer

    Consider Buffer as a way of accessing code points of an ASCII string or bytes of a Unicode string.

    Buffer("Hello, World!").map console.log "Char code = ",.
    

    It also can work in reverse, as an alternative to String.fromCharCode.

    console.log ""+Buffer [103,111,108,102]
    

    write

    If you need write, you can still use it in Node with process.stdout.write.

    Chars golfing

    Operators

    There are Unicode alternatives for many operators. ∈\∉\∋\∌ could be useful even in bytes scoring.

    Packing

    eval runs JavaScript code, not Civet code, so you'll need to edit your code accordingly before packing.

    //To pack,
    (Buffer.from "my source").toString "ucs2"
    
    //Unpack & run
    eval ""+Buffer "packed","ucs2"
    

    If you have an odd number of characters in your source, then you can prepend ; to it before packing, and use

    eval 0+Buffer "packed","ucs2"