I'm using CLX+STUMPWM+McCLIM and when I modify the keyboard layout via "setxkbmap us -variant dvorak -option ctrl:nocaps" the keyboard layout fails to update in my CLIM applications, but updates correctly for everything else (thus, to use COLEMAK I run the appropriate shell command prior to starting up CLIM for the first time).
Thoughts on why this might be?
This appears to be a bug in CLX independently affecting McCLIM and stumpwm.
For instance, I'm testing the difference between
setxkbmap -layout us
(querty) and
setxkbmap -layout fr
(azerty). Running those commands doesn't affect neither stumpwm's input bar, nor Climacs. The default querty remains in effect.
X server sends keycodes to applications. Applications may interpret these keycodes using the keymap table, which they can request from the server.
It seems that in CLX the keycode to keysym transformation is carried out by the keycode->keysym function defined in translate.lisp. It calls the display-keyboard-mapping function defined right above it:
(defun display-keyboard-mapping (display)
(declare (type display display))
(declare (clx-values (simple-array keysym (display-max-keycode keysyms-per-keycode))))
(or (display-keysym-mapping display)
(setf (display-keysym-mapping display) (keyboard-mapping display))))
Apparently, this function only requests the keymap table once and caches it. Changing it to
(defun display-keyboard-mapping (display)
(declare (type display display))
(declare (clx-values (simple-array keysym (display-max-keycode keysyms-per-keycode))))
(setf (display-keysym-mapping display) (keyboard-mapping display)))
fixes both the input bar and Climacs. CAVEAT: I don't claim this doesn't break anything else.
NB: If attempting to run a shell command from stumpwm's input bar using the French layout, mind that ! is positioned on /.
Related
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
I understand that Scheme uses ports to perform Input and Output. While trying to learn how to get console input and output, I have come across MIT-Scheme's console-i/o-port variable.
But, the guile interpreter says it is an Unbound Variable. I would like to know how we can use ports to get input from and output to the console (Terminal in Unix) in a Guile Scheme Script. I am still a rookie in Scheme and Linux, a clear step-by-step is appreciated.
Also, how does (display <object>) work? Does it use ports inherently or is there another way.
P.S. If there is another way without using ports please let me know how to use that too.
If you want to read and write SExps, in guile you have (read), (write), (display) etc., if you want to read characters only use (read-char) and (write-char) -- they all use the input/output ports resp. you picked, by default they are stdin and stdout. Everything is rather straightforward (https://www.gnu.org/software/guile/manual/html_node/Input-and-Output.html#Input-and-Output).
You might also be interested in guile-ncurses (https://www.gnu.org/software/guile-ncurses/).
Of some more goodies check out pretty-print module from ice-9 (on very long sexps it's slow but outputs them really nicely formatted, great for e.g. code generation):
(use-modules (ice-9 pretty-print))
(pretty-print `(super cool stuff (+ 2 3) => ,(+ 2 3)))
And if you need your own parser, check out the lalr module (system base lalr).
edit a small example which reads a number, multiplies by itself and prints out the result:
#!/usr/bin/guile -s
!#
(let ((x (read)))
(display (* x x))
(newline))
(remember to chmod +x this script).
edit changed the expression to let form as Chris suggested, indeed the fewer parentheses the better
In guile you have 2 functions: current-input-port and current-output-port (the docs)
to read and put text into string (if you don't want to read s-expressions) you can use this function:
(define (read-port port)
(let iter ((result '()) (chr (read-char port)))
(if (eof-object? chr)
(list->string result)
(iter (append result (list chr)) (read-char port)))))
reading from stdin will be:
(read-port (current-input-port))
to write to stdout you can use display it also accept second argument which is port relevant docs
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...
Following this question: Strange symbols in filespec when calling load I tried my luck with pathnames, but, as you see, failed. Below is an example of the error, which I cannot explain:
This code does not work:
(defun test-process-imgae-raw ()
(cl-gd:with-image-from-file
(test #P"digit-recognition:digit-7.png")
(process-image-raw test)))
Neither does this:
(defun test-process-imgae-raw ()
(cl-gd:with-image-from-file
(test "digit-recognition:digit-7.png")
(process-image-raw test)))
But this code does:
(defun test-process-imgae-raw ()
(cl-gd:with-image-from-file
(test (translate-logical-pathname "digit-recognition:digit-7.png"))
(process-image-raw test)))
And so does this:
(defun test-process-imgae-raw ()
(cl-gd:with-image-from-file
(test (translate-logical-pathname #P"digit-recognition:digit-7.png"))
(process-image-raw test)))
Here's the "translator":
(setf (logical-pathname-translations "DIGIT-RECOGNITION")
`(("**;*.*" "/home/wvxvw/Projects/digit-recognition/**/*.*")))
And here's the error I'm getting:
Pathname components from SOURCE and FROM args to TRANSLATE-PATHNAME
did not match:
:NEWEST NIL
[Condition of type SIMPLE-ERROR]
Restarts:
0: [RETRY] Retry SLIME REPL evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [ABORT] Abort thread (#<THREAD "repl-thread" RUNNING {1003800113}>)
Backtrace:
0: (SB-IMPL::DIDNT-MATCH-ERROR :NEWEST NIL)
1: (SB-IMPL::TRANSLATE-COMPONENT :NEWEST NIL :NEWEST T)
2: (TRANSLATE-PATHNAME #P"DIGIT-RECOGNITION:DIGIT-7.PNG.NEWEST" #P"DIGIT-RECOGNITION:**;*.*" #P"/home/wvxvw/Projects/digit-recognition/**/*.*")
3: (TRANSLATE-LOGICAL-PATHNAME #P"DIGIT-RECOGNITION:DIGIT-7.PNG.NEWEST")
4: (SB-IMPL::QUERY-FILE-SYSTEM #P"DIGIT-RECOGNITION:DIGIT-7.PNG" :TRUENAME NIL)
5: (PROBE-FILE #P"DIGIT-RECOGNITION:DIGIT-7.PNG")
6: (CREATE-IMAGE-FROM-FILE #<unavailable argument> NIL)
7: (TEST-PROCESS-IMGAE-RAW)
I'm trying to read the Hyperspec section on translate-pathname, but I can make absolutely no sense of what it says, neither from the examples it shows. Let alone it, I can't even understand how there can possibly be an error if you transform a string by whatever rules you put in place, so far it's only one way transformation...
I'm trying to read SBCL sources for this function, but they are really lengthy, and trying to figure out the problem this way is taking huge amounts of time.
tl;dr How is it even possible that translate-logical-pathname called from user's code will produce something different to what is produced from that function if called from system code? This is not only non-portable, this is just outright broken.
EDIT:
Adding one more asterisk to the pattern on the left side, but not on the right solved this. But the purpose or logic of why is this necessary is beyond me.
I.e.
(setf (logical-pathname-translations "DIGIT-RECOGNITION")
`(("**;*.*.*" "/home/wvxvw/Projects/digit-recognition/**/*.*")))
This allows pathnames like digit-recognition:foo.bar.newest to succeed, just like digit-recognition:foo.bar but why is that asterisk a requirement flies beyond me. Also, why is the system function feels entitled to change the pathname to something else of what it was given?.. But just not to get you confused, with-image-from-file will only work with the path already expanded by translate-logical-pathname, it won't work otherwise.
EDIT2:
OK, it seems like this is the problem with cl-gd, instead of trying to expand the file name, it takes it literally. This code taken from create-image-from-file probably best answers my question:
(when (pathnamep file-name)
(setq file-name
#+:cmu (ext:unix-namestring file-name)
#-:cmu (namestring file-name)))
(with-foreign-object (err :int)
(with-cstring (c-file-name file-name)
(let ((image (ecase %type
((:jpg :jpeg)
(gd-image-create-from-jpeg-file c-file-name err))
I.e. instead of doing (namestring file-name) it has to do (namestring (trnaslate-logical-pathname file-name)). Duh...
Another way is to use TRUENAME, which returns the real file name. Normally this would not make a difference.
Image a file system with file versions (like the file systems of VMS, ...). If you have a logical pathname foo:bar;baz.png.newest, then it might translate to, say, /myfiles/images/baz.png~newest (again, just assume that it has version numbers). This still is not a real physical file. If such a Lisp system tries to open the file, it has to look into the file system to actually determine the newest file. That might be /myfiles/images/baz.png~42.
So, if you want to pass real physical filenames to external tools (like a C library), it might not be sufficient to expand the logical pathname, but it might be necessary to compute the truename - the real physical file.
The ability to deal with file versions comes from a time when file versions where quite common (see Versioning file system) with operating systems like ITS, VMS or the various Lisp Machine operating systems.
The main practical problem for this is that there is no common test suite for pathname operations for the various CL implementations and thus implementations differ in a lot of subtle details (especially when you need to deal with different file systems from different operating systems). Plus real file systems have complications - for example file names in Mac OS X use a special unicode encoding when dealing with Umlauts.
Quite often I find myself with bunch of R processes running in ESS buffers. There's a convenient Lisp function ess-request-a-process that asks for R process, and brings it to front. The only downside is that it somehow defaults to S, so each time I'm about to make a switch, I have to type R, ad nauseam.
I tried customising the ess-language variable, but even if I set value to "R", i.e. 4 for current session, or even if I save settings for future session, as soon as I type C-c C-k, automagically S appears once again. It's very annoying, and I really don't want to end up with C-x C-b and then C-s for desired R session! =)
I even tried setting (setq-default ess-language "R") in .emacs, but with no luck...
BTW, I'm running Emacs v. 23.1.1 on Linux Mint and Emacs v. 23.2 on Arch Linux, with ESS v. 5.12. If that's relevant, I run Emacs from terminal with -nw argument. Here's my .emacs:
;; start server
(server-start)
;; load ESS
(require 'ess-site)
(require 'ess-rutils)
;; set HTML help as default
(setq inferior-ess-r-help-command "help(\"%s\", help_type = \"html\")\n")
(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.
'(ess-help-kill-bogus-buffers t)
'(ess-rutils-keys nil)
'(show-paren-mode t))
(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.
)
(put 'upcase-region 'disabled nil)
So... how to set R once and for all? (I don't use S/S+/SAS)
I did not know about this function so far. C-c C-k is bound to ess-force-buffer-current in ESS buffers.
[edit: C-c C-k is indeed bound to ess-request-a-process in iESS, in ESS it's ess-force-buffer-current]
In any case the variable you have to customize is ess-dialect
(setq-default ess-dialect "R")
It's buffer-local variable and some other stuff in ess-mode-hook might set it a different value.
Check it in each buffer with C-h v ess-dialect
Additionally, if you already running several processes then ess-switch-process (C-c C-s) might be the right way to go.
[edit: it will not jump to a process but just reset the associated process of the current ESS buffer]
[edit: After dwelling deeper on the issue it turned out that ess-request-a-process uses ess-language variable were the ess-dialect seems to be more appropriate. The problem is that each time an ess-inferior process starts it resets the global value of ess-language. This is why setting it in your case didn't work.
Here is a quick fix:
(defun ess-set-language ()
(setq-default ess-language "R")
(setq ess-language "R")
)
(add-hook 'ess-post-run-hook 'ess-set-language t)
]