;;; buffer-sqlite.el --- Sqlite-powered buffers -*- lexical-binding: t; -*- ;; Copyright (C) 2024 Vladimir Kazanov ;; Author: Vladimir Kazanov ;; Keywords: lisp (require 'sqlite) (defvar buffer-sqlite-db-file "~/tmp/buffer-content.sqlite" "Path to the SQLite database for storing buffer content.") (defun buffer-sqlite-create-table () "Create a table for storing buffer content and metadata." (let ((db (sqlite-open buffer-sqlite-db-file))) (sqlite-execute db "CREATE TABLE IF NOT EXISTS buffer_contents (buffer_name TEXT, content TEXT, modified_at INTEGER);") (sqlite-close db))) (defun buffer-sqlite-save-buffer () "Save the current buffer content into the SQLite database." (when buffer-sqlite-db-file (let* ((buffer-name (buffer-name)) (content (buffer-string)) (modified-at (float-time (current-time))) (db (sqlite-open buffer-sqlite-db-file))) (sqlite-execute db "DELETE FROM buffer_contents WHERE buffer_name = ?;" (list buffer-name)) (sqlite-execute db "INSERT INTO buffer_contents (buffer_name, content, modified_at) VALUES (?, ?, ?);" (list buffer-name content modified-at)) (sqlite-close db) (set-buffer-modified-p nil) (message "Buffer '%s' saved to database." buffer-name)))) (defun buffer-sqlite-load-buffer (buffer-name) "Load buffer content from the SQLite database into a new buffer." (let* ((db (sqlite-open buffer-sqlite-db-file)) (result (sqlite-select db "SELECT content FROM buffer_contents WHERE buffer_name = ?;" (list buffer-name)))) (sqlite-close db) (if result (let ((buffer (get-buffer-create buffer-name))) (with-current-buffer buffer (erase-buffer) (insert (caar result)) (sqlite-backed-minor-mode 1) (set-buffer-modified-p nil) (message "Buffer '%s' loaded from database." buffer-name)) (switch-to-buffer buffer)) (message "No buffer found with name: %s" buffer-name)))) (define-minor-mode sqlite-backed-minor-mode "Minor mode for buffers backed by SQLite." :lighter " SQLiteBuffer" (if sqlite-backed-minor-mode (progn (buffer-sqlite-create-table) (add-hook 'write-contents-functions 'buffer-sqlite-save-buffer nil t) (setq-local revert-buffer-function #'buffer-sqlite-revert-buffer-function)) (remove-hook 'write-contents-functions 'buffer-sqlite-save-buffer t) (setq-local revert-buffer-function #'revert-buffer--default))) (defun buffer-sqlite-revert-buffer-function (&optional ignore-auto noconfirm) "Revert the current buffer content from the SQLite database." (let ((buffer-name (buffer-name))) (buffer-sqlite-load-buffer buffer-name))) (defun buffer-sqlite-select-buffer () "Prompt for a buffer name stored in the SQLite database and load it." (interactive) (let* ((db (sqlite-open buffer-sqlite-db-file)) (buffers (mapcar 'car (sqlite-select db "SELECT buffer_name FROM buffer_contents;")))) (sqlite-close db) (if buffers (let ((buffer-name (completing-read "Select buffer to load: " buffers))) (buffer-sqlite-load-buffer buffer-name)) (message "No buffers found in the SQLite database."))))