How can the mouse be moved programatically in Common Lisp? - common-lisp

The code should run on Windows 10. I tried asking on Reddit, but the ideas are Unix/Linux only. There's also CFFI, but I didn't understand how to use it for this problem (the main usability part of the documentation I found is just an elaborate example not related to this problem).
I also looked through the SetCursorPos of Python, and found that it calls ctypes.windll.user32.SetCursorPos(x, y), but I have no clue what that would look like in CL.
And finally, there's CommonQt, but while there seems to be QtCursor::setPos in Qt, I couldn't find the CL version.

The function called by the Python example seems to be documented here. It is part of a shared library user32.dll, which you can load with CFFI,
(ql:quickload :cffi)
#+win32
(progn
(cffi:define-foreign-library user32
(:windows "user32.dll"))
(cffi:use-foreign-library user32))
The #+win32 means that this is only evaluated on Windows.
Then you can declare the foreign SetCursorPos-function with CFFI:DEFCFUN. According to the documentation, it takes in two ints and returns a BOOL. CFFI has a :BOOL-type, however the Windows BOOL seems to actually be an int. You could probably use cffi-grovel to automatically find the typedef from some Windows header, but I'll just use :INT directly here.
#+win32
(cffi:defcfun ("SetCursorPos" %set-cursor-pos) (:boolean :int)
(x :int)
(y :int))
I put a % in the name to indicate this is an internal function that should not be called directly (because it is only available on Windows). You should then write a wrapper that works on different platforms (actually implementing it on other platforms is left out here).
(defun set-cursor-pos (x y)
(check-type x integer)
(check-type y integer)
#+win32 (%set-cursor-pos x y)
#-win32 (error "Not supported on this platform"))
Now calling (set-cursor-pos 100 100) should move the mouse near the top left corner.

There are two problems here:
How to move the mouse in windows
How to call that function from CL.
It seems you have figured out a suitable win32 function exists so the challenge is to load the relevant library, declare the functions name and type, and then call it. I can’t really help you with that unfortunately.
Some other solutions you might try:
Write and compile a trivial C library to call the function you want and see if you can call that from CL (maybe this is easier?)
Write and compile a trivial C library and see if you can work out how to call it from CL
Write/find some trivial program in another language to move the mouse based on arguments/stdin and run that from CL

Related

How to remove a defmethod for a struct

I have 2 destructs: monster & orc. The orc includes monster. The generic monster has generic defmethods on it named monster-show & monster-hit. The orc has a specialized monster-hit but still keeps the generic monster-show. My problem is that I accidentally named the specialized method for the orc the wrong name (monster-show), so now when I try to use the generic monster-show, it runs code that it shouldn't (the wrongly named defmethod I compiled) instead of running the generic method.
Is there a way to get rid of a specialized defmethod in Slime + SBCL?
If you don't have an IDE or such, you can use remove-method:
(remove-method #'monster-show
(find-method #'monster-show
()
(list (find-class 'orc))))
Here’s how I would do it using the slime inspector:
Enter the generic function you want to modify:
CL-USER> #'monster-show
#<GENERIC FUNCTION: MONSTER-SHOW>
Move your cursor on to it and inspect the object by typing C-c C-v TAB
The inspector should show a list of methods for the function identified by their specialisers. Navigate to one and press the button to remove/unbind the method. You can click for this too.
Also by the description of your hierarchy it would probably be wiser to use real classes and not structs. Structs tens not to give a particularly big speedup compared to classes.
On spacemacs w/ evil mode :slime-inspect RET #'monster-show. Select remove-method on the orc.

Strange autocompletion result in emacs + common lisp

I am using Emacs with SLIME for my development environment. When I type (write-to and then C-M-i I get the following autocompletions:
Click on a completion to select it.
In this buffer, type RET to select the completion near point.
Possible completions are:
write-to-sting
write-to-string
I know Common Lisp is powerful, but I guess write-to-sting is not in the ANSI standard. Google didn't offer a single hit for this function. Then I tried to find it in the SBCL code, but alas
(documentation 'write-to-sting 'function) returns nil so it doesn't have a documentation string.
When I try to execute the function (write-to-sting) I get The function COMMON-LISP-USER::WRITE-TO-STING is undefined.
Apropos also finds an unbound function:
(apropos 'write-to)
WRITE-TO
WRITE-TO-STING
WRITE-TO-STRING (fbound)
My question is: What is going on? Does anyone knows the story behind this function?
At some point during your interaction with the Lisp environment, you wrote write-to-sting and it was read by the Lisp reader. The symbol was interned in the COMMON-LISP-USER package. After all, maybe you intended to implement a function that sends an email to Sting, who knows?
Auto-completion works by filtering the currently known symbols in the environment.
You can safely (unintern 'write-to-sting) (or implement it).

What's the meaning of "#+" in the code of cl-mysql? [duplicate]

This question already has answers here:
operator #+ and #- in .sbclrc
(2 answers)
Closed 6 years ago.
Recently I tried to read code about cl-mysql, but got stuck with the #+.
Tried to google it, but not work, so turn to here
(defun make-lock (name)
#+sb-thread (sb-thread:make-mutex :name name)
#+ecl (mp:make-lock :name name)
#+armedbear (ext:make-thread-lock)
#+ (and clisp mt) (mt:make-mutex :name name)
#+allegro (mp:make-process-lock :name name))
And looks like it is for different backend lisp compiler. But still no idea why write something like this.
Anyone can help me make it clear, thx.
#+ is a reader-macro that checks if a keyword is in the special variable *FEATURES*. If it isn't there, the following form will be skipped over (by the reader; the compiler will never see it). There is also #- which does the opposite.
There are some things that aren't part of the Common Lisp standard, but are important enough that all (or most) implementations provide a non-standard extension for them. When you want to use them in code that needs to work on multiple implementations, you have to use read-time conditionals to provide the correct code for the current implementation. Mutexes (and threads in general) are one of those things.
Of course there may be features provided by third party libraries as well. The contents of *FEATURES* will look something like this:
(:SWANK :QUICKLISP :SB-BSD-SOCKETS-ADDRINFO :ASDF-PACKAGE-SYSTEM :ASDF3.1
:ASDF3 :ASDF2 :ASDF :OS-UNIX :NON-BASE-CHARS-EXIST-P :ASDF-UNICODE :64-BIT
:64-BIT-REGISTERS :ALIEN-CALLBACKS :ANSI-CL :ASH-RIGHT-VOPS
:C-STACK-IS-CONTROL-STACK :COMMON-LISP :COMPARE-AND-SWAP-VOPS
:COMPLEX-FLOAT-VOPS :CYCLE-COUNTER :ELF :FLOAT-EQL-VOPS
:FP-AND-PC-STANDARD-SAVE :GENCGC :IEEE-FLOATING-POINT :INLINE-CONSTANTS
:INTEGER-EQL-VOP :INTERLEAVED-RAW-SLOTS :LARGEFILE :LINKAGE-TABLE :LINUX
:LITTLE-ENDIAN :MEMORY-BARRIER-VOPS :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLADDR
:OS-PROVIDES-DLOPEN :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL
:OS-PROVIDES-PUTWC :OS-PROVIDES-SUSECONDS-T :PACKAGE-LOCAL-NICKNAMES
:PRECISE-ARG-COUNT-ERROR :RAW-INSTANCE-INIT-VOPS :SB-DOC :SB-EVAL :SB-FUTEX
:SB-LDB :SB-PACKAGE-LOCKS :SB-SIMD-PACK :SB-SOURCE-LOCATIONS :SB-TEST
:SB-THREAD :SB-UNICODE :SBCL :STACK-ALLOCATABLE-CLOSURES
:STACK-ALLOCATABLE-FIXED-OBJECTS :STACK-ALLOCATABLE-LISTS
:STACK-ALLOCATABLE-VECTORS :STACK-GROWS-DOWNWARD-NOT-UPWARD :SYMBOL-INFO-VOPS
:UNIX :UNWIND-TO-FRAME-AND-CALL-VOP :X86-64)
So if you wanted to write code that depends on Quicklisp for example, you could use #+quicklisp. If you wanted code that is only run if Quicklisp is not available, you'd use #-quicklisp.
You can also use a boolean expression of features. For example,
#+(or sbcl ecl) (format t "Foo!")
would print Foo! on either SBCL or ECL.
#+(and sbcl quicklisp) (format t "Bar!")
would only print Bar! on SBCL that has Quicklisp available.
One could imagine that we can write:
(defun make-lock (name)
(cond ((member :sb-thread *features)
(sb-thread:make-mutex :name name))
((member :ecl *features*)
(mp:make-lock :name name))
...))
But that does usually not work, because we can't read symbols when their package is not existing and some packages are implementation/library/application specific. Packages are not created at read time in a lazy/automatic fashion.
In Common Lisp, reading a symbol of a package, which does not exist, leads to an error:
CL-USER 1 > (read-from-string "foo:bar")
Error: Reader cannot find package FOO.
1 (continue) Create the FOO package.
2 Use another package instead of FOO.
3 Try finding package FOO again.
4 (abort) Return to level 0.
5 Return to top loop level 0.
In your example sb-thread:make-mutex is a symbol which makes sense in SBCL, but not in Allegro CL. Additionally the package SB-THREAD does not exist in Allegro CL. Thus Allegro CL needs to be protected from reading it. In this case, the symbol sb-thread:make-mutex will only be read, if the the feature sb-thread is present on the cl:*features* list. Which is likely only for SBCL, or a Lisp which claims to have sb-threads available.
The feature expressions here prevents the Lisp from trying to read symbols with unknown packages - the packages are unknown, because the respective software is not loaded or not available.

Updating the window in response to CLIM frame commands

While trying to figure out CLIM, I ran into this example program. It's a simple maze game. The author claims to have tested it in LispWorks (and even has #+Genera in there, implying that this program would work on a real Lisp Machine), but I'm trying to get it working in SBCL with McCLIM.
Under SBCL/McCLIM, the window draws, but nothing visible happens when you press the movement keys. Non-movement keys cause text to be entered into the pane with the game instructions.
I figured out that the game command keys are changing the game's internal state, so the only problem is that the screen does not update.
Then I realized that you couldn't write code to redraw the maze from the scope of the code that implements the commands. All the methods that draw receive a stream argument from CLIM, which must be passed to the graphics primitives. For example:
(defun draw-stone (stream x y cell-width cell-height)
(let ((half-cell-width (/ cell-width 2))
(half-cell-height (/ cell-height 2)))
(draw-ellipse* stream
(+ (* x cell-width) half-cell-width)
(+ (* y cell-height) half-cell-height)
half-cell-width 0
0 half-cell-height
:ink +red+)))
But the code that handles keystrokes receives no stream argument:
(defmacro define-stone-move-command (name keystroke dx dy)
`(define-maze-frame-command (,name :keystroke ,keystroke) ()
(let ((maze-array (maze-array *application-frame*)))
(move-stone maze-array ,dx ,dy)
(check-for-win maze-array))))
What I ended up having to do is to save the stream argument from the first (and only) call to draw-maze-array to a global variable, so that I could add update code to the define-stone-command macro as follows:
(defmacro define-stone-move-command (name keystroke dx dy)
`(define-maze-frame-command (,name :keystroke ,keystroke) ()
(let ((maze-array (maze-array *application-frame*)))
(move-stone maze-array ,dx ,dy)
(check-for-win maze-array)
(draw-maze-array *application-frame* *maze-stream*))))
This slight alteration gives the desired behavior on SBCL with McCLIM, but this doesn't seem right, however. After all, the author claimed that the code worked fine on LispWorks. I have a few questions:
Can somebody who has LispWorks confirm that this program works as-is on LispWorks?
Does my alteration to the code make it fail on LispWorks?
What is the accepted way to handle screen updating in CLIM applications?
Drawing the maze in the command is not the right approach. Putting a maze-stream into a global variable is also bad. ;-)
The display pane has a :display-function. The idea is that after a command the whole application frame gets updated automagically. For example for :display-time :command-loop, the display pane would be updated automagically, after a command runs. There are other ways to update panes, but in this case a keystroke runs a command and then the top-level-loop would just call the display-function for each applicable pane. The default toplevel-loop reads a command (via mouse, command lines, keystrokes, ...), executes it and updates the application frame - in a loop.
The whole redisplay thing is extremely tricky/powerful. It allows from fully automagical redisplay mechanisms to extremely fine-grained control.
You can read about it here: CLIM 2 Spec. Note: there might be quite a bit difference between the spec and what implementations provide...

Defining aliases to standard Common Lisp functions?

Lisp is said to enable redefinitions of its core functions.
I want to define an alias to the function cl:documentation function, such that
(doc 'write 'function) === (documentation 'write 'function)
How can this be done and made permanent in SBCL?
Creating an Alias
You are not trying to redefine (i.e., change the definition of) the system function documentation, you want to define your own function with a shorter name which would do the same thing as the system function.
This can be done using fdefinition:
(setf (fdefinition 'doc) #'documentation)
How to make your change "permanent" in common lisp
There is no standard way, different implementation may do it differently, but, generally speaking, there are two common ways.
Add code to an init file - for beginners and casual users
SBCL
CLISP
Clozure
ECL
The code in question will be evaluated anew every time lisp starts.
Pro:
Easy to modify (just edit file)
Takes little disk space
Normal lisp invocation captures the change
Con:
Evaluated every time you start lisp (so, slows start up time if the code is slow)
Save image - for heavy-weight professionals
SBCL
CLISP
Clozure
ECL - not supported
The modified lisp world is saved to disk.
Pro:
Start uptime is unaffected
Con:
Requires re-dumping the world on each change
Lisp image is usually a large file (>10MB)
Must specify the image at invocation time
Even though #sds has already answered pretty thoroughly I just wanted to add that the utility library serapeum has defalias
I use a simple macro for this:
(defmacro alias (to fn)
`(setf (fdefinition ',to) #',fn))
e.g.
(alias neg -) => #<Compiled-function ... >
(neg 10) => -10
Other answers include detail about how to make this permanent.

Resources