@@ -27,6 +27,10 @@ export function getRangeDescription(range: string): string {
2727 if ( range . startsWith ( '{' ) && range . endsWith ( '}' ) ) {
2828 return `Format: ${ range . substring ( 1 , range . length - 1 ) } ` ;
2929 }
30+ if ( range . startsWith ( '!' ) && range . includes ( ',' ) ) {
31+ const vals = range . substring ( 1 ) . split ( ',' ) . map ( v => v . trim ( ) ) ;
32+ return `Bus letters (one per parameter): ${ vals . join ( ', ' ) } ` ;
33+ }
3034 if ( range . startsWith ( '+' ) && range . includes ( ',' ) ) {
3135 const vals = range . substring ( 1 ) . split ( ',' ) ;
3236 return `Accumulative values: ${ vals . join ( ', ' ) } (can combine, e.g. ${ vals . slice ( 0 , 3 ) . join ( '' ) } )` ;
@@ -57,14 +61,34 @@ export function getRangeDescription(range: string): string {
5761 return range ;
5862}
5963
64+ // Devuelve los valores individuales del rango ! (e.g. ["M","A","B","C","D","E","F","G"])
65+ export function getRangeProgressiveValues ( range : string ) : string [ ] {
66+ if ( ! range . startsWith ( '!' ) || ! range . includes ( ',' ) ) { return [ ] ; }
67+ return range . substring ( 1 ) . split ( ',' ) . map ( v => v . trim ( ) ) ;
68+ }
69+
70+ // Devuelve un array de arrays, uno por overload.
71+ // !M,A,B → [["M"], ["M","A"], ["M","A","B"]]
72+ export function getRangeProgressiveOverloads ( range : string ) : string [ ] [ ] {
73+ const values = getRangeProgressiveValues ( range ) ;
74+ const result : string [ ] [ ] = [ ] ;
75+ for ( let i = 0 ; i < values . length ; i ++ ) {
76+ result . push ( values . slice ( 0 , i + 1 ) ) ;
77+ }
78+ return result ;
79+ }
80+
6081export function getRangeCompletionItems ( range : string ) : string [ ] {
82+ if ( range . startsWith ( '!' ) && range . includes ( ',' ) ) {
83+ return getRangeProgressiveValues ( range ) ;
84+ }
6185 if ( range . startsWith ( '+' ) && range . includes ( ',' ) ) {
6286 return range . substring ( 1 ) . split ( ',' ) . map ( v => v . trim ( ) ) ;
6387 }
6488 if ( range . startsWith ( '=' ) && range . includes ( ',' ) ) {
6589 return range . substring ( 1 ) . split ( ',' ) . map ( v => v . trim ( ) ) ;
6690 }
67- if ( ! range . startsWith ( '+' ) && ! range . startsWith ( '=' ) && ! range . startsWith ( '{' ) && ! range . startsWith ( '@' ) && ! range . startsWith ( '<' ) && ! range . startsWith ( '?' ) && range !== 'url' && range !== '' && range . includes ( ',' ) && ! range . includes ( ':' ) ) {
91+ if ( ! range . startsWith ( '+' ) && ! range . startsWith ( '=' ) && ! range . startsWith ( '!' ) && ! range . startsWith ( ' {') && ! range . startsWith ( '@' ) && ! range . startsWith ( '<' ) && ! range . startsWith ( '?' ) && range !== 'url' && range !== '' && range . includes ( ',' ) && ! range . includes ( ':' ) ) {
6892 return range . split ( ',' ) . map ( v => v . trim ( ) ) ;
6993 }
7094 return [ ] ;
@@ -82,22 +106,23 @@ export function validateValueAgainstRange(value: string, range: string, valueTyp
82106 return null ;
83107 }
84108
85- if ( range . startsWith ( '@' ) ) {
86- return null ;
87- }
88-
89- if ( range . startsWith ( '{' ) && range . endsWith ( '}' ) ) {
90- return null ;
91- }
109+ if ( range . startsWith ( '@' ) ) { return null ; }
110+ if ( range . startsWith ( '{' ) && range . endsWith ( '}' ) ) { return null ; }
92111
93112 if ( range === '+' ) {
94- if ( trimmedValue === '""' ) {
95- return 'Value cannot be empty' ;
96- }
113+ if ( trimmedValue === '""' ) { return 'Value cannot be empty' ; }
97114 return null ;
98115 }
99116
100- if ( range === '' ) {
117+ if ( range === '' ) { return null ; }
118+
119+ // Para ! el valor es un identificador sin comillas (constante de letra)
120+ if ( range . startsWith ( '!' ) && range . includes ( ',' ) ) {
121+ const validVals = getRangeProgressiveValues ( range ) . map ( v => v . toLowerCase ( ) ) ;
122+ const unquoted = trimmedValue . replace ( / ^ " | " $ / g, '' ) . toLowerCase ( ) ;
123+ if ( ! validVals . includes ( unquoted ) ) {
124+ return `Invalid bus letter '${ trimmedValue } '. Valid: ${ getRangeProgressiveValues ( range ) . join ( ', ' ) } ` ;
125+ }
101126 return null ;
102127 }
103128
@@ -118,20 +143,14 @@ export function validateValueAgainstRange(value: string, range: string, valueTyp
118143 return `Invalid character '${ ch } '. Valid: ${ range . substring ( 1 ) } ` ;
119144 }
120145 }
121- if ( unquoted . length === 0 ) {
122- return 'Value cannot be empty' ;
123- }
146+ if ( unquoted . length === 0 ) { return 'Value cannot be empty' ; }
124147 return null ;
125148 }
126149
127150 if ( range === '<?:?' || range === '?:?' ) {
128151 const num = parseFloat ( unquoted ) ;
129- if ( isNaN ( num ) ) {
130- return 'Value must be a number' ;
131- }
132- if ( range === '?:?' && num < 0 ) {
133- return 'Value must be >= 0' ;
134- }
152+ if ( isNaN ( num ) ) { return 'Value must be a number' ; }
153+ if ( range === '?:?' && num < 0 ) { return 'Value must be >= 0' ; }
135154 return null ;
136155 }
137156
@@ -140,20 +159,14 @@ export function validateValueAgainstRange(value: string, range: string, valueTyp
140159 const min = parseFloat ( parts [ 0 ] ) ;
141160 const max = parseFloat ( parts [ 1 ] ) ;
142161 const num = parseFloat ( unquoted ) ;
143- if ( isNaN ( num ) ) {
144- return 'Value must be a number' ;
145- }
146- if ( num < min || num > max ) {
147- return `Value out of range. Expected: ${ min } to ${ max } ` ;
148- }
162+ if ( isNaN ( num ) ) { return 'Value must be a number' ; }
163+ if ( num < min || num > max ) { return `Value out of range. Expected: ${ min } to ${ max } ` ; }
149164 return null ;
150165 }
151166
152- if ( ! range . startsWith ( '+' ) && ! range . startsWith ( '=' ) && ! range . startsWith ( '{' ) && ! range . startsWith ( '@' ) && ! range . startsWith ( '<' ) && ! range . startsWith ( '?' ) && range !== 'url' && range !== '' && range . includes ( ',' ) && ! range . includes ( ':' ) ) {
167+ if ( ! range . startsWith ( '+' ) && ! range . startsWith ( '=' ) && ! range . startsWith ( '!' ) && ! range . startsWith ( ' {') && ! range . startsWith ( '@' ) && ! range . startsWith ( '<' ) && ! range . startsWith ( '?' ) && range !== 'url' && range !== '' && range . includes ( ',' ) && ! range . includes ( ':' ) ) {
153168 const validVals = range . split ( ',' ) . map ( v => v . trim ( ) ) ;
154- if ( ! validVals . includes ( unquoted ) ) {
155- return `Invalid value. Valid options: ${ range } ` ;
156- }
169+ if ( ! validVals . includes ( unquoted ) ) { return `Invalid value. Valid options: ${ range } ` ; }
157170 return null ;
158171 }
159172
0 commit comments