I'm a newbie in Common Lisp and did some experiments on it.
I was trying hard to get some access to the windows clipboard, then I found this reference:
https://groups.google.com/forum/#!topic/comp.lang.lisp/hyNqn2QhUY0
That was perfect, except for it was tailored for CLISP FFI, and I wanted it working with CFFI.
Then I tried to convert the code, and partially succeed but there's a problem with the routine
(get-clip-string), testing with Clozure CL 1.10 on WinXP(!):
Test text: Have Space Suit-Will Travel
? (get-clip-string)
Error: The value "Have Space Suit-Will Travel" is not of the expected type (UNSIGNED-BYTE 32).
While executing: GLOBAL-LOCK-STRING, in process listener(1).
Type :POP to abort, :R for a list of available restarts.
Type :? for other options.
I think I didn't get the type thing on CFFI (although I've read the manual), or the original prescription on CLISP. have someone any hint?
the following sequence of commands work, but I'm afraid that's not secure:
(open-clip 0)
(get-clip 1)
(close-clip 0)
(open-clip 0)
(get-clip 1)
(close-clip 0)
here is the code:
(ql:quickload :cffi)
(cffi:load-foreign-library "user32.dll")
(cffi:load-foreign-library "kernel32.dll")
(cffi:load-foreign-library "msvcrt.dll")
(cffi:defcfun ("GetClipboardData" get-clip) :string
(uformat :unsigned-int))
(cffi:defcfun ("OpenClipboard" open-clip) :int
(hOwner :unsigned-int))
(cffi:defcfun ("CloseClipboard" close-clip) :int
(hOwner :unsigned-int))
(cffi:defcfun ("EmptyClipboard" empty-clip) :int)
(cffi:defcfun ("SetClipboardData" set-clip) :int
(data :unsigned-int)
(format :unsigned-int))
(cffi:defcfun ("GlobalAlloc" global-alloc) :int
(flags :unsigned-int)
(numbytes :unsigned-int))
(cffi:defcfun ("GlobalLock" global-lock) :unsigned-int
(typ :unsigned-int))
(cffi:defcfun ("GlobalLock" global-lock-string) :string
(typ :unsigned-int))
(cffi:defcfun ("GlobalUnlock" global-unlock) :int
(typ :unsigned-int))
(cffi:defcfun ("memcpy" memcpy) :int
(dest :unsigned-int)
(src :string)
(coun :unsigned-int))
(defun get-clip-string ()
(open-clip 0)
(let* ((h (get-clip 1)) (s (global-lock-string h)))
(global-unlock h) (close-clip 0) s))
(defun set-clip-string (s)
(let* ((slen (+ 1 (length s)))(newh (global-alloc 8194 slen))
(newp (global-lock newh)))
(memcpy newp s (+ 1 slen)) (global-unlock newh) (open-clip 0)
(set-clip 1 newh) (close-clip 0)))
The error is in the return type you used for GetClipboardData and the argument type you used for GlobalLock and GlobalUnlock. You define GetClipboardData to return a string, but in C, GetClipboardData returns a HANDLE, which is defined as a pointer to void, and the argument accepted by GlobalLock and GlobalUnlock is also a HANDLE. Change your C function definitions to this:
(cffi:defcfun ("GetClipboardData" get-clip) :pointer
(uformat :unsigned-int))
(cffi:defcfun ("GlobalLock" global-lock-string) :string
(type :pointer))
(cffi:defcfun ("GlobalUnlock" global-unlock) :int
(type :pointer))
...and the problem goes away.
You also need to fix the other global-lock-* functions and also memcpy if you want to use set-clip-string.
There's another bug, though: When you type-correct the entire program so that the set-clip-string function can also be called, then set-clip-string only seems to be able to put a string onto a clipboard that is local to the Lisp process (I'm using a console build of SBCL via SLIME on Win7). Suppose you copied Have Space Suit-Will Travel to the Clipboard with Notepad. Then try this:
CL-USER> (set-clip-string "MY CLIPBOARD")
1
CL-USER> (get-clip-string)
"MY CLIPBOARD"
So it seems to have worked. But then if you try to paste into EMACS from the Clipboard using ShiftIns, you get:
CL-USER> Have Space Suit-Will Travel
So the real clipboard still has what Notepad put there, and your Lisp program only has a private clipboard that can't be used to copy data to other programs, not even the EMACS session that is hosting it.
This is happening because set-clip-string needs to call empty-clip after calling open-clip.
Also, every one of those Windows calls can fail, but your code doesn't check for failures or handle errors.
Related
In the (amateurish, convoluted) code below, I am trying create an environment where there may be multiple serial-term buffers/windows at the same time. I am doing everything I can think of (and just random desperate things) to make the variables local to the buffer running the terminal to which they pertain. For instance, there may be a buffer "serial-1a2b-buffer" with the terminal "serial-1a2b-term" running in it while at the same time there's a buffer "serial-3c4d-buffer" with the terminal "serial-3crd-term" running in it.
I can get the buffers/terminals setup and running with defun setupserial, but defun killserial and defun resetserial don't get the right value for "termname" and "buffname". It might be the values in the other buffer or it may be past values for buffers and terminals that no longer exist.
(In case anyone is wondering, I do a lot of work with microcontrollers. If the serial connection to them is interrupted, like with a hardware reset, then the serial process dies. The idea was to have a quick way to reset the connection - like with a function bound to a key sequence.)
(defvar serialspeed "115200")
(defvar serialport "/dev/ttyACM0")
(defvar serialbasename "serial")
(require 'term)
(defun setupserial (serialport serialspeed)
(interactive
(list
(read-string
(format "Serial Port (%s): "
serialport)
nil nil
serialport)
(read-string
(format "Speed (%s): "
serialspeed)
nil nil
serialspeed)))
(setq uniqueid (format "%04x" (random (expt 16 4))))
(setq serialid (concat serialbasename "-" uniqueid))
(setq buffname (concat serialid "-buffer"))
(setq termname (concat serialid "-term"))
(setq bufferid (get-buffer-create buffname))
(setq procid (make-serial-process
:speed (string-to-number serialspeed)
:port serialport
:name termname
:buffer buffname))
(switch-to-buffer bufferid)
(make-local-variable 'serialid)
(make-local-variable 'buffname)
(make-local-variable 'bufferid)
(make-local-variable 'termname)
(make-local-variable 'procid)
(make-local-variable 'serialspeed)
(make-local-variable 'serialport)
(term-mode)
(term-char-mode)
(local-set-key (kbd "M-r") #'resetserial)
(local-set-key (kbd "M-k") #'killserial)
(local-set-key (kbd "M-x") #'execute-extended-command)
(local-set-key (kbd "M-o") #'ace-window)
(message "Started Serial Terminal"))
(defun resetserial ()
(interactive)
(make-serial-process
:speed (string-to-number serialspeed)
:port serialport
:name termname
:buffer bufferid)
(message "Restarted Serial Terminal"))
(defun killserial ()
(interactive)
(delete-process termname))
(global-set-key (kbd "C-c s") #'setupserial)
(provide 'setup-serial)
Your problems are sequential. Having created all of your buffer-local variables, you are then destroying them all by calling a new major mode.
The section on "Derived modes, and mode hooks" in this answer might be useful reading, but the key point is that the first thing that happens when you call a major mode is kill-all-local-variables.
Because you are setting global values too, in the absence of local values your other commands will end up using whatever the most-recent global value happened to be.
Set the major mode first.
When I call org-content from the active buffer I get the outline I want. However if I use it in a lisp function like this
(split-window-right (truncate (* W 0.75)))
(if (get-buffer "inbox.org")
(set-window-buffer nil "inbox.org")
(progn
(find-file "~/Documents/GTD/inbox.org")
(text-scale-set -1)))
(org-content)
The windows splits and the right buffer gets loaded but the org-content bit doesn't seem to do anything.
Any ideas of what I do wrong ?
Thanks,
Jouke
Here is a reproducible example, open a new buffer named test.org and define the following function in the *scratch* buffer:
(defun test ()
(let ((buffer (get-buffer "test.org")))
(when buffer
(set-window-buffer nil buffer)
(message "%s" (current-buffer)))))
The message being outputted is *scratch*: only the buffer associated with the window was changed, but what Emacs considers the current buffer did not.
If instead you use switch-to-buffer, as follows, the message displays the selected buffer:
(defun test ()
(let ((buffer (get-buffer "test.org")))
(when buffer
(switch-to-buffer buffer)
(message "%s" (current-buffer)))))
Applying the same change to your code makes (org-content) happy.
Sorry if this is a silly question; I am a complete novice when it comes to emacs.
Recently, I began to do research on how to set up emacs and stumbled upon a great video series by Mike Zamansky. However, whilst following this video (creating an org init file), all of the packages I installed onto my emacsclient proceeded to not work. During initialization, there was an error - namely, "Symbol's value as variable is void: Removes." I copied his tutorial verbatim and I don't see any potential syntactical errors - perhaps I overlooked some errors. However, I've been searching throughout the internet, but could not find any answers to this problem.
Here is the contents of the init.el file:
(require 'package)
(setq package-enable-at-startup nil)
(add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/"))
(package-initialize)
;; Bootstrap 'use-package'
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(org-babel-load-file (expand-file-name "~/.emacs.d/myinit.org"))
Here is the error:
Warning (initialization): An error occurred while loading
‘/Users/Kyojin/.emacs.d/init.el’:
Symbol's value as variable is void: Removes
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.
Debugger Output (--debug-init):
Debugger entered--Lisp error: (void-variable Removes)
eval-buffer(#<buffer *load*-527594> nil
"/Users/Kyojin/.emacs.d/myinit.el" nil t) ; Reading at buffer position
8
load-with-code-conversion("/Users/Kyojin/.emacs.d/myinit.el"
"/Users/Kyojin/.emacs.d/myinit.el" nil nil)
load("/Users/Kyojin/.emacs.d/myinit.el" nil nil t)
load-file("/Users/Kyojin/.emacs.d/myinit.el")
(progn (load-file exported-file) "Loaded")
(if compile (progn (byte-compile-file exported-file (quote load))
"Compiled and loaded") (progn (load-file exported-file) "Loaded"))
(message "%s %s" (if compile (progn (byte-compile-file exported-file
(quote load)) "Compiled and loaded") (progn (load-file exported-file)
"Loaded")) exported-file)
(let* ((age (function (lambda (file) (float-time (time-subtract
(current-time) (nth 5 ...)))))) (base-name (file-name-sans-extension
file)) (exported-file (concat base-name ".el"))) (if (and (file-exists-
p exported-file) (> (funcall age file) (funcall age exported-file)))
nil (setq exported-file (car (last (org-babel-tangle-file file
exported-file "emacs-lisp"))))) (message "%s %s" (if compile (progn
(byte-compile-file exported-file (quote load)) "Compiled and loaded")
(progn (load-file exported-file) "Loaded")) exported-file))
org-babel-load-file("/Users/Kyojin/.emacs.d/myinit.org")
eval-buffer(#<buffer *load*> nil "/Users/Kyojin/.emacs.d/init.el"
nil t) ; Reading at buffer position 358
load-with-code-conversion("/Users/Kyojin/.emacs.d/init.el"
"/Users/Kyojin/.emacs.d/init.el" t t)
load("/Users/Kyojin/.emacs.d/init" t t)
#[0"\205\266\306=\203\307\310Q\202?\311=\204\307\312Q\202?\313\307
\314\315#\203* \316\202?\313\307\314\317#\203>\320\321\322!D\nB\323
\202?\316\324\325\324\211#\210\324=\203e\326\327\330\307\331Q!\"\325
\324\211#\210\324=\203d\210\203\247\332!\333\232\203\247\334!
\211\335P\336!\203\201\211\202\214\336!\203\213\202\214\314\262\
\203\245\337\"\203\243\340\341#\210\342\343!\210\266\f\205\264\314\325
\344\324\211#)\262\207"[init-file-user system-type
delayed-warnings-list user-init-file inhibit-default-init inhibit-
startup-screen ms-dos "~" "/_emacs" windows-nt "/.emacs" directory-
files nil "^\\.emacs\\(\\.elc?\\)?$" "~/.emacs" "^_emacs\\(\\.elc?\\)?
$" initialization format-message "`_emacs' init file is deprecated,
please use `.emacs'" "~/_emacs" t load expand-file-name "init" file-
name-as-directory "/.emacs.d" file-name-extension "elc" file-name-sans-
extension ".el" file-exists-p file-newer-than-file-p message "Warning:
%s is newer than %s" sit-for 1 "default"] 7]()
command-line()
normal-top-level()
Search for the word Removes in your init file, "/Users/Kyojin/.emacs.d/myinit.el" (or possibly in some file that it loads).
If you don't find it immediately then recursively bisect your init file to find the code that is problematic. You can do that by commenting out first 1/2, then 3/4, then 7/8,... of the file until you locate the problem. You can comment a block of text/code by selecting it and then using M-x comment-region. You can uncomment a selection the same way, but with C-u first: C-u M-x comment-region.
I would like to load "~/todo.org" file content in scratch buffer at startup.
I have tried:
(setq initial-buffer-choice "~/todo.org")
But it opens the file in a new buffer (not scratch).
I have also tried:
(setq initial-scratch-message "~/todo.org")
But it prints the file path in the scratch buffer and i would like it's content.
I also would like to change the mode of the scratch buffer to org-mode.
I have tried:
(setq initial-major-mode org-mode)
But i have an initialisation error
Symbol's value as variable is void: org-mode
You can achieve the desired effect with a little bit of Lisp code that you put in your init file:
(condition-case err
(with-current-buffer "*scratch*"
(let ((min (point-min))
(max (point-max))
(goto-char max)
(insert-file-contents "~/todo.org")
(delete-region min max)
(org-mode)))
(error (message "%s" error-message-string err)))
But as #phils pointed out in a comment to your question, the *scratch* buffer might not be the best buffer to use for this functionality. Thus, I suggest to consider the following alternative:
(condition-case err
(let ((buffer (get-buffer-create "*todo*")))
(with-current-buffer buffer
(insert-file-contents "~/todo.org")
(org-mode))
(setq initial-buffer-choice buffer))
(error (message "%s" error-message-string err)))
By using this version, you leave the *scratch* buffer alone. Your .org file will be inserted in a separate buffer by the name of *todo*. This buffer is not associated with your ~/todo.org file, so when you first try save it, you will have to specify a file name.
Finally, i'll go for this:
(condition-case err
(when (get-buffer "*scratch*")
(with-current-buffer "*scratch*"
(erase-buffer)
(insert-file-contents "~/todo.org")
(org-mode)
)
)
(error (message "%s" error-message-string err)))
If I execute a shell command asynchronously in emacs lisp like so:
(shell-command "mycommand &")
Is there a way to wait for the command to generate output before continuing? For my current application, it is probably sufficient to wait until the command generates any output at all, but ideally I'd like to capture the output for additional processing. Is this possible?
You should use comint-output-filter-functions variable that contains function to call after output is inserted into the buffer.
For example, you can do :
(add-hook 'comint-output-filter-functions '(lambda (txt) (message "hello")))
N.B. : From Emacs 23.2, you have the new command async-shell-command, bound globally to M-&.
This executes your command asynchronously without requiring an ampersand. The output of your command is sent to the buffer
*Async Shell Command*.
Perhaps you need to register a Process Filter to give you the callback timing you need? See 37.9 Receiving Output from Processes in the Elisp manual (I see this in my copy for Emacs 22.3).
Here is an example of running a callback when you get the first process output and also storing it into an "associated buffer". Copy it to your *scratch* buffer and eval-region it, but make sure to split-window and show the *Messages* buffer visible so that you can see what's going on.
;; this is emacs lisp (and a comment line)
(defvar my-callback-got-some-already nil)
(defun my-callback ()
(message "callback ran at %s" (current-time-string)))
(defun my-filter-waits-for-first-time-input (proc string)
(unless my-callback-got-some-already
(setq my-callback-got-some-already t)
;; do your one-time thing
(my-callback))
;; insert into the associated buffer as if no process filter was
;; registered
(with-current-buffer (process-buffer proc)
(let ((moving (= (point) (process-mark proc))))
(save-excursion
;; Insert the text, advancing the process marker.
(goto-char (process-mark proc))
(insert string)
(set-marker (process-mark proc) (point)))
(if moving (goto-char (process-mark proc))))))
(defun async-callback-test-harness ()
(interactive)
(let ((process-handle "async-callback-test")
(associated-process-buffer "*async-callback-test*")
(command "ls")
(busy-loop-var ""))
(setq my-callback-got-some-already nil)
(message "start test %s" (current-time-string))
(start-process process-handle associated-process-buffer command)
;; Supposedly async but Emacs doesn't get the input until
;; "Emacs is waiting" so the following set-process-filter
;; can be registered in time.
;; To prove the point, make emacs busy loop to show that the
;; emacs doesn't drop its input and
;; the callback will get the unskipped input.
(switch-to-buffer associated-process-buffer)
(dotimes (k 2000) ; about two seconds on my machine
(setq busy-loop-var (concat busy-loop-var "busy looping...")))
(message "done busy waiting %s" (current-time-string))
(set-process-filter (get-process process-handle)
'my-filter-waits-for-first-time-input)
nil))
;; run it!
(async-callback-test-harness)