Translations of this page are also available in the following languages: Русский.

Guile scripting

gEDA/gaf uses Guile Scheme to provide Scheme scripting capabilities, and all of the features of Guile are available to use. The Guile Reference Manual is available as an Info manual (info guile on most systems), or on the Guile website.

A collection of modules is provided for accessing and modifying gEDA objects and pages, called the gEDA Scheme API. The gEDA Scheme Reference Manual is also available as an Info manual (info geda-scheme).

Tutorials

Reference documents

Scripting examples

You can download each script example and load it in gschem:

  • just hit : and enter
    (load "filename.scm")
  • then hit Enter

You can install them as well if you don't want to load them every time:

  • copy the script you want into your ~/.gEDA directory
  • put the line
    (load "filename.scm")

    into your ~/.gEDA/gschemrc (replace filename.scm with the real name of the script)

Removing objects with specific properties

For instance, let's remove all objects which are circles or arcs with zero radius:

remove-objects.scm
(use-modules (geda page))
 
; Checks if the OBJECT is a circle or an arc with zero radius
(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))))

Let's suppose we have a component with a known attribute to remove, then we have to detach and remove all its attributes, too. The function below does exactly this.

remove-components-with-attribs.scm
(use-modules (geda page))
(use-modules (geda object))
(use-modules (geda attrib))
 
; Removes all components having the attrib NAME=VALUE from 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)))

After loading the file, hit : and enter, for example,

(delete-components-by-attrib! (active-page) "refdes" "R1")

Procedures for input-output

The following script defines two procedures that can be used in gaf shell batch scripts:

  • schematic-file→page
  • page→schematic-file
geda-io.scm
(use-modules (ice-9 lineio))
(use-modules (geda page))
 
; Input/output procedures
; reads FILE and outputs string
(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) ; test
       (close-port port)  ; expression(s) to evaluate in the end
       s)                 ; return value
      ; empty body
      )))
 
; reads schematic FILE and outputs PAGE object
(define (schematic-file->page file)
    (string->page file (file->string file)))
 
; saves schematic PAGE to FILE
(define (page->schematic-file page file)
  (with-output-to-file file
    (lambda () (display (page->string page)))))

Copy, move, and rotate objects

move-and-rotate.scm
; Scripting example by vzh per request of Kai-Martin Knaak :-)
; Use at your own risk.
 
; The main procedure here is
; multiple-copy-move-and-rotate-selection which can be abbreviated
; as mcmars.
; Usage:
;   launch gschem so it can use this script, e.g.
;     gschem -s move-and-rotate.scm
;   select objects in gschem, then hit ':' (semicolon) and type
;     (mcmars '(1000 . 500) 90 10)
;   hit <Enter>
; Enjoy!
 
 
(use-modules (gschem selection))
 
; align coords by ALIGN
(define (ceiling-coords vector align)
  (cons
    (* (ceiling-quotient (car vector) align) align)
    (* (ceiling-quotient (cdr vector) align) align)
    ))
 
; Get minimum X and minimum Y of two pairs of coords
(define (min-coords coord1 coord2)
  (let ((x (min (car coord1) (car coord2)))
        (y (min (cdr coord1) (cdr coord2))))
    ; return value
    (cons x y)))
 
; Copy, move and rotate current selection. The selected objects
; are first copied, then translated by VECTOR and finally rotated
; by ANGLE about center which is calculated as rounded by 100
; lower left coordinate of all objects in selection.
; If no objects are selected, opens gschem message dialog with
; warning.
; Returns the copied objects.
(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)
      )))
 
; Multiply VECTOR which must be a pair by NUMBER
(define (multiply-vector-by vector number)
  (cons (* number (car vector)) (* number (cdr vector))))
 
; Copy, move and rotate current selection NUMBER times. Applies
; the copy-move-and-rotate-selection procedure multiple times
; increasing every time vector and angle by given values of VECTOR
; and ANGLE.
; If no objects are selected, opens gschem message dialog with
; warning.
; Return value is unspecified.
(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)))
    ))
 
; Abbreviated name for the multiple-copy-move-and-rotate-selection
; procedure
(define mcmars multiple-copy-move-and-rotate-selection)

Group attribute editing

Let's suppose you have selected several resistors' refdeses and want to rename them at once, e.g., if they were copy from another place.

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))))

Usage of the procedure in gschem:

(set-selected-attribs-value! "R100.?")

Now, after renumbering them using T U, you copy them all and want to rename those copied resistors appending a suffix:

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))))

Usage of the procedure in gschem:

(append-selected-attribs-suffix! "-top")

Now, let's rename some other attributes by adding a prefix:

append-selected-attribs-prefix.scm
(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))))

Usage of the procedure in gschem:

(append-selected-attribs-prefix! "A1.")

Let's replace first letters of selected attribs with prefix:

append-selected-attribs-prefix.scm
(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))))

Usage of the procedure in gschem:

(replace-selected-attribs-prefix! "C")

Let's rename selected netname= attributes increasing them by a fixed number:

add-selected-attribs-number.scm
(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))))

Usage of the procedure in gschem:

(add-selected-attribs-number! 100)

We could set any function instead of ”+” on the net number in this procedure. For instance:

use-another-func.scm
(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))))

Usage of the procedure in gschem:

(use-another-func! -)
(define (multiply-by-2 x)
  (* 2 x))
(use-another-func! multiply-by-2)

Moving objects using arrows

Let's define actions to move selected objects using Shift + arrow keys.

arrow-move.scm
(use-modules (gschem selection))
 
; Default offset to move
(define offset 100)
 
; Get moving vector
(define (move-selection direction)
  (apply translate-objects!
    (case direction
      ((left ) (cons (- offset) 0))
      ((right) (cons (+ offset) 0))
      ((down ) (cons 0 (- offset)))
      ((up   ) (cons 0 (+ offset)))
      (else #f))
    (page-selection (active-page))))
 
; Define actions
(define (&move-selection-left ) (move-selection 'left ))
(define (&move-selection-right) (move-selection 'right))
(define (&move-selection-down ) (move-selection 'down ))
(define (&move-selection-up   ) (move-selection 'up   ))
 
; Define shortcuts
(global-set-key "<Shift>Left"  '&move-selection-left)
(global-set-key "<Shift>Right" '&move-selection-right)
(global-set-key "<Shift>Up"    '&move-selection-up)
(global-set-key "<Shift>Down"  '&move-selection-down)

The following script redefines current shortcuts so that if nothing is selected the canvas is moved with arrow keys (without Shift in this case), otherwise selected objects are moved.

arrow-move2.scm
(use-modules (gschem selection))
 
; Default offset to move
(define offset 100)
 
; Get moving vector
(define (move-selection direction)
  (let ((selection (page-selection (active-page))))
    (if (null? selection)
      ; default behaviour
      (case direction
          ((left ) (&view-pan-left))
          ((right) (&view-pan-right))
          ((down ) (&view-pan-down))
          ((up   ) (&view-pan-up))
          (else #f))
      ; modified behaviour
      (apply translate-objects!
        (case direction
          ((left ) (cons (- offset) 0))
          ((right) (cons (+ offset) 0))
          ((down ) (cons 0 (- offset)))
          ((up   ) (cons 0 (+ offset)))
          (else #f))
        (page-selection (active-page))))
    ))
 
; Define actions
(define (&move-selection-left ) (move-selection 'left ))
(define (&move-selection-right) (move-selection 'right))
(define (&move-selection-down ) (move-selection 'down ))
(define (&move-selection-up   ) (move-selection 'up   ))
 
; Define shortcuts
(global-set-key "Left"  '&move-selection-left)
(global-set-key "Right" '&move-selection-right)
(global-set-key "Up"    '&move-selection-up)
(global-set-key "Down"  '&move-selection-down)
geda/guile_scripting.txt · Last modified: 2016/02/09 11:56 by vzh
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki