Search code examples
schemelispgimpscript-fu

lisp iterate through list


I just started GIMP script-fu scripting yesterday for a script I need but I have no idea how automate the adding of the layers in the local variables and calling the function for adding the layers to the image. I tried iterating over lists but failed gracefully. Can someone push me in the right direction?

(define (script-fu-gifslot inText inFont inFontSize inTextColor)
    (let*
        ((theImageWidth  700) ; define our local variables
         (theImageHeight 100) ; create a new image:
         (theImage)
         (layerX)
         (inOffset)
         (theImage (car (gimp-image-new theImageWidth theImageHeight RGB)))
         (theText)             ;a declaration for the text

         (theLayer (car (gimp-layer-new theImage theImageWidth theImageHeight RGB-IMAGE "layer 1" 100 NORMAL)))
         (theLayer2 (car (gimp-layer-new theImage theImageWidth theImageHeight RGB-IMAGE "layer 2" 100 NORMAL)))
         (theLayer3 (car (gimp-layer-new theImage theImageWidth theImageHeight RGB-IMAGE "layer 3" 100 NORMAL)))
         (theLayer4 (car (gimp-layer-new theImage theImageWidth theImageHeight RGB-IMAGE "layer 4" 100 NORMAL))))

      (define (yannis-add-new-layer layerX inOffset)
          (gimp-image-add-layer theImage layerX 0)
        (gimp-context-set-background '(255 255 255))
        (gimp-context-set-foreground inTextColor)
        (gimp-drawable-fill layerX BACKGROUND-FILL)

        (set! theText (car (gimp-text-fontname theImage layerX 0 0 inText 0 TRUE inFontSize PIXELS "Sans")))
        (set! theImageHeight  (car (gimp-drawable-height theText)))

        (gimp-layer-resize layerX theImageWidth theImageHeight 0 0)
        (gimp-layer-set-offsets theText 0 (- 0 inOffset)))
      (yannis-add-new-layer theLayer 0)
      (yannis-add-new-layer theLayer2 10)
      (yannis-add-new-layer theLayer3 20)
      (yannis-add-new-layer theLayer4 30)
      (gimp-display-new theImage)
      (list theImage layerX theText)))

(script-fu-register 
 "script-fu-gifslot"
 "_GGGIF WORD Slotmachine..."
 "Creates an image with a user specified text string."
 "Yannis De Cleene <yannisdcl@gmail.com>"
 "Yannis De Cleene"
 "July, 2014"
 ""
 SF-TEXT       "Text"                "PASTE\nMULTILINE TEXT\nIN HERE"
 SF-FONT       "Font"                "Sans"
 SF-ADJUSTMENT "Font size (pixels)"  '(100 2 1000 1 10 0 1)
 SF-COLOR      "Color"               '(0 0 0))

(script-fu-menu-register "script-fu-gifslot" "<Image>/File/Create")

Solution

  • Use either map or for-each or do.

    If you want to add 1 to a list you could use (map 1+ '(1 2 3)). Or if you want to define the function on the fly, use lambda: (map (lambda (x) (+ 1 x)) '(1 2 3))

    If you want a more imperative style use do. You can read about it here.

    You can search for functions (and other bound symbols) using the function apropos. e.j. (apropos "for") (Apparently not in gimp to my surpise)

    However I sense your problem is larger than just iterate over a list. For example does it make sense to define the function over the let? why are you not explicitly passing the image to the add-new-layer-function?

    To make your code more readable I would drop the 'the', use '-' instead of camelCase and don't leave one parentesis in each line. it hurts readability. I can see however it is not your fault as that style is used in the gimp's tutorial. e.j. theImage becomes image and TheLayer1 becomes layer-1.

    If you want to learn more about scheme you should download racket and read how to design programs which is a good introduction to programming.