История изменений
Исправление ei-grad, (текущая версия) :
GREP-МАНИФЕСТ
против LSP-навигации по коду
Тезис
Код — это текст. Навигация по тексту должна быть текстовой. grep/rg дают истинную, мгновенную, воспроизводимую картину. LSP для навигации избыточен, хрупок и лжёт, когда индекс устаревает.
Почему grep
- Скорость: O(размер текста), без демонов и прогрева индексов.
- Надёжность: смотрит в файл, а не в кеш. Нет рассинхронизации.
- Универсальность: любой язык, любой генерат, любой билд-стадж.
- Комбинаторика: пайплайны UNIX решают 90% задач навигации.
- Контроль: точные паттерны, детерминированные результаты, легко ревьюить.
- Портируемость: локально, по SSH, в CI, в контейнере, в монорепо.
Почему LSP плох
- Хрупкая индексация: одна сломанная зависимость → “нет определения”.
- Ложные гарантии: “перейти к определению” ведёт в кеш, не в правду файла.
- Цена: память, CPU, сетевые RPC, фоновые краши.
- Полиглот-страдания: один сервер на язык, конфликт версий, ад.
- Плохая деградация: частично собранный проект = слепая навигация.
- Непрозрачность: JSON-RPC внутри, трудно отладить и воспроизвести.
Принципы навигации текстом
- Источник истины — git ls-files+ рабочее дерево.
- Сначала грубый поиск по идентификатору, затем уточнение контекста.
- Превью до перехода. Переход по координатам file:line.
- Скриптуемость выше кликов. Команда = артефакт, её можно положить в repo.
- Никаких демонов. Только stdin/stdout.
Базовые приёмы
Опорный набор: rg/git grep, fzf, sed/awk, xargs, fd, ctags как опциональный индекс.
Поиск определения символа:
rg -n --pcre2 -w "^(\\s*(fn|def|class|struct|type|interface)\\s+)?<SYMBOL>\\b" \
  --glob '!*.min.*' --glob '!dist/*' --hidden
Поиск всех упоминаний:
rg -n -w '<SYMBOL>' $(git ls-files)
Поиск вызовов функции:
rg -n --pcre2 '\\b<SYMBOL>\\s*\\('
Ограничение по языку/папке:
rg -n -w '<SYMBOL>' -g '!tests/**' -g '*.go' -g '*.ts'
Живой превью с выбором:
rg -n --no-heading -w '<SYMBOL>' | \
  fzf --delimiter : --nth=3.. \
      --preview 'bat --style=numbers --color=always {1}:{2}'
Список TODO рядом с местами использования:
rg -n 'TODO|FIXME' | rg -n -w '<SYMBOL>' -n
Быстрые шорткаты (обёртки)
def()  { rg -n --pcre2 -w "^(\\s*(fn|def|class|struct|type)\\s+)?$1\\b" $(git ls-files); }
refs() { rg -n -w "$1" $(git ls-files); }
calls(){ rg -n --pcre2 "\\b$1\\s*\\(" $(git ls-files); }
jump() { rg -n -w "$1" $(git ls-files) | fzf | awk -F: '{print "+"$2" "$1}' | xargs ${EDITOR:-vim}; }
Опционально: ctags как ускоритель стартового “jump-to-def”, но без магии:
ctags -R --fields=+n
grep -m1 -P "^\Q<SYMBOL>\E\t" tags | cut -f2,3 | awk -F'\t' '{print "+"$2" "$1}' | xargs ${EDITOR:-vim}
Моно- и мегарепозитории
— Фильтруйте область поиска: git grep -n -w '<SYMBOL>' -- :^vendor :^node_modules.
— Делите по модулям: fd . src/moduleA | xargs rg -n -w '<SYMBOL>'.
— Кэшируйте списки файлов: git ls-files > .files && rg -n -w '<SYMBOL>' -f .files.
В CI и код-ревью
— Проверка утечек/рефакторов:
rg -n -w '<OLD_NAME>' && echo "Rename незавершён" && exit 1
- Навигация в артефактах билдов: распаковали, затем всё те же команды.
Анти-паттерны LSP-навигации
- “Жду индекса” — потери времени.
- “Сервер упал” — потеря контекста.
- “Переход не нашёлся” — ложный сигнал, символ существует.
- “Работает только в IDE X” — лок-ин, плохая переносимость.
Клятва grep
- Не доверяю демонам. Доверяю тексту.
- Любая навигация должна быть воспроизводима одной строкой.
- Каждый переход должен быть объясним простым регулярным выражением.
- Скорость важнее украшений. Точность важнее подсказок. Свобода важнее интеграций.
Когда LSP уместен
Автодополнение, сложные безопасные рефакторы, подсказки типов.
Быстрый старт набора инструментов
alias GG="git grep -n --heading --break"
alias RR="rg -n --hidden --follow -S -g '!.git' -g '!node_modules' -g '!dist'"
export RIPGREP_CONFIG_PATH=~/.ripgreprc
# ~/.ripgreprc: --hidden
#                 --follow
#                 --colors line:style:nobold
Заключение
Откройте глаза: переход по коду — это поиск по тексту. grep не обещает магии. Он показывает правду.
Исправление ei-grad, :
GREP-МАНИФЕСТ
против LSP-навигации по коду
Тезис
Код — это текст. Навигация по тексту должна быть текстовой. grep/rg дают истинную, мгновенную, воспроизводимую картину. LSP для навигации избыточен, хрупок и лжёт, когда индекс устаревает.
Почему grep
- Скорость: O(размер текста), без демонов и прогрева индексов.
- Надёжность: смотрит в файл, а не в кеш. Нет рассинхронизации.
- Универсальность: любой язык, любой генерат, любой билд-стадж.
- Комбинаторика: пайплайны UNIX решают 90% задач навигации.
- Контроль: точные паттерны, детерминированные результаты, легко ревьюить.
- Портируемость: локально, по SSH, в CI, в контейнере, в монорепо.
Почему LSP плох
— Хрупкая индексация: одна сломанная зависимость → “нет определения”. — Ложные гарантии: “перейти к определению” ведёт в кеш, не в правду файла. — Цена: память, CPU, сетевые RPC, фоновые краши. — Полиглот-страдания: один сервер на язык, конфликт версий, ад. — Плохая деградация: частично собранный проект = слепая навигация. — Непрозрачность: JSON-RPC внутри, трудно отладить и воспроизвести.
Принципы навигации текстом
- Источник истины — git ls-files+ рабочее дерево.
- Сначала грубый поиск по идентификатору, затем уточнение контекста.
- Превью до перехода. Переход по координатам file:line.
- Скриптуемость выше кликов. Команда = артефакт, её можно положить в repo.
- Никаких демонов. Только stdin/stdout.
Базовые приёмы
Опорный набор: rg/git grep, fzf, sed/awk, xargs, fd, ctags как опциональный индекс.
Поиск определения символа:
rg -n --pcre2 -w "^(\\s*(fn|def|class|struct|type|interface)\\s+)?<SYMBOL>\\b" \
  --glob '!*.min.*' --glob '!dist/*' --hidden
Поиск всех упоминаний:
rg -n -w '<SYMBOL>' $(git ls-files)
Поиск вызовов функции:
rg -n --pcre2 '\\b<SYMBOL>\\s*\\('
Ограничение по языку/папке:
rg -n -w '<SYMBOL>' -g '!tests/**' -g '*.go' -g '*.ts'
Живой превью с выбором:
rg -n --no-heading -w '<SYMBOL>' | \
  fzf --delimiter : --nth=3.. \
      --preview 'bat --style=numbers --color=always {1}:{2}'
Список TODO рядом с местами использования:
rg -n 'TODO|FIXME' | rg -n -w '<SYMBOL>' -n
Быстрые шорткаты (обёртки)
def()  { rg -n --pcre2 -w "^(\\s*(fn|def|class|struct|type)\\s+)?$1\\b" $(git ls-files); }
refs() { rg -n -w "$1" $(git ls-files); }
calls(){ rg -n --pcre2 "\\b$1\\s*\\(" $(git ls-files); }
jump() { rg -n -w "$1" $(git ls-files) | fzf | awk -F: '{print "+"$2" "$1}' | xargs ${EDITOR:-vim}; }
Опционально: ctags как ускоритель стартового “jump-to-def”, но без магии:
ctags -R --fields=+n
grep -m1 -P "^\Q<SYMBOL>\E\t" tags | cut -f2,3 | awk -F'\t' '{print "+"$2" "$1}' | xargs ${EDITOR:-vim}
Моно- и мегарепозитории
— Фильтруйте область поиска: git grep -n -w '<SYMBOL>' -- :^vendor :^node_modules.
— Делите по модулям: fd . src/moduleA | xargs rg -n -w '<SYMBOL>'.
— Кэшируйте списки файлов: git ls-files > .files && rg -n -w '<SYMBOL>' -f .files.
В CI и код-ревью
— Проверка утечек/рефакторов:
rg -n -w '<OLD_NAME>' && echo "Rename незавершён" && exit 1
- Навигация в артефактах билдов: распаковали, затем всё те же команды.
Анти-паттерны LSP-навигации
- “Жду индекса” — потери времени.
- “Сервер упал” — потеря контекста.
- “Переход не нашёлся” — ложный сигнал, символ существует.
- “Работает только в IDE X” — лок-ин, плохая переносимость.
Клятва grep
- Не доверяю демонам. Доверяю тексту.
- Любая навигация должна быть воспроизводима одной строкой.
- Каждый переход должен быть объясним простым регулярным выражением.
- Скорость важнее украшений. Точность важнее подсказок. Свобода важнее интеграций.
Когда LSP уместен
Автодополнение, сложные безопасные рефакторы, подсказки типов.
Быстрый старт набора инструментов
alias GG="git grep -n --heading --break"
alias RR="rg -n --hidden --follow -S -g '!.git' -g '!node_modules' -g '!dist'"
export RIPGREP_CONFIG_PATH=~/.ripgreprc
# ~/.ripgreprc: --hidden
#                 --follow
#                 --colors line:style:nobold
Заключение
Откройте глаза: переход по коду — это поиск по тексту. grep не обещает магии. Он показывает правду.
Исходная версия ei-grad, :
GREP-МАНИФЕСТ
против LSP-навигации по коду
Тезис
Код — это текст. Навигация по тексту должна быть текстовой. grep/rg дают истинную, мгновенную, воспроизводимую картину. LSP для навигации избыточен, хрупок и лжёт, когда индекс устаревает.
Почему grep
- Скорость: O(размер текста), без демонов и прогрева индексов.
- Надёжность: смотрит в файл, а не в кеш. Нет рассинхронизации.
- Универсальность: любой язык, любой генерат, любой билд-стадж.
- Комбинаторика: пайплайны UNIX решают 90% задач навигации.
- Контроль: точные паттерны, детерминированные результаты, легко ревьюить.
- Портируемость: локально, по SSH, в CI, в контейнере, в монорепо.
Почему LSP плох
— Хрупкая индексация: одна сломанная зависимость → “нет определения”. — Ложные гарантии: “перейти к определению” ведёт в кеш, не в правду файла. — Цена: память, CPU, сетевые RPC, фоновые краши. — Полиглот-страдания: один сервер на язык, конфликт версий, ад. — Плохая деградация: частично собранный проект = слепая навигация. — Непрозрачность: JSON-RPC внутри, трудно отладить и воспроизвести.
Принципы навигации текстом
- Источник истины — git ls-files+ рабочее дерево.
- Сначала грубый поиск по идентификатору, затем уточнение контекста.
- Превью до перехода. Переход по координатам file:line.
- Скриптуемость выше кликов. Команда = артефакт, её можно положить в repo.
- Никаких демонов. Только stdin/stdout.
Базовые приёмы
Опорный набор: rg/git grep, fzf, sed/awk, xargs, fd, ctags как опциональный индекс.
Поиск определения символа:
rg -n --pcre2 -w "^(\\s*(fn|def|class|struct|type|interface)\\s+)?<SYMBOL>\\b" \
  --glob '!*.min.*' --glob '!dist/*' --hidden
Поиск всех упоминаний:
rg -n -w '<SYMBOL>' $(git ls-files)
Поиск вызовов функции:
rg -n --pcre2 '\\b<SYMBOL>\\s*\\('
Ограничение по языку/папке:
rg -n -w '<SYMBOL>' -g '!tests/**' -g '*.go' -g '*.ts'
Живой превью с выбором:
rg -n --no-heading -w '<SYMBOL>' | \
  fzf --delimiter : --nth=3.. \
      --preview 'bat --style=numbers --color=always {1}:{2}'
Список TODO рядом с местами использования:
rg -n 'TODO|FIXME' | rg -n -w '<SYMBOL>' -n
Быстрые шорткаты (обёртки)
def()  { rg -n --pcre2 -w "^(\\s*(fn|def|class|struct|type)\\s+)?$1\\b" $(git ls-files); }
refs() { rg -n -w "$1" $(git ls-files); }
calls(){ rg -n --pcre2 "\\b$1\\s*\\(" $(git ls-files); }
jump() { rg -n -w "$1" $(git ls-files) | fzf | awk -F: '{print "+"$2" "$1}' | xargs ${EDITOR:-vim}; }
Опционально: ctags как ускоритель стартового “jump-to-def”, но без магии:
ctags -R --fields=+n
grep -m1 -P "^\Q<SYMBOL>\E\t" tags | cut -f2,3 | awk -F'\t' '{print "+"$2" "$1}' | xargs ${EDITOR:-vim}
Моно- и мегарепозитории
— Фильтруйте область поиска: git grep -n -w '<SYMBOL>' -- :^vendor :^node_modules.
— Делите по модулям: fd . src/moduleA | xargs rg -n -w '<SYMBOL>'.
— Кэшируйте списки файлов: git ls-files > .files && rg -n -w '<SYMBOL>' -f .files.
В CI и код-ревью
— Проверка утечек/рефакторов:
rg -n -w '<OLD_NAME>' && echo "Rename незавершён" && exit 1
— Навигация в артефактах билдов: распаковали, затем всё те же команды.
Анти-паттерны LSP-навигации — “Жду индекса” — потери времени. — “Сервер упал” — потеря контекста. — “Переход не нашёлся” — ложный сигнал, символ существует. — “Работает только в IDE X” — лок-ин, плохая переносимость.
Клятва grep
— Не доверяю демонам. Доверяю тексту. — Любая навигация должна быть воспроизводима одной строкой. — Каждый переход должен быть объясним простым регулярным выражением. — Скорость важнее украшений. Точность важнее подсказок. Свобода важнее интеграций.
Когда LSP уместен
Автодополнение, сложные безопасные рефакторы, подсказки типов.
Быстрый старт набора инструментов
alias GG="git grep -n --heading --break"
alias RR="rg -n --hidden --follow -S -g '!.git' -g '!node_modules' -g '!dist'"
export RIPGREP_CONFIG_PATH=~/.ripgreprc
# ~/.ripgreprc: --hidden
#                 --follow
#                 --colors line:style:nobold
Заключение
Откройте глаза: переход по коду — это поиск по тексту. grep не обещает магии. Он показывает правду.