Перейти к основному содержимому

API и техническая документация Switch

Архитектура программы

Компоненты системы

┌─────────────────────────────────────────┐
│ Пользовательский интерфейс │
│ (main.c) │
└─────────────────┬───────────────────────┘

┌─────────▼──────────┐
│ Парсинг команд │
│ (getopt) │
└─────────┬──────────┘

┌─────────▼──────────┐
│ Загрузчик модулей │
│ (module.c) │
└─────────┬──────────┘

┌────────────┼────────────┐
│ │ │
┌────▼────┐ ┌───▼────┐ ┌───▼────┐
│ editor │ │ java │ │ python │
│ .sh │ │ .sh │ │ .sh │
└─────────┘ └────────┘ └────────┘

Исходные файлы

ФайлОписание
main.cТочка входа, обработка аргументов командной строки
module.cЗагрузка, парсинг и выполнение модулей
module.hЗаголовочный файл для работы с модулями
config.cУправление конфигурацией
config.hЗаголовочный файл конфигурации
utils.cВспомогательные функции
utils.hЗаголовочный файл утилит

Структуры данных

module_info_t

Структура, представляющая информацию о модуле.

typedef struct {
char *name; // Имя модуля
char *category; // Категория (system, development, etc.)
char *description; // Описание
char *link; // Основная символическая ссылка
char *extra_links; // Дополнительные ссылки
char *path; // Путь к файлу модуля
} module_info_t;

module_list_t

Список загруженных модулей.

typedef struct {
module_info_t *modules; // Массив модулей
size_t count; // Количество модулей
size_t capacity; // Вместимость массива
} module_list_t;

alternative_t

Структура, представляющая альтернативу.

typedef struct {
char *path; // Полный путь к программе
char *name; // Отображаемое имя
int priority; // Приоритет
} alternative_t;

switch_config_t

Конфигурация программы.

typedef struct {
char *modules_dir; // Путь к системным модулям
char *user_modules_dir; // Путь к пользовательским модулям
bool color_enabled; // Включен ли цветной вывод
} switch_config_t;

API модулей

Функции инициализации

module_list_init

Инициализация списка модулей.

int module_list_init(module_list_t *list);

Параметры:

  • list — указатель на структуру module_list_t

Возвращает:

  • 0 при успехе
  • -1 при ошибке

module_list_free

Освобождение памяти списка модулей.

void module_list_free(module_list_t *list);

Параметры:

  • list — указатель на структуру module_list_t

Функции сканирования

module_scan

Сканирование директорий на наличие модулей.

int module_scan(module_list_t *list, const switch_config_t *config);

Параметры:

  • list — список для добавления найденных модулей
  • config — конфигурация с путями к директориям

Возвращает:

  • 0 при успехе
  • -1 при ошибке

Логика работы:

  1. Сканирует системную директорию модулей
  2. Сканирует пользовательскую директорию модулей
  3. Пользовательские модули перезаписывают системные при совпадении имен

Функции поиска

module_find

Поиск модуля по имени.

const module_info_t *module_find(const module_list_t *list, const char *name);

Параметры:

  • list — список модулей
  • name — имя искомого модуля

Возвращает:

  • Указатель на module_info_t при нахождении
  • NULL если модуль не найден

Функции действий

module_action_list

Показать список доступных альтернатив для модуля.

int module_action_list(const module_info_t *module);

Параметры:

  • module — информация о модуле

Возвращает:

  • 0 при успехе
  • -1 при ошибке

Вывод:

Available alternatives for editor:
[1] nvim /usr/bin/nvim (priority: 80)
[2] vim /usr/bin/vim (priority: 70)

module_action_show

Показать текущую конфигурацию модуля.

int module_action_show(const module_info_t *module);

Параметры:

  • module — информация о модуле

Возвращает:

  • 0 при успехе
  • -1 при ошибке

module_action_set

Установить альтернативу.

int module_action_set(const module_info_t *module, const char *target);

Параметры:

  • module — информация о модуле
  • target — имя или путь к устанавливаемой альтернативе

Возвращает:

  • 0 при успехе
  • -1 при ошибке

Логика работы:

  1. Выполняет find_alternatives() модуля
  2. Ищет совпадение с target по имени или пути
  3. Создает/обновляет символическую ссылку
  4. Если указаны EXTRA_LINKS, создает дополнительные ссылки

module_action_help

Показать справку по модулю.

int module_action_help(const module_info_t *module);

Параметры:

  • module — информация о модуле

Возвращает:

  • 0 при успехе
  • -1 при ошибке

Функции вывода

module_print_list

Показать список всех доступных модулей.

void module_print_list(const module_list_t *list);

Параметры:

  • list — список модулей

Вывод:

Available modules:
editor (system) Manage default text editor
java (development) Manage Java version

API конфигурации

config_init

Инициализация конфигурации.

int config_init(switch_config_t *config);

Параметры:

  • config — указатель на структуру конфигурации

Возвращает:

  • 0 при успехе
  • -1 при ошибке

Устанавливает:

  • modules_dir = SWITCH_MODULES_DIR (из meson.build)
  • user_modules_dir = ~/.local/share/switch/modules/
  • color_enabled = true (если не установлены NO_COLOR или SWITCH_NO_COLOR)

config_free

Освобождение памяти конфигурации.

void config_free(switch_config_t *config);

Параметры:

  • config — указатель на структуру конфигурации

API утилит

Цветной вывод

color_init

Инициализация цветного вывода.

void color_init(void);

Проверяет переменные окружения NO_COLOR и SWITCH_NO_COLOR.

color_set_enabled

Включение/отключение цветного вывода.

void color_set_enabled(bool enabled);

Параметры:

  • enabled — true для включения, false для отключения

Вывод сообщения об ошибке (красным цветом).

void print_error(const char *format, ...);

Параметры:

  • format — строка формата printf
  • ... — дополнительные аргументы

Вывод сообщения об успехе (зеленым цветом).

void print_success(const char *format, ...);

Вывод информационного сообщения (синим цветом).

void print_info(const char *format, ...);

Вывод предупреждения (желтым цветом).

void print_warning(const char *format, ...);

Работа с файлами

file_exists

Проверка существования файла.

bool file_exists(const char *path);

Параметры:

  • path — путь к файлу

Возвращает:

  • true если файл существует
  • false если не существует

is_executable

Проверка, является ли файл исполняемым.

bool is_executable(const char *path);

Параметры:

  • path — путь к файлу

Возвращает:

  • true если файл исполняемый
  • false если нет

Протокол взаимодействия с модулями

Загрузка модуля

  1. Switch читает shell-скрипт модуля
  2. Извлекает метаданные через grep и sed:
    MODULE_NAME=$(grep '^MODULE_NAME=' module.sh | cut -d'"' -f2)
  3. Сохраняет информацию в структуру module_info_t

Выполнение find_alternatives

  1. Switch выполняет скрипт модуля в subshell:
    bash module.sh find_alternatives
  2. Читает вывод построчно
  3. Парсит формат path|name|priority
  4. Создает массив структур alternative_t

Создание символической ссылки

  1. Удаляет существующую ссылку (если есть):
    unlink(link_path);
  2. Создает новую символическую ссылку:
    symlink(target_path, link_path);
  3. Проверяет результат и выводит сообщение

Переменные компиляции

Определяются в meson.build:

ПеременнаяЗначение по умолчаниюОписание
SWITCH_VERSIONИз meson.projectВерсия программы
SWITCH_MODULES_DIR{datadir}/switch/modulesСистемная директория модулей
SWITCH_USER_MODULES_DIR.local/share/switch/modulesПользовательская директория

Коды возврата

КодЗначение
0Успех
1Общая ошибка
2Ошибка парсинга аргументов
3Модуль не найден
4Альтернатива не найдена
5Ошибка создания символической ссылки

Примеры использования API

Пример 1: Программная загрузка модулей

#include "module.h"
#include "config.h"

int main() {
switch_config_t config;
module_list_t modules;

// Инициализация
config_init(&config);
module_list_init(&modules);

// Сканирование модулей
module_scan(&modules, &config);

// Поиск модуля editor
const module_info_t *editor = module_find(&modules, "editor");
if (editor) {
// Показать альтернативы
module_action_list(editor);
}

// Очистка
module_list_free(&modules);
config_free(&config);

return 0;
}

Пример 2: Создание собственной обертки

#include "module.h"

// Функция для автоматической установки приоритетной альтернативы
int auto_set_best_alternative(const char *module_name) {
switch_config_t config;
module_list_t modules;

config_init(&config);
module_list_init(&modules);
module_scan(&modules, &config);

const module_info_t *module = module_find(&modules, module_name);
if (!module) {
module_list_free(&modules);
config_free(&config);
return -1;
}

// Получить список альтернатив
// Найти с наивысшим приоритетом
// Установить её
// (логика упрощена)

module_list_free(&modules);
config_free(&config);
return 0;
}

Расширение функциональности

Добавление новых действий

  1. Определить функцию в module.c:

    int module_action_custom(const module_info_t *module) {
    // Ваша логика
    return 0;
    }
  2. Добавить в module.h:

    int module_action_custom(const module_info_t *module);
  3. Обработать в main.c:

    else if (strcmp(action, "custom") == 0) {
    ret = module_action_custom(module);
    }

Добавление новых полей модуля

  1. Расширить структуру module_info_t
  2. Обновить логику парсинга в module.c
  3. Обновить функцию освобождения памяти