Scriptfu not executing in the correct order, Why? - lisp

I'm trying to write a basic script for GIMP but it doesn't seem to want to work right. It should follow this order after I make my selection: Lower active layer, expand selection 2px, floodfill w/ foreground color, raise active layer. The final product should be a solid color beneath my lines on the top layer. But with the code i wrote, it jumps active layers, but floodfills on the top layer and not the one below. Here is the code I have:
(define (quick-fill image drawable)
(gimp-undo-push-group-start image)
(let* ((layer (car (gimp-image-get-active-layer image))))
(gimp-selection-grow image 2)
(gimp-image-set-active-layer image (aref (cadr (gimp-image-get-layers image)) 1))
(gimp-bucket-fill drawable FG-BUCKET-FILL NORMAL-MODE 100 0 FALSE 0 0)
(gimp-image-set-active-layer image (aref (cadr (gimp-image-get-layers image)) 0)))
(gimp-undo-push-group-end image)
(gimp-displays-flush))

If you're trying to make a filter that makes a 2-pixel border around an object on the current layer by making a fill behind it on the layer below (at least that's what it appears you're trying to-do), try this:
(define (quick-fill image)
(gimp-undo-push-group-start image)
(gimp-selection-grow image 2)
(gimp-image-set-active-layer image (aref (cadr (gimp-image-get-layers image)) 1))
(let* ((active-drawable (car (gimp-image-get-active-drawable image))))
(gimp-bucket-fill active-drawable FG-BUCKET-FILL NORMAL-MODE 100 0 FALSE 0 0)
(gimp-image-set-active-layer image (aref (cadr (gimp-image-get-layers image)) 0)))
(gimp-undo-push-group-end image)
(gimp-displays-flush))
A couple notes:
1) You never use the layer variable in your let* section, so I've removed it.
2) Gimp doesn't draw or fill or do anything with the active layer ... rather it works on the active drawable. If you're getting a fill on the top layer when you want it on the layer below, then that means you're passing in the drawable for the top layer, so it's going to fill on the top layer ... switching the active layer to the layer below doesn't change the value of the passed-in drawable. So in this modification, I've created a new active-drawable variable in the let* section that gets initialized to the currently active drawable after you've changed the active layer from the top-layer to the layer underneath. That way you're filling the drawable that is the layer below, not the original passed-in drawable that is the top-layer. In fact, you don't need to pass-in a drawable argument at all, since you can get the new drawable from the active layer (which is what's done in this modification).

Related

Why is racket passing #<void> to my function instead of the state?

I'm learning Racket, and using the book Realm Of Racket. I reached the point where they show you how to animate an image moving down the window, and then suggest you try modifying it to react to a left or right-arrow key press to move the image sideways.
Seemed simple enough...
#lang racket
(require 2htdp/universe 2htdp/image)
(define WIDTH 500)
(define DX 0)
(define HEIGHT 500)
(define IMAGE .) ; The image doesn't show up here
(define (add3-to-state current-state)
(+ current-state 3))
(define (draw-image current-state)
(place-image IMAGE (+ DX (/ WIDTH 2)) current-state (empty-scene WIDTH HEIGHT)))
(define (state-is-500 current-state)
(>= current-state 459))
(define (set-delta current-state key)
(set! DX (+ DX 10)))
(big-bang 0
(on-tick add3-to-state)
(on-key set-delta)
(to-draw draw-image)
(stop-when state-is-500)
)
When I run this, the image moves downwards as before, but as soon as I hit a key, I get an error...
>=: contract violation
expected: real?
given: #<void>
...in the state-is-500 function.
Anyone able to explain why this is happening? As far as I can see, my function for on-key has the same form as the ones they show in the book.
I tried modifying the state-is-500 function to look like this...
(define (state-is-500 current-state)
(printf "~a\n" current-state)
(>= current-state 459))
...and the output I got was...
102
105
#<void>
...before the error happened.
So it looks like #<void> is being passed to the function, but why?
Thanks
The issue is that big-bang expects the function call on-key to return the new state of the game. You are not retuning anything thus the frameworks reports <void>
Thus if the state does not change the you should just return the input state e.g.
(define (set-delta current-state key)
current-state)
Also this framework and Racket itself makes you want to not mutate variables, that is you don't assign to them, or at least you assign to them only once. Thus set! is not something you should use often.
In this case the state of the app that the book provides is just the vertical distance so is just a single number as shown in add3-to-state. The original state is passed in as the first parameter to big-bang.
The change you have to make is that the current state is not just the up-down movement but also the side to side. This movement shows up as the second parameter to place-image. So you have to have a state that can provide the second and third parameters to that.

How to make inline images responsive in org-mode?

When I toggle inline image using org-toggle-inline-images which shows the image(s). However, when the image it too large it will overflow the editor's frame (See screenshot below).
How to make the image responsive which means the max size of the image should never exceed the width of window size.
Of course, I can use the code below to fix the size of the image. But what I truly want is some kind of responsive image displaying.
(setq org-mode-actual-width 600)
Thanks for your time viewing this question.
From the documentation of org-image-actual-width:
Documentation:
Should we use the actual width of images when inlining them?
When set to t, always use the image width.
When set to a number, use imagemagick (when available) to set
the image's width to this value.
When set to a number in a list, try to get the width from any
#+ATTR.* keyword if it matches a width specification like
#+ATTR_HTML: :width 300px
and fall back on that number if none is found.
When set to nil, try to get the width from an #+ATTR.* keyword
and fall back on the original width if none is found.
So you could use the attribute #+ATTR_HTML to specify the width. It has to be specified manually though. Is this responsive enough?
The function below re-renders the org-mode inline images whenever the window is resized by using hooks. It shrinks the image only when the window is displaying less than 80 columns (usually 1/3 of the screen). I believe it works better than always rendering in window width.
(defun org-image-resize (frame)
(when (derived-mode-p 'org-mode)
(if (< (window-total-width) 80)
(setq org-image-actual-width (window-pixel-width))
(setq org-image-actual-width (* 80 (window-font-width))))
(org-redisplay-inline-images)))
(add-hook 'window-size-change-functions 'org-image-resize)
GIF Demo of the code above
If you want the image just matching the size of your window width:
(defun org-image-resize (frame)
(when (derived-mode-p 'org-mode)
(setq org-image-actual-width (window-pixel-width))
(org-redisplay-inline-images)))
(add-hook 'window-size-change-functions 'org-image-resize)
Or change the (window-pixel-width) into (- (window-pixel-width) 20) if you want some margin on the right side.

Setting Both `fullheight` and `width` in Emacs on OS X

I find the default size of the Emacs frame a little too small. From reading around I know that I can set the height and width quite easily with something like the following:
;;; 140 x 60 window size
(setq default-frame-alist '((width . 140) (height . 60)))
Which works great on my external monitor, however it is a litte too big for the laptop display. I can solve the height problem by changing to the follwing:
;;; automatically set the height
(setq default-frame-alist '((fullscreen . fullheight)))
Which sets the frame to be as tall as possible for the current screen. I can't however set the width of the frame if I use this method. Adding (width . 140) to the above alist sets the width to the right value but also sets the height to the default height again.
When I see the frame appear it sets itself to the full height, and then sets the width to the value I requested, and shrinks in height.
I can overcome this problem with the following code:
;;; Full height for the default window
(setq default-frame-alist
'((fullscreen . fullheight)))
;; Set the width in a hook and have all windows inherit
(setq frame-inherited-parameters
'(width height))
(add-hook 'after-init-hook
(lambda ()
(set-frame-parameter nil 'width 140)))
Which uses a hook to set the width of the first frame to the value I want, and then sets all other windows to inherit this value.
This isn't very elegant however, so the question is "how can I accomplish this in a simpler (or less hackish) way?".
If you want to see my exact init.el script, take a look at this gist
TL;DR
How can I set both the width of a frame, and set the frame to be as tall as possible on the current monitor, on OS X? It seems you can't specify (width . 140) and (fullscreen . fullheight) in the default-frame-alist.
I have come up with a solution to this. I explicitly calculate the height of the window rather than relying on (fullscreen . fullheight) to do it for me.
The updated code to set the values for the height and width is quite simple:
;;; Nice size for the default window
(defun get-default-height ()
(/ (- (display-pixel-height) 120)
(frame-char-height)))
(add-to-list 'default-frame-alist '(width . 140))
(add-to-list 'default-frame-alist (cons 'height (get-default-height)))
In this code the subtraction of 120 from the height of the screen makes sure that the height of the window takes into account the height of the dock and the menubar. For correct results you will have to make sure that this code is executed after you have chosen the font face to use, otherwise the computed height value will not be valid.
Placing the height calculation in its own function should allow special casing certain operating systems and versions. This method also has the added advantage that is faster to open the window as it doesn't "animate" the height to the full height value.
The last paragraph of the help text for display-pixel-height is:
For graphical terminals, note that on "multi-monitor" setups this
refers to the pixel height for all physical monitors associated
with DISPLAY. To get information for each physical monitor, use
‘display-monitor-attributes-list’.
What got me to this page is what looks like a bug in the X11 implementation but I'm not sure yet. In any case, display-pixel-height works only often but not always.
Sample output from display-monitor-attributes-list is:
(
(
(geometry 0 0 1920 1080)
(workarea 0 25 1920 1055)
(mm-size 478 268)
(frames #<frame *scratch* 0x14489a030>)
(source . "NS")
)
(
(geometry 192 1080 1512 982)
(workarea 192 1080 1512 950)
(mm-size 301 195)
(frames)
(source . "NS")
)
)
In my case, I have a laptop (bottom entry) and a monitor connected to it (the top entry).
One possible solution would be to go through the list, find the monitor with the largest height and do the computations based upon that height and then at the end also do something like (set-frame-position nil 192 1080) where the two coordinates come from the top and left coordinates (the first two values of geometry and work area of the monitor that has the greatest height.
It appears that the workarea is the more prudent set of values to use.
And to further make a robust solution, a hook should be added to window-configuration-change-hook so that when a monitor is added or removed, things will get updated.
I am currently asking some questions on the Emacs developers mailing list and working on a solution for myself. I plan to return and update this entry when I have a solution that I'm happy with but thought this information may be of use to others as is.
Update:
There is no bug. x-display-pixel-height has various X11 rude facts of life. For more details, see this reply.
The "Frame Layout" node in the info documentation for ELisp as a description of the Inner and Outer Frame along with many other concepts that are pertinent to this question.
Here is my current solution. I have not done the hook yet. I don't claim to know how to program in lisp but this code is working for me.
(defun workarea-height ( monitor )
"MONITOR is an entry from `display-monitor-attributes-list' The
height entry (4th value) of the 'workarea' is returned"
(nth 4 (assoc 'workarea monitor)))
(defun monitor-with-largest-height-helper ( a b )
"Compares the height of the workarea of two monitor entries such as
those contained in the output of `display-monitor-attributes-list'"
(let* ((a-height (workarea-height a))
(b-height (workarea-height b)))
(if (> a-height b-height)
a
b)))
(defun monitor-with-largest-height ()
"Returns the monitor entry from `display-monitor-attributes-list'
with the largest 'workarea' height"
(cl-reduce #'monitor-with-largest-height-helper
(display-monitor-attributes-list)))
(defun largest-monitor-height ()
"Returns the usable height in lines of the largest monitor currently
attached"
(let* ((largest-monitor (monitor-with-largest-height)))
(/ (- (workarea-height largest-monitor)
(- (frame-outer-height)
(frame-inner-height)))
(frame-char-height))))
(defun my-resize-frame-height ()
"Resizes the current frame to the full height of the largest monitor
currently attached."
(interactive)
(set-frame-height nil (largest-monitor-height)))
The other work left to do is to make sure the left and top of the frame are within the area of the largest monitor to the frame will be displayed on that monitor.

How to recenter an Emacs buffer around an overlay

I want to recenter an Emacs buffer so as to show as much as possible of an overlay and of its context around it. Specifically, I want this behavior:
If the overlay fits in the visible window, I want to show as much as line before it as lines after it;
Otherwise, I want the beginning of the overlay to be shown.
This behavior is somewhat similar to what I see when using different regions highlighted in ediff.
Is there a not-so-complicated way to achieve this? I tried to look into the ediff code (specifically ediff-util.el) but things seems very complicated to me.
I'm not quite sure what usage you're looking for, but this code should do what you want.
It can be called with an overlay, or if called interactively, will choose one of the overlays at the current position and do the action on it.
(defun make-overlay-visible (overlay)
"given an overlay, center it on the window
(or make beginning visible if it cannot fit in the window)"
(interactive (list (car (overlays-at (point)))))
(when overlay
(goto-char (overlay-start overlay))
(recenter 0)
(when (and (pos-visible-in-window-p (overlay-start overlay))
(pos-visible-in-window-p (overlay-end overlay)))
(goto-char (/ (+ (overlay-start overlay) (overlay-end overlay)) 2))
(recenter))))

How to resize a buffer so it only takes a small part of the screen?

In Emacs how can I resize a buffer so it only takes a small part of the screen ?
Is there any way ?
I would like to have the src taking 70% of the screen and a file manager in the other 30%
Set width of current window on current frame to ~ 70%:
(window-resize nil (- (truncate (* 0.7 (frame-width))) (window-width)) t)
The other windows are shrunk automatically. If you want to adjust more than one it gets more difficult.
As command:
(defun window-resize-to-70-percent ()
(interactive)
(window-resize nil (- (truncate (* 0.7 (frame-width))) (window-width)) t))
Use separate window-manager frames for individual buffers (by default). Automatically shrink-fit the frames to fit the buffer content.
See One-On-One Emacs, in particular, libraries fit-frame.el and autofit-frame.el.