This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
geda:guile_scripting.ru [2012/02/20 15:14] 127.0.0.1 external edit |
geda:guile_scripting.ru [2016/02/09 08:10] (current) vzh Added a link to a new document |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | //Эта страница доступна также на следующих языках:// | ||
+ | [[guile_scripting|English]] | ||
+ | |||
===== Скрипты Guile ===== | ===== Скрипты Guile ===== | ||
+ | В gEDA/gaf для обеспечения возможности написания скриптов на Scheme | ||
+ | используется [[http://www.gnu.org/s/guile/|Guile Scheme]], и в распоряжении | ||
+ | разработчика оказываются все возможности языка Guile. //Справочное | ||
+ | руководство по Guile// [//Guile Reference Manual//] можно найти либо в | ||
+ | формате Info (''[[info://guile|info guile]]'' на большинстве систем), либо в | ||
+ | формате HTML на | ||
+ | [[http://www.gnu.org/software/guile/docs/docs.html|веб-странице Guile]]. | ||
+ | Для доступа к объектам и страницам gEDA и для их изменения имеется набор | ||
+ | модулей, называемый gEDA Scheme API. Есть и //Справочное руководство по | ||
+ | Scheme в gEDA// [//gEDA Scheme Reference Manual//] в формате Info | ||
+ | (''[[info://geda-scheme|info geda-scheme]]''). | ||
+ | ==== Учебники ==== | ||
- | ==== Руководства ==== | ||
* [[gnetlist scheme tutorial.ru|Написание скриптов драйверов gnetlist на Scheme]] (//John Doty//) | * [[gnetlist scheme tutorial.ru|Написание скриптов драйверов gnetlist на Scheme]] (//John Doty//) | ||
- | * Смотрите также раздел [[geda:gnetlist_ug.ru#API драйвера в Scheme]] Руководства пользователя **gEDA gnetlist** | ||
+ | Смотрите также раздел [[geda:gschem_ug:extensions.ru|Расширение | ||
+ | функциональности gschem]] //[[geda:gschem_ug.ru|Руководства пользователя | ||
+ | gEDA gschem]]// и раздел [[geda:gnetlist_ug.ru#API драйвера в Scheme]] | ||
+ | //[[geda:gnetlist_ug.ru|Руководства пользователя gEDA gnetlist]]//. | ||
+ | |||
+ | ==== Справочная информация ==== | ||
+ | * [[geda>gEDA:gnetlist Scheme primitives|Примитивы Scheme для gnetlist]] | ||
+ | * [[gEDA:gschem repl.ru|Использование REPL в gschem]] | ||
+ | |||
+ | ==== Примеры скриптов ==== | ||
+ | Каждый скрипт можно скачать и загрузить в **gschem**: | ||
+ | * нажмите <key>:</key> и введите <code lisp>(load "filename.scm")</code> | ||
+ | * затем нажмите <key>Enter</key> | ||
+ | |||
+ | === Удаление объектов с заданными свойствами === | ||
+ | Например, удалим все объекты, являющиеся окружностями или дугами с нулевым | ||
+ | радиусом | ||
+ | |||
+ | <file lisp remove-objects.scm> | ||
+ | (use-modules (geda page)) | ||
+ | |||
+ | ; Проверяет, является ли объект OBJECT окружностью (circle) | ||
+ | ; или дугой (arc) с нулевым радиусом | ||
+ | (define (zero-radius-object? object) | ||
+ | (or | ||
+ | (and (circle? object) (= (circle-radius object) 0)) | ||
+ | (and (arc? object) (= (arc-radius object) 0)))) | ||
+ | |||
+ | (apply page-remove! (active-page) | ||
+ | (filter | ||
+ | zero-radius-object? | ||
+ | (page-contents (active-page)))) | ||
+ | </file> | ||
+ | |||
+ | Предположим, нам необходимо удалить компонент с известным атрибутом, тогда | ||
+ | нам нужно также отделить и удалить все его атрибуты. Функция, определённая | ||
+ | ниже делает именно это. <file lisp remove-components-with-attribs.scm> | ||
+ | (use-modules (geda page)) | ||
+ | (use-modules (geda object)) | ||
+ | (use-modules (geda attrib)) | ||
+ | |||
+ | ; Удаляет все компоненты, имеющие атрибут NAME=VALUE, со страницы PAGE | ||
+ | (define (delete-components-by-attrib! page name value) | ||
+ | (for-each | ||
+ | (lambda (obj) | ||
+ | (if (component? obj) | ||
+ | (for-each | ||
+ | (lambda (attr) | ||
+ | (and | ||
+ | (string=? (attrib-name attr) name) | ||
+ | (string=? (attrib-value attr) value) | ||
+ | (let ((attached-attribs (object-attribs obj))) | ||
+ | (apply detach-attribs! obj attached-attribs) | ||
+ | (apply page-remove! page obj attached-attribs)))) | ||
+ | (object-attribs obj)))) | ||
+ | (page-contents page))) | ||
+ | </file> | ||
+ | |||
+ | После загрузки файла, нажмите <key>:</key> и введите, например, <code lisp> | ||
+ | (delete-components-by-attrib! (active-page) "refdes" "R1") </code> | ||
+ | |||
+ | === Процедуры для ввода/вывода === | ||
+ | Следующий скрипт определяет две процедуры, которые могут использоваться | ||
+ | в режиме пакетной обработки с помощью скриптов для **gaf shell**: | ||
+ | * ''schematic-file->page'' | ||
+ | * ''page->schematic-file'' | ||
+ | |||
+ | <file lisp geda-io.scm> | ||
+ | (use-modules (ice-9 lineio)) | ||
+ | (use-modules (geda page)) | ||
+ | |||
+ | ; Процедуры ввода/вывода | ||
+ | ; Читает файл FILE и выводит строку | ||
+ | (define (file->string file) | ||
+ | (let* ((port (make-line-buffering-input-port (open-file file "r")))) | ||
+ | (do ((line "" (read-string port)) | ||
+ | (s "" (string-append s line))) | ||
+ | ((eof-object? line) ; тест | ||
+ | (close-port port) ; выражение(я) для вычисления в конце | ||
+ | s) ; возвращаемое значение | ||
+ | ; empty body | ||
+ | ))) | ||
+ | |||
+ | ; читает файл схемы FILE и возвращает объект страницы PAGE | ||
+ | (define (schematic-file->page file) | ||
+ | (string->page file (file->string file))) | ||
+ | |||
+ | ; сохраняет страницу схемы PAGE в файл FILE | ||
+ | (define (page->schematic-file page file) | ||
+ | (with-output-to-file file | ||
+ | (lambda () (display (page->string page))))) | ||
+ | </file> | ||
+ | |||
+ | |||
+ | === Копирование, перемещение и вращение объектов === | ||
+ | <file lisp move-and-rotate.scm> ; Scripting example by vzh per request of | ||
+ | ; Kai-Martin Knaak :-) | ||
+ | ; Use at your own risk. | ||
+ | |||
+ | ; Основная процедура здесь | ||
+ | ; multiple-copy-move-and-rotate-selection, что можно сократить до | ||
+ | ; mcmars. | ||
+ | ; Использование: | ||
+ | ; запустите gschem, чтобы там можно было использовать этот скрипт, например | ||
+ | ; gschem -s move-and-rotate.scm | ||
+ | ; выделите объекты в gschem, нажмите ':' (двоеточие) и наберите | ||
+ | ; (mcmars '(1000 . 500) 90 10) | ||
+ | ; нажмите <Enter> | ||
+ | ; Наслаждайтесь! | ||
+ | |||
+ | |||
+ | (use-modules (gschem selection)) | ||
+ | |||
+ | ; округление координат по ALIGN | ||
+ | (define (ceiling-coords vector align) | ||
+ | (cons | ||
+ | (* (ceiling-quotient (car vector) align) align) | ||
+ | (* (ceiling-quotient (cdr vector) align) align) | ||
+ | )) | ||
+ | |||
+ | ; Получение минимума X и минимума Y двух пар координат | ||
+ | (define (min-coords coord1 coord2) | ||
+ | (let ((x (min (car coord1) (car coord2))) | ||
+ | (y (min (cdr coord1) (cdr coord2)))) | ||
+ | ; возвращаемое значение | ||
+ | (cons x y))) | ||
+ | |||
+ | ; Копирование, перемещение и вращение текущего выделения. Выделенные объекты | ||
+ | ; сначала копируются, затем перемещаются на вектор VECTOR и, наконец, вращаются | ||
+ | ; на угол ANGLE вокруг центра, который рассчитывается как округлённая до | ||
+ | ; множителей 100 левая нижняя координата всех объектов в выделении. | ||
+ | ; Если никакие объекты не выделены, открывает диалоговое окно сообщений gschem | ||
+ | ; с предупреждением. | ||
+ | ; Возвращает скопированные объекты. | ||
+ | (define (copy-move-and-rotate-selection vector angle) | ||
+ | (let ((objects (page-selection (active-page)))) | ||
+ | (if (null? objects) | ||
+ | (gschem-msg "Select something first!") | ||
+ | ; else | ||
+ | (let* ((copied-objects (map copy-object objects)) | ||
+ | (translated-objects (apply translate-objects! vector copied-objects)) | ||
+ | (bounds (apply object-bounds translated-objects)) | ||
+ | (rotation-center (ceiling-coords (min-coords (car bounds) (cdr bounds)) 100)) | ||
+ | (rotated-objects (apply rotate-objects! rotation-center angle translated-objects))) | ||
+ | (apply page-append! (active-page) rotated-objects) | ||
+ | rotated-objects) | ||
+ | ))) | ||
+ | |||
+ | ; Умножает VECTOR, который должен быть парой, на число NUMBER | ||
+ | (define (multiply-vector-by vector number) | ||
+ | (cons (* number (car vector)) (* number (cdr vector)))) | ||
+ | |||
+ | ; Копирование, перемещение и вращение текущего выделения количество | ||
+ | ; раз, указанное аргументом NUMBER. Применяет процедуру | ||
+ | ; copy-move-and-rotate-selection несколько раз, каждый раз увеличивая | ||
+ | ; вектор и угол на заданные значения VECTOR и ANGLE. | ||
+ | ; Если никакие объекты не выделены, открывает gschem message dialog with | ||
+ | ; warning. | ||
+ | ; Если никакие объекты не выделены, открывает диалоговое окно сообщений gschem | ||
+ | ; с предупреждением. | ||
+ | ; Возвращаемое значение не определено. | ||
+ | (define (multiple-copy-move-and-rotate-selection vector angle num) | ||
+ | (if (null? (page-selection (active-page))) | ||
+ | (gschem-msg "Select something first!") | ||
+ | ; else | ||
+ | (do ((i num (1- i))) | ||
+ | ((= i 0)) | ||
+ | (copy-move-and-rotate-selection | ||
+ | (multiply-vector-by vector i) (* angle i))) | ||
+ | )) | ||
+ | |||
+ | ; Сокращение для имени процедуры multiple-copy-move-and-rotate-selection | ||
+ | (define mcmars multiple-copy-move-and-rotate-selection) </file> | ||
+ | |||
+ | |||
+ | === Редактирование группы атрибутов === | ||
+ | Допустим, вы выделили несколько позиционных обозначений (атрибут refdes) | ||
+ | резисторов и хотите переименовать их все сразу, например, если они были | ||
+ | скопированы из другого места. <file lisp set-selected-attribs-value> | ||
+ | (use-modules (gschem selection)) | ||
+ | |||
+ | (define (set-selected-attribs-value! value) | ||
+ | (for-each | ||
+ | (lambda (attrib) | ||
+ | (set-attrib-value! attrib value)) | ||
+ | (page-selection (active-page)))) | ||
+ | </file> | ||
+ | |||
+ | Использование процедуры в **gschem**: <code lisp> | ||
+ | (set-selected-attribs-value! "R100.?") </code> | ||
- | ==== Справка по C-библиотеке libgeda ==== | + | Теперь, после изменения их номеров с помощью <key>t</key> <key>u</key>, вы |
- | **libgeda** определяет набор низкоуровневых функций на **C**, таких как | + | копируете их все и хотите переименовать эти скопированные резисторы, добавив |
- | функции библиотеки компонентов и библиотеки подсхем, для конфигурирования | + | суффикс: <file lisp append-selected-attribs-suffix.scm> |
- | своего поведения и возможностей обработки. | + | (use-modules (gschem selection)) |
+ | (define (append-selected-attribs-suffix! suffix) | ||
+ | (for-each | ||
+ | (lambda (attrib) | ||
+ | (set-attrib-value! | ||
+ | attrib | ||
+ | (string-append (attrib-value attrib) suffix))) | ||
+ | (page-selection (active-page)))) | ||
+ | </file> | ||
- | === Типы === | + | Использование процедуры в **gschem**: <code lisp> |
- | * attribute | + | (append-selected-attribs-suffix! "-top") </code> |
- | * object | + | |
- | * page | + | |
+ | Теперь переименуем несколько других атрибутов, добавив префикс: <file lisp | ||
+ | append-selected-attribs-prefix.scm> | ||
+ | (use-modules (gschem selection)) | ||
- | === Переменные === | + | (define (append-selected-attribs-prefix! prefix) |
- | Основная конфигурация (определённая в **libgeda**, только для чтения) | + | (for-each |
- | * path-sep | + | (lambda (object) |
- | * geda-rc-path | + | (and (attribute? object) |
- | * geda-data-path | + | (set-attrib-value! |
+ | object | ||
+ | (string-append prefix (attrib-value object))))) | ||
+ | (page-selection (active-page)))) | ||
+ | </file> | ||
- | Идентификаторы типов объектов (определённые в **libgeda**, только для чтения) | + | Использование процедуры в **gschem**: <code lisp> |
- | * OBJ_LINE | + | (append-selected-attribs-prefix! "A1.") </code> |
- | * OBJ_BOX | + | |
- | * OBJ_PICTURE | + | |
- | * OBJ_CIRCLE | + | |
- | * OBJ_NET | + | |
- | * OBJ_BUS | + | |
- | * OBJ_COMPLEX | + | |
- | * OBJ_TEXT | + | |
- | * OBJ_PIN | + | |
- | * OBJ_ARC | + | |
- | * OBJ_ROUTE | + | |
- | * OBJ_THRU_HOLE | + | |
- | * OBJ_PLACEHOLDER | + | |
+ | Давайте заменим первые буквы выделенных атрибутов префиксом: <file lisp | ||
+ | append-selected-attribs-prefix.scm> | ||
+ | (use-modules (gschem selection)) | ||
- | === Функции === | + | (define (replace-selected-attribs-prefix! prefix) |
- | Библиотека компонентов: | + | (for-each |
- | * component-library | + | (lambda (object) |
- | * component-library-command | + | (and (attribute? object) |
- | * component-library-funcs | + | (set-attrib-value! |
- | * component-library-search | + | object |
- | * reset-component-library | + | (string-append |
+ | prefix | ||
+ | (string-copy (attrib-value object) 1))))) | ||
+ | (page-selection (active-page)))) | ||
+ | </file> | ||
- | Библиотека подсхем: | + | Использование процедуры в **gschem**: <code lisp> |
- | * source-library | + | (replace-selected-attribs-prefix! "C") </code> |
- | * source-library-search | + | |
- | * reset-source-library | + | |
- | Конфигурация поведения **libgeda** (только для записи): | + | Давайте переименуем выделенные атрибуты ''netname='', увеличив их значения |
- | * always-promote-attributes | + | на определённое число: <file lisp add-selected-attribs-number.scm> |
- | * attribute-promotion | + | (use-modules (gschem selection)) |
- | * bitmap-directory | + | |
- | * bus-ripper-symname | + | |
- | * font-directory | + | |
- | * keep-invisible | + | |
- | * map-font-character-to-file | + | |
- | * postscript-prolog | + | |
- | * promote-invisible | + | |
- | * scheme-directory | + | |
- | * untitled-name | + | |
- | * world-size | + | |
- | Манипуляторы типа ''smob'': | + | (define (add-selected-attribs-number! number) |
- | * get-attribute-name-value | + | (for-each |
- | * get-attribute-bounds | + | (lambda (object) |
- | * get-attribute-angle | + | (and (attribute? object) |
- | * calcule-new-attrib-bounds | + | (set-attrib-value! |
- | * get-object-attributes | + | object |
- | * get-attrib-value-by-attrib-name | + | (number->string |
- | * get-object-type | + | (+ (string->number (attrib-value object)) number))))) |
- | * get-line-width | + | (page-selection (active-page)))) |
- | * get-page-filename | + | </file> |
+ | Использование процедуры в **gschem**: <code lisp> | ||
+ | (add-selected-attribs-number! 100) </code> | ||
- | ==== libgeda geda.scm ==== | + | Мы могли бы задать любую функцию вместо "+" для номера соединения в этой |
- | Файл //''geda.scm''//, установленный с **libgeda**, предоставляет несколько | + | процедуре. Например: <file lisp use-another-func.scm> |
- | полезных функций как для простой обработки путей доступа и файлов, так и для | + | (use-modules (gschem selection)) |
- | загрузки rc-файлов из каталогов //''gafrc.d''//. | + | |
+ | (define (use-another-func! func) | ||
+ | (for-each | ||
+ | (lambda (object) | ||
+ | (and (attribute? object) | ||
+ | (set-attrib-value! | ||
+ | object | ||
+ | (number->string | ||
+ | (func (string->number (attrib-value object))))))) | ||
+ | (page-selection (active-page)))) | ||
+ | </file> | ||
- | === Функции === | + | Использование процедуры в **gschem**: |
- | * build-path | + | <code lisp> |
- | * regular-file? | + | (use-another-func! -) |
- | * directory? | + | (define (multiply-by-2 x) |
- | * has-suffix? | + | (* 2 x)) |
- | * load-scheme-dir | + | (use-another-func! multiply-by-2) |
+ | </code> | ||