# Справка по интересным моментам в коде ## Функция получения версии `python` в `lsp.lua` ```lua local function get_python_version() local handle = io.popen("python --version 2>&1") -- Redirect stderr to stdout if handle then local result = handle:read("*a") handle:close() -- Check if the output contains a version number local version = result:match("Python (%d+%.%d+%.%d+)") if version then return version end end handle = io.popen("python3 --version 2>&1") -- Redirect stderr to stdout if handle then local result = handle:read("*a") handle:close() -- Check if the output contains a version number local version = result:match("Python (%d+%.%d+%.%d+)") if version then return version end end -- TODO: Add some exception handling if python not installed on user machine return "Python 0.0.0" end ``` Что тут есть примечательного: - Получение данных, выполняя команду в shell оболочке системы с помощью `io.popen`. *Важно*: Данная функция может работать не во всех ОС - Функция выполняет команду, указанную в аргументе, и возвращает *файловый дескриптор*, который можно использовать для чтения вывода команды (или записи в нее) Разберем флоу подробнее: Если про `python --version` - все понятно, то вот: ```lua 2>&1 ``` Уже надо прояснить: - В UNIX-подобных системах есть три стандартных потока - `stdin` = 0; `stdout` = 1; `strerr` = 2; - По умолчанию `io.popen` передает только вывод `stdout` в handle, поэтому для обработки ошибок, надо дополнительно захватывать поток `stderr` - `2>&1` означает, что мы хотим перенаправить поток ошибок 2 в стандартный вывод 1; - Это нужно для того, чтобы захватить не только вывод команды, но и возможные ошибки (например если питон не установлен); - `>&` - оператор перенаправления потоков. Дополнительно: `*a` внутри `read` - конструкция формата чтения файловых объектов в `Lua`. Они указывают - как именно стоит читать данные из файла или потока. Помимо `a` есть еще: - `*a` - читать все содержимое - `*l` - читать строку - `*n` - читать число.