@@ -545,62 +545,73 @@ function registerStandardHints(successFunc) {
545
545
}
546
546
}
547
547
548
- // If there's a chance to find an exact match, clear out the fuzzy matches
549
- // so that the exact match is chosen.
550
- if ( found [ 0 ] . length + found [ 1 ] . length === 1 ) {
551
- found [ 2 ] = [ ] ;
552
- }
553
-
554
- const options = found [ 0 ] . concat ( found [ 1 ] , found [ 2 ] ) ;
555
-
548
+ let options = found [ 0 ] . concat ( found [ 1 ] , found [ 2 ] ) ;
549
+ let foundReplacementPrefix = false ;
556
550
options . forEach ( ( candidate ) => {
557
551
const { text } = candidate ;
558
- const originalTermCost = substitutionCost (
559
- token . string ,
560
- text ,
561
- term . length
562
- ) ;
552
+ candidate . cost = substitutionCost ( token . string , text , term . length ) ;
563
553
564
- for ( const [ module , mapping ] of Object . entries ( replacementTerms ) ) {
565
- if ( window . codeWorldSymbols [ text ] ) {
566
- const mappedTerms =
567
- Object . prototype . hasOwnProperty . call ( mapping , text ) &&
568
- mapping [ text ] ;
569
- const { definingModule } = window . codeWorldSymbols [ text ] ;
570
-
571
- if ( mappedTerms && definingModule && definingModule === module ) {
572
- const mappedTermsWithCosts = mappedTerms . map ( ( mappedTerm ) => {
573
- return {
574
- replacementExplanation : mappedTerm . explanation ,
575
- cost : substitutionCost (
576
- token . string ,
577
- mappedTerm . value ? mappedTerm . value : mappedTerm ,
578
- term . length ,
579
- true
580
- ) ,
581
- } ;
582
- } ) ;
554
+ if ( ! window . codeWorldSymbols [ text ] ) {
555
+ return ;
556
+ }
583
557
584
- const lowestCost = Math . min (
585
- ...mappedTermsWithCosts . map ( ( { cost } ) => cost ) ,
586
- originalTermCost
587
- ) ;
588
- candidate . cost = lowestCost ;
589
-
590
- const winningMappedTerm = mappedTermsWithCosts . find (
591
- ( { cost } ) => cost === lowestCost
592
- ) ;
593
- if ( winningMappedTerm ) {
594
- candidate . replacementExplanation =
595
- winningMappedTerm . replacementExplanation ;
596
- }
597
- } else {
598
- candidate . cost = originalTermCost ;
599
- }
558
+ const { definingModule } = window . codeWorldSymbols [ text ] ;
559
+ if ( ! definingModule ) {
560
+ return ;
561
+ }
562
+
563
+ const mapping = replacementTerms [ definingModule ] ;
564
+ const mappedTerms =
565
+ Object . prototype . hasOwnProperty . call ( mapping , text ) && mapping [ text ] ;
566
+
567
+ if ( ! mappedTerms ) {
568
+ return ;
569
+ }
570
+
571
+ const mappedTermsWithCosts = mappedTerms . map ( ( mappedTerm ) => {
572
+ const replacementWord = mappedTerm . value
573
+ ? mappedTerm . value
574
+ : mappedTerm ;
575
+ if ( replacementWord . startsWith ( term ) ) {
576
+ foundReplacementPrefix = true ;
600
577
}
578
+
579
+ return {
580
+ replacementExplanation : mappedTerm . explanation ,
581
+ cost : substitutionCost (
582
+ token . string ,
583
+ mappedTerm . value ? mappedTerm . value : mappedTerm ,
584
+ term . length ,
585
+ true
586
+ ) ,
587
+ } ;
588
+ } ) ;
589
+
590
+ const lowestCost = Math . min (
591
+ ...mappedTermsWithCosts . map ( ( { cost } ) => cost ) ,
592
+ candidate . cost
593
+ ) ;
594
+ candidate . cost = lowestCost ;
595
+
596
+ const winningMappedTerm = mappedTermsWithCosts . find (
597
+ ( { cost } ) => cost === lowestCost
598
+ ) ;
599
+ if ( winningMappedTerm ) {
600
+ candidate . replacementExplanation =
601
+ winningMappedTerm . replacementExplanation ;
601
602
}
602
603
} ) ;
603
604
605
+ // If there's a chance to complete an exact prefix, clear out the fuzzy
606
+ // matches so that the exact match is chosen.
607
+ if (
608
+ found [ 0 ] . length === 0 &&
609
+ found [ 1 ] . length === 1 &&
610
+ ! foundReplacementPrefix
611
+ ) {
612
+ options = found [ 1 ] ;
613
+ }
614
+
604
615
if ( options . length > 0 ) {
605
616
options . sort ( ( a , b ) => {
606
617
if ( a . cost < b . cost ) return - 1 ;
0 commit comments