Args for sb-ext:run-program - common-lisp

Can someone tell me exactly what the args argument should look like for sb-ext:run-program?
If I do this:
(sb-ext:run-program "C:/Program Files/iTunes/iTunes.exe"
"C:/lispbox-0.7/opus.mid")
I get this error:
debugger invoked on a TYPE-ERROR:
The value "C:/lispbox-0.7/opus.mid" is not of type LIST.
However, if I do this:
(sb-ext:run-program "C:/Program Files/iTunes/iTunes.exe"
(list "C:\lispbox-0.7\opus.mid"))
iTunes opens, but the MIDI file doesn't play, even though this invocation from the Windows command prompt works just fine:
U:\>"C:\Program Files\iTunes\iTunes.exe" C:\lispbox-0.7\opus.mid
Note that this (with forward slashes):
CL-USER> (sb-ext:run-program "C:/Program Files/iTunes/iTunes.exe"
(list "C:/lispbox-0.7/opus.mid"))
has the same effect: iTunes opens, but the file is not played.

In the list version you're using single backslashes, which get parsed as escape sequences. You need to use double backslashes.

Related

Changing the dir errors and hunchentoot - Dir not found?

I use a macro called use-db and change-to-path in a lot of my projects.
(defmacro use-db (db project-name &body query)
`(progn
(change-to-path ,project-name)
(clsql:connect ,db :database-type :sqlite3)
(unwind-protect (progn ,#query)
(clsql:disconnect :database ,db))))
(defmacro change-to-path (project-name)
`(uiop:chdir (merge-pathnames (write-to-string ,project-name) "/Users/vince/quicklisp/local-projects/")))
As you can see, change to path changes the repl dir. Then use-db reads the sqlite db from the root of the project folder. This works fine.
However, when I try to read a db as part of a route (easy-routes + hunchentoot):
(defroute test-file ("/results" :method :post)
()
(get-one-col-as-list-db #'first "firstname"))
(defun get-one-col-as-list-db (fn tablename)
(ki:use-db "new.db" 'custom-sender
(mapcar fn
(clsql:query
(concatenate 'string "Select * from " tablename)))))
I get the following error:
Error in SB-POSIX:CHDIR: No such file or directory (2)
without using the change-to-path macro, clsql function would note find the database.
Is there a better way to use sqlite (from the file system) and manage the pathing for specific db files?
To change the current working directory, temporarily, use uiop:with-current-directory:
(uiop:with-current-directory ("/tmp/")
(uiop:getcwd))
(edit) chdir has a side effect: it effectively changes the current working directory (uiop:getcwd), while with-current-directory doesn't, or it does but only temporarily for the code under it. For your sanity you want to avoid chdir's side effets (or I do, I want to work at a project root). It could have an effect on bare-bones Hunchentoot, if it looks at a www/ directory under the project root, but in your case I'm not sure.
Your use-db mimics a well-known pattern: get a resource, and be sure to release it in case of errors. These macros are often named "with-something", just like "with-current-directory". Does CLSQL have such a macro? It does: with-database.
Why is your change-to-path a macro? It can be a function that concatenates strings and calls chdir.
Inside use-db, "project-name" is an unknown variable. Look at the compiler warnings:
; caught WARNING:
; undefined variable: COMMON-LISP-USER::PROJECT-NAME
How do you use the two anyways?
Error in SB-POSIX:CHDIR: No such file or directory (2) […] without using the change-to-path macro
what is the directory it tries to go to? You'd have a tip on how things are not working.
I try to never rely on the process working directory, because from Common Lisp I am much happier using *default-pathname-defaults* (no side effects!). This is a special variable with a long name, and what I want is to use merge-pathnames in most of the cases, so I have this macro:
(defmacro with-path (pathname &body body)
`(let ((*default-pathname-defaults* (merge-pathnames ,pathname)))
,#body))
It is just a local binding of a special variable so unwinding is trivial, and it comes with all the benefits of CL pathnames (and some of its drawbacks but that's fine).
On the Posix side of things, programs want a native namestring so I also use this a lot:
(defun fullname (pathname)
(osicat:native-namestring (merge-pathnames pathname)))
I do also have a concept of projects in my environment so it looks as follows. Note that I try to carry the special variable until the last moment, until it needs to be given to other processes, like:
(within-project projects:my-project
(with-path "build/"
(run "make")))
Here run grabs the current *default-pathname-defaults* for its :directory argument (using sb-ext:run-program but this is a detail).
Since it is a pathname, some components can be wild too, if that makes sense in your use case. For example, you can avoid giving a ".db" suffix if you prefer:
(defmacro using-db ((name db) &body body)
`(with-path #P"*.db"
(with-database (,name (list (fullname ,db)) :database-type :sqlite3)
,#body)))
For example, here I enter the "/tmp/" directory and open database "test.db":
(with-path "/tmp/"
(using-db (database "test")
database)))
#<CLSQL-SQLITE3:SQLITE3-DATABASE /tmp/test.db CLOSED {100DD6CE63}>
Edit: with respect to the following code:
(uiop:chdir
(merge-pathnames (write-to-string project-name)
"/Users/vince/quicklisp/local-projects/")))
Note that you can use ASDF to access files relative to systems:
(asdf:system-relative-pathname :cl-ppcre "ppcre.lisp")
#P"..../quicklisp/software/cl-ppcre-20220220-git/ppcre.lisp"

How do I use the live-code feature in sbcl?

I am trying to get live-coding to work in lisp. i have the file t.cl which contains only this line: (loop(write(- 2 1))). Now, when i run the file in bash with sbcl --load t.cl --eval '(quit)', it runs the line, but when I try to edit the file in another terminal and save it while it runs, nothing changes ..
Why your example fails
When running sbcl --load t.cl --eval '(quit)' in a shell, what this does is spin-up a SBCL Lisp image in a process, compile the file and run it. You then modify the file and save it to your disk. This last action is of no concern to the already running SBCL process, which has already compiled the previous file. SBCL read the file once when you asked it to, once it has the compiled instructions to run, it has no reason to look at the file again unless you explicitly ask it to.
A 'live' example with Emacs+SLIME
In order to perform 'live' changes to your running program, you must interact with the already running Lisp image. This is easily doable with Emacs+Slime. You can, for example, have a loop like so:
(defun foo (x) (+ x 3))
(dotimes (it 20)
(format t "~A~%" (foo it))
(sleep 1))
and then recompile foo during execution within the REPL with a new definition:
(defun foo (x) (+ x 100))
Another thread will be used to recompile the function. The new function will be used for future calls as soon as its compilation is finished.
The output in the REPL will look like:
3
4
5
CL-USER> (defun foo (x) (+ x 100))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
FOO
103
104
105
...
This would also work with the new definition of foo being compiled from another file as opposed to being entered directly in the REPL.
Working from the system shell
While you can already use the example above for development purposes, you might want to interact with a running SBCL Lisp image from the shell. I am not aware of how to do that. For your exact example, you want to get SBCL to reload eventual files that you have modified. A brief look at the SBCL manual doesn't seem to provide ways to pipe lisp code to an already running SBCL process.

Emacs Warning An error occurred while loading `.../.emacs.el':

When edit .emacs.el in emacs, I have run Alt + X eval-buffer command.
My os is windows.
And when I restart emacs it display following warning:
Warning (initialization): An error occurred while loading
`.../.emacs.el':
error: Non-hex digit used for Unicode escape
To ensure normal operation, you should investigate and remove the
cause of the error in your initialization file. Start Emacs with the
`--debug-init' option to view a complete error backtrace.
.emacs.el is:
;;Open all fine in one running instance
;;Ref:http://www.johndcook.com/blog/2010/07/28/miscellaneous-emacs-adventures/
;;(server-start)
;;TEST
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
`(ansi-color-names-vector ["#242424" "#e5786d" "#95e454" "#cae682" "#8ac6f2" "#333366" "#ccaa8f" "#f6f3e8"])
`(custom-enabled-themes (quote (wheatgrass))))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
;;Set auto save backup location, failed with following warning
(setq backup-directory-alist
`((".*" . ,"D:\Unix-Tmp")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\Unix-Tmp" t)))
(require 'recentf)
(recentf-mode 1)
(setq inhibit-startup-screen t)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
;;Aspell install failed
;;(setq-default ispell-program-name "C:/bin/Aspell/bin/aspell.exe")
;;(setq text-mode-hook '(lambda() (flyspell-mode t) ))
How I can resolve it?
The problem is these lines:
(setq backup-directory-alist
`((".*" . ,"D:\Unix-Tmp")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\Unix-Tmp" t)))
The \U introduces a unicode escape ... and has to be followed by hex digits.
What you actually appear to want is a literal backslash character, so you need to escape it; i.e.
(setq backup-directory-alist
`((".*" . ,"D:\\Unix-Tmp")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\\Unix-Tmp" t)))
Reference: http://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Char-Syntax.html#Basic-Char-Syntax
UPDATE
However, this appears to lead to another problem. A better solution would be to do what #Stefan suggests. Use "/" instead of "\" as the pathname separator. (It should work even on Windows ...)
Error is caused by D:\Unix-Tmp, \U introduces unicode escape as Stephen stated.
But when I change to :
(setq backup-directory-alist
`((".*" . ,"D:\\Unix-Tmp")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\\Unix-Tmp" t)))
It will throw another:
Loading d:/git_root_tfs/WorkStation/Unix-Home/.recentf...done Cleaning
up the recentf list...done (0 removed) For information about GNU Emacs
and the GNU system, type C-h C-a. make-auto-save-file-name: Invalid
use of `\' in replacement text
At last I change the path to D:\Tmp-Unix and it works.
(setq backup-directory-alist
`((".*" . ,"D:\Tmp-Unix")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\Tmp-Unix" t)))
Total .eamcs.el is
;;Open all fine in one running instance
;;Ref:http://www.johndcook.com/blog/2010/07/28/miscellaneous-emacs-adventures/
;;(server-start)
;;TEST
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
`(ansi-color-names-vector ["#242424" "#e5786d" "#95e454" "#cae682" "#8ac6f2" "#333366" "#ccaa8f" "#f6f3e8"])
`(custom-enabled-themes (quote (wheatgrass))))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
;;Set auto save backup location, failed with following warning
(setq backup-directory-alist
`((".*" . ,"D:\Tmp-Unix")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\Tmp-Unix" t)))
(require 'recentf)
(recentf-mode 1)
(setq inhibit-startup-screen t)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
;;Aspell install failed
;;(setq-default ispell-program-name "C:/bin/Aspell/bin/aspell.exe")
;;(setq text-mode-hook '(lambda() (flyspell-mode t) ))
Always use forward slashes rather than backward slashes for file names in Emacs. Windows usually prefers backward slashes, but other than in a few rare exceptions, Windows actually accepts forward slashes just as well.
Emacs in Windows treats forward slashes (/) as backslashes (\). When you are specifying any type of path, you should always use forward slashes. Emacs will interpret them correctly. This allows you to control the escape sequence use to times where that is the intended effect.
C:/Users/username/AppData/Roaming/.emacs is a perfectly valid path/filename in Emacs.

How can I automate these emacs ESS (ess-remote) commands?

I'm using a local emacs instance (aquamacs) to run R processes on a remote server, and I'd like to automate the process of connecting to my server. The process is as follows:
[in emacs]
M-x shell
[in the resulting console]
TERM=xterm
ssh -Y -C <my remote server>
screen -rd [and/or] R
[in emacs]
M-x ess-remote
r
I discovered this general approach here: http://blog.nguyenvq.com/2010/07/11/using-r-ess-remote-with-screen-in-emacs/. The -Y -C options allow you use xterm to view plots. I don't know lisp and tho I've googled around a bit, I can't seem to piece together how to actually define a function to automate this (e.g., in .emacs.el). Has anyone implemented anything like this?
Let's assume you just want to call shell in code. In Lisp, everything is prefix notation surrounded by parentheses. So we enter this into a buffer (say, the scratch buffer):
(shell)
Move your pointer to the end of the line after the close-paren, and type <C-x C-e> to execute the Lisp code. You should see that the shell function is called.
Now, let's make it a function, so we can add other things to it. The command to create a function is defun, and it takes the name of the function, the argument list (in parentheses), and then the body of the function:
(defun automate-connection ()
(shell))
Move your cursor to the end of the code, hit <C-x C-e>, and the function will be defined. You can call it from Lisp by executing
(automate-connection)
Ok, now we just need to put some text into the shell buffer.
(defun automate-connection ()
(shell)
(insert "TERM=xterm"))
Now, when we run that, we get "TERM=xterm" put into the shell buffer. But it doesn't actually send the command. Let's try putting a newline.
(defun automate-connection ()
(shell)
(insert "TERM=xterm\n"))
That puts in a newline, but doesn't actually make the command run. Why not? Let's see what the enter key does. Go to your *shell* buffer, and type <C-h c>, then hit the return key. (<C-h c> runs describe-key-briefly, which prints the name of the function invoked by hitting the given key). That says that when you hit RET, it's not putting a newline, but actually calling comint-send-input. So let's do that:
(defun automate-connection ()
(shell)
(insert "TERM=xterm")
(comint-send-input))
Now, when you run `(automate-connection) from any Lisp code, you should get the given thing sent. I leave it as an exercise to the reader to add your other commands.
But wait! We're not really done, are we? I assume you don't want to have to move to a Lisp scratch buffer, type in (automate-connection), then evaluate that code. You probably just want to type , and call it a day. You can't do that by default with the function we just created. Luckily, it's simple to allow that: just add a call to (interactive) in your function:
(defun automate-connection ()
(interactive)
(shell)
(insert "TERM=xterm")
(comint-send-input))
Now you can call it as you want, and it'll open the *shell* buffer, put in the text, and tell Emacs to tell the shell to run that text.

Emacs, Auto Complete Mode, CSS, pain. (illustrated!)

I've got Auto Complete Mode installed for Emacs.
First: When I'm typing declarations I get the normal auto-complete behavior:
So I hit Tab to complete — no problem. But then I hit ;:
It instantly tries to complete something! And I can't hit Enter because that'll accept the erroneous completion!
So I have to hit C-j. What a pain.
Second: Once I'm done with a declaration, I type }:
...but it doesn't get indented properly unless I type Tab.
What gives?
Update, settings:
I'm using Emacs 23. My css-electric-keys are } and ;. My Auto Complete configuration is as follows:
(ac-config-default)
(setq ac-auto-start t)
(setq ac-delay 0.1)
(setq ac-auto-show-menu nil)
(setq ac-show-menu-immediately-on-auto-complete t)
(setq ac-trigger-key nil)
Here's a few suggestions:
(setq ac-auto-start t) starts autocomplete automatically. If you change that to (setq ac-auto-start 1) (or 2 or 3) then it will only start after that many characters have been typed. This might not solve your problem though if after you type the ;, it considers the entire preceding word as part of the current auto-complete search.
Maybe the problem is that it isn't recognizing the semicolon as a delimiting character (like whitespace), so it thinks you're still adding to the last word. Perhaps adding the semicolon string to ac-ignores would do the trick? (Not sure what the syntax for that would be)
Maybe you can prevent auto-completion via the enter key by adding: (define-key ac-complete-mode-map "\t" 'ac-complete) and (define-key ac-complete-mode-map "\r" nil). I'm not sure how this will interact with DWIM though (enabled by default).
Try adding semicolon as an auto-complete key?
My .emacs knowledge on a scale of 0 to 10 is like a 1.5, but maybe this will jog some better ideas.
Old stuff I know, but try the following:
(add-hook 'css-mode-hook
(lambda ()
(make-local-variable 'ac-ignores)
(add-to-list 'ac-ignores ";")))
From the manual

Resources