MemoPad — консольный редактор и SQLite-база заметок

О проекте MemoPad

CLI-редактор заметок MemoPad

MemoPad — программа для создания, редактирования и просмотра заметок в терминале, использующая SQLite как базу заметок. Идея данной программы была подсказана проектом jrnl, тоже, кстати, созданном на языке программирования Python 3, но с другим интерфейсом и функционалом (см. раздел Техническое задание). В итоге получился совершенно отличный от jrnl проект, с кодом которого можно познакомиться на GitHub.

Проект использует стандартную общественную лицензию GNU (General Public License version 3).

Техническое задание

Контекстная справка в редакторе МемоPad

При создании MemoPad были поставлены следующие задачи:

  1. это должен быть редактор заметок для консоли (графический интерфейс пользователя — GUI — изначально не предусматривался);
  2. работа с редактором заметок должна быть основана на интерфейсе командной строки (CLI), желательно с возможностью подсказки или автодополнения вводимых команд;
  3. для удобства пользователя приглашение командной строки должно выделяться шрифтом и/или цветом;
  4. по всем командам приложения и по работе с текстовой строкой должна быть доступна справочная информация (справка, how-to);
  5. заметки должны включать следующие поля:
    • ID (присваивается автоматически),
    • дата и время создания/редактирования (также присваивается автоматически),
    • заголовок заметки,
    • основной текст и
    • хэштег;
  6. для основного текста заметки должна быть предусмотрена возможность ввода текста, состоящего из нескольких строк (абзацев);
  7. текст заметки может поддерживать форматирование с использованием элементов языка разметки Markdown;
  8. программа по команде пользователя должна отображать либо последнюю заметку, либо несколько последних заметок в обратном хронологическом порядке (до 5-ти включительно), или же все заметки в порядке их создания, а также количество заметок в базе;
  9. необходим поиск заметки по её ID, дате создания/редактирования, фрагменту текста (в заголовке, теле заметки или хэштеге);
  10. должна быть предусмотрена возможно редактирования уже созданных заметок;
  11. пользователь должен получить возможность удалять заметки из базы (по одной или все сразу).

Техническое задание вышло достаточно объёмным (впрочем, для любого текстового редактора эти функции являются базовыми). Ниже мы посмотрим на особенности реализации данных функций.

Работа с базой данных SQLite

Просмотр последней заметки в редакторе МемоPad

Для хранения заметок и выборки из базы в проекте MemoPad используется встраиваемая реляционная СУБД SQLite 3.

Данная СУБД не требует настройки сервера, её файловая структура состоит всего из одного файла (поэтому для базы заметок легко создать резервную копию и потом восстановить из этой копии, что и предусмотрено в нашей программе). Базовых возможностей SQLite вполне достаточно для того, чтобы хранить все элементы заметок (ID при этом создается автоматически в виде столбца ROWID), выводить результаты SQL-запросов и удалять кортежи с заметками.

Для работы с SQLite используется стандартный модуль пайтоновской библиотеки — sqlite3.

Единственная проблема, которую пришлось решать при использовании SQLite, состояла в том, что в готовой сборке данная СУБД не поддерживает регистронезависимый поиск по тексту, использующему символы за пределами стандартной кодовой таблицы ASCII, в том числе и буквы кириллицы.

Обновлено (c версии 1.1.9):

Для работы с символами, отличными от базовой латиницы, можно либо самостоятельно собрать из предлагаемого разработчиками SQLite кода библиотеку для интеграции компонентов Unicode (ICU ), либо воспользоваться готовым расширением, например sqlite-icu.

Ранее в проекте использовался упомянутый подключаемый модуль sqlite-icu, но в версии 1.1.9 эта зависимость исключена в пользу строкового метода .casefold(), который применяется в определяемой SQL-функции connection.create_function(). Данный метод корректно «сворачивает» юникодовскую строку в нижний регистр, благодаря чему возможно сравнивать приведенные к нижнему регистру строку пользовательского запроса и строку, извлечённую из базы данных.

Использование Prompt Toolkit для командной строки

Подсказки по командам редактора МемоPad

Для создания полнофункциональной командной строки используется внешний модуль Python Prompt Toolkit. Он предоставляет богатые возможности настройки приглашения командной строки, в том числе и за счёт переопределения цветовой гаммы текста и фона (в проекте реализован вариант изменения цвета через управляющие последовательности ANSI). Данный модуль поддерживает ввод многострочного текста: завершение ввода текста происходит не при нажатии на клавишу ENTER (это действие создаёт новую строку), а путём последовательного нажатия клавиш ESC и ENTER.

Также данный модуль даёт возможность определить подсказки для вводимых команд и даже собственный заголовок терминала. Примеры использования Python Prompt Toolkit можно посмотреть на GitHub.

Работа с буфером обмена

Редактирование заметки из базы MemoPad

При редактировании заметки из базы данных доступны два варианта:

  1. ввод нового текста для заголовка, самой заметки и/или тега;
  2. редактирование прежнего текста данных элементов заметки.

Редактирование прежнего текста реализовано через механизм копирования и вставки с использованием буфера обмена ОС. Пользователь вставляет старый текст (клавиши CTRL+Y), который уже был скопирован программой в буфер обмена, и затем его редактирует.

Для реализации этой функции используется внешний модуль Pyperclip. В системах GNU/Linux также может потребоваться установка дополнительной утилиты работы с буфером обмена (xsel, xclip) или же модуля Python (gtk/PyQt4).

Обновлено (c версии 1.1.8):

Теперь в заметку при её создании или редактировании можно добавлять несколько хэштегов (разделённых пробелами). При поиске программа найдёт любой из этих тегов.

Отображение разметки Markdown

Поиск заметки в базе MemoPad по тексту.

В редакторе заметок реализована поддержка элементов языка разметки Markdown не только для отображения собственно заметок, но и для системных сообщений и справочной информации. Для вывода в терминале текста с разметкой Markdown используется простое и универсальное решение — внешний модуль Rich.

Взаимодействие с файловой системой

Резервное копирование в МемоPad

С целью определения путей в ОС и для работы с файлами и папками используется объектно-ориентированный модуль стандартной библиотеки pathlib. Кстати, метод Path.unlink() также используется и для удаления базы заметок (удаление БД напрямую пользователю недоступно, но является частью команды пересоздания БД вместе с функцией создания новой БД). При резервном копировании БД задействована команда shutil.copy() из модуля shutil, также являющегося частью стандартной библиотеки языка Python.

Для хранения файла БД и его резервной копии программа MemoPad использует папку в пользовательском каталоге — ~/.memopad (и создаёт такую папку при необходимости). Если при загрузке программы в этой папке отсутствует файл memos.db, программа проверяет, имеется ли в той же папке резервная копия (memos.db.backup) и, при её наличии, восстанавливает базу заметок. Если резервная копия не найдена, то создаётся пустая БД.

При выходе из программы пользователю предлагается создать новую резервную копию. Он может при работе с программой создать такую копию самостоятельно, а также восстановить базу заметок из её резервной копии. Если база данных по какой-то причине повреждена, а резервная копия отсутствует (или также повреждена), то пользователь может пересоздать БД — конечно, в этом случае база заметок будет пустой.

Обновлено (c версии 1.1.5):

Теперь MemoPad умеет «подчищать» за собой: специальной командой clear можно удалить и базу данных, и резервную копию, и рабочую папку программы (где эти файлы БД, собственно, и хранятся).

В общем, вот такой получился проект редактора заметок для терминала. Программа построена по модульному принципу: основные функции и выводимая текстовая информация собраны в тематические модули, которые затем подключаются к главному файлу main.py.

Основные задачи, поставленные в техническом задании, были успешно реализованы (и даже больше, поскольку в MemoPad, как отмечалось выше, имплементирована возможность создания резервных копий базы заметок).