(ns data)

(def categories
  [{:id :mini-notation
    :name "Mini Notation"
    :items
    [{:symbol "~" :description "Creates silence/rests" :example "s \"~ hh\""}
     {:symbol "[ ]" :description "Groups subdivisions into one step" :example "s \"[bd sd] hh\""}
     {:symbol "." :description "Shorthand for ][ grouping" :example "s \"bd sd . hh hh hh\""}
     {:symbol "," :description "Polyrhythm - play simultaneously" :example "s \"[bd sd, hh hh hh]\""}
     {:symbol "*" :description "Repeat element n times" :args [{:name "n" :type "Int" :range "1-16"}] :example "s \"bd*2 sd\""}
     {:symbol "/" :description "Slow down/divide element" :args [{:name "n" :type "Int" :range "2-8"}] :example "s \"bd/2\""}
     {:symbol "|" :description "Random choice each cycle" :example "s \"[bd|cp|hh]\""}
     {:symbol "< >" :description "Alternate across cycles" :example "s \"bd <sd hh cp>\""}
     {:symbol "!" :description "Replicate (multiple steps)" :args [{:name "n" :type "Int" :range "2-8"}] :example "s \"bd!3 sd\""}
     {:symbol "_" :description "Elongate/sustain duration" :example "s \"bd _ _ ~ sd _\""}
     {:symbol "@" :description "Elongate with weight" :args [{:name "w" :type "Int" :range "1-8"}] :example "s \"piano@3 piano\""}
     {:symbol "?" :description "50% chance to remove" :example "s \"bd? sd\""}
     {:symbol ":" :description "Sample index" :args [{:name "n" :type "Int" :range "0-..."}] :example "s \"bd:3\""}
     {:symbol "( )" :description "Euclidean rhythm" :args [{:name "pulses" :type "Int"} {:name "steps" :type "Int"}] :example "s \"bd(3,8)\""}
     {:symbol "{ }" :description "Polymetric sequence" :example "s \"{bd bd bd, cp hh}\""}
     {:symbol "%" :description "Subdivision modifier" :args [{:name "n" :type "Int"}] :example "s \"{bd hh}%8\""}]}

   {:id :oscillators
    :name "Oscillators"
    :items
    [{:name "sine" :description "Sinusoidal wave 0-1" :example "# pan sine"}
     {:name "cosine" :description "Cosine wave (sine + 0.25)" :example "# pan cosine"}
     {:name "square" :description "Square wave 0/1" :example "# pan square"}
     {:name "tri" :description "Triangle wave" :example "# pan tri"}
     {:name "saw" :description "Sawtooth 0 to 1" :example "# pan saw"}
     {:name "isaw" :description "Inverted sawtooth 1 to 0" :example "# pan isaw"}
     {:name "rand" :description "Random values 0-1" :example "# pan rand"}
     {:name "irand" :description "Random integers 0 to n-1" :args [{:name "n" :type "Int" :range "2-128"}] :example "# n (irand 8)"}
     {:name "perlin" :description "Smooth Perlin noise" :example "# pan perlin"}
     {:name "perlin2" :description "2D Perlin noise" :args [{:name "pat" :type "Pattern"}] :example "# pan (perlin2 saw)"}
     {:name "range" :description "Scale oscillator to min/max" :args [{:name "min" :type "Num"} {:name "max" :type "Num"} {:name "osc" :type "Pattern"}] :example "# lpf (range 200 4000 sine)"}
     {:name "rangex" :description "Exponential range (for freq)" :args [{:name "min" :type "Float"} {:name "max" :type "Float"} {:name "osc" :type "Pattern"}] :example "# lpf (rangex 200 4000 sine)"}
     {:name "smooth" :description "Linear interpolation" :args [{:name "pat" :type "Pattern"}] :example "# pan (smooth \"0 1 0.5\")"}]}

   {:id :time
    :name "Time"
    :items
    [{:name "fast" :description "Speed up pattern" :args [{:name "n" :type "Time" :range "0.25-16"}] :example "fast 2 $ s \"bd sd\""}
     {:name "slow" :description "Slow down pattern" :args [{:name "n" :type "Time" :range "0.25-16"}] :example "slow 2 $ s \"bd sd\""}
     {:name "hurry" :description "Speed up + pitch up" :args [{:name "n" :type "Rational" :range "0.5-4"}] :example "hurry 2 $ s \"bd\""}
     {:name "fastGap" :description "Speed up with gaps" :args [{:name "n" :type "Time" :range "2-8"}] :example "fastGap 2 $ s \"bd sd hh\""}
     {:name "compress" :description "Squeeze into time span" :args [{:name "start" :type "Time"} {:name "end" :type "Time"}] :example "compress (0.25, 0.75) $ s \"bd sd\""}
     {:name "zoom" :description "Play portion over full cycle" :args [{:name "start" :type "Time"} {:name "end" :type "Time"}] :example "zoom (0.25, 0.75) $ s \"bd sd hh cp\""}
     {:name "within" :description "Apply func to time range" :args [{:name "start" :type "Time"} {:name "end" :type "Time"} {:name "f" :type "Func"}] :example "within (0, 0.5) (fast 2) $ s \"bd sd\""}
     {:name "off" :description "Layer offset transformed copy" :args [{:name "t" :type "Time" :range "0-1"} {:name "f" :type "Func"}] :example "off 0.125 (# crush 4) $ s \"bd sd\""}
     {:name "rev" :description "Reverse each cycle" :example "rev $ s \"bd sd hh cp\""}
     {:name "jux" :description "Apply func to right channel" :args [{:name "f" :type "Func"}] :example "jux rev $ s \"bd sd hh cp\""}
     {:name "juxBy" :description "jux with stereo width" :args [{:name "w" :type "Double" :range "0-1"} {:name "f" :type "Func"}] :example "juxBy 0.5 rev $ s \"bd sd\""}
     {:name "spin" :description "Multiple panned copies" :args [{:name "n" :type "Int" :range "2-8"}] :example "spin 4 $ s \"bd sd\""}
     {:name "swingBy" :description "Swing feel" :args [{:name "amt" :type "Time" :range "0-0.5"} {:name "div" :type "Time"}] :example "swingBy (1/8) 4 $ s \"hh*8\""}
     {:name "swing" :description "Swing with 1/3 delay" :args [{:name "div" :type "Time"}] :example "swing 4 $ s \"hh*8\""}
     {:name "echo" :description "Delay with repeats" :args [{:name "n" :type "Int" :range "1-8"} {:name "t" :type "Time"} {:name "fb" :type "Double" :range "0-1"}] :example "echo 4 0.125 0.5 $ s \"bd\""}
     {:name "echoWith" :description "Echo with transform" :args [{:name "n" :type "Int"} {:name "t" :type "Time"} {:name "f" :type "Func"}] :example "echoWith 4 0.125 (|* speed 0.9) $ s \"bd\""}
     {:name "rotL" :description "Shift backward in time" :args [{:name "t" :type "Time" :range "0-1"}] :example "rotL 0.25 $ s \"bd sd hh cp\""}
     {:name "rotR" :description "Shift forward in time" :args [{:name "t" :type "Time" :range "0-1"}] :example "rotR 0.25 $ s \"bd sd hh cp\""}
     {:name "inside" :description "Apply within divided cycles" :args [{:name "n" :type "Time"} {:name "f" :type "Func"}] :example "inside 4 rev $ s \"bd sd hh cp\""}
     {:name "outside" :description "Apply across multiple cycles" :args [{:name "n" :type "Time"} {:name "f" :type "Func"}] :example "outside 4 rev $ s \"bd sd hh cp\""}
     {:name "stretch" :description "Zoom to avoid silence" :example "stretch $ s \"bd ~ sd ~\""}
     {:name "loopFirst" :description "Loop only first cycle" :example "loopFirst $ s \"bd sd hh cp\""}
     {:name "timeLoop" :description "Apply modulo to cycles" :args [{:name "n" :type "Time"}] :example "timeLoop 4 $ s \"bd sd hh cp\""}]}

   {:id :alteration
    :name "Alteration"
    :items
    [{:name "degrade" :description "Remove 50% randomly" :example "degrade $ s \"bd sd hh cp\""}
     {:name "degradeBy" :description "Remove with probability" :args [{:name "p" :type "Double" :range "0-1"}] :example "degradeBy 0.75 $ s \"bd sd hh cp\""}
     {:name "unDegradeBy" :description "Keep with probability" :args [{:name "p" :type "Double" :range "0-1"}] :example "unDegradeBy 0.25 $ s \"bd sd hh cp\""}
     {:name "ply" :description "Repeat each event n times" :args [{:name "n" :type "Int" :range "2-8"}] :example "ply 2 $ s \"bd sd\""}
     {:name "plyWith" :description "Repeat with transform" :args [{:name "n" :type "Int"} {:name "f" :type "Func"}] :example "plyWith 4 (|* gain 0.8) $ s \"bd\""}
     {:name "stutter" :description "Repeat separated by time" :args [{:name "n" :type "Int" :range "2-16"} {:name "t" :type "Time"}] :example "stutter 4 0.125 $ s \"bd\""}
     {:name "trunc" :description "Play only start fraction" :args [{:name "t" :type "Time" :range "0-1"}] :example "trunc 0.5 $ s \"bd sd hh cp\""}
     {:name "linger" :description "Play fraction, repeat to fill" :args [{:name "t" :type "Time" :range "0.125-0.5"}] :example "linger 0.25 $ s \"bd sd hh cp\""}
     {:name "chunk" :description "Apply func to parts cyclically" :args [{:name "n" :type "Int" :range "2-8"} {:name "f" :type "Func"}] :example "chunk 4 (fast 2) $ s \"bd sd hh cp\""}
     {:name "shuffle" :description "Random permutation" :args [{:name "n" :type "Int" :range "2-8"}] :example "shuffle 4 $ s \"bd sd hh cp\""}
     {:name "scramble" :description "Random with replacement" :args [{:name "n" :type "Int" :range "2-8"}] :example "scramble 4 $ s \"bd sd hh cp\""}
     {:name "bite" :description "Slice and reorder" :args [{:name "n" :type "Int" :range "2-16"} {:name "order" :type "Pattern Int"}] :example "bite 4 \"0 2 1 3\" $ s \"bd sd hh cp\""}
     {:name "chew" :description "bite + speed adjustment" :args [{:name "n" :type "Int"} {:name "order" :type "Pattern Int"}] :example "chew 4 \"0 2 1 3\" $ s \"bd sd hh cp\""}
     {:name "rot" :description "Rotate values, keep structure" :args [{:name "n" :type "Int"}] :example "rot 1 $ s \"bd sd hh cp\""}
     {:name "stripe" :description "Repeat at random speeds" :args [{:name "n" :type "Int" :range "2-8"}] :example "stripe 4 $ s \"bd sd\""}
     {:name "palindrome" :description "Alternate fwd/back each cycle" :example "palindrome $ s \"bd sd hh cp\""}
     {:name "spread" :description "Apply func with cycling values" :args [{:name "f" :type "Func"} {:name "vals" :type "List"}] :example "spread fast [1, 2, 3] $ s \"bd sd\""}
     {:name "fastspread" :description "spread within single cycle" :args [{:name "f" :type "Func"} {:name "vals" :type "List"}] :example "fastspread fast [1, 2, 3] $ s \"bd sd\""}
     {:name "spreadChoose" :description "Random value each cycle" :args [{:name "f" :type "Func"} {:name "vals" :type "List"}] :example "spreadChoose fast [1, 2, 3, 4] $ s \"bd sd\""}
     {:name "quantise" :description "Round to nearest fraction" :args [{:name "n" :type "RealFrac" :range "0.1-1"}] :example "# pan (quantise 0.25 rand)"}
     {:name "segment" :description "Sample at n events/cycle" :args [{:name "n" :type "Int"}] :example "segment 8 $ s \"bd sd hh cp\""}]}

   {:id :conditions
    :name "Conditions"
    :items
    [{:name "every" :description "Apply func every n cycles" :args [{:name "n" :type "Int" :range "2-16"} {:name "f" :type "Func"}] :example "every 4 rev $ s \"bd sd hh cp\""}
     {:name "every'" :description "every with offset" :args [{:name "n" :type "Int"} {:name "off" :type "Int"} {:name "f" :type "Func"}] :example "every' 4 2 rev $ s \"bd sd hh cp\""}
     {:name "foldEvery" :description "Apply at multiple intervals" :args [{:name "ns" :type "[Int]"} {:name "f" :type "Func"}] :example "foldEvery [3, 5] (fast 2) $ s \"bd sd\""}
     {:name "when" :description "Apply when test is true" :args [{:name "test" :type "Int -> Bool"} {:name "f" :type "Func"}] :example "when ((== 0) . (`mod` 4)) rev $ s \"bd sd\""}
     {:name "whenmod" :description "Apply when cycle mod >= threshold" :args [{:name "n" :type "Int"} {:name "thresh" :type "Int"} {:name "f" :type "Func"}] :example "whenmod 8 4 (fast 2) $ s \"bd sd hh cp\""}
     {:name "ifp" :description "If-else on cycle number" :args [{:name "test" :type "Int -> Bool"} {:name "then" :type "Func"} {:name "else" :type "Func"}] :example "ifp ((== 0) . (`mod` 2)) rev id $ s \"bd sd\""}
     {:name "fix" :description "Apply func when control matches" :args [{:name "match" :type "ControlPattern"} {:name "f" :type "Func"}] :example "fix (s \"bd\") (# crush 4) $ s \"bd sd hh\""}
     {:name "unfix" :description "Apply func when control doesn't match" :args [{:name "match" :type "ControlPattern"} {:name "f" :type "Func"}] :example "unfix (s \"bd\") (# crush 4) $ s \"bd sd hh\""}
     {:name "contrast" :description "If-else for control patterns" :args [{:name "test" :type "Func"} {:name "then" :type "Func"} {:name "else" :type "Func"}] :example "contrast (== s \"bd\") (# crush 4) id $ s \"bd sd\""}
     {:name "struct" :description "Apply boolean rhythm" :args [{:name "pat" :type "Pattern Bool"}] :example "struct \"t f t t\" $ s \"bd\""}
     {:name "mask" :description "Filter through boolean mask" :args [{:name "pat" :type "Pattern Bool"}] :example "mask \"t f t t\" $ s \"bd sd hh cp\""}
     {:name "sew" :description "Switch patterns on bool" :args [{:name "sel" :type "Pattern Bool"} {:name "p1" :type "Pattern"} {:name "p2" :type "Pattern"}] :example "sew \"t f\" (s \"bd\") (s \"hh\")"}
     {:name "stitch" :description "sew using bool's structure" :args [{:name "sel" :type "Pattern Bool"} {:name "p1" :type "Pattern"} {:name "p2" :type "Pattern"}] :example "stitch \"t f t\" (s \"bd\") (s \"hh\")"}
     {:name "euclid" :description "Euclidean rhythm" :args [{:name "pulses" :type "Int" :range "1-16"} {:name "steps" :type "Int" :range "2-16"}] :example "euclid 3 8 $ s \"bd\""}
     {:name "euclidInv" :description "Inverted euclidean" :args [{:name "pulses" :type "Int"} {:name "steps" :type "Int"}] :example "euclidInv 3 8 $ s \"bd\""}]}

   {:id :randomness
    :name "Randomness"
    :items
    [{:name "choose" :description "Random from list" :args [{:name "vals" :type "[a]"}] :example "# n (choose [0, 2, 4, 7])"}
     {:name "chooseBy" :description "Choose using pattern" :args [{:name "sel" :type "Pattern Double"} {:name "vals" :type "[a]"}] :example "# n (chooseBy sine [0, 2, 4, 7])"}
     {:name "wchoose" :description "Weighted random choice" :args [{:name "weighted" :type "[(a, Double)]"}] :example "s (wchoose [(\"bd\", 4), (\"sd\", 2)])"}
     {:name "cycleChoose" :description "One random value per cycle" :args [{:name "vals" :type "[a]"}] :example "# n (cycleChoose [0, 2, 4, 7])"}
     {:name "select" :description "Choose pattern by float 0-1" :args [{:name "sel" :type "Pattern Double"} {:name "pats" :type "[Pattern]"}] :example "select sine [s \"bd\", s \"sd\", s \"hh\"]"}
     {:name "selectF" :description "Choose function by float 0-1" :args [{:name "sel" :type "Pattern Double"} {:name "fns" :type "[Func]"}] :example "selectF sine [rev, fast 2, id] $ s \"bd sd\""}
     {:name "squeeze" :description "Choose pattern by int" :args [{:name "sel" :type "Pattern Int"} {:name "pats" :type "[Pattern]"}] :example "squeeze \"0 1 2\" [s \"bd\", s \"sd\", s \"hh\"]"}
     {:name "sometimes" :description "Apply func ~50% of time" :args [{:name "f" :type "Func"}] :example "sometimes rev $ s \"bd sd hh cp\""}
     {:name "sometimesBy" :description "Apply with probability" :args [{:name "p" :type "Double" :range "0-1"} {:name "f" :type "Func"}] :example "sometimesBy 0.25 rev $ s \"bd sd hh cp\""}
     {:name "someCycles" :description "Apply to random cycles" :args [{:name "f" :type "Func"}] :example "someCycles rev $ s \"bd sd hh cp\""}
     {:name "someCyclesBy" :description "Apply to cycles with prob" :args [{:name "p" :type "Double"} {:name "f" :type "Func"}] :example "someCyclesBy 0.25 rev $ s \"bd sd hh cp\""}
     {:name "markovPat" :description "Markov chain pattern" :args [{:name "len" :type "Int"} {:name "start" :type "Int"} {:name "matrix" :type "[[Double]]"}] :example "markovPat 8 0 [[0.5, 0.5], [0.3, 0.7]]"}]}

   {:id :composition
    :name "Composition"
    :items
    [{:name "cat" :description "Concat patterns, one cycle each" :args [{:name "pats" :type "[Pattern]"}] :example "cat [s \"bd\", s \"sd\", s \"hh hh\"]"}
     {:name "fastcat" :description "Concat into single cycle" :args [{:name "pats" :type "[Pattern]"}] :example "fastcat [s \"bd\", s \"sd\", s \"hh\"]"}
     {:name "timeCat" :description "Concat with proportions" :args [{:name "pairs" :type "[(Time, Pattern)]"}] :example "timeCat [(3, s \"bd*3\"), (1, s \"hh\")]"}
     {:name "randcat" :description "Random pattern each cycle" :args [{:name "pats" :type "[Pattern]"}] :example "randcat [s \"bd\", s \"sd\", s \"hh*2\"]"}
     {:name "wrandcat" :description "Weighted random concat" :args [{:name "weighted" :type "[(Pattern, Double)]"}] :example "wrandcat [(s \"bd\", 4), (s \"sd\", 1)]"}
     {:name "stack" :description "Play simultaneously" :args [{:name "pats" :type "[Pattern]"}] :example "stack [s \"bd*2\", s \"hh*4\", s \"~ sd\"]"}
     {:name "overlay" :description "Layer two patterns" :args [{:name "p1" :type "Pattern"} {:name "p2" :type "Pattern"}] :example "overlay (s \"bd*2\") (s \"hh*4\")"}
     {:name "superimpose" :description "Layer with transform" :args [{:name "f" :type "Func"}] :example "superimpose (fast 2) $ s \"bd sd hh cp\""}
     {:name "layer" :description "Apply multiple funcs" :args [{:name "fns" :type "[Func]"}] :example "layer [id, rev, fast 2] $ s \"bd sd\""}
     {:name "append" :description "Alternate between two" :args [{:name "p1" :type "Pattern"} {:name "p2" :type "Pattern"}] :example "append (s \"bd*2\") (s \"hh*4\")"}
     {:name "wedge" :description "Combine with time ratio" :args [{:name "r" :type "Time" :range "0-1"} {:name "p1" :type "Pattern"} {:name "p2" :type "Pattern"}] :example "wedge 0.75 (s \"bd*4\") (s \"hh*8\")"}
     {:name "brak" :description "Breakbeat mangling" :example "brak $ s \"bd sd hh cp\""}
     {:name "iter" :description "Shift start each cycle" :args [{:name "n" :type "Int" :range "2-8"}] :example "iter 4 $ s \"bd sd hh cp\""}
     {:name "iter'" :description "iter but backward" :args [{:name "n" :type "Int" :range "2-8"}] :example "iter' 4 $ s \"bd sd hh cp\""}
     {:name "run" :description "Numbers 0 to n-1" :args [{:name "n" :type "Int"}] :example "# n (run 8)"}
     {:name "scan" :description "Progressive run" :args [{:name "n" :type "Int"}] :example "# n (scan 8)"}
     {:name "ur" :description "Named pattern composition" :args [{:name "dur" :type "Time"} {:name "struct" :type "Pattern String"} {:name "pats" :type "[(String, Pattern)]"} {:name "fx" :type "[(String, Func)]"}] :example "ur 8 \"a b\" [(\"a\", s \"bd\"), (\"b\", s \"hh*4\")] []"}
     {:name "seqP" :description "Sequence with timing" :args [{:name "seq" :type "[(Time, Time, Pattern)]"}] :example "seqP [(0, 4, s \"bd*4\"), (4, 8, s \"hh*8\")]"}
     {:name "seqPLoop" :description "Looping seqP" :args [{:name "seq" :type "[(Time, Time, Pattern)]"}] :example "seqPLoop [(0, 4, s \"bd*4\"), (4, 8, s \"hh*8\")]"}]}

   {:id :sampling
    :name "Sampling"
    :items
    [{:name "chop" :description "Granular - cut into parts" :args [{:name "n" :type "Int" :range "2-64"}] :example "chop 16 $ s \"breaks\""}
     {:name "striate" :description "Cut and interleave" :args [{:name "n" :type "Int" :range "2-64"}] :example "striate 16 $ s \"breaks\""}
     {:name "striateBy" :description "striate with part length" :args [{:name "n" :type "Int"} {:name "len" :type "Double"}] :example "striateBy 16 0.25 $ s \"breaks\""}
     {:name "slice" :description "Rearrange slices by pattern" :args [{:name "n" :type "Int"} {:name "order" :type "Pattern Int"}] :example "slice 8 \"0 3 2 1 4 7 6 5\" $ s \"breaks\""}
     {:name "splice" :description "slice + pitch adjustment" :args [{:name "n" :type "Int"} {:name "order" :type "Pattern Int"}] :example "splice 8 \"0 3 2 1\" $ s \"breaks\""}
     {:name "randslice" :description "Random slice each cycle" :args [{:name "n" :type "Int" :range "2-32"}] :example "randslice 8 $ s \"breaks\""}
     {:name "loopAt" :description "Fit sample to n cycles" :args [{:name "n" :type "Time"}] :example "loopAt 4 $ s \"breaks\""}
     {:name "smash" :description "spread + striate" :args [{:name "n" :type "Int"} {:name "speeds" :type "[Time]"}] :example "smash 4 [1, 2, 3] $ s \"breaks\""}
     {:name "smash'" :description "smash using chop" :args [{:name "n" :type "Int"} {:name "speeds" :type "[Time]"}] :example "smash' 4 [1, 2, 3] $ s \"breaks\""}]}

   {:id :harmony
    :name "Harmony & Melody"
    :items
    [{:name "scale" :description "Apply named scale" :args [{:name "name" :type "String"} {:name "pat" :type "Pattern Int"}] :example "# n (scale \"minor\" \"0 2 4 6\")"}
     {:name "scaleList" :description "Show all scale names" :example "scaleList"}
     {:name "toScale" :description "Apply custom scale" :args [{:name "intervals" :type "[Int]"} {:name "pat" :type "Pattern Int"}] :example "# n (toScale [0, 2, 4, 5, 7] \"0 1 2 3 4\")"}
     {:name "arpeggiate" :description "Spread chord over time" :example "arpeggiate $ n \"c'maj\""}
     {:name "arpg" :description "Alias for arpeggiate" :example "arpg $ n \"c'maj\""}
     {:name "arp" :description "Arpeggiate with mode" :args [{:name "mode" :type "Pattern String" :notes "up, down, updown, converge, diverge, etc"}] :example "arp \"up down\" $ n \"c'maj\""}
     {:name "chordList" :description "Show all chord names" :example "chordList"}]}

   {:id :transitions
    :name "Transitions"
    :items
    [{:name "xfade" :description "Crossfade to new pattern" :args [{:name "id" :type "PatternId"}] :example "xfade 1 $ s \"bd sd\""}
     {:name "xfadeIn" :description "Crossfade over n cycles" :args [{:name "id" :type "PatternId"} {:name "n" :type "Time"}] :example "xfadeIn 1 4 $ s \"bd sd\""}
     {:name "clutch" :description "Degrade old while undegrade new" :args [{:name "id" :type "PatternId"}] :example "clutch 1 $ s \"bd sd\""}
     {:name "clutchIn" :description "clutch over n cycles" :args [{:name "id" :type "PatternId"} {:name "n" :type "Time"}] :example "clutchIn 1 4 $ s \"bd sd\""}
     {:name "jump" :description "Immediate switch" :args [{:name "id" :type "PatternId"}] :example "jump 1 $ s \"bd sd\""}
     {:name "jumpIn" :description "Jump after n cycles" :args [{:name "id" :type "PatternId"} {:name "n" :type "Int"}] :example "jumpIn 1 4 $ s \"bd sd\""}
     {:name "jumpMod" :description "Jump at cycle divisible by n" :args [{:name "id" :type "PatternId"} {:name "n" :type "Int"}] :example "jumpMod 1 4 $ s \"bd sd\""}
     {:name "interpolate" :description "Morph controls over 4 cycles" :example "interpolate 1 $ s \"bd sd\""}
     {:name "interpolateIn" :description "Morph over n cycles" :args [{:name "id" :type "PatternId"} {:name "n" :type "Time"}] :example "interpolateIn 1 8 $ s \"bd sd\""}
     {:name "anticipate" :description "Build up then drop" :args [{:name "id" :type "PatternId"}] :example "anticipate 1 $ s \"bd sd\""}
     {:name "anticipateIn" :description "anticipate over n cycles" :args [{:name "id" :type "PatternId"} {:name "n" :type "Time"}] :example "anticipateIn 1 8 $ s \"bd sd\""}
     {:name "histpan" :description "Pan recent patterns L to R" :args [{:name "id" :type "PatternId"} {:name "n" :type "Int"}] :example "histpan 1 4 $ s \"bd sd\""}]}

   {:id :performance
    :name "Performance"
    :items
    [{:name "setcps" :description "Set cycles per second" :args [{:name "cps" :type "Double" :notes "0.5 = 60bpm for 2-beat cycle"}] :example "setcps 0.5"}
     {:name "resetCycles" :description "Reset cycle count to 0" :example "resetCycles"}
     {:name "setCycle" :description "Set cycle to n" :args [{:name "n" :type "Int"}] :example "setCycle 0"}
     {:name "trigger" :description "Start pattern from eval time" :args [{:name "id" :type "PatternId"}] :example "trigger 1 $ s \"bd sd\""}
     {:name "qtrigger" :description "Start at next cycle boundary" :args [{:name "id" :type "PatternId"}] :example "qtrigger 1 $ s \"bd sd\""}
     {:name "qt" :description "Alias for qtrigger" :args [{:name "id" :type "PatternId"}] :example "qt 1 $ s \"bd sd\""}
     {:name "mtrigger" :description "Start at cycle divisible by n" :args [{:name "id" :type "PatternId"} {:name "n" :type "Int"}] :example "mtrigger 1 4 $ s \"bd sd\""}
     {:name "once" :description "Play pattern once" :example "once $ s \"bd sd hh cp\""}
     {:name "hush" :description "Silence all patterns" :example "hush"}
     {:name "solo" :description "Solo a pattern" :args [{:name "id" :type "PatternId"}] :example "solo 1"}
     {:name "unsolo" :description "Unsolo a pattern" :args [{:name "id" :type "PatternId"}] :example "unsolo 1"}
     {:name "mute" :description "Mute a pattern" :args [{:name "id" :type "PatternId"}] :example "mute 1"}
     {:name "unmute" :description "Unmute a pattern" :args [{:name "id" :type "PatternId"}] :example "unmute 1"}]}

   {:id :state
    :name "State"
    :items
    [{:name "nTake" :description "Sequential values from list" :args [{:name "name" :type "String"} {:name "vals" :type "[a]"}] :example "# n (nTake \"seq\" [0, 2, 4, 7])"}
     {:name "nCount" :description "Incrementing counter" :args [{:name "name" :type "String"}] :example "# n (nCount \"cnt\")"}
     {:name "nCountTo" :description "Counter with modulo" :args [{:name "name" :type "String"} {:name "max" :type "Int"}] :example "# n (nCountTo \"cnt\" 8)"}
     {:name "setF" :description "Reset counter to value" :args [{:name "name" :type "String"} {:name "val" :type "Double"}] :example "setF \"cnt\" 0"}]}

   {:id :audio-effects
    :name "Audio Effects"
    :items
    [{:name "delay" :description "Delay wet/dry" :args [{:name "amt" :type "Double" :range "0-1"}] :example "# delay 0.5 # delaytime 0.25 # delayfb 0.5"}
     {:name "delaytime" :description "Delay time" :args [{:name "t" :type "Double" :range "0-1" :notes "cycle fraction"}] :example "# delaytime 0.125"}
     {:name "delayfb" :description "Delay feedback" :args [{:name "fb" :type "Double" :range "0-1"}] :example "# delayfb 0.8"}
     {:name "room" :description "Reverb room size" :args [{:name "sz" :type "Double" :range "0-1"}] :example "# room 0.8 # sz 0.9"}
     {:name "sz" :description "Reverb decay" :args [{:name "sz" :type "Double" :range "0-1"}] :example "# sz 0.9"}
     {:name "dry" :description "Reverb dry signal" :args [{:name "amt" :type "Double" :range "0-1"}] :example "# room 0.8 # dry 0.5"}
     {:name "lpf" :description "Low-pass filter cutoff" :args [{:name "freq" :type "Double" :range "20-20000" :notes "Hz"}] :example "# lpf 800"}
     {:name "lpq" :description "Low-pass resonance" :args [{:name "q" :type "Double" :range "0-1"}] :example "# lpf 800 # lpq 0.3"}
     {:name "hpf" :description "High-pass filter cutoff" :args [{:name "freq" :type "Double" :range "20-20000"}] :example "# hpf 400"}
     {:name "hpq" :description "High-pass resonance" :args [{:name "q" :type "Double" :range "0-1"}] :example "# hpf 400 # hpq 0.3"}
     {:name "bpf" :description "Band-pass center freq" :args [{:name "freq" :type "Double" :range "20-20000"}] :example "# bpf 1000 # bpq 0.5"}
     {:name "bpq" :description "Band-pass Q/width" :args [{:name "q" :type "Double" :range "0-1"}] :example "# bpq 0.1"}
     {:name "djf" :description "DJ filter" :args [{:name "amt" :type "Double" :range "0-1" :notes "0=lpf, 0.5=off, 1=hpf"}] :example "# djf (slow 4 saw)"}
     {:name "vowel" :description "Vowel formant filter" :args [{:name "v" :type "String" :notes "a e i o u"}] :example "# vowel \"a e i o\""}
     {:name "crush" :description "Bit crushing" :args [{:name "bits" :type "Double" :range "1-16" :notes "1=extreme"}] :example "# crush 4"}
     {:name "coarse" :description "Sample rate reduction" :args [{:name "amt" :type "Int" :range "1-32"}] :example "# coarse 8"}
     {:name "distort" :description "Distortion" :args [{:name "amt" :type "Double" :range "0-1"}] :example "# distort 0.5"}
     {:name "shape" :description "Wave shaping" :args [{:name "amt" :type "Double" :range "0-1"}] :example "# shape 0.7"}
     {:name "triode" :description "Tube distortion" :args [{:name "amt" :type "Double" :range "0-1"}] :example "# triode 0.5"}
     {:name "squiz" :description "Pitch-raising squiz" :args [{:name "amt" :type "Double" :range "1-16" :notes "try powers of 2"}] :example "# squiz 4"}
     {:name "pan" :description "Stereo position" :args [{:name "pos" :type "Double" :range "0-1" :notes "0=L, 0.5=C, 1=R"}] :example "# pan \"0 0.5 1\""}
     {:name "gain" :description "Volume (power curve)" :args [{:name "lvl" :type "Double" :range "0-1.5"}] :example "# gain \"1 0.8\""}
     {:name "amp" :description "Volume (linear)" :args [{:name "lvl" :type "Double" :range "0-1" :notes "0.4=default"}] :example "# amp 0.6"}
     {:name "attack" :description "Envelope attack" :args [{:name "t" :type "Double" :range "0-1" :notes "seconds"}] :example "# attack 0.1"}
     {:name "hold" :description "Envelope hold" :args [{:name "t" :type "Double" :range "0-2"}] :example "# hold 0.5"}
     {:name "release" :description "Envelope release" :args [{:name "t" :type "Double" :range "0-2"}] :example "# release 1"}
     {:name "leslie" :description "Leslie cabinet" :args [{:name "amt" :type "Double" :range "0-1"}] :example "# leslie 1 # lrate 6.7"}
     {:name "lrate" :description "Leslie rotation rate" :args [{:name "rate" :type "Double" :range "0.7-6.7"}] :example "# lrate 6.7"}
     {:name "phasr" :description "Phaser rate" :args [{:name "rate" :type "Double" :range "0.1-10"}] :example "# phasr 2 # phasdp 0.5"}
     {:name "phasdp" :description "Phaser depth" :args [{:name "depth" :type "Double" :range "0-1"}] :example "# phasdp 0.8"}
     {:name "tremr" :description "Tremolo rate" :args [{:name "rate" :type "Double" :range "0.1-20"}] :example "# tremr 8 # tremdp 0.5"}
     {:name "tremdp" :description "Tremolo depth" :args [{:name "depth" :type "Double" :range "0-1"}] :example "# tremdp 0.8"}
     {:name "ring" :description "Ring mod amount" :args [{:name "amt" :type "Double" :range "0-1"}] :example "# ring 0.5 # ringf 300"}
     {:name "ringf" :description "Ring mod frequency" :args [{:name "freq" :type "Double" :range "20-2000"}] :example "# ringf 440"}]}

   {:id :samplers
    :name "Samplers"
    :items
    [{:name "speed" :description "Playback speed/pitch" :args [{:name "rate" :type "Double" :range "-4 to 4" :notes "neg=reverse, 2=octave up"}] :example "# speed 2"}
     {:name "accelerate" :description "Speed change over time" :args [{:name "amt" :type "Double" :range "-4 to 4"}] :example "# accelerate 2"}
     {:name "unit" :description "How speed interprets" :args [{:name "mode" :type "String" :notes "r=rate, c=cycles, s=seconds"}] :example "# speed 2 # unit \"c\""}
     {:name "begin" :description "Sample start position" :args [{:name "pos" :type "Double" :range "0-1"}] :example "# begin 0.25"}
     {:name "end" :description "Sample end position" :args [{:name "pos" :type "Double" :range "0-1"}] :example "# end 0.75"}
     {:name "loop" :description "Loop sample n times" :args [{:name "n" :type "Int" :range "1-8"}] :example "# loop 4"}
     {:name "cut" :description "Cut group" :args [{:name "grp" :type "Int" :range "1-16" :notes "cuts same-group sounds"}] :example "# cut 1"}
     {:name "legato" :description "Note overlap" :args [{:name "amt" :type "Double" :range "0-2" :notes "<1=staccato"}] :example "# legato 0.5"}
     {:name "sustain" :description "Note duration" :args [{:name "t" :type "Double" :range "0-4" :notes "seconds"}] :example "# sustain 2"}
     {:name "timescale" :description "Time-stretch ratio" :args [{:name "r" :type "Double" :range "0.1-3"}] :example "# timescale 0.5"}
     {:name "n" :description "Sample index" :args [{:name "idx" :type "Int"}] :example "# n \"0 1 2 3\""}
     {:name "note" :description "Note/pitch" :args [{:name "n" :type "Double" :notes "semitones, 0=C4"}] :example "# note \"0 4 7\""}
     {:name "octave" :description "Octave shift" :args [{:name "o" :type "Int" :range "0-8" :notes "5=default"}] :example "# octave 4"}
     {:name "freq" :description "Frequency in Hz" :args [{:name "f" :type "Double" :range "20-20000"}] :example "# freq 440"}]}

   {:id :synthesizers
    :name "Synthesizers"
    :items
    [{:name "superpiano" :description "Piano emulation" :args [{:name "velocity" :type "Double" :range "0-1"} {:name "sustain" :type "Double" :range "0-4"}] :example "s \"superpiano\" # n \"c4 e4 g4\""}
     {:name "supersaw" :description "Detuned sawtooth" :args [{:name "voice" :type "Double" :range "0-1"} {:name "decay" :type "Double" :range "0-2"} {:name "resonance" :type "Double" :range "0-1"}] :example "s \"supersaw\" # n \"c4\""}
     {:name "supersquare" :description "Square wave" :args [{:name "voice" :type "Double"} {:name "decay" :type "Double"}] :example "s \"supersquare\" # n \"c4\""}
     {:name "superpwm" :description "Pulse width mod" :args [{:name "lfo" :type "Double" :range "0-1"} {:name "rate" :type "Double" :range "0.1-20"}] :example "s \"superpwm\" # n \"c4\" # lfo 0.5"}
     {:name "superfm" :description "6-op FM (DX7-style)" :args [{:name "voice" :type "Int" :range "0-5"} {:name "lfofreq" :type "Double"} {:name "lfodepth" :type "Double"}] :example "s \"superfm\" # n \"c4\" # voice 1"}
     {:name "superhammond" :description "Hammond B3 organ" :args [{:name "voice" :type "Int" :range "0-9"} {:name "vibrato" :type "Double" :range "0-1"}] :example "s \"superhammond\" # n \"c4\""}
     {:name "supervibe" :description "Vibraphone" :args [{:name "modamp" :type "Double" :range "0-1"} {:name "modfreq" :type "Double" :range "1-10"}] :example "s \"supervibe\" # n \"c4 e4 g4\""}
     {:name "supermandolin" :description "Plucked string" :args [{:name "sustain" :type "Double" :range "0-4"} {:name "detune" :type "Double" :range "0-0.1"}] :example "s \"supermandolin\" # n \"c4 e4 g4\""}
     {:name "supergong" :description "Gong/bell" :args [{:name "decay" :type "Double" :range "0-8"}] :example "slow 4 $ s \"supergong\""}
     {:name "superhoover" :description "Classic hoover" :args [{:name "slide" :type "Double" :range "0-1"} {:name "decay" :type "Double" :range "0-2"}] :example "s \"superhoover\" # n \"c3\""}
     {:name "superchip" :description "Chiptune" :args [{:name "pitch2" :type "Int" :range "0-24"} {:name "pitch3" :type "Int" :range "0-24"}] :example "s \"superchip\" # n \"c4\" # pitch2 7"}
     {:name "superkick" :description "Synth kick" :args [{:name "decay" :type "Double" :range "0-2"} {:name "pitch1" :type "Double" :range "0-1"}] :example "s \"superkick\""}
     {:name "supersnare" :description "Synth snare" :args [{:name "decay" :type "Double" :range "0-1"}] :example "s \"supersnare\""}
     {:name "superhat" :description "Synth hi-hat" :args [{:name "n" :type "Int" :range "0-5"}] :example "s \"superhat*4\""}
     {:name "superclap" :description "Synth clap" :args [{:name "delay" :type "Double" :range "0-0.1"} {:name "rate" :type "Double"}] :example "s \"superclap\""}
     {:name "super808" :description "808 kick" :args [{:name "rate" :type "Double" :range "0.1-10"} {:name "voice" :type "Double" :range "0-1"}] :example "s \"super808\""}]}

   {:id :mi-ugens
    :name "MI-UGens"
    :items
    [{:name "omi" :description "Vibraphone-like synth" :example "s \"omi\" # n \"c4 e4 g4\""}
     {:name "braids" :description "Digital sound source" :args [{:name "timbre" :type "Double" :range "0-1"} {:name "color" :type "Double" :range "0-1"}] :example "s \"braids\" # n \"c4\" # timbre 0.5"}
     {:name "plaits" :description "16 synthesis engines" :args [{:name "engine" :type "Int" :range "0-15"} {:name "timbre" :type "Double"} {:name "harm" :type "Double"}] :example "s \"plaits\" # engine 0 # n \"c4\""}
     {:name "tides" :description "Tidal modulator" :args [{:name "shape" :type "Double"} {:name "slope" :type "Double"}] :example "s \"tides\" # n \"c4\""}
     {:name "verb" :description "Global reverb" :args [{:name "wet" :type "Double"} {:name "time" :type "Double"} {:name "damp" :type "Double"}] :example "# verb 0.5 0.8 0.5"}
     {:name "clouds" :description "Granular processor" :args [{:name "pos" :type "Double"} {:name "size" :type "Double"} {:name "dens" :type "Double"}] :example "# clouds 0.5 0.5 0.5"}
     {:name "elements" :description "Modal synthesis" :args [{:name "strength" :type "Double"} {:name "contour" :type "Double"}] :example "s \"elements\" # n \"c4\""}
     {:name "rings" :description "Resonator" :args [{:name "struct" :type "Double"} {:name "bright" :type "Double"} {:name "damp" :type "Double"}] :example "# rings 0.5 0.5 0.5"}
     {:name "ripples" :description "4-pole filter" :args [{:name "cf" :type "Double" :notes "cutoff"} {:name "rq" :type "Double" :notes "resonance"}] :example "# ripples 1000 0.5"}
     {:name "warps" :description "Wave shaping/crossmod" :args [{:name "algo" :type "Int"} {:name "timbre" :type "Double"}] :example "# warps 0 0.5"}]}

   {:id :control-busses
    :name "Control Busses"
    :items
    [{:name "ampbus" :description "Route amp through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# ampbus 1 (range 0 1 sine)"}
     {:name "gainbus" :description "Route gain through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# gainbus 1 \"0.5 1\""}
     {:name "panbus" :description "Route pan through bus (-1 to 1)" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double" :range "-1 to 1"}] :example "# panbus 1 (slow 2 sine)"}
     {:name "lpfbus" :description "Route lpf through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# lpfbus 1 (range 200 2400 saw)"}
     {:name "hpfbus" :description "Route hpf through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# hpfbus 1 (range 100 1000 sine)"}
     {:name "djfbus" :description "Route djf through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# djfbus 1 (slow 4 saw)"}
     {:name "crushbus" :description "Route crush through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# crushbus 1 \"16 8 4 2\""}
     {:name "squizbus" :description "Route squiz through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# squizbus 1 \"1 2 4 8\""}
     {:name "roombus" :description "Route room through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# roombus 1 (range 0 0.8 sine)"}
     {:name "sizebus" :description "Route size through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# sizebus 1 \"0.5 0.9\""}
     {:name "delaybus" :description "Route delay through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# delaybus 1 (range 0 0.5 tri)"}
     {:name "cutoffbus" :description "Route cutoff through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# cutoffbus 1 (segment 32 $ range 200 2400 saw)"}
     {:name "hcutoffbus" :description "Route hcutoff through bus" :args [{:name "id" :type "Int"} {:name "pat" :type "Pattern Double"}] :example "# hcutoffbus 1 (range 50 500 sine)"}
     {:name "cF" :description "MIDI CC float input (0-1)" :args [{:name "default" :type "Double"} {:name "cc" :type "String"}] :example "# djfbus 1 (cF 0.5 \"21\")"}
     {:name "cI" :description "MIDI CC int input" :args [{:name "default" :type "Int"} {:name "cc" :type "String"}] :example "# n (cI 0 \"22\")"}
     {:name "cP" :description "MIDI CC pattern input" :args [{:name "default" :type "Pattern"} {:name "cc" :type "String"}] :example "# n (cP \"0 2 4\" \"23\")"}]}

   {:id :pattern-ops
    :name "Pattern Operators"
    :items
    [{:symbol "#" :description "Apply control (alias |>)" :example "s \"bd sd\" # crush 4"}
     {:symbol "|>" :description "Values from right, structure from left" :example "s \"bd sd\" |> crush 4"}
     {:symbol "<|" :description "Values from left, structure from right" :example "crush \"4 8\" <| s \"bd sd hh cp\""}
     {:symbol "|+|" :description "Add, structure from both" :example "n (\"0 2\" |+| \"0 1 2 3\")"}
     {:symbol "|+" :description "Add, structure from left" :example "n (\"0 2\" |+ \"0 1 2 3\")"}
     {:symbol "+|" :description "Add, structure from right" :example "n (\"0 2\" +| \"0 1 2 3\")"}
     {:symbol "|-|" :description "Subtract, structure from both" :example "n (\"4 6\" |-| \"0 1\")"}
     {:symbol "|*|" :description "Multiply, structure from both" :example "speed (\"1 2\" |*| \"1 0.5\")"}
     {:symbol "|/|" :description "Divide, structure from both" :example "speed (\"2 4\" |/| \"2 1\")"}
     {:symbol "$" :description "Function application" :example "fast 2 $ s \"bd sd\""}
     {:symbol "." :description "Function composition" :example "(fast 2 . rev) $ s \"bd sd hh cp\""}]}])

;; Helper to get all items flattened
(defn all-items []
  (mapcat :items categories))
