Csound Manual Parser
A robust parser that converts the Csound reference manual into TypeScript reference files for use in code editors with hover tooltips and searchable documentation.
Features
- Downloads markdown files directly from GitHub
- Parses 1000+ Csound opcodes
- Extracts structured data (syntax, parameters, examples)
- Generates organized TypeScript files by category
- Creates a main aggregator file with lookup functions
- Handles edge cases and provides detailed error reporting
Installation
cd scripts/csound-parser
pnpm install
Usage
Option 1: Download and Parse (Recommended)
Download fresh markdown files from GitHub and parse them:
pnpm run download
This will:
- Download all opcode markdown files from the Csound manual repository
- Parse them into structured data
- Generate TypeScript reference files in
src/lib/csound-reference/
Option 2: Parse Local Files
If you already have the Csound manual cloned locally:
pnpm run parse -- --input=/path/to/csound-manual/docs/opcodes
Custom Output Directory
pnpm run parse -- --output=/custom/output/path
Output Structure
The parser generates:
src/lib/csound-reference/
├── types.ts # Type definitions
├── csoundReference.ts # Main aggregator
├── signal-generators-basic-oscillators.ts
├── signal-modifiers-standard-filters.ts
├── mathematical-operations-trigonometric-functions.ts
└── ... (100+ category files)
Each category file contains an array of CsoundReference objects:
export const signalGeneratorsBasicOscillators: CsoundReference[] = [
{
name: 'oscil',
type: 'opcode',
category: 'Signal Generators:Basic Oscillators',
description: 'A simple oscillator without any interpolation.',
syntax: 'ares = oscil(xamp, xcps [, ifn, iphs])\nkres = oscil(kamp, kcps [, ifn, iphs])',
rates: ['a-rate', 'k-rate', 'i-rate'],
parameters: [
{
name: 'ifn',
description: 'function table number. Requires a wrap-around guard point.',
type: 'initialization'
},
// ...
],
seeAlso: ['oscili', 'poscil']
},
// ...
]
Integration
Import in your application:
import {
allCsoundReferences,
getCsoundReference,
getCsoundReferencesByCategory
} from './lib/csound-reference/csoundReference'
// Get a specific opcode
const oscil = getCsoundReference('oscil')
// Get all oscillators
const oscillators = getCsoundReferencesByCategory('Signal Generators:Basic Oscillators')
// Search all references
const filtered = allCsoundReferences.filter(ref =>
ref.description.includes('filter')
)
Use Cases
1. Hover Tooltips in CodeMirror
Create a tooltip extension similar to the GLSL tooltips:
import { hoverTooltip } from '@codemirror/view'
import { getCsoundReference } from './lib/csound-reference/csoundReference'
export const csoundTooltip = hoverTooltip((view, pos) => {
const word = getWordAt(view, pos)
if (!word) return null
const reference = getCsoundReference(word.text)
if (!reference) return null
return {
pos: word.from,
end: word.to,
above: true,
create() {
const dom = document.createElement('div')
dom.innerHTML = `
<div class="tooltip-header">
<strong>${reference.name}</strong>
<span>${reference.type}</span>
</div>
<div class="tooltip-description">${reference.description}</div>
${reference.syntax ? `<pre>${reference.syntax}</pre>` : ''}
`
return { dom }
}
}
})
2. Searchable Help Panel
Create a reference panel with fuzzy search:
import { allCsoundReferences } from './lib/csound-reference/csoundReference'
import Fuse from 'fuse.js'
const fuse = new Fuse(allCsoundReferences, {
keys: ['name', 'description', 'category'],
threshold: 0.4
})
const results = fuse.search('oscillator')
3. Autocomplete
Use the reference data for intelligent autocomplete:
import { allCsoundReferences } from './lib/csound-reference/csoundReference'
const completions = allCsoundReferences.map(ref => ({
label: ref.name,
type: ref.type,
info: ref.description,
detail: ref.syntax
}))
Data Structure
CsoundReference Interface
interface CsoundReference {
name: string // Opcode name (e.g., "oscil")
type: 'opcode' | 'keyword' | 'header' | 'constant'
category: string // Full category path
description: string // Brief description
syntax?: string // Syntax examples
example?: string // Code example
rates?: string[] // ['a-rate', 'k-rate', 'i-rate']
parameters?: {
name: string
description: string
type: 'initialization' | 'performance'
}[]
seeAlso?: string[] // Related opcodes
}
Parser Architecture
1. Downloader (downloader.ts)
- Fetches markdown files from GitHub API
- Handles rate limiting and retries
- Downloads to
downloaded-opcodes/directory
2. Parser (parser.ts)
- Parses markdown frontmatter (id, category)
- Extracts sections using regex
- Extracts parameters from initialization/performance sections
- Handles modern and classic syntax variants
- Detects rate types (a-rate, k-rate, i-rate)
3. Generator (generator.ts)
- Groups opcodes by category
- Sanitizes category names for file names
- Generates TypeScript files with proper escaping
- Creates main aggregator with imports
- Provides lookup functions
Troubleshooting
Download Fails
If the GitHub download fails, manually clone the repository:
git clone https://github.com/csound/manual.git
cd manual
git checkout develop
Then run the parser with the local path:
pnpm run parse -- --input=../manual/docs/opcodes
Missing Categories
Some opcodes may not have categories defined. The parser will skip these and log warnings.
Parse Errors
The parser is robust and will continue parsing even if individual files fail. Check the console output for warnings about skipped files.
Extending the Parser
Adding New Extraction
To extract additional information from the markdown files, modify parser.ts:
extractNewField(content: string): string {
const section = this.extractSection(content, 'NewSection')
// Parse the section content
return parsed
}
Then add the field to the CsoundReference interface in types.ts.
Custom Categories
To reorganize categories, modify the category field in the parser or create a mapping function in the generator.
Performance
- Parsing 1000+ opcodes: ~2-5 seconds
- Generating TypeScript files: ~1-2 seconds
- Download from GitHub: ~30-60 seconds (network dependent)
License
MIT