@@ -4,7 +4,6 @@ import type {
44 InsertSnippetArg ,
55 WrapWithSnippetArg ,
66} from "@cursorless/common" ;
7- import { compareSnippetDefinitions } from "./compareSnippetDefinitions" ;
87
98export function getPreferredSnippet (
109 snippetDescription : InsertSnippetArg ,
@@ -29,13 +28,11 @@ export function getPreferredSnippet(
2928 return snippetDescription ;
3029 }
3130
32- const filteredSnippets = filterSnippetDefinitions (
31+ const preferredSnippet = tryToFindPreferredSnippet (
3332 snippetDescription . snippets ,
3433 languageId ,
3534 snippetDescription . fallbackLanguage ,
3635 ) ;
37- filteredSnippets . sort ( compareSnippetDefinitions ) ;
38- const preferredSnippet = filteredSnippets [ 0 ] ;
3936
4037 if ( preferredSnippet == null ) {
4138 const languages = getUniqueLanguagesString ( snippetDescription . snippets ) ;
@@ -54,36 +51,53 @@ function getUniqueLanguagesString(snippets: CustomInsertSnippetArg[]): string {
5451 return Array . from ( languages ) . sort ( ) . join ( ", " ) ;
5552}
5653
57- /**
58- * Filter snippet definitions by language.
59- * @param snippetDescriptions The snippets to filter
60- * @returns The snippets that are relevant to the current language
61- */
62- function filterSnippetDefinitions <
54+ function tryToFindPreferredSnippet <
6355 T extends CustomInsertSnippetArg | CustomWrapWithSnippetArg ,
6456> (
6557 snippetDescriptions : T [ ] ,
6658 languageId : string ,
6759 fallbackLanguage : string | undefined ,
68- ) : T [ ] {
60+ ) : T | undefined {
6961 // First try to find snippet matching language id
70- let snippets = snippetDescriptions . filter ( ( snippetDescription ) => {
71- return snippetDescription . languages ?. includes ( languageId ) ;
72- } ) ;
62+ let snippet = findSnippetWithFewestLanguages (
63+ snippetDescriptions . filter ( ( snippetDescription ) => {
64+ return snippetDescription . languages ?. includes ( languageId ) ;
65+ } ) ,
66+ ) ;
7367
7468 // Secondly try to find snippet matching fallback language
75- if ( snippets . length === 0 && fallbackLanguage != null ) {
76- snippets = snippetDescriptions . filter ( ( snippetDescription ) => {
77- return snippetDescription . languages ?. includes ( fallbackLanguage ) ;
78- } ) ;
69+ if ( snippet == null && fallbackLanguage != null ) {
70+ snippet = findSnippetWithFewestLanguages (
71+ snippetDescriptions . filter ( ( snippetDescription ) => {
72+ return snippetDescription . languages ?. includes ( fallbackLanguage ) ;
73+ } ) ,
74+ ) ;
7975 }
8076
81- // Finally use global snippets
82- if ( snippets . length === 0 ) {
83- snippets = snippetDescriptions . filter ( ( snippetDescription ) => {
77+ // Finally try to find global snippet
78+ if ( snippet == null ) {
79+ snippet = snippetDescriptions . find ( ( snippetDescription ) => {
8480 return snippetDescription . languages == null ;
8581 } ) ;
8682 }
8783
88- return snippets ;
84+ return snippet ;
85+ }
86+
87+ function findSnippetWithFewestLanguages <
88+ T extends CustomInsertSnippetArg | CustomWrapWithSnippetArg ,
89+ > ( snippets : T [ ] ) : T | undefined {
90+ if ( snippets . length === 0 ) {
91+ return undefined ;
92+ }
93+
94+ // Find the snippet with the fewest languages
95+ return snippets . reduce ( ( prev , curr ) => {
96+ if ( prev . languages == null || curr . languages == null ) {
97+ throw Error (
98+ "Snippet must have languages defined to find the one with the fewest languages" ,
99+ ) ;
100+ }
101+ return curr . languages . length < prev . languages . length ? curr : prev ;
102+ } ) ;
89103}
0 commit comments