Map a file path to its language name. Extension-based lookup is tried first. For extension-less files (typical for Unix scripts like ``bin/myapp`` or ``.git/hooks/pre-commit``) we fall back to reading the first line for a shebang. Files that already have a known ex
(self, path: Path)
| 852 | return self._parsers[language] |
| 853 | |
| 854 | def detect_language(self, path: Path) -> Optional[str]: |
| 855 | """Map a file path to its language name. |
| 856 | |
| 857 | Extension-based lookup is tried first. For extension-less files |
| 858 | (typical for Unix scripts like ``bin/myapp`` or ``.git/hooks/pre-commit``) |
| 859 | we fall back to reading the first line for a shebang. Files that |
| 860 | already have a known extension are never re-read — shebang probing |
| 861 | only runs when the extension lookup returns ``None`` **and** the path |
| 862 | has no suffix at all. See issue #237. |
| 863 | """ |
| 864 | suffix = path.suffix.lower() |
| 865 | lang = self._extension_map.get(suffix) |
| 866 | if lang is not None: |
| 867 | return lang |
| 868 | # Only probe shebang for files without any extension — "README", "LICENSE", |
| 869 | # and other extension-less text files also fall here, but the probe is a |
| 870 | # cheap 256-byte read that returns None when no shebang is found. |
| 871 | if suffix == "": |
| 872 | return self._detect_language_from_shebang(path) |
| 873 | return None |
| 874 | |
| 875 | @staticmethod |
| 876 | def _detect_language_from_shebang(path: Path) -> Optional[str]: |