0f23d17640ca30e2c9ee456c7e15966cabd3bc57
max
  Mon Sep 7 23:32:24 2026 -0700
Position box: let a hyphen separate a range of codons, e.g. "BRCA1 100-200"

A bare number after a gene symbol has always meant a codon, and "KAT6A 495-533"
was already accepted -- it just landed on codon 495 and dropped the rest, the
same silent truncation that the underscore form had. A hyphen now separates a
range wherever the coordinates are protein: after a gene symbol with no prefix,
and after an explicit p. with a symbol or a transcript accession.

The hyphen stays out of c. and n. terms, where HGVS already uses it for an
intron offset. KAT6A c.1483-1599 is still the single base 1599 nt before
c.1483, not codons 1483 to 1599, and there are now regression tests pinning
both readings so the two do not drift into each other.

refs #38285

diff --git src/hg/lib/hgHgvs.c src/hg/lib/hgHgvs.c
index de78af5a6a6..d59038f581a 100644
--- src/hg/lib/hgHgvs.c
+++ src/hg/lib/hgHgvs.c
@@ -394,31 +394,36 @@
 //                                                     4......  replacement sequence
 
 #define pseudoHgvsGeneSymbolProtRangeExp "^" geneSymbolExp maybePDot hgvsAaRangeExp "\\)?"
 //      0.....................................................  whole matching string
 //      1...................                                    gene symbol
 //                                 2...                         original start AA
 //                                       3...                   1-based start position
 //                                           4................  optional range sep and AA+pos
 //                                             5...             original end AA
 //                                                  6...         1-based end position
 //                                                       7.....  change description
 
 // As above but omitting the protein change, and allowing a range of codon numbers.
 // Someone reading about a mutation usually has the codon number but not the amino acid,
 // so "KAT6A p.495" and "KAT6A p.495_533" have to work as well as "KAT6A p.Lys495".
-#define posIntRangeExp posIntExp "(_" posIntExp ")?"
+// A hyphen is allowed as the range separator alongside the HGVS underscore, but ONLY here in
+// protein coordinates, where HGVS has no other use for it: proteins have neither introns nor
+// negative positions.  In c. and n. terms a hyphen is an intron offset -- c.1483-1599 is a
+// single base 1599 nt before c.1483 -- so those keep the underscore as their only range
+// separator, and posIntRangeExp must not be used to build a c. or n. pattern.
+#define posIntRangeExp posIntExp "([-_]" posIntExp ")?"
 #define pseudoHgvsGeneSymbolProtPosExp "^" geneSymbolExp maybePDot posIntRangeExp "\\)?"
 //      0..........................                             whole matching string
 //      1...................                                    gene symbol
 //                           2.....                             1-based start position
 //                                 3.......                     optional range sep and end position
 //                                    4.....                    1-based end position
 
 // The same bare codon number or range, but after a transcript accession rather than a gene
 // symbol.  Here the "p" is required: without it "NM_006766.5 1483" would silently become a
 // codon number, and a bare number after an accession is far more likely to be something else.
 #define pDot "[ :]+p\\.?\\(?"
 #define pseudoHgvsNMPDotPosExp "^" versionedRefSeqNMExp pDot posIntRangeExp "\\)?"
 //      0..........................                             whole matching string
 //      1...............                                        acc & optional dot version
 //             2........                                        optional dot version