Skip to content

Instantly share code, notes, and snippets.

@0racle
Last active December 20, 2023 07:09
Show Gist options
  • Save 0racle/0267f04990beb33d31bcfbbbecab0664 to your computer and use it in GitHub Desktop.
Save 0racle/0267f04990beb33d31bcfbbbecab0664 to your computer and use it in GitHub Desktop.
Janitor - J code formatter
#!/usr/bin/env jconsole
NB. No space before these tokens
bef =: ;: ') @ @. @: & &. &: &.: " ` ;. !. !: / /. \ ~ }'
NB. No space after these tokens
aft =: ;: '( @ @. @: & &. &: &.: " ` ;. !. !:'
Cont =: {{ +./ ((dltb > x) (-: ;)"1 0 y) }}
Fmt =: {{
tokens =. ;: y
res =. {. tokens
for_next. }. tokens do.
last =. > {. res
if. -. ((last Cont aft) +. (next Cont bef)) do.
next =. ' ', dltb ; next
end.
res =. res ;~ > next
end.
'' joinstring |. res
}}
NB. Reads boxed lines from ARGV filenames, otherwise from STDIN
ARGLINES =: {{ <;._2 stdin _ }}`{{ ,/ ('b' fread ])@> 2 }. y }}@.(2 < #)
MAIN =: {{
for_line. ARGLINES y do.
indent =. ' ' #~ {. I. ' ' ~: > line
if. ((line_index -: 0) *. ('#' -: {. > line)) do.
echo > line
continue.
end.
echo indent , Fmt > line
end.
}}
MAIN ARGV
exit 0
@0racle
Copy link
Author

0racle commented Dec 20, 2023

Better version using j-lex

#!/usr/bin/env jconsole

load 'tangentstorm/j-lex'

Fmt =: {{)m
    tokens =. ;: y
    parts =. jtype_jlex_@> tokens
    rep =: ; (+/ 'DP' =/ parts)} (<"0 parts) ,: ({.&.> tokens)

    if. 1 > # tokens do.
        EMPTY return.
    end.
    s =. 0,~ (<: # tokens) $ 1

    NB. No space after open paren, conj
    s =. s *.      rep -.@e. '(c'
    NB. No space before close paren, conj, adverb
    s =. s *. 1 |. rep -.@e. ')ca'

    NB. No space around : :. ::
    s =. s +. 0,~ 2 ~:/\ tokens e. ;: ': :. ::'

    NB. No space before .
    s =. s +. 1 |. tokens e. ;: '.'

    NB. after close paren (except adjacent close paren when preceeded by '{{')
    s =. s - (Rs rep e. '{') *. rep e. ')'

    ; tokens #!.(<' ')~ (# tokens) {. 1 j. 0,~ }: s
}}

ARGLINES =: {{ <;._2 stdin _ }}`{{ ,/ ('b' fread ])@> 2 }. y }}@.(2 < #)

MAIN =: {{
    for_line. ARGLINES y do.
        indent =. ' ' #~ {. I. ' ' ~: > line
        if. ((line_index -: 0) *. ('#' -: {. > line)) do.
            echo > line
            continue.
        end.
        echo indent , Fmt > line
    end.
}}

MAIN ARGV

exit 0

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