How to detect operating system with GIMP scheme? - operating-system

I am using a few simple script-fus written in GIMP's scheme. (And that is the most I've used of scheme...)
I use them on machines running either Windows or Linux. Most times that is not a problem, but sometimes it is, namely when dealing with '\' vs. '/' on file paths.
Is there a simple way to detect on which operating system GIMP is running, from a Scheme script-fu? I haven't found anything on "Revised^5 Report on the Algorithmic Language Scheme" (but I may have not looked in the correct place)
One trick I can do is to check for the existence of a given file, e.g., the following works just fine
(define (script-fu-operating-system)
(let* ((the-os "windows"))
(if (= 1 (car (file-glob "/usr/bin/gimp" 0)))
(set! the-os "linux"))
(gimp-message the-os)))
As suggested by Michael Schumacher, I tried using both '/' and '\'.
On Windows it worked as expected, e.g. for (file-jpeg-load), with ...
... backslashes (only needs to escape them):
(file-jpeg-load RUN-INTERACTIVE "C:\\Users\\my.user\\Pictures\\test.jpg" "")
... slashes:
(file-jpeg-load RUN-INTERACTIVE "C:/Users/my.user/Pictures/test.jpg" "")
... even works with mixed (back)slashes !!
(file-jpeg-load RUN-INTERACTIVE "C:/Users\\my.user/Pictures\\test.jpg" "")
Yet for (file-glob) it only works with the proper backslashes:
(file-glob "C:\\Users\\my.user\\Pictures\\*.jpg" 1) => OK (the file list)
(file-glob "C:/Users/my.user/Pictures/*.jpg" 1) => NOK (empty list)

Tricks like what you describe are all you gonna get using scheme (script-fu). If you intend to write full-fledged, multi-platform scripts, I suggest you to write your GIMP scripts in Python instead. (Detecting the O.S. is a matter of e import sys and the O.S. name is available in the variable sys.platform.
- but them, you would not actually need the system for this spefic case, since for file access the language automatically translates "/" to "\" as needed under Windows.
Moreover, scheme is generally harder to learn, write and maintain, besides having a standard library which is a fraction of the one used in a standard Python install. The only cases I could recommend Script-fu instead of scheme are: if you are already proficient in scheme/lisp and not in Python at all, or, if you are just adapting/fixing an existing script.

Related

Writing an Emacs Backend Plugin in Common Lisp

I am interested in creating an emacs extension that delegates the work to an external program.
I have my logic as a library, however, written in Common Lisp. If I can directly call the CL library from Elisp, that would be simpler for me; otherwise, I can use a client/server architecture.
I have looked into emacs LSP implementation, but I couldn't find a simple entry on how to do it.
You could build a binary of your CL app and call it from the Elisp side. It seems to suit you fine, so here are more pointers:
How to build a Common Lisp executable
short answer: see https://lispcookbook.github.io/cl-cookbook/scripting.html
Building a binary is done by calling sb-ext:save-lisp-and-die from the terminal (and not from a running image). Note that this function name changes on the different implementations.
ASDF has a directive that allows to do it declaratively, and portably (for all implementations). You add 3 lines in your .asd file and you mention what is your program's entry point. For example:
;; myprogram.asd
:build-operation "program-op" ;; leave this as is.
:build-pathname "myprogram"
:entry-point "myprogram::main" ;; up to you to write main.
Now, call (asdf:make :myprogram).
See a more complete example in the Cookboo.
Call it from Elisp
See https://wikemacs.org/wiki/Emacs_Lisp_Cookbook#Processes
This returns the output as a string:
(shell-command-to-string "seq 8 12 | sort")
Full documentation: https://www.gnu.org/software/emacs/manual/html_node/elisp/Synchronous-Processes.html
Other approaches
Other approaches are discussed here: https://www.reddit.com/r/lisp/comments/kce20l/what_is_the_best_way_to_call_common_lisp_inside/
For example, one could start a lisp process with Slime and execute CL code with slime-eval.

Getting number of processors in emacs

Is there a good cross-platform method for determining the number of processors a machine has in elisp? I'm trying to make my config auto detect some build options, and would like to have it automatically use the number of processors + 1. Grepping /proc/cpuinfo isn't a solution for me because it won't work on Windows.
Emacs 24.3 Lisp doesn't have access to that information. Your options would seem to include:
writing an Elisp library which uses the value of SYSTEM-TYPE to choose a system-specific method for getting the processor count;
modifying the Emacs C source and rebuilding it so that it can, for each potentially multiprocessor platform on which Emacs builds, expose the processor count at the Lisp level.
At least, that was true four hours ago, when I first started writing this answer. But then I got interested in the problem, and now you have a third option:
downloading my system-cores.el library, which implements the first of the two options above, and calling (system-cores :physical) to get the number of physical processors, (system-cores :logical) to get the number of logical cores, or just plain (system-cores) to get an alist containing both.
Caveats include:
This library relies strongly on the PROCESS-LINES function. If that function can't do anything sensible in the context where you need to call SYSTEM-CORES, then SYSTEM-CORES can't either. (For example, if you're on Darwin and (getenv "PATH") doesn't contain /usr/sbin, PROCESS-LINES will bomb out with "Searching for program: no such file or directory, system_profiler".)
The systems currently known to be supported are GNU/Linux (anything with /proc/cpuinfo, more or less), Windows NT (and its derivatives, including 2000, XP, and all subsequent versions), and Darwin (OS X, at least 10.8, theoretically as far back as 10.2). Not coincidentally, these are also the systems to which I have access.
I've also included a delegate which should work properly on at least some flavors of BSD, but I don't have a BSD box on which to test it, so there's no telling whether or not it'll really work -- at the very least, you'll almost certainly need to modify the list of sysctls examined by the SYSTEM-CORES-SYSCTL delegate.
If you're using a modern variety of Linux, Windows, or OS X, great! You should be good to go, right out of the box. If not, and if your platform includes a command-line utility which provides the requisite information in its results, then it shouldn't be hard to write a delegate for your system. Or, if you don't want to write a delegate yourself, then email me all of:
the proper invocation for the command-line utility in question
a sample of the output it produces on your system
the output of M-: system-type in Emacs
the output of M-: system-configuration in Emacs
and I'll be able to write a delegate myself and add it to the library.
Edit: The :cores and :processors keywords have been replaced with :physical and :logical, respectively; I couldn't keep them straight, and I don't see why I should expect anyone else to, either.
Edit: Per #lunaryorn, replaced (split-string (shell-command-to-string ...)) with (process-lines ...). This saves invoking a shell, which might make the library more reliable, and certainly makes its code easier to read.

Best way to customize auto-formatting/auto-indenting in vim for Common Lisp

I would like to know the best way to customize auto-formatting/auto-indenting in vim for Common Lisp.
Auto-formatting (I usually do this by typing '==' in command mode per line) works very well for the base lisp language in vim (e.g., defmacro, defun, lambda, if, with-output-to-string), but any time that new language constructs are defined (e.g., using macros), I find that the formatting for the new construct is often not what I'd like it to be.
For example, here's how vim formats 'when (standard lisp construct) and 'awhen (commonly-used anaphoric version of 'when; not part of lisp standard)
(when 'this
(process 'this))
(awhen 'this
(process it))
I would like 'awhen to auto-format like 'when. Any ideas how I can do this?
Edit: Thanks Gilligan and Tamas for the Slimv recommendation. As a test, I downloaded MacVim (will need this working with terminal vim, but that's a different problem) and slimv, rsynched the slimv download into ~/.vim, launched MacVim, and loaded a .lisp file.
I then started up the lisp server (done through a GUI with MacVim), which loaded up my default lisp executable and core file.
And* since my core file is already loaded with the language extensions that I commonly use (awhen being one of them), awhen formatted correctly right out of the box.
I really like this solution. Instead of [1] having to learn how to tell vim to indent particular functions properly, and [2] writing the code that does this explicitly for each language extension that I define, and [3] updating that code every time I add a new language construct. Instead I leverage slimv to do the formatting for me. And slimv can 'learn' new language extensions, as long as those macros are already loaded into the lisp core that the server session is using. Pretty slick!
I have found that this works well for a particular class of language extensions. Usually ones defined as a macro, using the &body keyword. This seems to 'do the right thing' most of the time, but there are macros I use that still don't properly auto-format. Although I'd say that this is more likely to be an issue with how the macro is written (non-standard language extension) than anything else.
So, this solution works well for me for most cases, and I didn't have to code (and maintain) anything. Great stuff!
This might not be a direct answer to your question but I strongly suggest that you install
the slimv plugin: http://www.vim.org/scripts/script.php?script_id=2531
Its a great plugin which integrates SLIME functionality into vim and besides many other things it also comes with an improved indentation for clisp&clojure. It won't indent awhen the way you want though.
For those who are looking for this topic and don't want to run Slimv, because they aren't working with Common Lisp or other reasons, here is the scoop.
Vim's Lisp indentation is not like that for other languages; it has a special "Lisp mode". This mode is turned on by
:set lisp
which is done automatically for .lisp files. Lisp mode isn't a Vim invention; classic Vi implementations have a Lisp mode turned on with :set lisp. (It's not described by POSIX, unfortunately).
Vim's Lisp mode has a simple mechanism for recognizing forms that require operator-style indentation: namely, there is a parameter called lispwords which holds a comma-separated list of identifiers.
You can prove to yourself that this is the identifier list which is used, even when you're editing a Common Lisp .lisp file with syntax highlighting and all. Simply do :set listwords[TAB] and edit the list to remove something from it, such as defun. Then try to reindent a defun: you will see the function-style indentation now instead of the operator-style.
The syntax highlighting support for Common Lisp is separate from Lisp mode's lispwords parameter; it has its own list of identifiers. For example, in Vim 7.3 if you enter this:
(symbol-macrolet ((foo bar))
you get indented out to here!)
This is in spite of the fact that symbol-macrolet is recognized and colored. Why? It's because symbol-macrolet does not appear in the rather scanty lispwords list, whereas it does appear in the lisp.vim syntax highlighting definition file.
The upshot is that you can cob together some script which scans your directory of .lisp files for macros and generates a set lispwords=... command that is placed into a directory .vimrc.
Or if you are working on a custom Lisp dialect, you can just make its Vim syntax highlighting file customize lispwords when it loads.
Here is an implementation oversight: the lispwords option has no local value; you cannot use setlocal lispwords ... to give it a buffer-specific value. In other words, it appears that (at least in the Vim 7.3 I'm using under Ubuntu) you can't have two or more buffers open holding different dialects of Lisp with different identifiers for indentation. The default contents of lispwords contains a smattering of Lisp and Scheme symbols to try to be a kind of "one size almost fits all" solution.
If you filetype is 'lisp' then I think you need to add indenting rules for your special case in the 'lisp.vim' file in the '/vim7x/indent' directory. You can find a bit more info in help at :h indent-expr and :h indentexpr.
Someone may be able to tell you better, but I believe the default lisp.vim indent file basically does nothing because the built-in function lispindent() is used to get indent values. You will want to:
(1) set function used to get indent values (i.e., indentexpr) to a function in your own indent/lisp.vim file, e.g., GetLispIndent().
(2) in your your GetLispIndent() function you will use lispindent() to get indent values to return for all lines except your special case. See other languages' indent files and read the docs to get an idea for how indentexpr works, e.g, java.vim.
#Kaz's answer is completely correct, but they don't go all the way to answering the original question. Vim's lispwords config string is a comma-delimited list of words; when any of the words in lispwords is found at the beginning of an S-expression, Vim will change the way that S-expression is indented. In other words, it defines the "standard lisp constructs" to which the OP refers. If you view your current lispwords config with :set lispwords, you'll see "when" is included, but "awhen" is not, resulting in the following indentation:
(when 'this
(process 'this))
(awhen 'this
(process it))
To fix this, simply add "awhen" to the config string somewhere in your config, like so:
set lispwords+=awhen,
The trailing comma isn't strictly necessary, but the default value includes it, and is probably wise in case you or a plugin modifier elsewhere. That would turn the original formatting into this:
(when 'this
(process 'this))
(awhen 'this
(process it))
(Tested on my current installation of Vim 9.0)
Note that, as #Kaz points out, this config string is universal, so if you have different dialects of lisp their indentation will all be controlled by this setting. Vim is pretty good about auto-detecting lisps, but you may need so :set lisp if it doesn't recognize your filetype or dialect.

Is there a way to write a .emacs that will always stay upward compatible?

I have been using Emacs since version 18. Emacs Lisp isn't my routine programming language, but years ago I invested some time studying it to the point of creating a .emacs that's better (for me) than any GUI IDE to date.
That was a one-time effort and since then, I forgot completely how to program in lisp.
Alas, every time I upgrade my Emacs (18 > 19 > 20 > 21 > 22 > 23), something in my .emacs breaks, and I end up spending way too many hours (sometimes days) fixing these.
In many other languages I program routinely, it is possible to write code that never becomes obsolete. In emacs, on the other hand, I can never predict how things will change. For example [M-TAB] that used to work up until version 21.4.1, no longer works in version 23 and must be replaced with "\M-\t". Another example is dired-omit-toggle that used to work in version 21 but stopped working in version 22, being replaced by dired-omit-mode.
Now, I know that if a .emacs doesn't do much, it's possible to write "an almost empty" .emacs that can (probably) stay compatible with future versions.
But my .emacs is huge, designed to run on many different operating systems (and their different flavors, editions and versions, including non-GUI systems) without a single change. I wish there was a core-API or subset that is guaranteed to always work.
Is there really such a way to write a .emacs that will always stay upward compatible?
If so, where can I find a "cook book" or authoritative guidelines for accomplishing this?
Use (when (boundp 'some-variable) …) or (when (fboundp 'some-function) …) around any piece of code that relies on a specific feature. (While you're at it, start with (require 'cl) for those older versions that don't have when built-in.)
When all else fails, discriminate on emacs-major-version, emacs-minor-version and running-xemacs (defined as (string-match "XEmacs\\|Lucid" emacs-version)).
Avoid syntax and library functions that are only supported in newer versions.
It's rare that something breaks when you stick to documented interfaces. So try to look for a way to do things that's mentioned in the manual, and only fall back to modifying some random non-customizable variable if you see no other way. In my experience there is always a reasonably easy way to get something to work in all versions (at least with GNU Emacs, XEmacs is sometimes harder to please) if you allow the occasional conditional.
For example, "\e\t" has always worked for M-TAB. With dired-omit-mode, fall back to dired-omit-toggle if the former does not exist:
(set (if boundp 'dired-omit-mode 'dired-omit-mode 'dired-omit-toggle) t)
Yes, it's slightly painful, but not as dramatic as you make it out to be. I maintain a .emacs that works with anything since 19.23 (IIRC, it's been a while since I tested with anything older than 19.34) on all of DOS, Windows and unix. Compatibility with Windows is in fact more of a burden than keeping up with GNU Emacs version changes.
As for a cookbook, well, most differences between versions have to do with features that aren't very widely used (otherwise the maintainers would give more importance to strict upward compatibility). Since Emacs is big, there's undoubtedly plenty of it that you use but the cookbook writer wouldn't have heard of. You'll have to play it by ear. Fortunately it's not too hard.
Since Its impossible to predict future changes of anything, no one can guarantee the future compatibility.
I think the following points are few of many general ways to make it easy to maintain .emacs or init.el (which I am practicing right now.)
put .emacs.d/ version control (MUST one)
split init file into several small files.
use when to load specific customizations for a version of emacs.
for eg:
(when (= emacs-major-version 24)
;;load my settings for 24
)
I sympathize, and I share your pain. The answer is no, there is no such holy grail, I'm afraid. As you said, if your init file is simple enough then you might not need to change anything. Actually, even that's not true: the init file name and where Emacs looks for it have both changed over time.

Possible to reset user environment in Scheme REPL?

Scheme newbie question-
Is there a way for me to reset my current REPL environment (i.e. the default user environment) without quitting and restarting my REPL? Basically I'd like a way to wipe out my current environment so that none of my previous defines are in effect. This is using GNU/MIT Scheme.
If this is impossible, what's the best practice here when just messing around with code in the REPL? I've heard people talk about creating and deleting packages, but most examples seem to be for Common Lisp which is a bit different.
I did find information on how to do this in the Clojure REPL but there were caveats and it seems like it's Clojure-specific: Can I clean the repl?
Thanks!
Edit: I'm able to accomplish functionally the same thing by quitting and restarting the REPL process itself. I found a way to do this but keep the connection to my editor (vim) alive using vim-screen. This is an acceptable solution if there's no way to do it from within the REPL. However, I'll keep the question open a bit longer to see if there's a way to do this inside the language as I think it will be instructive.
I think that this is implementation specific, but in MIT Scheme you can clear the REPL environment with:
1 ]=> (ge (make-top-level-environment))
The function (ge [environment]) "Changes the current REP loop environment to [environment]." and the function make-top-level-environment "returns a newly allocated top-level environment".
MIT Scheme has a bunch of environment-management functions that you can peruse here
I tested this on Mac OS X (10.6.7) with MIT Scheme 9.0.1 installed via the pre-built binary from the GNU site, with the following REPL session:
1 ]=> (define foo 1)
;Value: foo
1 ]=> foo
;Value: 1
1 ]=> (ge (make-top-level-environment))
;Value 13: #[environment 13]
1 ]=> foo
;Unbound variable: foo
;To continue, call RESTART with an option number:
; (RESTART 3) => Specify a value to use instead of foo.
; (RESTART 2) => Define foo to a given value.
; (RESTART 1) => Return to read-eval-print level 1.
2 error>
I think that different implementations have different conventions but I don't think there's anything quite like Common Lisp's packages. If you're not wedded to MIT Scheme, you should check out Racket and Dr Racket, which is a nice IDE that might be more powerful than a plain REPL at the command line, and I think it has some kind of module system. Racket is its own dialect of Scheme, so depending on what you're doing, it might not be appropriate. (the default language module in Racket is not the same as MIT Scheme)
I've struggled with all this recently (past few months) when I went looking for a Scheme that could run the code from Lisp in Small Pieces, which has a bunch of weird macros. Gambit ended up being the best bet. If you don't have a need like this though, check out Racket.