TestFuzzyReplace_EndingAndWhitespace exercises the line-endings and per-position whitespace behavior of the fuzzy matcher in both single-replace and replace-all modes. Match rule: content and search lines are compared after splitting off trailing (pass 2) or surrounding (pass 3) whitespace. The lin
(t *testing.T)
| 1813 | // Pass 1 (byte-literal substring match) is untouched; tests that |
| 1814 | // exercise it are noted. |
| 1815 | func TestFuzzyReplace_EndingAndWhitespace(t *testing.T) { |
| 1816 | t.Parallel() |
| 1817 | |
| 1818 | tmpdir := os.TempDir() |
| 1819 | logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug) |
| 1820 | |
| 1821 | type edit struct { |
| 1822 | search, replace string |
| 1823 | replaceAll bool |
| 1824 | } |
| 1825 | tests := []struct { |
| 1826 | name string |
| 1827 | content string |
| 1828 | edits []edit |
| 1829 | expected string |
| 1830 | }{ |
| 1831 | // CRLF file, LF search: the ending rule lets "line\n" |
| 1832 | // match "line\r\n"; the replacement is empty so the |
| 1833 | // matched line is removed entirely. |
| 1834 | { |
| 1835 | name: "CRLF_Content_LFSearch_Delete", |
| 1836 | content: "foo\r\nline\r\nbar\r\n", |
| 1837 | edits: []edit{{search: "line\n", replace: ""}}, |
| 1838 | expected: "foo\r\nbar\r\n", |
| 1839 | }, |
| 1840 | // Pass 2 tolerates the file's trailing whitespace on |
| 1841 | // the matched line when search omits it. Empty |
| 1842 | // replacement removes the line. |
| 1843 | { |
| 1844 | name: "TrailingWhitespace_Delete", |
| 1845 | content: "foo\nline \nbar\n", |
| 1846 | edits: []edit{{search: "line\n", replace: ""}}, |
| 1847 | expected: "foo\nbar\n", |
| 1848 | }, |
| 1849 | // Pass 1 handles a search without a trailing newline |
| 1850 | // when the content contains an exact substring match: |
| 1851 | // strings.Replace preserves the surrounding "\n" bytes |
| 1852 | // verbatim. |
| 1853 | { |
| 1854 | name: "Pass1_SearchNoNewline_ExactSubstring", |
| 1855 | content: "foo\nfirst line\nbar\n", |
| 1856 | edits: []edit{{search: "first line", replace: "LINE"}}, |
| 1857 | expected: "foo\nLINE\nbar\n", |
| 1858 | }, |
| 1859 | // Fuzzy path, both search and replace lack a newline |
| 1860 | // ending AND share a trailing space. The empty ending |
| 1861 | // on search is a wildcard against content's "\n"; |
| 1862 | // pass 2's content comparator ignores the shared |
| 1863 | // trailing space to match "key". At splice time, |
| 1864 | // search and replace agree on the trailing space so |
| 1865 | // the file's lack of trailing whitespace wins; search |
| 1866 | // and replace agree on empty ending so the file's |
| 1867 | // "\n" wins. |
| 1868 | { |
| 1869 | name: "FuzzyMatchingWhitespace_FileEndingWins", |
| 1870 | content: "foo\nkey\nbar\n", |
| 1871 | edits: []edit{{search: "key ", replace: "KEY "}}, |
| 1872 | expected: "foo\nKEY\nbar\n", |