Story
I almost finished one project and, as always, at the last moment it was necessary to make massive routine changes.
It was a Bash script to automate the build process on various Unixes, and the reality is that there was nothing in common between my environment and the build server environment.
The conclusion was the same: it was necessary to use the absolute paths to the utilities that were encountered in the script. For this, I decided to use variables, as in the
GNU Autoconf Makefile:
“RM=/usr/local/bin/rm”
and
“${RM} -vf foo”
.
The job is almost done, but I have 3 such scripts that look very similar and I absolutely don’t want to do these replacements with my hands ... so I tried to make a version of
`replace-string ' in
Emacs' new
* scratch * buffer, just for my problem:
')
(defun foo () (interactive) (let ((begin (region-beginning)) (end (region-end))) (mapcar #'(lambda (p) (replace-string (format "%s " (cadr p)) (format "${%s} " (car p)) nil begin end)) '((GNUTAR tar) (GUNZIP gunzip) (GZIP gzip) (GMAKE gmake) (AUTORECONF autoreconf) (MKDIR mkdir) (ECHO echo) (CP cp) (FIND find) (RM rm) (TEST test) (LN ln)))))
And it's all!
A little more detailed what kind of code
This is the
`foo ' function, which can be called interactively in the editor, i.e. while editing the text, and not just from the body of other functions. It extends the action of the function
replace-string by calling it for each item in the list:
((GNUTAR tar) (GUNZIP gunzip) (GZIP gzip) (GMAKE gmake) (AUTORECONF autoreconf) (MKDIR mkdir) (ECHO echo) (CP cp) (FIND find) (RM rm) (TEST test) (LN ln))
As a result, replacing the second value of each element found in the text with the first (for example,
"tar"
by
"GNUTAR"
).
At the beginning of its execution, the function
`foo ' defines the boundaries of the selected region in which it should make replacements: these are calls
to` region-beginning' and
`region-end ' .
Then the function
`mapcar ' is called, which calls the closing function`
lambda (p)' for each element of the list.
The task of the closure function is to disassemble the variable
`p ' into its constituents and call the function
replace-string for replacement in the text.
Epilogue
I note that the functions of the
`map ' family can operate on an arbitrary number of lists and, at first glance, it seems that instead of a list of lists, you could use two values:
(GNUTAR GUNZIP GZIP ...)
and
(tar gunzip gzip ...)
However, such an organization of the data structure is obviously more complicated due to the implicit links between the two lists, whereas in the proposed version such a link is not beyond the scope of the sublist.
findings
The considered function is a one-time design, designed to solve the problem that appeared before one person. The universalization of this design seems to the author a meaningless exercise. The purpose of this post was to show the simplicity and ease of programming a tool (Emacs editor) that a person can use if he wants to work with the mind, not with his hands.