commit 71068d225f0a54f53d413021836656f92923b187 Author: Maxim Lihachev Date: Sat Aug 31 13:54:10 2013 +0600 Загрузка на Github diff --git a/README b/README new file mode 100644 index 0000000..3bb846d --- /dev/null +++ b/README @@ -0,0 +1,18 @@ +Программа ведения базы данных [прочитанных] книг. +Написана в качестве Hello World на Common Lisp. + +Использование: + help вывод справки по использованию + r читаемые книги + d прочитанные книги + n не прочитанные книги + new добавить новые книги + edit <...> редактировать книги + set d|r|n <...> сменить статус для книг + del <...> удаление книг из базы + sort, sort+ сортировка по возрастанию + sort- сортировка по убыванию + report <...> вывод отчета по ключевому слову + reports вывод отчетов по всем ключевым словам + <...> поиск книг в базе данных + diff --git a/books.lisp b/books.lisp new file mode 100755 index 0000000..0f3a3db --- /dev/null +++ b/books.lisp @@ -0,0 +1,1085 @@ +; #!/usr/bin/sbcl --script + +;;;Создан: Ср 08 Сен 2010 19:29:10 +;;;Изменён: Пн 18 Июл 2011 18:41:57 + +;;;---------------------------------------------------------------------- +;;; +;;; Copyright (C) 2010, Maxim Lihachev, +;;; +;;; This program is free software: you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation, either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see . +;;;---------------------------------------------------------------------- +;;; +;;; Программа ведения базы данных [прочитанных] книг. +;;; Написана в качестве Hello World на Common Lisp. +;;; +;;; Использование: +;;; help вывод справки по использованию +;;; r читаемые книги +;;; d прочитанные книги +;;; n не прочитанные книги +;;; new добавить новые книги +;;; edit <...> редактировать книги +;;; set d|r|n <...> сменить статус для книг +;;; del <...> удаление книг из базы +;;; sort, sort+ сортировка по возрастанию +;;; sort- сортировка по убыванию +;;; report <...> вывод отчета по ключевому слову +;;; reports вывод отчетов по всем ключевым словам +;;; <...> поиск книг в базе данных +;;; +;;;---------------------------------------------------------------------- + +;;;;============================================================================ +;****h* books/books-main +;* NAME +;* Общие настройки программы +;****** ======================================================================== + +;****v* books-main/+db-file+ +;* NAME +;* book-info -- файл базы данных +;* +;* SOURCE +(defparameter +db-file+ "books.db") +;****** + +;****s* books-main/+colors+ +;* NAME +;* +colors+ - настройка цвета +;* +;* SOURCE +(defparameter +colors+ + '( :new "1;35m" ;Цвет непрочитанных книг + :read "1;33m" ;Цвет читаемых книг + :done "1;34m" ;Цвет прочитанных книг + :rating "1;31m" ;Цвет оценок и диаграмм статистики + :reset "00m")) +;***** + +;****s* books-main/book-info +;* NAME +;* book-info -- Структура записи о книге +;* +;* SOURCE +(defun book-info () + '( :Авторы + :Название + :Подзаголовок + :Издание + :Серия + :Язык + :Издательство + :Издательство_РФ + :ISBN_EN + :ISBN_RU + :Год_издания_EN + :Год_издания_RU + :Количество_страниц + :Категория + :Ключевые_слова + :Прочитана? + :Оценка)) +;***** + +;****s* books-main/reports-exclude +;* NAME +;* reports-exclude -- Список исключений ключевых слов, +;* для которых не нужно выводить отчеты +;* +;* SOURCE +(defun reports-exclude () + '( :Название + :Подзаголовок + :Издание + :ISBN_EN + :ISBN_RU)) +;***** + +;****f* books-main/set-color +;* FUNCTION +;* set-color :: String -> Symbol +;* +;* SYNOPSIS +;* Установка цвета текста в зависимости от статуса прочтения +;* +;* INPUTS +;* - color-status -- статус, для которого требуется определить цвет +;* +;* RESULT +;* Escape-последовательность цветового кода +;* +;* SOURCE +(defun set-color (color-status) + (getf +colors+ (cond + ((eql color-status 'none) :reset) + ((eql color-status 'star) :rating) + ((equalp color-status "да") :done) + ((equalp color-status "нет") :new) + (:read)))) +;***** + +;;;;============================================================================ +;****h* books/books-functions +;* NAME +;* Общие макросы и функции +;****** ======================================================================== + +;****f* books-functions/make-book-accessors +;* NAME +;* make-book-accessors -- создание макросов доступа к полям книг +;* +;* SYNOPSIS +;* Макрос создает макросы доступа к полям переданной структуры +;* +;* INPUTS +;* - key-list -- список полей +;* +;* NOTES +;* При использовании с макросом SETF для установки значения полей, +;* перед компиляцией следует загружать файл в REPL (LOAD-FILE <...>) +;* +;* SOURCE +(defmacro make-book-accessors (key-list) + `(dolist (key ,key-list) + (eval `(defmacro ,(symbol-value key) (book) + `(getf ,book ,,key))))) + +(make-book-accessors (book-info)) +;****** + +;****f* books-functions/push-end +;* NAME +;* push-end -- добавление элемента в конец списка +;* +;* INPUTS +;* - item -- элемент для добавления +;* - list -- список, к которому добавляют элемент +;* +;* SIDE EFFECTS +;* Изменяет переданный список +;* +;* SOURCE +(defmacro push-end (item list) + `(if (null ,list) + (setf ,list (list ,item)) + (nconc ,list (list ,item)))) +;****** + +;****f* books-functions/if-agree +;* NAME +;* if-agree - выполнение действий при согласии пользователя +;* +;* INPUTS +;* - prompt -- строка приглашения +;* - body -- одно или несколько действий для выполнения +;* +;* SOURCE +(defmacro if-agree (prompt &body body) + `(when (y-or-n-p ,prompt) ,@body)) +;****** + +;****f* books-functions/if-not-agree +;* NAME +;* if-not-agree - выполнение действий при отказе пользователя +;* +;* INPUTS +;* - prompt -- строка приглашения +;* - body -- одно или несколько действий для выполнения +;* +;* SOURCE +(defmacro if-not-agree (prompt &body body) + `(unless (y-or-n-p ,prompt) ,@body)) +;****** + +;****f* books-functions/number->bar +;* NAME +;* number->bar -- преобразование числа в строку символов +;* +;* FUNCTION +;* - number->bar :: Int # ?Char? -> String +;* - number->bar :: String # ?Char? -> String +;* +;* INPUTS +;* - num -- целое число или строка с числом для преобразования +;* - ch (опционально) -- символ для заполнения строки (по умолчанию -- *) +;* +;* EXAMPLE +;* - (number->bar 5) => "*****" +;* - (number->bar "4" #\=) => "====" +;* +;* SOURCE +(defun number->bar (num &optional (ch #\*)) + (make-string + (typecase num + (string (if (equal num "") 0 (parse-integer num))) + (number num) + (t 0)) :initial-element ch)) +;****** + +;****f* books-functions/get-status-chars +;* NAME +;* get-status-chars -- преобразование статуса прочтения +;* в символьное представление для вывода на экран +;* +;* FUNCTION +;* get-status-chars :: String -> String +;* +;* INPUTS +;* - str -- строковый статус прочтения [да|нет] +;* +;* SOURCE +(defun get-status-chars (str) + (cond + ((equalp str "да") "<+>") + ((equalp str "нет") "<->") + ("==>"))) +;****** + +;****f* books-functions/case-status +;* NAME +;* case-status -- выбор статуса прочтения книги +;* +;* FUNCTION +;* case-status :: Char -> String +;* +;* INPUTS +;* - status - статус прочтения книги, символы d, r, n +;* +;* RESULT +;* Статус прочтения: да/нет +;* +;* SOURCE +(defun case-status (status) + (case status + ((#\r reading) "") + ((#\d done) "да") + ((#\n new) "нет"))) +;****** + +;****f* books-functions/string-split +;* NAME +;* string-split -- разделение строки на список +;* +;* FUNCTION +;* string-split :: String # ?Char? -> [String] +;* +;* INPUTS +;* - string -- входная строка +;* - (опционально) char -- символ-разделитель. По умолчанию - пробел +;* +;* RESULT +;* Список строк, полученный путем разделения +;* входной строки по символу-разделителю +;* +;* SOURCE +(defun string-split (string &optional (char #\space)) + (loop for i = 0 then (1+ j) + as j = (position char string :start i) + collect (string-trim " " (subseq string i j)) + while j)) +;****** + +;;;;============================================================================ +;****h* books/books-db +;* NAME +;* Функции работы с базой данных +;****** ======================================================================== + +;****f* books-db/save-and-dump-changes +;* NAME +;* save-and-dump-changes -- сохранение базы данных в файл +;* и вывод изменений на экран +;* +;* INPUTS +;* - db -- база книг +;* - db-file -- имя файла для сохранения базы данных +;* - (опционально) patterns - измененные записи для вывода на экран +;* +;* SIDE EFFECTS +;* Сохранение базы данных в файл +;* +;* OUTPUT +;* Вывод книг, соответствующих PATTERNS, или всех, +;* если аргумент PATTERNS не задан +;* +;* NOTES +;* при удалении книг (remove-books) вывод будет пуст, так как книги, +;* подпадающие под PATTERNS отсутствуют в базе данных +;* +;* SOURCE +(defmacro save-and-dump-changes (db db-file &optional (patterns nil)) + `(let ((db-var ,db)) + (save-db db-var ,db-file) + (dump-books 'table (search-books ,patterns db-var)))) +;****** + +;****f* books-db/keyword->string +;* NAME +;* keyword->string -- преобразование ключа в строковое представление +;* +;* FUNCTION +;* keyword->string :: Symbol -> String +;* +;* INPUTS +;* - keyword -- имя ключа +;* +;* RESULT +;* Строковое представление ключа +;* +;* EXAMPLE +;* (keyword->string :АВТОРЫ) => "АВТОРЫ" +;* +;* SOURCE +(defun keyword->string (keyword) + (substitute #\space #\_ (symbol-name (copy-symbol keyword nil)))) +;****** + +;****f* books-db/add-record +;* NAME +;* add-record -- добавление книги в базу данных +;* +;* FUNCTION +;* add-record :: Book # [Book] -> [Book] +;* +;* INPUTS +;* - book -- книга в виде структуры (book-info) +;* - db -- база данных +;* +;* SIDE EFFECTS +;* Функция изменяет переданную базу данных +;* +;* SOURCE +(defun add-record (book db) + (push-end book db)) +;****** + +;****f* books-db/read-book-field +;* NAME +;* read-book-field -- чтение данных о книге с консоли +;* +;* FUNCTION +;* read-book-field :: String -> String +;* +;* INPUTS +;* - prompt -- приглашение +;* +;* OUTPUT +;* Выводит приглашение на консоль и считывает пользовательский ввод +;* +;* SOURCE +(defun read-book-field (prompt) + (format *query-io* "~a: " prompt) + (force-output *query-io*) + (read-line *query-io*)) +;****** + +;****f* books-db/get-book-from-shell +;* NAME +;* get-book-from-shell -- получение списка книг с консоли +;* +;* FUNCTION +;* get-book-from-shell :: [Book] +;* +;* RESULT +;* Список книг, введенный пользователем в консоли +;* +;* SOURCE +(defun get-book-from-shell () + (mapcan + #'(lambda (field) + (list field (read-book-field (keyword->string field)))) + (book-info))) +;****** + +;****f* books-db/add-books +;* NAME +;* add-book -- добавление книги в базу данных +;* +;* FUNCTION +;* add-book :: [Book] -> [Book] +;* +;* SYNOPSIS +;* Запрос на добавление книги в базу данных и вызов необходимых функций +;* +;* INPUTS +;* - db -- база данных +;* +;* OUTPUT +;* Выводит приглашение на консоль и считывает пользовательский ввод +;* +;* SIDE EFFECTS +;* Функция изменяет переданную базу данных +;* +;* SOURCE +(defun add-books (db) + "Добавление книг с консоли" + (let ((new-db (copy-list db)) (books-count 1)) + (loop (setq new-db (add-record (get-book-from-shell) new-db)) + (if-not-agree "Добавить следующую книгу? [y/n]: " + (format t "Добавлено новых книг: ~a~%" books-count) + (return)) + (incf books-count)) new-db)) +;****** + +;****f* books-db/load-db +;* NAME +;* load-db -- загрузка базы данных из файла +;* +;* SYNOPSIS +;* Загружает базу данных из файла или, если указанного файла +;* не существует, создает новую базу данных и предлагает пользователю +;* заполнить ее +;* +;* FUNCTION +;* load-db :: String -> [Book] +;* +;* INPUTS +;* - filename -- имя файла, содержащего БД +;* +;* RESULT +;* Список книг, содержащийся в файле БД +;* +;* SOURCE +(defun load-db (filename) + (with-open-file (in filename :if-does-not-exist :create) + (if (zerop (file-length in)) '() + (with-standard-io-syntax + (read in))))) +;****** + +;****f* books-db/save-db +;* NAME +;* save-db -- сохранение базы данных в файл +;* +;* FUNCTION +;* save-db :: [Book] # String -> IO +;* +;* INPUTS +;* - db -- база данных +;* - filename -- имя файла для сохранения базы данных +;* +;* SOURCE +(defun save-db (db filename) + "Сохранение базы данных в файл" + (with-open-file (out filename :direction :output :if-exists :supersede) + (with-standard-io-syntax (print db out)))) +;****** + +;;;;============================================================================ +;****h* books/books-reports +;* NAME +;* Функции вывода данных и генерации отчетов +;****** ======================================================================== + +;****f* books-reports/dump-books-plain +;* NAME +;* dump-books-plain -- вывод книг в подробном представлении +;* +;* FUNCTION +;* dump-books-plain :: [Book] -> String +;* +;* OUTPUT +;* Выводит список книг в stdout +;* +;* INPUTS +;* db -- Список книг +;* +;* SOURCE +(defun dump-books-plain (db) + "Информация о книгах из списка DB в подробном представлении" + (with-output-to-string (stream) + (dolist (book db) + (format stream "~{ ~a:~25t~a~%~}~%" book)))) +;***** + +;****f* books-reports/dump-books-table +;* NAME +;* dump-books-table -- вывод книг в виде таблицы +;* +;* FUNCTION +;* dump-books-table :: [Book] -> String +;* +;* OUTPUT +;* Выводит отформатированный список книг в stdout +;* +;* INPUTS +;* db -- база данных +;* +;* SOURCE +(defun dump-books-table (db) + "Информация о книгах из списка DB в виде таблицы" + (with-output-to-string (stream) + (let ((book-number 1)) + (dolist (book db) + ;;TODO: Добавить автоопределение ширины экрана + (format stream "~C[~a~5d. ~44a~62a| ~35a~6@a c. ~5a~C[~a~a~C[~a~%" + #\Esc(set-color (:Прочитана? book)) + book-number + (:Авторы book) + (:Название book) + (:Категория book) + (:Количество_страниц book) + (get-status-chars (:Прочитана? book)) + #\Esc(set-color 'star) + (number->bar (:Оценка book)) + #\Esc(set-color 'none)) + (incf book-number))))) +;***** + +;****f* books-reports/dump-books +;* NAME +;* dump-books -- вывод книг на экран в читаемом формате +;* +;* FUNCTION +;* dump-books :: Symbol # [Book] -> String +;* +;* INPUTS +;* - view -- форма вывода [table|plain] +;* - db -- Список книг +;* +;* SOURCE +(defun dump-books (view db) + "Информация о книгах в форме VIEW (table/plain)" + (ecase view + (table (dump-books-table db)) + (plain (dump-books-plain db)))) +;***** + +;****f* books-reports/get-report +;* NAME +;* get-report - получение отчетов +;* +;* SYNOPSIS +;* Обобщенная функция получения отчетов по различным полям книг +;* +;* METHODS +;* - get-report (key == количество_страниц) - формирование отчета по количеству страниц +;* - get-report -- формирование отчета по любому полю +;* +;* SOURCE +(defgeneric get-report (key db)) +;****** + +;****m* get-report/get-report-pages +;* NAME +;* get-report -- вывод отчёта по количеству страниц +;* +;* INPUTS +;* - key -- поле бд +;* - db -- база данных +;* +;* OUTPUT +;* Выводит отчёт по количеству страниц в книгах +;* +;* SOURCE +(defmethod get-report ((key (eql ':Количество_страниц)) db) + "Формирование отчета по количеству страниц" + (let ((result (list '(:key "до 300 стр." :count 0) + '(:key "300-500 стр." :count 0) + '(:key "500-700 стр." :count 0) + '(:key "700-1000 стр." :count 0) + '(:key "свыше 1000 стр." :count 0)))) + (sort (dolist (book db) + (let ((pages (parse-integer (getf book :КОЛИЧЕСТВО_СТРАНИЦ)))) + ;Увеличение счетчика количества страниц + (incf (getf (nth (cond ((< pages 300) 0) + ((< pages 500) 1) + ((< pages 700) 2) + ((< pages 1000) 3) + ((>= pages 1000) 4)) result) :count)))) + #'> :key #'(lambda (plist) (getf plist :count))) result)) +;****** + +;****m* get-report/get-report-any +;* NAME +;* get-report -- получение отчёта по полю БД +;* +;* INPUTS +;* - key -- поле бд +;* - db -- база данных +;* +;* SOURCE +(defmethod get-report (key db) + "Формирование отчета по указанному полю" + (labels ((item=car (item list) (equal item (getf list :key))) + (item-in-list (item l) (search (list item) l :test #'item=car))) + (let ((result)) + (dolist (book db) + (loop for item in (string-split (getf book key) #\,) + for known-field = (item-in-list item result) + ;Добавление нового ключевого слова к списку + if (not known-field) do + (setq result (append `(,(list :key item :count 1)) result)) + ;;Увеличение счетчика вхождений ключевого слова + else do + (incf (getf (nth known-field result) :count)))) + (sort result #'> :key #'(lambda (plist) (getf plist :count)))))) +;****** + +;****f* books-reports/get-reports +;* FUNCTION +;* get-reports :: [Book] # [Symbol] -> [String] +;* +;* SYNOPSIS +;* Получение отчетов по указанным полям KEYS +;* или по всем полям структуры (book-info), +;* если ключи не заданы +;* +;* INPUTS +;* - db -- база данных книг +;* - (опционально) keys -- поля, для которых необходимо сформировать отчеты +;* +;* RESULT +;* Список строк-отчетов +;* +;* SOURCE +(defun get-reports (db &optional (keys nil keys-p)) + (let ((keylist (if keys-p keys (book-info)))) + (mapcar #'(lambda (category) + (cons category (list (get-report category db)))) keylist))) +;****** + +;****f* books-reports/dump-report +;* NAME +;* dump-report -- создание диаграммы по статистическим данным +;* +;* INPUTS +;* - category -- категория +;* - db -- база данных +;* +;* OUTPUT +;* Вывод в stdout +;* +;* SOURCE +(defun dump-report (category db) + "Формирование диаграммы по статистическим данным" + (with-output-to-string (stream) + (format stream "~% > ~a:~%~%" (keyword->string category)) + (dolist (plist db) + (let ((key (getf plist :key)) + (num (getf plist :count))) + (format stream "~35@a ~4d: ~C[~a~a>~C[~a~%" key num + #\Esc (set-color 'star) + (number->bar num #\=) + #\Esc (set-color 'none)))))) +;****** + +;****f* books-reports/dump-reports +;* NAME +;* dump-report -- вывод всех возможных отчётов +;* +;* INPUTS +;* - db -- база данных +;* +;* OUTPUT +;* Вывод в stdout +;* +;* SOURCE +(defun dump-reports (db) + "Вывод всех отчетов" + (with-output-to-string (stream) + (loop for (category report) in db + unless (member category (reports-exclude)) + do (write-line (dump-report category report) stream)))) +;****** + +;;;;============================================================================ +;****h* books/books-select +;* NAME +;* Функции сортировки и выбора книг по определенному критерию +;****** +;;;;============================================================================ + +;****f* books-select/book-match +;* NAME +;* book-match -- сравнение книги с набором образцов +;* +;* INPUTS +;* - book -- книга в виде структуры (book-info) +;* - patterns -- список образцов +;* +;* RESULT +;* - t -- в случае совпадения книги с образцами +;* - nil -- в другом случае +;* +;* NOTES +;* Книга считается подходящей под условие при совпадении со всеми образцами +;* +;* SOURCE +(defmacro book-match (book patterns) + "Сравнение книги с набором образцов PATTERN. + Книга считается совпавшей при совпадении всех образцов" + `(= (length ,patterns) + (loop for pattern in ,patterns when + (loop for key in (book-info) when + (search pattern (getf ,book key) :test #'char-equal) + return 1) + counting pattern))) +;****** + +;****f* books-select/select-books +;* FUNCTION +;* select-books -- выбор книг по условию +;* +;* INPUTS +;* - :from db -- список книг, среди которых осуществляется выбор +;* - :where expr -- условие, которое должно выполняться +;* +;* WARNINGS +;* Переменная условия должна называться BOOK! +;* +;* SOURCE +(defmacro select-books (&key ((:from db)) ((:where expr))) + "Выбор книг, подходящих под условие. + Переменная условия должна называться BOOK" + `(remove-if-not #'(lambda (book) ,expr) ,db)) +;****** + +;****f* books-select/book-has-status +;* NAME +;* book-has-status -- проверка на наличие статуса книги +;* +;* INPUTS +;* - status -- проверяемый статус +;* +;* SOURCE +(defmacro book-has-status (status) + "Проверка совпадения статуса прочтения книги с требуемым" + `(equal (:Прочитана? book) (case-status ,status))) +;****** + +;****f* books-select/sort-books +;* NAME +;* dump-books -- вывод книг на экран в читаемом формате +;* +;* FUNCTION +;* sort-books :: Symbol # [Book] # [Key] -> [Book] +;* +;* INPUTS +;* - view -- форма вывода [table|plain] +;* - db -- Список книг +;* +;* SOURCE +(defun sort-books (ord books keys) + "Сортировка книг по возрастанию и убыванию по указанным ключам. + Ключи указываются в порядке убывания приоритета, + поэтому список сортируется, начиная с последнего ключа" + (let ((fun (if (eql ord 'up) #'string< #'string>)) + (sorted-books (copy-list books))) + (dolist (key (reverse keys)) + (setq sorted-books + (stable-sort sorted-books fun + :key #'(lambda (plist) (getf plist key))))) + sorted-books)) +;****** + +;****f* books-select/select-keys +;* NAME +;* dump-books -- вывод книг на экран в читаемом формате +;* +;* FUNCTION +;* select-keys :: String -> [Key] +;* +;* INPUTS +;* - view -- форма вывода [table|plain] +;* - db -- Список книг +;* +;* SOURCE +(defun select-keys (patterns) + "Выбор возможных ключей по подстроке" + (remove-duplicates + (mapcan + #'(lambda (pattern) + (remove-if-not + #'(lambda (key) + (search pattern (symbol-name key) :test #'char-equal)) + (book-info))) + patterns))) +;****** + +;****f* books-select/search-books +;* NAME +;* dump-books -- вывод книг на экран в читаемом формате +;* +;* FUNCTION +;* search-books :: [String] # [Book] -> [Book] +;* +;* INPUTS +;* - view -- форма вывода [table|plain] +;* - db -- Список книг +;* +;* SOURCE +(defun search-books (patterns db) + "Поиск книги в базе данных по условию. + Переменная условия должна называться BOOK" + (select-books :from db :where (book-match book patterns))) +;****** + +;****f* books-select/get-books +;* NAME +;* dump-books -- вывод книг на экран в читаемом формате +;* +;* FUNCTION +;* get-books :: Symbol # [Book] -> [Book] +;* +;* INPUTS +;* - view -- форма вывода [table|plain] +;* - db -- Список книг +;* +;* SOURCE +(defun get-books (status db) + "Выбор книг по статусу прочтения, + задаваемому символами 'read, 'done и 'new" + (select-books :from db :where (book-has-status status))) +;****** + +;;;;============================================================================ +;****h* books/books-edit +;* NAME +;* Функции изменения книг +;****** ======================================================================== + +(defmacro for-books ((var expr) &body body) + "Выполнение PROGS для всех найденных книг" + `(dolist (,var ,expr) + (format t "~%Найдена книга:~%~a~%" (dump-books 'plain (list ,var))) + ,@body)) + +;****f* books-edit/set-books-status +;* NAME +;* set-books-status -- изменение статуса прочтения книги +;* +;* FUNCTION +;* set-books-status :: Symbol # [String] # [Book] -> Nil +;* +;* INPUTS +;* - status-char -- символ статуса прочтения +;* 'd - 'done -- книга прочитана +;* 'n - 'new -- книга не прочитана +;* 'r - 'read -- книга в процессе чтения +;* - db -- список книг, предназначенных для изменения +;* +;* SOURCE +(defun set-books-status (status-char patterns db) + "Установка статуса прочтения книги. + Статус задается символами 'd, 'n или 'r." + (let ((new-db (copy-list db)) + (status (case-status (character status-char)))) + (for-books (book (search-books patterns new-db)) + (if-agree "Сменить статус книги? [y/n]: " + (setf (:Прочитана? book) status) + ;Если статус меняется на "Прочитано", установить оценку + (if (equal status "да") + (setf (:Оценка book) (read-book-field "Оценка [1-5]")) + ;Иначе установить оценку, равную нулю + (setf (:Оценка book) "0")))) new-db)) +;****** + +;****f* books-edit/edit-books +;* NAME +;* edit-books -- редактирование информации о книгах +;* +;* SYNOPSIS +;* Редактирование информации о книгах, совпадающих с PATTERNS. +;* Функция выводит на экран информацию о книгах и, при согласии +;* пользователя, позволяет редактировать данные. +;* +;* Не требуется редактировать все поля записи. +;* Ввод пустой строки - сохранение прежней информации в текущем поле. +;* +;* FUNCTION +;* set-books-status :: [String] # [Book] -> IO +;* +;* INPUTS +;* - patterns -- список образцов +;* - db -- список книг +;* +;* RESULT +;* Измененный список книг +;* +;* SOURCE +(defun edit-books (patterns db) + (let ((new-db (copy-list db))) + (for-books (book (search-books patterns new-db)) + (if-agree "Редактировать информацию? [y/n]: " + (dolist (field (book-info)) + (let ((new-info (read-book-field + (format nil "~a [~a]" + (keyword->string field) + (getf book field))))) + (unless (equal "" new-info) + (setf (getf book field) new-info)))))) new-db)) +;****** + +;****f* books-edit/remove-books +;* NAME +;* remove-books -- удаление книг из базы +;* +;* NOTES +;* Удаление производится после подтверждения +;* +;* FUNCTION +;* set-books-status :: Symbol # [String] # [Book] -> Nil +;* +;* INPUTS +;* - patterns -- список образцов +;* - db -- список книг +;* +;* RESULT +;* Измененный список книг +;* +;* SOURCE +(defun remove-books (patterns db) + "Удаление книг из базы" + (let ((new-db (copy-list db))) + (for-books (book (search-books patterns db)) + (if-agree "Удалить книгу? [y/n]" + (setq new-db (remove-if #'(lambda (x) + (equal x book)) new-db)))) + new-db)) +;****** + +;;;;============================================================================ +;****h* books/books-usage +;* NAME +;* Использование программы +;****** ======================================================================== + +;****f* books-usage/format-help +;* NAME +;* show-help -- вывод справки по использованию +;* +;* FUNCTION +;* show-help :: IO +;* +;* OUTPUT +;* Вывод аргументов командной строки, +;* с которыми можно запускать программу +;* +;* SOURCE +(defmacro format-help ((output) &body message) + "Форматирование элементов справки по использованию" + `(loop for (command description) in ',message do + (format ,output "~4t~20a - ~a~%" command description))) +;****** + +;****f* books-usage/show-help +;* NAME +;* show-help -- вывод справки по использованию +;* +;* FUNCTION +;* show-help :: IO +;* +;* OUTPUT +;* Вывод аргументов командной строки, +;* с которыми можно запускать программу +;* +;* SOURCE +(defun show-help () + "Вывод справки по использованию программы" + (with-output-to-string (help-stream) + (format-help (help-stream) + ("help" "вывод справки по использованию") + ("r" "читаемые книги") + ("d" "прочитанные книги") + ("n" "не прочитанные книги") + ("new" "добавить новые книги") + ("edit <...>" "редактировать книги") + ("set (d|r|n) <...>" "сменить статус для книг") + ("del <...>" "удаление книг из базы") + ("sort, sort+" "сортировка по возрастанию") + ("sort-" "сортировка по убыванию") + ("report <...>" "вывод отчета по ключевому слову") + ("reports" "вывод отчетов по всем ключевым словам") + ("<...>" "поиск книг в базе данных")))) +;***** + +;;;----------------------------------------------------------------------------- + +;****f* books-usage/get-argv-var +;* NAME +;* show-help -- вывод справки по использованию +;* +;* FUNCTION +;* show-help :: IO +;* +;* OUTPUT +;* Вывод аргументов командной строки, +;* с которыми можно запускать программу +;* +;* SOURCE +(defun get-argv-var () + "Параметры командной строки для различных реализация CL" + #+sbcl (rest *posix-argv*) + #+clisp *args*) +;****** + +;****f* books-usage/parse-commandline-arguments +;* NAME +;* show-help -- вывод справки по использованию +;* +;* FUNCTION +;* show-help :: IO +;* +;* OUTPUT +;* Вывод аргументов командной строки, +;* с которыми можно запускать программу +;* +;* SOURCE +(defun parse-commandline-arguments () + "Разбор аргументов коммандной строки" + (let* ((argv (get-argv-var)) + (first-arg (intern (or (first argv) ""))) + (second-arg (second argv)) + (db-file +db-file+) + (db (load-db +db-file+))) + + ;;Создание и заполнение новой базы данных + (if (null db) + (progn + (format t " #> Создана новая база данных: ~a~%~%" db-file) + (setq first-arg '|new|))) + + ;;Обработка команд пользователя + (format t "~%~a~%" + (case first-arg + (|help| (show-help)) + (|r| (dump-books 'table (get-books 'reading db))) + (|d| (dump-books 'table (get-books 'done db))) + (|n| (dump-books 'table (get-books 'new db))) + (|new| (save-and-dump-changes (add-books db) db-file)) + (|edit| + (let* ((patterns (rest argv)) + (new-db (edit-books patterns db))) + (save-and-dump-changes new-db db-file patterns))) + (|set| + (let* ((patterns (cddr argv)) + (new-db (set-books-status second-arg patterns db))) + (save-and-dump-changes new-db db-file patterns))) + (|del| + (let* ((patterns (rest argv)) + (new-db (remove-books patterns db))) + (save-and-dump-changes new-db db-file patterns))) + ((|sort| |sort+|) + (dump-books 'table (sort-books 'up db (select-keys (rest argv))))) + (|sort-| + (dump-books 'table (sort-books 'down db (select-keys (rest argv))))) + (|report| (dump-reports (get-reports db (select-keys (rest argv))))) + (|reports| (dump-reports (get-reports db))) + (t (dump-books 'table (search-books argv db))))))) + +(parse-commandline-arguments) +;****** + diff --git a/doc/books_lisp.html b/doc/books_lisp.html new file mode 100755 index 0000000..ceb4aea --- /dev/null +++ b/doc/books_lisp.html @@ -0,0 +1,1264 @@ + + + + + + + +./books.lisp + + + + + + +
+
+ +

books/books-main [ Modules ]

+ +

[ Top ] [ Modules ]

+

NAME

+
 Общие настройки программы
+
+ +
+ +

books-main/+db-file+ [ Variables ]

+ +

[ Top ] [ books-main ] [ Variables ]

+

NAME

+
 book-info -- файл базы данных
+
+

SOURCE

+
55 (defparameter +db-file+ "books.db")
+
+ +
+ +

books-main/+colors+ [ Structures ]

+ +

[ Top ] [ books-main ] [ Structures ]

+

NAME

+
 +colors+ - настройка цвета
+
+

SOURCE

+
63 (defparameter +colors+
+64           '( :new    "1;35m" ;Цвет непрочитанных книг
+65              :read   "1;33m" ;Цвет читаемых книг
+66              :done   "1;34m" ;Цвет прочитанных книг
+67              :rating "1;31m" ;Цвет оценок и диаграмм статистики
+68              :reset  "00m"))
+
+ +
+ +

books-main/book-info [ Structures ]

+ +

[ Top ] [ books-main ] [ Structures ]

+

NAME

+
 book-info -- Структура записи о книге
+
+

SOURCE

+
76 (defun book-info ()
+77   '( :Авторы
+78      :Название
+79      :Подзаголовок
+80      :Издание
+81      :Серия
+82      :Язык
+83      :Издательство
+84      :Издательство_РФ
+85      :ISBN_EN
+86      :ISBN_RU
+87      :Год_издания_EN
+88      :Год_издания_RU
+89      :Количество_страниц
+90      :Категория
+91      :Ключевые_слова
+92      :Прочитана?
+93      :Оценка))
+
+ +
+ +

books-main/reports-exclude [ Structures ]

+ +

[ Top ] [ books-main ] [ Structures ]

+

NAME

+
 reports-exclude -- Список исключений ключевых слов,
+ для которых не нужно выводить отчеты
+
+

SOURCE

+
102 (defun reports-exclude ()
+103   '( :Название
+104      :Подзаголовок
+105      :Издание
+106      :ISBN_EN
+107      :ISBN_RU))
+
+ +
+ +

books-main/set-color [ Functions ]

+ +

[ Top ] [ books-main ] [ Functions ]

+

FUNCTION

+
 set-color :: String -> Symbol
+
+

SYNOPSIS

+
 Установка цвета текста в зависимости от статуса прочтения
+
+

INPUTS

+
 - color-status -- статус, для которого требуется определить цвет
+
+

RESULT

+
 Escape-последовательность цветового кода
+
+

SOURCE

+
124 (defun set-color (color-status)
+125   (getf +colors+ (cond
+126                   ((eql    color-status 'none) :reset)
+127                   ((eql    color-status 'star) :rating)
+128                   ((equalp color-status "да")  :done)
+129                   ((equalp color-status "нет") :new)
+130                   (:read))))
+
+ +
+ +

books/books-functions [ Modules ]

+ +

[ Top ] [ Modules ]

+

NAME

+
 Общие макросы и функции
+
+ +
+ +

books-functions/make-book-accessors [ Functions ]

+ +

[ Top ] [ books-functions ] [ Functions ]

+

NAME

+
 make-book-accessors -- создание макросов доступа к полям книг
+
+

SYNOPSIS

+
 Макрос создает макросы доступа к полям переданной структуры
+
+

INPUTS

+
   - key-list -- список полей
+
+

NOTES

+
 При использовании с макросом SETF для установки значения полей,
+ перед компиляцией следует загружать файл в REPL (LOAD-FILE <...>)
+
+

SOURCE

+
154 (defmacro make-book-accessors (key-list)
+155   `(dolist (key ,key-list)
+156      (eval `(defmacro ,(symbol-value key) (book)
+157               `(getf ,book ,,key)))))
+158 
+159 (make-book-accessors (book-info))
+
+ +
+ +

books-functions/push-end [ Functions ]

+ +

[ Top ] [ books-functions ] [ Functions ]

+

NAME

+
 push-end -- добавление элемента в конец списка
+
+

INPUTS

+
   - item -- элемент для добавления
+   - list -- список, к которому добавляют элемент
+
+

SIDE EFFECTS

+
 Изменяет переданный список
+
+

SOURCE

+
174 (defmacro push-end (item list)
+175   `(if (null ,list)
+176      (setf ,list (list ,item))
+177      (nconc ,list (list ,item))))
+
+ +
+ +

books-functions/if-agree [ Functions ]

+ +

[ Top ] [ books-functions ] [ Functions ]

+

NAME

+
 if-agree - выполнение действий при согласии пользователя
+
+

INPUTS

+
   - prompt -- строка приглашения
+   - body -- одно или несколько действий для выполнения
+
+

SOURCE

+
189 (defmacro if-agree (prompt &body body)
+190   `(when (y-or-n-p ,prompt) ,@body))
+
+ +
+ +

books-functions/if-not-agree [ Functions ]

+ +

[ Top ] [ books-functions ] [ Functions ]

+

NAME

+
 if-not-agree - выполнение действий при отказе пользователя
+
+

INPUTS

+
   - prompt -- строка приглашения
+   - body -- одно или несколько действий для выполнения
+
+

SOURCE

+
202 (defmacro if-not-agree (prompt &body body)
+203   `(unless (y-or-n-p ,prompt) ,@body))
+
+ +
+ +

books-functions/number->bar [ Functions ]

+ +

[ Top ] [ books-functions ] [ Functions ]

+

NAME

+
 number->bar -- преобразование числа в строку символов
+
+

FUNCTION

+
   - number->bar :: Int # ?Char? -> String
+   - number->bar :: String # ?Char? -> String
+
+

INPUTS

+
   - num -- целое число или строка с числом для преобразования
+   - ch (опционально) -- символ для заполнения строки (по умолчанию -- *)
+
+

EXAMPLE

+
   - (number->bar 5)       => "*****"
+   - (number->bar "4" #\=) => "===="
+
+

SOURCE

+
223 (defun number->bar (num &optional (ch #\*))
+224   (make-string
+225     (typecase num
+226       (string (if (equal num "") 0 (parse-integer num)))
+227       (number num)
+228       (t 0)) :initial-element ch))
+
+ +
+ +

books-functions/get-status-chars [ Functions ]

+ +

[ Top ] [ books-functions ] [ Functions ]

+

NAME

+
 get-status-chars -- преобразование статуса прочтения
+ в символьное представление для вывода на экран
+
+

FUNCTION

+
 get-status-chars :: String -> String
+
+

INPUTS

+
   - str -- строковый статус прочтения [да|нет]
+
+

SOURCE

+
243 (defun get-status-chars (str)
+244   (cond
+245     ((equalp str "да") "<+>")
+246     ((equalp str "нет") "<->")
+247     ("==>")))
+
+ +
+ +

books-functions/case-status [ Functions ]

+ +

[ Top ] [ books-functions ] [ Functions ]

+

NAME

+
 case-status -- выбор статуса прочтения книги
+
+

FUNCTION

+
 case-status :: Char -> String
+
+

INPUTS

+
   - status - статус прочтения книги, символы d, r, n
+
+

RESULT

+
 Статус прочтения: да/нет
+
+

SOURCE

+
264 (defun case-status (status)
+265   (case status
+266     ((#\r reading) "")
+267     ((#\d done)    "да")
+268     ((#\n new)     "нет")))
+
+ +
+ +

books-functions/string-split [ Functions ]

+ +

[ Top ] [ books-functions ] [ Functions ]

+

NAME

+
 string-split -- разделение строки на список
+
+

FUNCTION

+
 string-split :: String # ?Char? -> [String]
+
+

INPUTS

+
   - string -- входная строка
+   - (опционально) char -- символ-разделитель. По умолчанию - пробел
+
+

RESULT

+
 Список строк, полученный путем разделения
+ входной строки по символу-разделителю
+
+

SOURCE

+
287 (defun string-split (string &optional (char #\space))
+288   (loop for i = 0 then (1+ j)
+289         as  j = (position char string :start i)
+290         collect (string-trim " " (subseq string i j))
+291         while j))
+
+ +
+ +

books/books-db [ Modules ]

+ +

[ Top ] [ Modules ]

+

NAME

+
 Функции работы с базой данных
+
+ +
+ +

books-db/save-and-dump-changes [ Functions ]

+ +

[ Top ] [ books-db ] [ Functions ]

+

NAME

+
 save-and-dump-changes -- сохранение базы данных в файл
+ и вывод изменений на экран
+
+

INPUTS

+
   - db -- база книг
+   - db-file -- имя файла для сохранения базы данных
+   - (опционально) patterns - измененные записи для вывода на экран
+
+

SIDE EFFECTS

+
 Сохранение базы данных в файл
+
+

OUTPUT

+
 Вывод книг, соответствующих PATTERNS, или всех,
+ если аргумент PATTERNS не задан
+
+

NOTES

+
 при удалении книг (remove-books) вывод будет пуст, так как книги,
+ подпадающие под PATTERNS отсутствуют в базе данных
+
+

SOURCE

+
322 (defmacro save-and-dump-changes (db db-file &optional (patterns nil))
+323   `(let ((db-var ,db))
+324      (save-db db-var ,db-file)
+325      (dump-books 'table (search-books ,patterns db-var))))
+
+ +
+ +

books-db/keyword->string [ Functions ]

+ +

[ Top ] [ books-db ] [ Functions ]

+

NAME

+
 keyword->string -- преобразование ключа в строковое представление
+
+

FUNCTION

+
 keyword->string :: Symbol -> String
+
+

INPUTS

+
   - keyword -- имя ключа
+
+

RESULT

+
 Строковое представление ключа
+
+

EXAMPLE

+
 (keyword->string :АВТОРЫ) => "АВТОРЫ"
+
+

SOURCE

+
345 (defun keyword->string (keyword)
+346   (substitute #\space #\_ (symbol-name (copy-symbol keyword nil))))
+
+ +
+ +

books-db/add-record [ Functions ]

+ +

[ Top ] [ books-db ] [ Functions ]

+

NAME

+
 add-record -- добавление книги в базу данных
+
+

FUNCTION

+
 add-record :: Book # [Book] -> [Book]
+
+

INPUTS

+
   - book -- книга в виде структуры (book-info)
+   - db -- база данных
+
+

SIDE EFFECTS

+
 Функция изменяет переданную базу данных
+
+

SOURCE

+
364 (defun add-record (book db)
+365   (push-end book db))
+
+ +
+ +

books-db/read-book-field [ Functions ]

+ +

[ Top ] [ books-db ] [ Functions ]

+

NAME

+
 read-book-field -- чтение данных о книге с консоли
+
+

FUNCTION

+
 read-book-field :: String -> String
+
+

INPUTS

+
   - prompt -- приглашение
+
+

OUTPUT

+
 Выводит приглашение на консоль и считывает пользовательский ввод
+
+

SOURCE

+
382 (defun read-book-field (prompt)
+383   (format *query-io* "~a: " prompt)
+384   (force-output *query-io*)
+385   (read-line *query-io*))
+
+ +
+ +

books-db/get-book-from-shell [ Functions ]

+ +

[ Top ] [ books-db ] [ Functions ]

+

NAME

+
 get-book-from-shell -- получение списка книг с консоли
+
+

FUNCTION

+
 get-book-from-shell :: [Book]
+
+

RESULT

+
 Список книг, введенный пользователем в консоли
+
+

SOURCE

+
399 (defun get-book-from-shell ()
+400   (mapcan
+401     #'(lambda (field)
+402         (list field (read-book-field (keyword->string field))))
+403     (book-info)))
+
+ +
+ +

books-db/add-books [ Functions ]

+ +

[ Top ] [ books-db ] [ Functions ]

+

NAME

+
 add-book -- добавление книги в базу данных
+
+

FUNCTION

+
 add-book :: [Book] -> [Book]
+
+

SYNOPSIS

+
 Запрос на добавление книги в базу данных и вызов необходимых функций
+
+

INPUTS

+
   - db -- база данных
+
+

OUTPUT

+
 Выводит приглашение на консоль и считывает пользовательский ввод
+
+

SIDE EFFECTS

+
 Функция изменяет переданную базу данных
+
+

SOURCE

+
426 (defun add-books (db)
+427   "Добавление книг с консоли"
+428   (let ((new-db (copy-list db)) (books-count 1))
+429     (loop (setq new-db (add-record (get-book-from-shell) new-db))
+430           (if-not-agree "Добавить следующую книгу? [y/n]: "
+431                         (format t "Добавлено новых книг: ~a~%" books-count)
+432                         (return))
+433           (incf books-count)) new-db))
+
+ +
+ +

books-db/load-db [ Functions ]

+ +

[ Top ] [ books-db ] [ Functions ]

+

NAME

+
 load-db -- загрузка базы данных из файла
+
+

SYNOPSIS

+
 Загружает базу данных из файла или, если указанного файла
+ не существует, создает новую базу данных и предлагает пользователю
+ заполнить ее
+
+

FUNCTION

+
 load-db :: String -> [Book]
+
+

INPUTS

+
   - filename -- имя файла, содержащего БД
+
+

RESULT

+
 Список книг, содержащийся в файле БД
+
+

SOURCE

+
455 (defun load-db (filename)
+456   (with-open-file (in filename :if-does-not-exist :create)
+457     (if (zerop (file-length in)) '()
+458       (with-standard-io-syntax
+459         (read in)))))
+
+ +
+ +

books-db/save-db [ Functions ]

+ +

[ Top ] [ books-db ] [ Functions ]

+

NAME

+
 save-db -- сохранение базы данных в файл
+
+

FUNCTION

+
 save-db :: [Book] # String -> IO
+
+

INPUTS

+
   - db -- база данных
+   - filename -- имя файла для сохранения базы данных
+
+

SOURCE

+
474 (defun save-db (db filename)
+475   "Сохранение базы данных в файл"
+476   (with-open-file (out filename :direction :output :if-exists :supersede)
+477     (with-standard-io-syntax (print db out))))
+
+ +
+ +

books/books-reports [ Modules ]

+ +

[ Top ] [ Modules ]

+

NAME

+
 Функции вывода данных и генерации отчетов
+
+ +
+ +

books-reports/dump-books-plain [ Functions ]

+ +

[ Top ] [ books-reports ] [ Functions ]

+

NAME

+
 dump-books-plain -- вывод книг в подробном представлении
+
+

FUNCTION

+
 dump-books-plain :: [Book] -> String
+
+

OUTPUT

+
 Выводит список книг в stdout
+
+

INPUTS

+
   db -- Список книг
+
+

SOURCE

+
500 (defun dump-books-plain (db)
+501   "Информация о книгах из списка DB в подробном представлении"
+502   (with-output-to-string (stream)
+503     (dolist (book db)
+504       (format stream "~{ ~a:~25t~a~%~}~%" book))))
+
+ +
+ +

books-reports/dump-books-table [ Functions ]

+ +

[ Top ] [ books-reports ] [ Functions ]

+

NAME

+
 dump-books-table -- вывод книг в виде таблицы
+
+

FUNCTION

+
 dump-books-table :: [Book] -> String
+
+

OUTPUT

+
 Выводит отформатированный список книг в stdout
+
+

INPUTS

+
   db -- база данных
+
+

SOURCE

+
521 (defun dump-books-table (db)
+522   "Информация о книгах из списка DB в виде таблицы"
+523   (with-output-to-string (stream)
+524     (let ((book-number 1))
+525       (dolist (book db)
+526         ;;TODO: Добавить автоопределение ширины экрана
+527         (format stream "~C[~a~5d. ~44a~62a| ~35a~6@a c. ~5a~C[~a~a~C[~a~%"
+528                 #\Esc(set-color (:Прочитана? book))
+529                 book-number
+530                 (:Авторы book)
+531                 (:Название book)
+532                 (:Категория book)
+533                 (:Количество_страниц book)
+534                 (get-status-chars (:Прочитана? book))
+535                 #\Esc(set-color 'star)
+536                 (number->bar (:Оценка book))
+537                 #\Esc(set-color 'none))
+538         (incf book-number)))))
+
+ +
+ +

books-reports/dump-books [ Functions ]

+ +

[ Top ] [ books-reports ] [ Functions ]

+

NAME

+
 dump-books -- вывод книг на экран в читаемом формате
+
+

FUNCTION

+
 dump-books :: Symbol # [Book] -> String
+
+

INPUTS

+
   - view -- форма вывода [table|plain]
+   - db -- Список книг
+
+

SOURCE

+
553 (defun dump-books (view db)
+554   "Информация о книгах в форме VIEW (table/plain)"
+555   (ecase view
+556     (table (dump-books-table db))
+557     (plain (dump-books-plain db))))
+
+ +
+ +

books-reports/get-report [ Functions ]

+ +

[ Top ] [ books-reports ] [ Functions ]

+

NAME

+
 get-report - получение отчетов
+
+

SYNOPSIS

+
 Обобщенная функция получения отчетов по различным полям книг
+
+

METHODS

+
   - get-report (key == количество_страниц) - формирование отчета по количеству страниц
+   - get-report -- формирование отчета по любому полю
+
+

SOURCE

+
572 (defgeneric get-report (key db))
+
+ +
+ +

get-report/get-report-pages [ Methods ]

+ +

[ Top ] [ get-report ] [ Methods ]

+

NAME

+
 get-report -- вывод отчёта по количеству страниц
+
+

INPUTS

+
   - key -- поле бд
+   - db -- база данных
+
+

OUTPUT

+
 Выводит отчёт по количеству страниц в книгах
+
+

SOURCE

+
587 (defmethod get-report ((key (eql ':Количество_страниц)) db)
+588   "Формирование отчета по количеству страниц"
+589   (let ((result (list '(:key "до 300 стр."     :count 0)
+590                       '(:key "300-500 стр."    :count 0)
+591                       '(:key "500-700 стр."    :count 0)
+592                       '(:key "700-1000 стр."   :count 0)
+593                       '(:key "свыше 1000 стр." :count 0))))
+594     (sort (dolist (book db)
+595             (let ((pages (parse-integer (getf book :КОЛИЧЕСТВО_СТРАНИЦ))))
+596               ;Увеличение счетчика количества страниц
+597               (incf (getf (nth (cond ((<  pages 300)  0)
+598                                      ((<  pages 500)  1)
+599                                      ((<  pages 700)  2)
+600                                      ((<  pages 1000) 3)
+601                                      ((>= pages 1000) 4)) result) :count))))
+602           #'> :key #'(lambda (plist) (getf plist :count))) result))
+
+ +
+ +

get-report/get-report-any [ Methods ]

+ +

[ Top ] [ get-report ] [ Methods ]

+

NAME

+
 get-report -- получение отчёта по полю БД
+
+

INPUTS

+
   - key -- поле бд
+   - db -- база данных
+
+

SOURCE

+
614 (defmethod get-report (key db)
+615   "Формирование отчета по указанному полю"
+616   (labels ((item=car (item list) (equal item (getf list :key)))
+617            (item-in-list (item l) (search (list item) l :test #'item=car)))
+618     (let ((result))
+619       (dolist (book db)
+620             (loop for item in (string-split (getf book key) #\,)
+621                   for known-field = (item-in-list item result)
+622                   ;Добавление нового ключевого слова к списку
+623                   if (not known-field) do
+624                           (setq result (append `(,(list :key item :count 1)) result))
+625                   ;;Увеличение счетчика вхождений ключевого слова
+626                   else do
+627                           (incf (getf (nth known-field result) :count))))
+628       (sort result #'> :key #'(lambda (plist) (getf plist :count))))))
+
+ +
+ +

books-reports/get-reports [ Functions ]

+ +

[ Top ] [ books-reports ] [ Functions ]

+

FUNCTION

+
 get-reports :: [Book] # [Symbol] -> [String]
+
+

SYNOPSIS

+
 Получение отчетов по указанным полям KEYS
+ или по всем полям структуры (book-info),
+ если ключи не заданы
+
+

INPUTS

+
   - db -- база данных книг
+   - (опционально) keys -- поля, для которых необходимо сформировать отчеты
+
+

RESULT

+
 Список строк-отчетов
+
+

SOURCE

+
648 (defun get-reports (db &optional (keys nil keys-p))
+649   (let ((keylist (if keys-p keys (book-info))))
+650     (mapcar #'(lambda (category)
+651                 (cons category (list (get-report category db)))) keylist)))
+
+ +
+ +

books-reports/dump-report [ Functions ]

+ +

[ Top ] [ books-reports ] [ Functions ]

+

NAME

+
 dump-report -- создание диаграммы по статистическим данным
+
+

INPUTS

+
   - category -- категория
+   - db -- база данных
+
+

OUTPUT

+
 Вывод в stdout
+
+

SOURCE

+
666 (defun dump-report (category db)
+667   "Формирование диаграммы по статистическим данным"
+668   (with-output-to-string (stream)
+669     (format stream "~% > ~a:~%~%" (keyword->string category))
+670     (dolist (plist db)
+671       (let ((key (getf plist :key))
+672             (num (getf plist :count)))
+673         (format stream "~35@a ~4d: ~C[~a~a>~C[~a~%" key num
+674                 #\Esc (set-color 'star)
+675                 (number->bar num #\=)
+676                 #\Esc (set-color 'none))))))
+
+ +
+ +

books-reports/dump-reports [ Functions ]

+ +

[ Top ] [ books-reports ] [ Functions ]

+

NAME

+
 dump-report -- вывод всех возможных отчётов
+
+

INPUTS

+
   - db -- база данных
+
+

OUTPUT

+
 Вывод в stdout
+
+

SOURCE

+
690 (defun dump-reports (db)
+691   "Вывод всех отчетов"
+692   (with-output-to-string (stream)
+693     (loop for (category report) in db
+694           unless (member category (reports-exclude))
+695           do (write-line (dump-report category report) stream))))
+
+ +
+ +

books/books-select [ Modules ]

+ +

[ Top ] [ Modules ]

+

NAME

+
 Функции сортировки и выбора книг по определенному критерию
+
+ +
+ +

books-select/book-match [ Functions ]

+ +

[ Top ] [ books-select ] [ Functions ]

+

NAME

+
 book-match -- сравнение книги с набором образцов
+
+

INPUTS

+
   - book -- книга в виде структуры (book-info)
+   - patterns -- список образцов
+
+

RESULT

+
   - t -- в случае совпадения книги с образцами
+   - nil -- в другом случае
+
+

NOTES

+
 Книга считается подходящей под условие при совпадении со всеми образцами
+
+

SOURCE

+
721 (defmacro book-match (book patterns)
+722   "Сравнение книги с набором образцов PATTERN.
+723   Книга считается совпавшей при совпадении всех образцов"
+724   `(= (length ,patterns)
+725       (loop for pattern in ,patterns when
+726             (loop for key in (book-info) when
+727                   (search pattern (getf ,book key) :test #'char-equal)
+728                   return 1)
+729             counting pattern)))
+
+ +
+ +

books-select/select-books [ Functions ]

+ +

[ Top ] [ books-select ] [ Functions ]

+

FUNCTION

+
 select-books -- выбор книг по условию
+
+

INPUTS

+
   - :from db -- список книг, среди которых осуществляется выбор
+   - :where expr -- условие, которое должно выполняться
+
+

WARNINGS

+
 Переменная условия должна называться BOOK!
+
+

SOURCE

+
744 (defmacro select-books (&key ((:from db)) ((:where expr)))
+745   "Выбор книг, подходящих под условие.
+746   Переменная условия должна называться BOOK"
+747   `(remove-if-not #'(lambda (book) ,expr) ,db))
+
+ +
+ +

books-select/book-has-status [ Functions ]

+ +

[ Top ] [ books-select ] [ Functions ]

+

NAME

+
 book-has-status -- проверка на наличие статуса книги
+
+

INPUTS

+
   - status -- проверяемый статус
+
+

SOURCE

+
758 (defmacro book-has-status (status)
+759   "Проверка совпадения статуса прочтения книги с требуемым"
+760   `(equal (:Прочитана? book) (case-status ,status)))
+
+ +
+ +

books-select/sort-books [ Functions ]

+ +

[ Top ] [ books-select ] [ Functions ]

+

NAME

+
 dump-books -- вывод книг на экран в читаемом формате
+
+

FUNCTION

+
 sort-books :: Symbol # [Book] # [Key] -> [Book]
+
+

INPUTS

+
   - view -- форма вывода [table|plain]
+   - db -- Список книг
+
+

SOURCE

+
775 (defun sort-books (ord books keys)
+776   "Сортировка книг по возрастанию и убыванию по указанным ключам.
+777   Ключи указываются в порядке убывания приоритета,
+778   поэтому список сортируется, начиная с последнего ключа"
+779   (let ((fun (if (eql ord 'up) #'string< #'string>))
+780         (sorted-books (copy-list books)))
+781     (dolist (key (reverse keys))
+782       (setq sorted-books
+783             (stable-sort sorted-books fun
+784                          :key #'(lambda (plist) (getf plist key)))))
+785     sorted-books))
+
+ +
+ +

books-select/select-keys [ Functions ]

+ +

[ Top ] [ books-select ] [ Functions ]

+

NAME

+
 dump-books -- вывод книг на экран в читаемом формате
+
+

FUNCTION

+
 select-keys :: String -> [Key]
+
+

INPUTS

+
   - view -- форма вывода [table|plain]
+   - db -- Список книг
+
+

SOURCE

+
800 (defun select-keys (patterns)
+801   "Выбор возможных ключей по подстроке"
+802   (remove-duplicates
+803     (mapcan
+804       #'(lambda (pattern)
+805           (remove-if-not
+806             #'(lambda (key)
+807                 (search pattern (symbol-name key) :test #'char-equal))
+808             (book-info)))
+809       patterns)))
+
+ +
+ +

books-select/search-books [ Functions ]

+ +

[ Top ] [ books-select ] [ Functions ]

+

NAME

+
 dump-books -- вывод книг на экран в читаемом формате
+
+

FUNCTION

+
 search-books :: [String] # [Book] -> [Book]
+
+

INPUTS

+
   - view -- форма вывода [table|plain]
+   - db -- Список книг
+
+

SOURCE

+
824 (defun search-books (patterns db)
+825   "Поиск книги в базе данных по условию.
+826   Переменная условия должна называться BOOK"
+827   (select-books :from db :where (book-match book patterns)))
+
+ +
+ +

books-select/get-books [ Functions ]

+ +

[ Top ] [ books-select ] [ Functions ]

+

NAME

+
 dump-books -- вывод книг на экран в читаемом формате
+
+

FUNCTION

+
 get-books :: Symbol # [Book] -> [Book]
+
+

INPUTS

+
   - view -- форма вывода [table|plain]
+   - db -- Список книг
+
+

SOURCE

+
842 (defun get-books (status db)
+843   "Выбор книг по статусу прочтения,
+844   задаваемому символами 'read, 'done и 'new"
+845   (select-books :from db :where (book-has-status status)))
+
+ +
+ +

books/books-edit [ Modules ]

+ +

[ Top ] [ Modules ]

+

NAME

+
 Функции изменения книг
+
+ +
+ +

books-edit/set-books-status [ Functions ]

+ +

[ Top ] [ books-edit ] [ Functions ]

+

NAME

+
 set-books-status -- изменение статуса прочтения книги
+
+

FUNCTION

+
 set-books-status :: Symbol # [String] # [Book] -> Nil
+
+

INPUTS

+
 - status-char -- символ статуса прочтения
+   'd - 'done -- книга прочитана
+   'n - 'new  -- книга не прочитана
+   'r - 'read -- книга в процессе чтения
+ - db          -- список книг, предназначенных для изменения
+
+

SOURCE

+
875 (defun set-books-status (status-char patterns db)
+876   "Установка статуса прочтения книги.
+877   Статус задается символами 'd, 'n или 'r."
+878   (let ((new-db (copy-list db))
+879         (status (case-status (character status-char))))
+880     (for-books (book (search-books patterns new-db))
+881                (if-agree "Сменить статус книги? [y/n]: "
+882                          (setf (:Прочитана? book) status)
+883                          ;Если статус меняется на "Прочитано", установить оценку
+884                          (if (equal status "да")
+885                            (setf (:Оценка book) (read-book-field "Оценка [1-5]"))
+886                            ;Иначе установить оценку, равную нулю
+887                            (setf (:Оценка book) "0")))) new-db))
+
+ +
+ +

books-edit/edit-books [ Functions ]

+ +

[ Top ] [ books-edit ] [ Functions ]

+

NAME

+
 edit-books -- редактирование информации о книгах
+
+

SYNOPSIS

+
 Редактирование информации о книгах, совпадающих с PATTERNS.
+ Функция выводит на экран информацию о книгах и, при согласии
+ пользователя, позволяет редактировать данные.
+
+ Не требуется редактировать все поля записи.
+ Ввод пустой строки - сохранение прежней информации в текущем поле.
+
+

FUNCTION

+
 set-books-status :: [String] # [Book] -> IO
+
+

INPUTS

+
   - patterns -- список образцов
+   - db -- список книг
+
+

RESULT

+
 Измененный список книг
+
+

SOURCE

+
913 (defun edit-books (patterns db)
+914   (let ((new-db (copy-list db)))
+915     (for-books (book (search-books patterns new-db))
+916                (if-agree "Редактировать информацию? [y/n]: "
+917                          (dolist (field (book-info))
+918                            (let ((new-info (read-book-field
+919                                              (format nil "~a [~a]"
+920                                                      (keyword->string field)
+921                                                      (getf book field)))))
+922                              (unless (equal "" new-info)
+923                                (setf (getf book field) new-info)))))) new-db))
+
+ +
+ +

books-edit/remove-books [ Functions ]

+ +

[ Top ] [ books-edit ] [ Functions ]

+

NAME

+
 remove-books -- удаление книг из базы
+
+

NOTES

+
 Удаление производится после подтверждения
+
+

FUNCTION

+
 set-books-status :: Symbol # [String] # [Book] -> Nil
+
+

INPUTS

+
   - patterns -- список образцов
+   - db -- список книг
+
+

RESULT

+
 Измененный список книг
+
+

SOURCE

+
944 (defun remove-books (patterns db)
+945   "Удаление книг из базы"
+946   (let ((new-db (copy-list db)))
+947     (for-books (book (search-books patterns db))
+948                (if-agree "Удалить книгу? [y/n]"
+949                          (setq new-db (remove-if #'(lambda (x)
+950                                                      (equal x book)) new-db))))
+951     new-db))
+
+ +
+ +

books/books-usage [ Modules ]

+ +

[ Top ] [ Modules ]

+

NAME

+
 Использование программы
+
+ +
+ +

books-usage/format-help [ Functions ]

+ +

[ Top ] [ books-usage ] [ Functions ]

+

NAME

+
 show-help -- вывод справки по использованию
+
+

FUNCTION

+
 show-help :: IO
+
+

OUTPUT

+
   Вывод аргументов командной строки,
+   с которыми можно запускать программу
+
+

SOURCE

+
972 (defmacro format-help ((output) &body message)
+973   "Форматирование элементов справки по использованию"
+974   `(loop for (command description) in ',message do
+975          (format ,output "~4t~20a - ~a~%" command description)))
+
+ +
+ +

books-usage/show-help [ Functions ]

+ +

[ Top ] [ books-usage ] [ Functions ]

+

NAME

+
 show-help -- вывод справки по использованию
+
+

FUNCTION

+
 show-help :: IO
+
+

OUTPUT

+
   Вывод аргументов командной строки,
+   с которыми можно запускать программу
+
+

SOURCE

+
 990 (defun show-help ()
+ 991   "Вывод справки по использованию программы"
+ 992   (with-output-to-string (help-stream)
+ 993     (format-help (help-stream)
+ 994                  ("help"              "вывод справки по использованию")
+ 995                  ("r"                 "читаемые книги")
+ 996                  ("d"                 "прочитанные книги")
+ 997                  ("n"                 "не прочитанные книги")
+ 998                  ("new"               "добавить новые книги")
+ 999                  ("edit <...>"        "редактировать книги")
+1000                  ("set (d|r|n) <...>" "сменить статус для книг")
+1001                  ("del <...>"         "удаление книг из базы")
+1002                  ("sort, sort+"       "сортировка по возрастанию")
+1003                  ("sort-"             "сортировка по убыванию")
+1004                  ("report <...>"      "вывод отчета по ключевому слову")
+1005                  ("reports"           "вывод отчетов по всем ключевым словам")
+1006                  ("<...>"             "поиск книг в базе данных"))))
+
+ +
+ +

books-usage/get-argv-var [ Functions ]

+ +

[ Top ] [ books-usage ] [ Functions ]

+

NAME

+
 show-help -- вывод справки по использованию
+
+

FUNCTION

+
 show-help :: IO
+
+

OUTPUT

+
   Вывод аргументов командной строки,
+   с которыми можно запускать программу
+
+

SOURCE

+
1023 (defun get-argv-var ()
+1024   "Параметры командной строки для различных реализация CL"
+1025   #+sbcl (rest *posix-argv*)
+1026   #+clisp *args*)
+
+ +
+ +

books-usage/parse-commandline-arguments [ Functions ]

+ +

[ Top ] [ books-usage ] [ Functions ]

+

NAME

+
 show-help -- вывод справки по использованию
+
+

FUNCTION

+
 show-help :: IO
+
+

OUTPUT

+
   Вывод аргументов командной строки,
+   с которыми можно запускать программу
+
+

SOURCE

+
1041 (defun parse-commandline-arguments ()
+1042   "Разбор аргументов коммандной строки"
+1043   (let* ((argv (get-argv-var))
+1044          (first-arg (intern (or (first argv) "")))
+1045          (second-arg (second argv))
+1046          (db-file +db-file+)
+1047          (db (load-db +db-file+)))
+1048 
+1049     ;;Создание и заполнение новой базы данных
+1050     (if (null db)
+1051       (progn
+1052         (format t " #> Создана новая база данных: ~a~%~%" db-file)
+1053         (setq first-arg '|new|)))
+1054 
+1055     ;;Обработка команд пользователя
+1056     (format t "~%~a~%"
+1057             (case first-arg
+1058               (|help| (show-help))
+1059               (|r|    (dump-books 'table (get-books 'reading db)))
+1060               (|d|    (dump-books 'table (get-books 'done db)))
+1061               (|n|    (dump-books 'table (get-books 'new db)))
+1062               (|new|  (save-and-dump-changes (add-books db) db-file))
+1063               (|edit|
+1064                 (let* ((patterns (rest argv))
+1065                        (new-db (edit-books patterns db)))
+1066                   (save-and-dump-changes new-db db-file patterns)))
+1067               (|set|
+1068                 (let* ((patterns (cddr argv))
+1069                        (new-db (set-books-status second-arg patterns db)))
+1070                   (save-and-dump-changes new-db db-file patterns)))
+1071               (|del|
+1072                 (let* ((patterns (rest argv))
+1073                        (new-db (remove-books patterns db)))
+1074                   (save-and-dump-changes new-db db-file patterns)))
+1075               ((|sort| |sort+|)
+1076                (dump-books 'table (sort-books 'up db (select-keys (rest argv)))))
+1077               (|sort-|
+1078                 (dump-books 'table (sort-books 'down db (select-keys (rest argv)))))
+1079               (|report|  (dump-reports (get-reports db (select-keys (rest argv)))))
+1080               (|reports| (dump-reports (get-reports db)))
+1081               (t (dump-books 'table (search-books argv db)))))))
+1082 
+1083 (parse-commandline-arguments)
+
+ +
+ + + diff --git a/doc/books_lisp.tex b/doc/books_lisp.tex new file mode 100755 index 0000000..be111e6 --- /dev/null +++ b/doc/books_lisp.tex @@ -0,0 +1,261 @@ +% Document: ./books.lisp +% Source: ./books.lisp +% Generated with ROBODoc Version 4.99.38 (Oct 24 2010) +\documentclass{article} +\usepackage{makeidx} +\usepackage{graphicx} +\oddsidemargin 0.25 in +\evensidemargin 0.25 in +\marginparwidth 0.75 in +\textwidth 5.875 in +\setlength{\parindent}{0in} +\setlength{\parskip}{.08in} + +\pagestyle{headings} +\title{API Reference} +\author{Generated with ROBODoc Version 4.99.38 (Oct 24 2010) +} +\makeindex +\begin{document} +\maketitle +\printindex +\tableofcontents +\newpage + +\subsection{books/books-edit} +\index{unsorted!books-edit}\index{Modules!books-edit} +\textbf{NAME:}\hspace{0.08in}\begin{verbatim} + Функции изменения книг +\end{verbatim} + +\subsection{Compiler/Parser} +\index{unsorted!Parser}\index{Modules!Parser} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + The parser module contains functions that scan a + preprocessed source file and build the syntax tree. +\end{verbatim} + +\subsection{D-Language/Compiler} +\index{unsorted!Compiler}\index{Modules!Compiler} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + The compiler takes a preprocessed source file and + turns it into an object file. +\end{verbatim} + +\subsection{D-Language/Linker} +\index{unsorted!Linker}\index{Modules!Linker} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + The linker module contains functions that scan a + object file and build the executable. +\end{verbatim} + +\subsection{books-edit/set-books-status} +\index{unsorted!set-books-status}\index{Functions!set-books-status} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + set-books-status -- изменение статуса прочтения книги +\end{verbatim} +\textbf{INPUTS:}\hspace{0.08in}\begin{verbatim} + - status-char -- символ статуса прочтения + 'd - 'done -- книга прочитана + 'n - 'new -- книга не прочитана + 'r - 'read -- книга в процессе чтения + - db -- список книг, предназначенных для изменения +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defun set-books-status (status-char patterns db) + "Установка статуса прочтения книги. + Статус задается символами 'd, 'n или 'r." + (let ((new-db (copy-list db)) + (status (case-status (character status-char)))) + (for-books (book (search-books patterns new-db)) + (if-agree "Сменить статус книги? [y/n]: " + (setf (:Прочитана? book) status) + ;Если статус меняется на "Прочитано", установить оценку + (if (equal status "да") + (setf (:Оценка book) (read-book-field "Оценка [1-5]")) + ;Иначе установить оценку, равную нулю + (setf (:Оценка book) "0")))) new-db)) +\end{verbatim} + +\subsection{books.main/+colors+} +\index{unsorted!+colors+}\index{Structures!+colors+} +\textbf{NAME:}\hspace{0.08in}\begin{verbatim} + +colors+ - настройка цвета +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defparameter +colors+ + '( :new "1;35m" ;Цвет непрочитанных книг + :read "1;33m" ;Цвет читаемых книг + :done "1;34m" ;Цвет прочитанных книг + :rating "1;31m" ;Цвет оценок и диаграмм статистики + :reset "00m")) +\end{verbatim} + +\subsection{books.main/+db-file+} +\index{unsorted!+db-file+}\index{Variables!+db-file+} +\textbf{NAME:}\hspace{0.08in}\begin{verbatim} + book-info -- файл базы данных +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defparameter +db-file+ "books.db") +\end{verbatim} + +\subsection{books.main/book-info} +\index{unsorted!book-info}\index{Structures!book-info} +\textbf{NAME:}\hspace{0.08in}\begin{verbatim} + book-info -- Структура записи о книге +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defun book-info () + '( :Авторы + :Название + :Подзаголовок + :Издание + :Серия + :Язык + :Издательство + :Издательство_РФ + :ISBN_EN + :ISBN_RU + :Год_издания_EN + :Год_издания_RU + :Количество_страниц + :Категория + :Ключевые_слова + :Прочитана? + :Оценка)) +\end{verbatim} + +\subsection{books.main/reports-exclude} +\index{unsorted!reports-exclude}\index{Structures!reports-exclude} +\textbf{NAME:}\hspace{0.08in}\begin{verbatim} + reports-exclude -- Список исключений ключевых слов, + для которых не нужно выводить отчеты +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defun reports-exclude () + '( :Название + :Подзаголовок + :Издание + :ISBN_EN + :ISBN_RU)) +\end{verbatim} + +\subsection{books.main/set-color} +\index{unsorted!set-color}\index{Functions!set-color} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + set-color -- Установка цвета текста в зависимости от статуса прочтения +\end{verbatim} +\textbf{INPUTS:}\hspace{0.08in}\begin{verbatim} + - color-status -- статус, для которого требуется определить цвет +\end{verbatim} +\textbf{RESULT:}\hspace{0.08in}\begin{verbatim} + Escape-последовательность цветового кода +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defun set-color (color-status) + (getf +colors+ (cond + ((eql color-status 'none) :reset) + ((eql color-status 'star) :rating) + ((equalp color-status "да") :done) + ((equalp color-status "нет") :new) + (:read)))) +\end{verbatim} + +\subsection{books.usage/show-help} +\index{unsorted!show-help}\index{Functions!show-help} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + show-help -- вывод справки по использованию +\end{verbatim} +\textbf{OUTPUT:}\hspace{0.08in}\begin{verbatim} + Вывод аргументов командной строки, + с которыми можно запускать программу +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defun show-help () + "Вывод справки по использованию программы" + (with-output-to-string (help-stream) + (format-help (help-stream) + ("help" "вывод справки по использованию") + ("r" "читаемые книги") + ("d" "прочитанные книги") + ("n" "не прочитанные книги") + ("new" "добавить новые книги") + ("edit <...>" "редактировать книги") + ("set (d|r|n) <...>" "сменить статус для книг") + ("del <...>" "удаление книг из базы") + ("sort, sort+" "сортировка по возрастанию") + ("sort-" "сортировка по убыванию") + ("report <...>" "вывод отчета по ключевому слову") + ("reports" "вывод отчетов по всем ключевым словам") + ("<...>" "поиск книг в базе данных")))) +\end{verbatim} + +\subsection{books/dump-books} +\index{unsorted!dump-books}\index{Functions!dump-books} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + dump-books -- вывод книг на экран в читаемом формате +\end{verbatim} +\textbf{INPUTS:}\hspace{0.08in}\begin{verbatim} + - view -- форма вывода [table|plain] + - db -- Список книг +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defun dump-books (view db) + "Информация о книгах в форме VIEW (table/plain)" + (ecase view + (table (dump-books-table db)) + (plain (dump-books-plain db)))) +\end{verbatim} + +\subsection{books/dump-books-plain} +\index{unsorted!dump-books-plain}\index{Functions!dump-books-plain} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + dump-books-plain -- вывод книг в подробном представлении +\end{verbatim} +\textbf{INPUTS:}\hspace{0.08in}\begin{verbatim} + db -- Список книг +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defun dump-books-plain (db) + "Информация о книгах из списка DB в подробном представлении" + (with-output-to-string (stream) + (dolist (book db) + (format stream "~{ ~a:~25t~a~%~}~%" book)))) +\end{verbatim} + +\subsection{books/dump-books-table} +\index{unsorted!dump-books-table}\index{Functions!dump-books-table} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + dump-books-table -- вывод книг в виде таблицы +\end{verbatim} +\textbf{INPUTS:}\hspace{0.08in}\begin{verbatim} + db -- Список книг +\end{verbatim} +\textbf{SOURCE:}\hspace{0.08in}\begin{verbatim} +(defun dump-books-table (db) + "Информация о книгах из списка DB в виде таблицы" + (with-output-to-string (stream) + (let ((book-number 1)) + (dolist (book db) + (format stream "~C[~a~4d. ~42a~60a~5@a c. ~4a~C[~a~a~C[~a~%" + #\Esc(set-color (:Прочитана? book)) + book-number + (:Авторы book) + (:Название book) + (:Количество_страниц book) + (get-status-chars (:Прочитана? book)) + #\Esc(set-color 'star) + (number->bar (:Оценка book)) + #\Esc(set-color 'none)) + (incf book-number))))) +\end{verbatim} + +\subsection{Parser/ReadToken} +\index{unsorted!ReadToken}\index{Functions!ReadToken} +\textbf{FUNCTION:}\hspace{0.08in}\begin{verbatim} + ReadToken reads the next token from the input + file. +\end{verbatim} + +\end{document} diff --git a/doc/dot_graph_1.png b/doc/dot_graph_1.png new file mode 100755 index 0000000..2459f29 Binary files /dev/null and b/doc/dot_graph_1.png differ diff --git a/doc/masterindex.html b/doc/masterindex.html new file mode 100755 index 0000000..044e28d --- /dev/null +++ b/doc/masterindex.html @@ -0,0 +1,91 @@ + + + + + + + +Index + + + + + +
+
+ + + + + diff --git a/doc/robo_functions.html b/doc/robo_functions.html new file mode 100755 index 0000000..c7b45a5 --- /dev/null +++ b/doc/robo_functions.html @@ -0,0 +1,77 @@ + + + + + + + +Functions + + + + + +
+
+ + + + + diff --git a/doc/robo_methods.html b/doc/robo_methods.html new file mode 100755 index 0000000..779bbd5 --- /dev/null +++ b/doc/robo_methods.html @@ -0,0 +1,41 @@ + + + + + + + +Methods + + + + + +
+
+ +
+

Methods

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

G

get-report-any +get-report-pages +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/robo_modules.html b/doc/robo_modules.html new file mode 100755 index 0000000..5b51312 --- /dev/null +++ b/doc/robo_modules.html @@ -0,0 +1,46 @@ + + + + + + + +Modules + + + + + +
+
+ +
+

Modules

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

B

books-db +books-edit +books-functions +books-main +books-reports +books-select +books-usage +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/robo_sourcefiles.html b/doc/robo_sourcefiles.html new file mode 100755 index 0000000..8df3ece --- /dev/null +++ b/doc/robo_sourcefiles.html @@ -0,0 +1,45 @@ + + + + + + + +Sourcefiles + + + + + +
+
+ +
+ +
+ + + diff --git a/doc/robo_strutures.html b/doc/robo_strutures.html new file mode 100755 index 0000000..fc7ef46 --- /dev/null +++ b/doc/robo_strutures.html @@ -0,0 +1,42 @@ + + + + + + + +Structures + + + + + +
+
+ +
+

Structures

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

+

+colors+ +

B

book-info +

R

reports-exclude +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/robo_variables.html b/doc/robo_variables.html new file mode 100755 index 0000000..feb5ae9 --- /dev/null +++ b/doc/robo_variables.html @@ -0,0 +1,40 @@ + + + + + + + +Variables + + + + + +
+
+ +
+

Variables

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

+

+db-file+ +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/robodoc.css b/doc/robodoc.css new file mode 100755 index 0000000..207a172 --- /dev/null +++ b/doc/robodoc.css @@ -0,0 +1,302 @@ +/****h* ROBODoc/ROBODoc Cascading Style Sheet + * FUNCTION + * This is the default cascading style sheet for documentation + * generated with ROBODoc. + * You can edit this file to your own liking and then use + * it with the option + * --css + * + * This style-sheet defines the following layout + * +----------------------------------------+ + * | logo | + * +----------------------------------------+ + * | extra | + * +----------------------------------------+ + * | | navi- | + * | | gation | + * | content | | + * | | | + * +----------------------------------------+ + * | footer | + * +----------------------------------------+ + * + * This style-sheet is based on a style-sheet that was automatically + * generated with the Strange Banana stylesheet generator. + * See http://www.strangebanana.com/generator.aspx + * + ****** + * $Id: html_generator.c,v 1.94 2008/06/17 11:49:27 gumpu Exp $ + */ + +body +{ + background-color: rgb(255,255,255); + color: rgb(98,84,55); + font-family: Arial, serif; + border-color: rgb(226,199,143); +} + +pre +{ + font-family: monospace; + margin: 15px; + padding: 5px; + white-space: pre; + color: #000; +} + +pre.source +{ + background-color: #ffe; + border: dashed #aa9 1px; +} + +p +{ + margin:15px; +} + +p.item_name +{ + font-weight: bolder; + margin:5px; + font-size: 120%; +} + +#content +{ + font-size: 100%; + color: rgb(0,0,0); + background-color: rgb(255,255,255); + border-left-width: 0px; + border-right-width: 0px; + border-top-width: 0px; + border-bottom-width: 0px; + border-left-style: none; + border-right-style: none; + border-top-style: none; + border-bottom-style: none; + padding: 40px 31px 14px 17px; + border-color: rgb(0,0,0); + text-align: justify; +} + +#navigation +{ + background-color: rgb(98,84,55); + color: rgb(230,221,202); + font-family: "Times New Roman", serif; + font-style: normal; + border-color: rgb(0,0,0); +} + +a.menuitem +{ + font-size: 120%; + background-color: rgb(0,0,0); + color: rgb(195,165,100); + font-variant: normal; + text-transform: none; + font-weight: normal; + padding: 1px 8px 3px 1px; + margin-left: 5px; + margin-right: 5px; + margin-top: 5px; + margin-bottom: 5px; + border-color: rgb(159,126,57); + text-align: right; +} + +#logo, #logo a +{ + font-size: 130%; + background-color: rgb(198,178,135); + color: rgb(98,84,55); + font-family: Georgia, serif; + font-style: normal; + font-variant: normal; + text-transform: none; + font-weight: bold; + padding: 20px 18px 20px 18px; + border-color: rgb(255,255,255); + text-align: right; +} + +#extra, #extra a +{ + font-size: 128%; + background-color: rgb(0,0,0); + color: rgb(230,221,202); + font-style: normal; + font-variant: normal; + text-transform: none; + font-weight: normal; + border-left-width: 0px; + border-right-width: 0px; + border-top-width: 0px; + border-bottom-width: 0px; + border-left-style: none; + border-right-style: none; + border-top-style: none; + border-bottom-style: none; + padding: 12px 12px 12px 12px; + border-color: rgb(195,165,100); + text-align: center; +} + +#content a +{ + color: rgb(159,126,57); + text-decoration: none; +} + +#content a:hover, #content a:active +{ + color: rgb(255,255,255); + background-color: rgb(159,126,57); +} + +a.indexitem +{ + display: block; +} + +h1, h2, h3, h4, h5, h6 +{ + background-color: rgb(221,221,221); + font-family: Arial, serif; + font-style: normal; + font-variant: normal; + text-transform: none; + font-weight: normal; +} + +h1 +{ + font-size: 151%; +} + +h2 +{ + font-size: 142%; +} + +h3 +{ + font-size: 133%; +} + +h4 +{ + font-size: 124%; +} + +h5 +{ + font-size: 115%; +} + +h6 +{ + font-size: 106%; +} + +#navigation a +{ + text-decoration: none; +} + +.menuitem:hover +{ + background-color: rgb(195,165,100); + color: rgb(0,0,0); +} + +#extra a +{ + text-decoration: none; +} + +#logo a +{ + text-decoration: none; +} + +#extra a:hover +{ +} + +/* layout */ +#navigation +{ + width: 22%; + position: relative; + top: 0; + right: 0; + float: right; + text-align: center; + margin-left: 10px; +} + +.menuitem {width: auto;} +#content {width: auto;} +.menuitem {display: block;} + + +div#footer +{ + background-color: rgb(198,178,135); + color: rgb(98,84,55); + clear: left; + width: 100%; + font-size: 71%; +} + +div#footer a +{ + background-color: rgb(198,178,135); + color: rgb(98,84,55); +} + +div#footer p +{ + margin:0; + padding:5px 10px +} + +span.keyword +{ + color: #00F; +} + +span.comment +{ + color: #080; +} + +span.quote +{ + color: #F00; +} + +span.squote +{ + color: #F0F; +} + +span.sign +{ + color: #008B8B; +} + +span.line_number +{ + color: #808080; +} + +@media print +{ + #navigation {display: none;} + #content {padding: 0px;} + #content a {text-decoration: underline;} +} diff --git a/doc/toc_index.html b/doc/toc_index.html new file mode 100755 index 0000000..80c9164 --- /dev/null +++ b/doc/toc_index.html @@ -0,0 +1,106 @@ + + + + + + + +Table of Contents + + + + + +
+
+ +
+

TABLE OF CONTENTS

+ +
+ + +