//Эта страница доступна также на следующих языках://
[[guile_scripting|English]]
===== Скрипты 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//)
Смотрите также раздел [[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**:
* нажмите : и введите (load "filename.scm")
* затем нажмите Enter
=== Удаление объектов с заданными свойствами ===
Например, удалим все объекты, являющиеся окружностями или дугами с нулевым
радиусом
(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))))
Предположим, нам необходимо удалить компонент с известным атрибутом, тогда
нам нужно также отделить и удалить все его атрибуты. Функция, определённая
ниже делает именно это.
(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)))
После загрузки файла, нажмите : и введите, например,
(delete-components-by-attrib! (active-page) "refdes" "R1")
=== Процедуры для ввода/вывода ===
Следующий скрипт определяет две процедуры, которые могут использоваться
в режиме пакетной обработки с помощью скриптов для **gaf shell**:
* ''schematic-file->page''
* ''page->schematic-file''
(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)))))
=== Копирование, перемещение и вращение объектов ===
; 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)
; нажмите
; Наслаждайтесь!
(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)
=== Редактирование группы атрибутов ===
Допустим, вы выделили несколько позиционных обозначений (атрибут refdes)
резисторов и хотите переименовать их все сразу, например, если они были
скопированы из другого места.
(use-modules (gschem selection))
(define (set-selected-attribs-value! value)
(for-each
(lambda (attrib)
(set-attrib-value! attrib value))
(page-selection (active-page))))
Использование процедуры в **gschem**:
(set-selected-attribs-value! "R100.?")
Теперь, после изменения их номеров с помощью t u, вы
копируете их все и хотите переименовать эти скопированные резисторы, добавив
суффикс:
(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))))
Использование процедуры в **gschem**:
(append-selected-attribs-suffix! "-top")
Теперь переименуем несколько других атрибутов, добавив префикс:
(use-modules (gschem selection))
(define (append-selected-attribs-prefix! prefix)
(for-each
(lambda (object)
(and (attribute? object)
(set-attrib-value!
object
(string-append prefix (attrib-value object)))))
(page-selection (active-page))))
Использование процедуры в **gschem**:
(append-selected-attribs-prefix! "A1.")
Давайте заменим первые буквы выделенных атрибутов префиксом:
(use-modules (gschem selection))
(define (replace-selected-attribs-prefix! prefix)
(for-each
(lambda (object)
(and (attribute? object)
(set-attrib-value!
object
(string-append
prefix
(string-copy (attrib-value object) 1)))))
(page-selection (active-page))))
Использование процедуры в **gschem**:
(replace-selected-attribs-prefix! "C")
Давайте переименуем выделенные атрибуты ''netname='', увеличив их значения
на определённое число:
(use-modules (gschem selection))
(define (add-selected-attribs-number! number)
(for-each
(lambda (object)
(and (attribute? object)
(set-attrib-value!
object
(number->string
(+ (string->number (attrib-value object)) number)))))
(page-selection (active-page))))
Использование процедуры в **gschem**:
(add-selected-attribs-number! 100)
Мы могли бы задать любую функцию вместо "+" для номера соединения в этой
процедуре. Например:
(use-modules (gschem selection))
(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))))
Использование процедуры в **gschem**:
(use-another-func! -)
(define (multiply-by-2 x)
(* 2 x))
(use-another-func! multiply-by-2)