GuidesDisable a rewrite rule

Disable a rewrite rule

Turn off a single rewrite rule by key when a profile normalizes more than you want, and see what disabling does and does not change.

Sometimes a profile is right about almost everything and wrong about one rule. You want corpus normalization across the board, but your downstream consumer needs \dv to survive as written, or a particular rewrite conflicts with a convention in your dataset. Rather than dropping to a weaker profile and losing everything else, you disable that one rule by key when you construct the engine.

Rules are identified by a package/rule-name key, the same key that appears in the transform report and in the rule reference. Pass the keys you want off to the engine constructor; the engine compiles its plan without them and behaves normally otherwise. The examples load physics explicitly, since it is not in the default package set.

import texform

kb = texform.KnowledgeBase(packages=["base", "ams", "physics"])
default = texform.TransformEngine(profile="corpus", knowledge_base=kb)
without_dv = texform.TransformEngine(
    profile="corpus",
    knowledge_base=kb,
    disable_rules=["physics/dv-to-frac-d"],
)

for src in [r"\dv{f}{x}", r"\pdv{f}{x}", r"a \over b"]:
    print(f"{src!r:16} default={default.normalize(src)!r}")
    print(f"{'':16} disabled={without_dv.normalize(src)!r}")
Output
'\\dv{f}{x}'     default='\\frac { \\mathrm { d } f } { \\mathrm { d } x }'
                 disabled='\\dv { f } { x }'
'\\pdv{f}{x}'    default='\\frac { \\partial f } { \\partial x }'
                 disabled='\\frac { \\partial f } { \\partial x }'
'a \\over b'     default='\\frac { a } { b }'
                 disabled='\\frac { a } { b }'
import { KnowledgeBase, TransformEngine } from 'texform';

const knowledgeBase = new KnowledgeBase({ packages: ['base', 'ams', 'physics'] });
const defaultEngine = new TransformEngine({ profile: 'corpus', knowledgeBase });
const withoutDv = new TransformEngine({
  profile: 'corpus',
  knowledgeBase,
  disableRules: ['physics/dv-to-frac-d'],
});

for (const src of ['\\dv{f}{x}', '\\pdv{f}{x}', 'a \\over b']) {
  console.log(src, 'default =', defaultEngine.normalize(src));
  console.log(' '.repeat(src.length), 'disabled =', withoutDv.normalize(src));
}

The disabled rule is the only thing that changed. \dv{f}{x} now passes through as the author wrote it, while \pdv still expands — it is a different rule (physics/pdv-to-frac-partial) and was never disabled — and a \over b still modernizes, because that belongs to base. Disabling is surgical, not a downgrade of the whole profile.

The transform report confirms it, which is the reliable way to check that a key you typed actually matched a rule:

Python
import texform

kb = texform.KnowledgeBase(packages=["base", "ams", "physics"])
default = texform.TransformEngine(profile="corpus", knowledge_base=kb)
without_dv = texform.TransformEngine(
    profile="corpus", knowledge_base=kb, disable_rules=["physics/dv-to-frac-d"]
)


def fired(engine, src):
    report = engine.normalize_with_report(src)["report"]
    return [r["key"] for r in report["rewrite"]["rules"] if r["applied_count"] > 0]


print("default :", fired(default, r"\dv{f}{x}"))
print("disabled:", fired(without_dv, r"\dv{f}{x}"))
Output
default : ['physics/dv-to-frac-d']
disabled: []

What disabling a rule does not do#

Three boundaries are worth stating plainly, because each is a thing people reasonably expect and TeXForm does not offer.

You cannot register your own rewrite rule at runtime. The rule set is compiled into the engine, and the public API exposes no way to add to it. disable_rules subtracts; nothing adds. Contributing a rule means adding it to the transform crate — see Rules and the transform contract. Injecting parser knowledge is a separate capability that does exist, covered in Inject custom commands; it teaches the parser a command's argument structure, which is not the same as teaching the engine a rewrite.

Disabling a phase is not the same as disabling a rule. The per-run config can switch off a whole pipeline phase, which is a much blunter instrument — turning off Rewrite drops every rule at once:

import texform

kb = texform.KnowledgeBase(packages=["base", "ams", "physics"])
engine = texform.TransformEngine(profile="corpus", knowledge_base=kb)
print(engine.normalize(r"\dv{f}{x}", rewrite={"enabled": False}))
Output
\dv { f } { x }
import { KnowledgeBase, TransformEngine } from 'texform';

const knowledgeBase = new KnowledgeBase({ packages: ['base', 'ams', 'physics'] });
const engine = new TransformEngine({ profile: 'corpus', knowledgeBase });
console.log(engine.normalize('\\dv{f}{x}', { rewrite: { enabled: false } }));

That output looks identical to disabling the single rule, which is exactly the trap: on this one input the two are indistinguishable, but across a corpus the phase switch also suppresses \over, \pdv, and everything else. Use disable_rules when you mean one rule.

Disabling a rule does not change the profile's rule level. A profile selects which levels of rules participate; disable_rules removes individual keys from whatever that selection produced. If you find yourself disabling many rules to approximate a different target, a different profile is probably the right answer — see the profile comparison in Transforms.

Next steps#

Last updated