Fun with Minimum Profit 5.x programming: a print dialog

From: Angel Ortega <angel_triptico.com>
Date: Sun, 8 Oct 2006 21:49:08 +0200
Minimum Profit 5.x lacks a print command, but it's easy to create one by
using its powerful scripting language (MPSL) and some external commands
used as pipes. The following example will create a dialog that will ask for
some printing options and print the current document, optionally with
preview. The external programs `paps', `psnup', `psselect' and `gv' must be
installed and accesible with the current path.

Copy this subroutine in an empty document and execute the menu option
"Edit / Execute document as MPSL". Hopefully, the script will compile
without errors and the new function my_print() will be created inside MP's
machine:

    sub my_print(doc) {
    
    	local r = mp.drv.form( [
    		{
    			'label'		=> 'Page range (empty: all):',
    			'type'		=> 'text'
    		},
    		{
    			'label'		=> 'Pages per page:',
    			'type'		=> 'text',
    			'value'		=> 1
    		},
    		{
    			'label'		=> 'Preview?',
    			'type'		=> 'checkbox'
    		}
    	]);
    
    	if(r != NULL)
    	{
    		local cmd = [];	/* empty array */
    		local f;
    
    		/* first program is the text to PostScript converter */
    		push(cmd, 'paps');
    
    		/* select range using psselect, if available */
    		if(r[0] != '')
    			push(cmd, 'psselect -p' ~ r[0]);
    
    		/* select pages-in-page using psnup */
    		if(r[1] > 1)
    			push(cmd, 'psnup -' ~ r[1]);
    
    		/* preview using gv? */
    		if(r[2])
    			push(cmd, 'gv -');
    		else
    			push(cmd, 'lpr');
    
    		local c = join('|', cmd);
    
    		/* now pipe */
    		if((f = popen(c, "w")) != NULL)
    		{
    			foreach(local l, doc.txt.lines)
    				write(f, l ~ "\n");
    
    			if(pclose(f) != 0)
    				f = NULL;
    		}
    
    		if(f == NULL)
    			mp.alert("Error '" ~ ERRNO ~ "' piping to '" ~ c ~ "'");
    	}
    }

The code should be self-explaining (I hope): a call to mp.drv.form()
creates a dialog box asking for the following printing options: a page
range suitable for the `psselect' utility, a number of n-up pages for
`psnup' (it's cool to avoid wasting paper by printing two pages into one)
and a preview checkbox. If the dialog box is validated, the return values
are used to construct an array of commands to pipe to. They are finally
joined into one string using the '|' separator to build a command that
will be used as a writable pipe.

To test the new code, hit the Escape key (twice if using the Curses
interface) and type the following:

    my_print(mp.active());

This is fine, but it would be much better if this new operation would be
accesible from a hotkey or a menu option.

In any of those two cases, an editor 'action' must be created. Actions are
special functions that live in the `mp.actions' name space, and accept a
document as the only argument. Optionally, actions have a description,
a human-readable string:

    mp.actions.my_print = sub(d) { my_print(d); };
    mp.actdesc.my_print = "Print...";

This is just one way of creating it, by using an anonymous subroutine;
another way would be:

    sub mp.actions.my_print(d) { my_print(d); }

or even

    mp.actions.my_print = my_print;

Because the my_print() and the action itself use the same number of
arguments.

If you want to bind this action to ctrl-p, it's also easy:

    mp.keycodes['ctrl-p'] = 'my_print';

Execute that and, from now on, every hit to `ctrl-p' will invoke my_print()
on the current document.

To add it to the menu, the mp.menu array must be patched. This is less
straightforward because the menu structure is a bit more complicated: it's
an array of two-element arrays, where the zeroth element is the menu bar
("File", "Edit", and so on) and the first one is itself another array, this
time of action names.

We want for our print option to live in the first menu bar ("File"), just
above the last option, which is "Exit". The ins() MPSL library function
inserts an element in a given position of an array, with negative
subscripts starting from the end, so the following code will do:

    ins(mp.menu[0][1], '-', -2);
    ins(mp.menu[0][1], 'my_print', -2);

The '-' special option creates a menu separator.

The menu is not automatically rebuilt, so a call to the mp.update_ui()
function is also needed:

    mp.update_ui();

Take note that on current version (4.99.12) the GTK version doesn't
rebuild its menu when calling mp.update_ui() (it's bug #1150).

This examples show the easy expandability of the new MP 5.x version.

I'm sure all this is fascinating, but everything will be lost on exit; the
way to make this changes permanent is to add all that code to the personal
configuration file, which is nothing more than an MPSL source code file
that is compiled and parsed on startup. It's called .mp.mpsl, on Unix/Linux
systems live in $HOME and on Win32 in the "My Documents" folder. The "File
/ Edit configuration file" menu option gives easy access to it.

-- 
Angel Ortega
http://www.triptico.com



-- 
To unsubscribe, send mail to mp-unsubscribe_lists.triptico.com.


Received on Sun Oct 08 2006 - 21:49:42 CEST

This archive was generated by hypermail 2.2.0 : Thu Apr 10 2008 - 08:59:26 CEST