On Tue, Feb 07, 2012 at 03:41:22PM -0500, Chris Siebenmann wrote: > I feel like I'm missing some important bits about how fvwm handles > functions. > > I'm trying to write a function that's fed a window name and has > following goals. First, it only operates on terminal windows. > Then: > - if no (terminal) window by that name exists, it should do nothing. > - if the currently selected/focused window has that name (and is a terminal > window), it should do nothing. > - otherwise, it should deiconify, focus, and raise the window, then > move the pointer to be inside the window. > > My current version is: > > AddToFunc ToWindow > + I Current ("XTerm|9term|Gnome-terminal", "$0") Break > + I Next ("XTerm|9term|Gnome-terminal", "$0") Iconify False > + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus > + I Next ("XTerm|9term|Gnome-terminal", "$0") Raise > + I Next ("XTerm|9term|Gnome-terminal", "$0") WarpToWindow 80 5
This is why it's better to do this: Style XTerm State 1 Style 9term State 1 Style Gnome-terminal State 1 DestroyFunc ToWindow AddToFunc ToWindow + I Current (State 1, $0) Break + I Next (State 1, $0) SomeFunction DestroyFunc SomeFunction AddToFunc SomeFunction + I Iconify False + I Focus + I Raise + I WarpToWindow 80 5 So you can see here, by using State, that we've shifted the repetitiveness to the style of the window, and not a pre-condition to all commands we might need to reference a bunch of terminals. > This works but seems unnecessarily repetitive (actually I'm suddenly > not convinced that it does nothing if the current window is a terminal > window called $0). So I thought I could rewrite it like this (with > comments about the logic): > > AddToFunc ToWindow > # do nothing if current window is called $0 > + I Current ("XTerm|9term|Gnome-terminal", "$0") Break > + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus > # if no window is called $0, this stops; otherwise Focus has > # made that window the current window. > + I TestRc (NoMatch) Break > # do the rest of the work > + I Iconify False > + I Raise > + I WarpToWindow 80 5 > > However, this doesn't work if no such window actually exists; before > anything from the function seems to execute (even an 'Echo' statement Context is about how functions run, and the way you have it there, FVWM will need a window context to run in -- that is, a window to operate on. Your use of "$0" implies this to some extent, in that you have a name or something being passed in, but you don't say how. If FVWM doesn't have an operand window, then it will ask for one. This will depend on how you're trying to call this function. This is perhaps the most important piece of information you've failed to provide. > Do I need to make all commands conditional in this function in order > to have things work right, by putting plain 'Current ' in front of the > last three lines? (A version with this change seems to do nothing if > there's no terminal window by that name, but I feel I'm just sort of > writing code by superstition instead of actual understanding at this > point.) No you don't. Consider this: AddToFunc ToWindow + I Current ("XTerm|9term|Gnome-terminal", "$0") Break + I Next ("XTerm|9term|Gnome-terminal", "$0") Focus + I TestRc (NoMatch) Break + I Iconify False + I Raise + I WarpToWindow 80 5 If I bind this to a key like this: Key f A M ToWindow Then press Alt-f, FVWM evaluates the context of the binding. It may well be that the window we're operating on is implied, in which case FVWM won't ask for a window -- and indeed, your implementation of ToWindow doesn't. FVWM processes the commands in order, top-to-bottom. It comes across "Current" and evaluates that in the context of the binding. Of course, there is nothing special about Current, Next, or TestRc, they can run inside a function just fine, and at this point assume no specific window -- but because you have this: + I Iconify False ... if FVWM processes this from your ToWindow function and there is no implied operand window for ToWindow to be running in, it will prompt for a window to run against, because it needs a window. Let me elaborate more on what I mean by operand window, and implied context. Mouse bindings are good for this: Mouse 0 1 A FuncWindowOpsOrClose DestroyFunc FuncWindowOpsOrClose AddToFunc FuncWindowOpsOrClose + H Nop + C Echo Clicked $[w.id] + D Close Pressing any mouse button on button 1 on a window will call FuncWindowOpsOrClose -- and note that here: + D Close I do not need: + D ThisWindow Close Nor do I need: + D Current Close It's because the binding happens on a window already. Once you have a window you're hooked on it though. So really, establishing a binding to one window can happen outside the function before invoking it, and that's precisely what I did with my original suggestion to you above: DestroyFunc ToWindow AddToFunc ToWindow + I Current (State 1, $0) Break + I Next (State 1, $0) SomeFunction DestroyFunc SomeFunction AddToFunc SomeFunction + I Iconify False + I Focus + I Raise + I WarpToWindow 80 5 So can you not see now, why in SomeFunction I do not need to prefix the commands with Current, because they're all called in the matched window from ToWindow, coming from the Next command? There are other ways of achieving this though. 'Pick' is another useful command which would have helped you as well, but I shied away from mentioning it above to help illustrate what was going on. But: Pick ToWindow Would work just as well with how you've written things. -- Thomas Adam -- "Deep in my heart I wish I was wrong. But deep in my heart I know I am not." -- Morrissey ("Girl Least Likely To" -- off of Viva Hate.)