LINUX.ORG.RU

История изменений

Исправление ei-grad, (текущая версия) :

GREP-МАНИФЕСТ

против LSP-навигации по коду

Тезис

Код — это текст. Навигация по тексту должна быть текстовой. grep/rg дают истинную, мгновенную, воспроизводимую картину. LSP для навигации избыточен, хрупок и лжёт, когда индекс устаревает.

Почему grep

  1. Скорость: O(размер текста), без демонов и прогрева индексов.
  2. Надёжность: смотрит в файл, а не в кеш. Нет рассинхронизации.
  3. Универсальность: любой язык, любой генерат, любой билд-стадж.
  4. Комбинаторика: пайплайны UNIX решают 90% задач навигации.
  5. Контроль: точные паттерны, детерминированные результаты, легко ревьюить.
  6. Портируемость: локально, по SSH, в CI, в контейнере, в монорепо.

Почему LSP плох

  • Хрупкая индексация: одна сломанная зависимость → “нет определения”.
  • Ложные гарантии: “перейти к определению” ведёт в кеш, не в правду файла.
  • Цена: память, CPU, сетевые RPC, фоновые краши.
  • Полиглот-страдания: один сервер на язык, конфликт версий, ад.
  • Плохая деградация: частично собранный проект = слепая навигация.
  • Непрозрачность: JSON-RPC внутри, трудно отладить и воспроизвести.

Принципы навигации текстом

  1. Источник истины — git ls-files + рабочее дерево.
  2. Сначала грубый поиск по идентификатору, затем уточнение контекста.
  3. Превью до перехода. Переход по координатам file:line.
  4. Скриптуемость выше кликов. Команда = артефакт, её можно положить в repo.
  5. Никаких демонов. Только 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

  1. Скорость: O(размер текста), без демонов и прогрева индексов.
  2. Надёжность: смотрит в файл, а не в кеш. Нет рассинхронизации.
  3. Универсальность: любой язык, любой генерат, любой билд-стадж.
  4. Комбинаторика: пайплайны UNIX решают 90% задач навигации.
  5. Контроль: точные паттерны, детерминированные результаты, легко ревьюить.
  6. Портируемость: локально, по SSH, в CI, в контейнере, в монорепо.

Почему LSP плох

— Хрупкая индексация: одна сломанная зависимость → “нет определения”. — Ложные гарантии: “перейти к определению” ведёт в кеш, не в правду файла. — Цена: память, CPU, сетевые RPC, фоновые краши. — Полиглот-страдания: один сервер на язык, конфликт версий, ад. — Плохая деградация: частично собранный проект = слепая навигация. — Непрозрачность: JSON-RPC внутри, трудно отладить и воспроизвести.

Принципы навигации текстом

  1. Источник истины — git ls-files + рабочее дерево.
  2. Сначала грубый поиск по идентификатору, затем уточнение контекста.
  3. Превью до перехода. Переход по координатам file:line.
  4. Скриптуемость выше кликов. Команда = артефакт, её можно положить в repo.
  5. Никаких демонов. Только 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

  1. Скорость: O(размер текста), без демонов и прогрева индексов.
  2. Надёжность: смотрит в файл, а не в кеш. Нет рассинхронизации.
  3. Универсальность: любой язык, любой генерат, любой билд-стадж.
  4. Комбинаторика: пайплайны UNIX решают 90% задач навигации.
  5. Контроль: точные паттерны, детерминированные результаты, легко ревьюить.
  6. Портируемость: локально, по SSH, в CI, в контейнере, в монорепо.

Почему LSP плох

— Хрупкая индексация: одна сломанная зависимость → “нет определения”. — Ложные гарантии: “перейти к определению” ведёт в кеш, не в правду файла. — Цена: память, CPU, сетевые RPC, фоновые краши. — Полиглот-страдания: один сервер на язык, конфликт версий, ад. — Плохая деградация: частично собранный проект = слепая навигация. — Непрозрачность: JSON-RPC внутри, трудно отладить и воспроизвести.

Принципы навигации текстом

  1. Источник истины — git ls-files + рабочее дерево.
  2. Сначала грубый поиск по идентификатору, затем уточнение контекста.
  3. Превью до перехода. Переход по координатам file:line.
  4. Скриптуемость выше кликов. Команда = артефакт, её можно положить в repo.
  5. Никаких демонов. Только 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 не обещает магии. Он показывает правду.