@@ -149,30 +149,63 @@ class FortranRegularExpressions:
149149 OBJBREAK : Pattern = compile (r"[\/\-(.,+*<>=$: ]" , I )
150150
151151
152- def src_file_exts (input_exts : list [str ] = []) -> Pattern [str ]:
153- """Create a REGEX for which file extensions the Language Server should parse
154- Default extensions are
155- F F03 F05 F08 F18 F77 F90 F95 FOR FPP f f03 f05 f08 f18 f77 f90 f95 for fpp
152+ # TODO: use this in the main code
153+ def create_src_file_exts_regex (input_exts : list [str ] = []) -> Pattern [str ]:
154+ r"""Create a REGEX for which sources the Language Server should parse.
155+
156+ Default extensions are (case insensitive):
157+ F F03 F05 F08 F18 F77 F90 F95 FOR FPP
156158
157159 Parameters
158160 ----------
159161 input_exts : list[str], optional
160- Additional Fortran, by default []
162+ Additional list of file extensions to parse, in Python REGEX format
163+ that means special characters must be escaped
164+ , by default []
165+
166+ Examples
167+ --------
168+ >>> regex = create_src_file_exts_regex([r"\.fypp", r"\.inc"])
169+ >>> regex.search("test.fypp")
170+ <re.Match object; span=(4, 9), match='.fypp'>
171+ >>> regex.search("test.inc")
172+ <re.Match object; span=(4, 8), match='.inc'>
173+
174+ >>> regex = create_src_file_exts_regex([r"\.inc.*"])
175+ >>> regex.search("test.inc.1")
176+ <re.Match object; span=(4, 10), match='.inc.1'>
177+
178+ Invalid regex expressions will cause the function to revert to the default
179+ extensions
180+
181+ >>> regex = create_src_file_exts_regex(["*.inc"])
182+ >>> regex.search("test.inc") is None
183+ True
161184
162185 Returns
163186 -------
164187 Pattern[str]
165- A compiled regular expression, by default
166- '.(F|F03|F05|F08|F18|F77|F90|F95|FOR|FPP|f|f03|f05|f08|f18|f77|f90|f95|for|fpp)?'
188+ A compiled regular expression for matching file extensions
167189 """
168- EXTS = ["" , "77" , "90" , "95" , "03" , "05" , "08" , "18" , "OR" , "PP" ]
169- FORTRAN_FILE_EXTS = []
170- for e in EXTS :
171- FORTRAN_FILE_EXTS .extend ([f"F{ e } " .upper (), f"f{ e } " .lower ()])
172- # Add the custom extensions for the server to parse
173- for e in input_exts :
174- if e .startswith ("." ):
175- FORTRAN_FILE_EXTS .append (e .replace ("." , "" ))
176- # Cast into a set to ensure uniqueness of extensions & sort for consistency
177- # Create a regular expression from this
178- return compile (rf"\.({ '|' .join (sorted (set (FORTRAN_FILE_EXTS )))} )?$" )
190+ import re
191+
192+ DEFAULT = r"\.[fF](77|90|95|03|05|08|18|[oO][rR]|[pP]{2})?"
193+ EXPRESSIONS = [DEFAULT ]
194+ try :
195+ EXPRESSIONS .extend (input_exts )
196+ # Add its expression as an OR and force they match the end of the string
197+ return re .compile (rf"(({ '$)|(' .join (EXPRESSIONS )} $))" )
198+ except re .error :
199+ # TODO: Add a warning to the logger
200+ return re .compile (rf"({ DEFAULT } $)" )
201+
202+
203+ def create_src_file_exts_str (input_exts : list [str ] = []) -> Pattern [str ]:
204+ """This is a version of create_src_file_exts_regex that takes a list
205+ sanitises the list of input_exts before compiling the regex.
206+ For more info see create_src_file_exts_regex
207+ """
208+ import re
209+
210+ input_exts = [re .escape (ext ) for ext in input_exts ]
211+ return create_src_file_exts_regex (input_exts )
0 commit comments