Custom interactive codes for interactive elisp function - elisp

I'm reading the interactive codes section of the manual, and I'd really like to have something similar to D (default is the current default directory of the current buffer), but that uses the current buffer's file extension (if any).
Since there is no such default interactive code, I was wondering if there is a way to register new interactive codes.

You cannot add a new interactive code.
You would have to pass a form which evaluates to a list:
(interactive (list (read-directory-name "Enter directory" ...)))

Related

Is it possible to add elements to a list, and have the list save these values even after closing an Emacs session?

I have a variable called my-projects that points to a list of strings of my current projects (e.g., "chores", "lectures", etc.). Whenever I call a function, say (completing-read ...), and I happen to create a new project on the fly, I would like to have a function that adds this new project to the list of projects forever. What I can't figure out is how to "save" the updated list my-projects so that it keeps the newly added values even after the end of the current Emacs session. I can only come up with convoluted solutions involving replacing strings in the file where the variable my-projects is defined, but I surmise that there must be a more efficient way to do this.
You could start by developing a function that saves your data structure to a file.
(defvar my-projects
'("chores"
"lectures"))
(defun my-save-my-projects ()
"Saves my projects in my home folder."
(interactive)
(with-temp-buffer
(insert (prin1-to-string my-projects))
(write-region (point-min)
(point-max)
"~/.my-projects.eld")))
Next you may want to find a suitable event that you can hook your saving function onto. For example, you could save your project list whenever Emacs closes down:
(when (not (memq 'my-save-my-projects kill-emacs-hook))
(add-hook 'kill-emacs-hook
'my-save-my-projects)))
There may be better hooks for your use-case.
Ultimately, you will want to repopulate your variable by reading in that file when Emacs starts. I'll leave that out here (or as an "exercise to the reader" ;-). There's plenty of examples out there.
You could use defcustom to create a user-customizable variable. Emacs already has built-in ways to persist the value of customized variables. Use customize-var to interactively update its value when you start a new project.

How to debug script-fu scripts for gimp in scheme?

I try to make some script for gimp, using script-fu, scheme.
Naturally, as a beginner, there are lots of errors and misunderstandings.
Now I'm looking for a way to debug those scripts.
I found (gimp-message), but the result does not show up. I'm not aware if there is a possibility to print debug messages to anywhere I could check them.
Generating new images filled with text would probably work ;-) but looks a bit like an overkill.
What ways to debug a script in gimp are there?
There may be a better way, but, the way I do it is to:
open the script fu console (Filters -> Script Fu -> Console)
edit a file (say for example: /Users/jamesanderson/code/scheme/gimp/learn1.scm
type: (load "/Users/jamesanderson/code/scheme/gimp/learn1.scm") into the console
hit enter
edit file for changes
keyboard arrow up (to get get the load function call again without typing)
hit enter
Note this is an extension of my answer based on the comment. When going beyond the simple proof of concept scripts like the above, its important to know that that console retains state between calls. So for instance, if we run this scheme script:
(define jea-test-img-id nil)
(define (jea-find-test-img)
(car (gimp-image-list)))
and then go to the console and type:
jea-test-img-id
we get as a result:
> jea-test-img-id
()
which is good, the script initiated the variable as needed and we see the result. So var set in script, console retains state change from script. Now lets change the state in the console:
(set! jea-test-img-id (jea-find-test-img))
we call a convenience function that grabs the first image ID in the active image list and store it in the variable we previously declared (which was then nil). Now lets examine the question again:
jea-test-img-id
then the result:
> jea-test-img-id
1
so high level: when you are working on a script, create working variables that hold the things you want to work on, like image, pxiels, widths etc then piece by piece get the functions working. In the end you may collapse it into one clean function once you have the short snippet pieces.
The output of gimp-message goes to the "Error console" (if you have this dockable dialog setup), otherwise in a warning dialog.
If you are in Linux or OSX, you can also start Gimp from a terminal and use (print ...) calls, they will show in the terminal.
You can make your life easier and write your scripts in Python (easier to learn, and more powerful...). See here for the doc, here for some examples, and here for some debug tricks for Windows.
If you run gimp from the command line with the -c flag, messages are printed in the terminal:
$ gimp -c myfile.xcf
# run my plugin from the GUI menu
My Plugin-Warning: this is a message
Tested with GIMP v2.10.18 see gimp --help for more command line options.

Providing a meaningful default directory name in GIMP Scheme (script-Fu)

I'm a total newbie to Scheme (about 1 week).
I'm registering a script for which the second parameter is an output directory name - via SF-DIRNAME. How do I supply a meaningful default to the front-end widget that does not use host platform-specific names? Ideally, I'd like it to be '/Users/[username]' - or if possible - the Scheme equivalent of ${PWD}. As an illustration, when you create a new image and hit 'Save' for the first time, the default directory there is '/Users/[username]/Documents' - so it must be possible. How does the widget know what your user home directory is? How can this be referred to in the default field of the registration statement? Finally, it would be really nice if Gimp could 'remember' which output directory was selected last time (within the scope of the lifetime of the Gimp instance) and offer that up as the default on the second and subsequent invocations of the script. I've scoured hundreds of other people's scripts, the Gimp community pages and the Scheme documentation and I've found, literally, nothing on this requirement. Thanks in advance. VV
Gimp uses the GTKFileChooser widget, and there is nothing you can do in your script to make it different from the other instances of GTKFileChooser used in Gimp.
But what you supply as a default name can be a variable, it doesn't need to be a static string, and it can be set by any means available in to your Scheme interpreter at the time of registration (looking for the HOME environment variable, for instance).
Btw, if you are new to this, write your scripts in Python, it is both easier and more powerful.

Save colored emacs text from shell

I am attempting to save a few hundred short files (~100 lines ea.) as a Post Script (or pdf) file using the colors as emacs renders them. So I am writing a bash script that opens them in emacs and saves them as a .ps file.
My best attempt so far is to iteratively use the following command:
emacs --file $(filename).m --no-desktop --eval '(ps-print-buffer-with-faces)' --eval '(kill-emacs)'
However, this directly sends it to the default printer. I'd like to save it as $(filename)_PS.ps. Within the emacs gui, I can do
C-u M-x ps-print-buffer-with-faces
and it brings up the file save prompt. However doing this by hand is cumbersome. How might this be done with a shell script?
The easy answer is to just provide the code, but then I'm the one learning and
your still having to ask each time you need help with Emacs! Much more fun for
me to try and point you in the right direction - probably less fun for you
initially, but if I get it right, you won't need to ask as many questions in the
future and then have to wait for another opinionated answer like this one :)
The most important skill to learn with Emacs is how to use the built-in help
facility. The second most important is to learn some basic Emacs lisp by reading
the Emacs Lisp Reference (bundled with Emacs). The third is learning to scratch
your own itch.
You have the basic function, so we can start there. C-h f
ps-print-buffer-with-faces tells us....
ps-print-buffer-with-faces is an interactive autoloaded Lisp function
in ‘ps-print.el’.
It is bound to .
(ps-print-buffer-with-faces &optional FILENAME)
Generate and print a PostScript image of the buffer. Like
‘ps-print-buffer’, but includes font, color, and underline information
in the generated image. This command works only if you are using a
window system, so it has a way to determine color values.
OK, but at first glance, there doesn't seem to be much useful info
there. However, there is a link to ps-print-buffer which is clickable. Clicking
on it we get...
ps-print-buffer is an interactive autoloaded Lisp function in
‘ps-print.el’.
It is bound to .
(ps-print-buffer &optional FILENAME)
Generate and print a PostScript image of the buffer.
Interactively, when you use a prefix argument (C-u), the command
prompts the user for a file name, and saves the PostScript image in
that file instead of sending it to the printer.
Noninteractively, the argument FILENAME is treated as follows: if it
is nil, send the image to the printer. If FILENAME is a string, save
the PostScript image in a file with that name.
This gives us a bit more, including important details on how calling it
non-interactively, the argument is the name of the file to write the output
to. This seems promising as we don't want to be forced to call this
interactively using C-u for every one of the many files we want to print.
If we could define a new command which would take care of this, we could just
use M-x - even better, we could bind it to a key and then we only need to use
that shortcut.
Looking in the Emacs Lisp Reference (also bundled with Emacs), we see the menu
option Command Loop. Looking in that node, we see a menu option for Defining
Commands. This looks promising. After reading that node and following some links
in that node about defining functions etc, we get a basic starting point of ...
(defun buffer-to-ps ()
(interactive)
;; do something
)
We put that in the scratch buffer and evaluate it. Not terribly exciting. Lets
add some documentation so we can remember what this is for ...
(defun buffer-to-ps ()
"Write the current buffer to a PS file"
(interactive)
;; do something
)
Now we can do C-h f buffer-to-ps and we will see our documentation. Still, not
doing a lot. We need to call our function and provide it with a file name
argument. We try ...
(defun buffer-to-ps ()
"Write the current buffer to a PS file"
(interactive)
(ps-print-buffer-with-faces "test.ps"))
With the cursor at the end of the definition, while in the scratch buffer, we do
C-x C-e to evaluate our definition. We try running our new command while in the
scratch buffer, we do M-x buffer-to-ps and we see a message in the echo area
which says a file call test.ps has been written. Opening that file with a viewer
and we see the file has been created and it has the colours etc. However, we
don't want all the files to be called test.ps, so now we need to find a way to
generate a unique name to use as the file name argument. There are a few ways we
could do this, but the first obvious one is to somehow try and use the name of
the buffer. We use C-h a and enter "buffer name", which gives a few hits. Going
through the list, we see buffer-name. Doing C-h f buffer-name gives us
buffer-name is a built-in function in ‘C source code’.
(buffer-name &optional BUFFER)
Return the name of BUFFER, as a string. BUFFER defaults to the current
buffer. Return nil if BUFFER has been killed.
Looks promising, so let's give it a go. ...
(defun buffer-to-ps ()
"Write the current buffer to a PS file"
(interactive)
(ps-print-buffer-with-faces (buffer-name)))
Evaluating the definition and running it with M-x results in a new file being
created called scratch. Looking at it with a ps viewer and we see it is our
buffer contents with colour etc. So we have done it!
But wait, we have a problem Huston! If we run this with a buffer which contains
contents from a file, the buffer name will be the same as the file name and when
we run our command, it will overwrite our file - probably not what we want.
We probably want the output file to be similar to the corresponding script, but
we also probably want it to reflect that it is a postscript rendering of that
script. There are a few things we can try, but being lazy, we will go for the
easiest first. What about if we just generate a file name which has ".ps"
appended to it. This will also mean we have a file name with an extension which
is a better fit with file name conventions. How do we concatenate a ".ps" to the
file name string returned by buffer-name? C-h a concat and we get
concat is a built-in function in ‘C source code’.
(concat &rest SEQUENCES)
Concatenate all the arguments and make the result a string. The result
is a string whose elements are the elements of all the arguments. Each
argument may be a string or a list or vector of characters (integers).
So we update our function to be ...
(defun buffer-to-ps ()
"Write the current buffer to a PS file"
(interactive)
(ps-print-buffer-with-faces (concat (buffer-name) ".ps")))
We use M-x to try it out and end up with the file scratch.ps.
So we now have the basic functionality. We could bind this command to a key
sequence so that when we are in a buffer, we just hit the key sequence and emacs
will generate a file with the extension .ps based on the current buffer name and
which contains a postscript rendering of the buffer contents with the
corresponding face colours.
What next? Well, using this function requires that we first open the file in a
buffer and then call the function (possibly just by hitting a key). We could do
it on the command line as your earlier version shows, but starting emacs each
time just to do this is woefully inefficient. What would be a better approach?
One thing to try would be to define a function which lists all the files in a
directory with a particular file name pattern i.e. all script files and for each
of them, load them into a buffer and then call the function you have just
defined. This is left as an exercise for the reader! Post an update to this
question or create a new one and perhaps someone will provide some more help :)

Debugging a Scheme program

I am using Festival, a text-to-speech synthesizer, for a project. It has a Scheme scripting language. I'm very new to scheme and hope someone can help. I just want to see the current configuration parameters of Festival. I have a Scheme prompt and can change existing parameters with the following commands:
festival> (Parameter.set 'Horse 3)
3
festival> (Parameter.get 'Horse)
3
Now, I'd like to see every parameter at once, instead of just one at a time. Is there a simple Scheme command to do this?
Look at how Parameter is internally represented. If it is an association list, you can just print it. You can also try these free Scheme debuggers:
Schemeide
Psd

Resources