I'm trying to use cl-sdl2 with Clozure Common Lisp (on MS-Windows, although I'd think it should work as-is on other platforms and compilers) to draw to two individual graphics windows. When I try the code below:
(ql:quickload "sdl2")
(require :sdl2)
(defun make-two-SDL-2-windows ()
(let* ((win1 (sdl2:create-window :title "Win 1" :w 400 :h 400))
(ren1 (sdl2:create-renderer win1))
(win2 (sdl2:create-window :title "Win 2" :w 300 :h 300))
(ren2 (sdl2:create-renderer win2)))
(sdl2:with-event-loop (:method :poll)
(:keyup
(:keysym keysym)
(when (sdl2:scancode= (sdl2:scancode-value keysym) :scancode-escape)
(sdl2:push-event :quit)))
(:idle ()
(progn
(sdl2:render-present ren1)
(sdl2:render-present ren2)))
(:quit ()
(progn
(sdl2:destroy-renderer ren1)
(sdl2:destroy-renderer ren2)
(sdl2:destroy-window win1)
(sdl2:destroy-window win2)
t)))))
(defun main ()
(sdl2:init :everything)
;;;Clozure...
(process-run-function "window" #'make-two-SDL-2-windows))
(main)
...both of the new windows created "hang", and don't respond/redraw to keypress or mouse movements. I've tried to base this snippet on what I found in the SDL2 examples. I must be misunderstanding how to use the cl-sdl2 wrapper for the event loop, or something similar. Has anyone had success in using multiple windows and SDL2 with Common Lisp?
Here's a working version, thanks to help from Rei:
(defun make-two-SDL-2-windows ()
(sdl2:with-init (:everything)
(sdl2:with-window (win1 :title "Win1" :flags '(:shown))
(sdl2:with-window (win2 :title "Win2" :flags '(:shown))
(sdl2:with-renderer (ren1 win1 :flags '(:renderer-accelerated))
(sdl2:with-renderer (ren2 win2 :flags '(:renderer-accelerated))
(sdl2:with-event-loop (:method :poll)
(:keyup
(:keysym keysym)
(when (sdl2:scancode= (sdl2:scancode-value keysym) :scancode-escape)
(sdl2:push-event :quit)))
(:idle
()
(progn
(sdl2:set-render-draw-color ren1 0 0 255 255)
(sdl2:set-render-draw-color ren2 0 255 0 255)
(sdl2:render-draw-line ren1 150 20 100 300)
(sdl2:render-draw-line ren2 20 20 150 150)
(sdl2:render-present ren1)
(sdl2:render-present ren2)))
(:quit () t))))))))
You defined two windows and renderers without actually using them in the event loop; use sdl2:with-renderer and sdl2:with-window to bind them.
Related
I'm trying to get intero running. After install, opening a Haskell file from an existing stack project results in:
Debugger entered--Lisp error: (wrong-type-argument stringp nil)
signal(wrong-type-argument (stringp nil))
flycheck-buffer()
flycheck-buffer-automatically()
flycheck-perform-deferred-syntax-check()
set-window-buffer(#<window 1 on Lib.hs> #<buffer Lib.hs>)
window--display-buffer(#<buffer Lib.hs> #<window 1 on Lib.hs> reuse ((inhibit-same-window)))
display-buffer-same-window(#<buffer Lib.hs> ((inhibit-same-window)))
display-buffer(#<buffer Lib.hs> (display-buffer-same-window (inhibit-same-window)))
pop-to-buffer(#<buffer Lib.hs> (display-buffer-same-window (inhibit-same-window)) nil)
pop-to-buffer-same-window(#<buffer Lib.hs>)
find-file("~/test/src/Lib.hs" t)
funcall-interactively(find-file "~/test/src/Lib.hs" t)
call-interactively(find-file nil nil)
command-execute(find-file)
When I run flycheck-buffer in the same buffer, nothing happens, even when there are errors in the source code.
Here are the contents of my .emacs file:
(setq debug-on-error t)
(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(package-initialize)
(package-refresh-contents)
(package-install 'intero)
(add-hook 'haskell-mode-hook 'intero-mode)
Since I'm on Mac Os I also tried adding (as suggested on the flycheck page):
(package-install 'exec-path-from-shell)
(exec-path-from-shell-initialize)
But it makes no difference.
Here are the installed package versions:
$ ls ~/.emacs.d/elpa/
archives/
company-20191114.1356/
dash-20191109.1327/
epl-20180205.2049/
flycheck-20191126.1329/
haskell-mode-20191120.1923/
intero-20191103.1239/
pkg-info-20150517.1143/
This is using GNU Emacs 26.3.
TL;DR
I found two issues and a (at least temporary) fix for each of them.
I am submitting pull requests for both of them, but in the mean time you can fix the issue for yourself either by editing the intero.el file directly, or (recommended way) by using the great el-patch package.
1) intero-ghc-version not set
This is due to the fact of using the intero-ghc-version local variable instead of calling the function (intero-ghc-version) in the intero-ghci-output-flags function (L.2668) intero.el
Fix: patch the function intero-ghci-output-flags :
replace
(split-string intero-ghc-version "\\."))))
by
(split-string (intero-ghc-version) "\\."))))
(notice the added parentheses)
2) misuse of append for string concatenation in intero-start-process-in-buffer
append is for lists, concat is for strings, an easy mistake, especially when in Haskell String is equivalent to [Char] (so technically... a list!)
fix: patch the function intero-start-process-in-buffer, L.2335 of the intero.el:
replace
(process-send-string process (append ":set " flag "\n")))
by
(process-send-string process (concat ":set " flag "\n")))
line 2335 of the current version of the source code, using el-patch)
Once these modifications are made, you should be up and running!
Initial answer
Same issue here.
Not a definitive answer, but I have the same issue and might have pinned down the issue to the function intero-ghci-output-flags being run as the intero-ghc-version variable is not set properly.
Feel free to correct me as I might have missed some things.
By following the error messages, I confirm it happens in (flycheck-start-current-syntax-check checker) in the flycheck-buffer function.
Running this directly from the haskell buffer shows that the error happens when calling (split-string intero-ghc-version "\\.") from the intero-ghci-output-flags function in the intero.el file (Line 2671).
This tries to split the intero version (as set by the intero-ghc-version function above in the file).
It seems the variable's value is nil, as confirmed by running M-x describe-variable -> intero-ghc-version.
During my tests I got seemingly imprevisible results from (intero-ghc-version).
Sometimes (at least on the first run?) it returns "8.4.4",
sometimes it fails with "Wrong type argument: stringp, (58 115 101 116 32 45 102 111 98 106 ...)
I am able to manually run the function intero-ghci-output-flags and get the proper output without error, once, and it fails if I run it a second time.
the function (intero-ghc-version-raw) consistently returns "8.4.4" however.
After experimenting the error message that spontaneously appears is transformed to:
Debugger entered--Lisp error: (wrong-type-argument stringp (58 115 101 116 32 45 102 111 98 106 101 99 116 45 99 111 100 101 . "\n"))
process-send-string(#<process stack> (58 115 101 116 32 45 102 111 98 106 101 99 116 45 99 111 100 101 . "\n"))
#f(compiled-function (flag) #<bytecode 0x1785fe9>)("-fobject-code")
mapc(#f(compiled-function (flag) #<bytecode 0x1785fe9>) ("-fobject-code"))
intero-start-process-in-buffer(#<buffer intero:backend:pubiber /home/mika/programmation/haskell/pubiber> nil #<buffer Lib.hs> nil)
intero-get-worker-create(backend nil #<buffer Lib.hs> nil)
intero-buffer(backend)
intero-eldoc()
The ASCII char sequence in the error message is ":set -fobject-code".
The "-fobject-code" in the message is the result of the intero-ghci-output-flags function, so it seems it finally worked properly but the rest of the code failed.
Note:
The fact that the file gets re-evaluated whenever intero tries to start a session might to explain why I get inconsistent results when running the functions several times.
PS running arch linux, system updated a few minutes ago, all emacs package updated.
---- EDIT ----
So after looking a bit more, in the function intero-start-process-in-buffer, that uses the flags to start the intero process in the lines 2334-2337:
(set-process-query-on-exit-flag process nil)
(mapc
(lambda (flag)
(process-send-string process (append ":set " flag "\n")))
(intero-ghci-output-flags))
(process-send-string process ":set -fdefer-type-errors\n")
they use append instead of concat to create the command.
replacing append by concat fixes this second error, and intero boots normally and seems to work properly (after setting intero-ghc-version).
---- EDIT 2 ----
Just figured out the original issue:
The function uses the variable intero-ghc-version instead of calling the function with the same name. The function is supposed to act as a lazy loader of the value, calling intero-ghc-version-raw the first time, and returning the cached value the subsequent times.
Calling the variable directly didn't allow the value to be set initially.
See the TL;DR for the temporary fix.
I want to compile my .cljs file for both browser and node.js environments, to get server side rendering. As I understand, there's no way to define cljs env in compile time with reader macro conditions like:
#?(:clj ...)
#?(:cljs ...)
so, I can't easily tell compiler to process something like #?(:cljs-node ...) in node.js env.
Second option I see here is to develop a macro file which will define env at compile time. But how to define that current build is targeting node.js? May be, I could pass some params somehow to compiler or get :target compiler param?
Here are my boot files:
application.cljs.edn:
{:require [filemporium.client.core]
:init-fns [filemporium.client.core/init]}
application.node.cljs.edn:
{:require [filemporium.ssr.core]
:init-fns [filemporium.ssr.core/-main]
:compiler-options
{:preamble ["include.js"]
:target :nodejs
:optimizations :simple}}
I am not aware of a public API to achive this. However, you might use cljs.env/*compiler* dynamic var in your macro to check the target platform (i.e. NodeJS vs browser) configured with :target in your :compiler-options and either emit or suppress the code wrapped in the macro:
(defn- nodejs-target?
[]
(= :nodejs (get-in #cljs.env/*compiler* [:options :target])))
(defmacro code-for-nodejs
[& body]
(when (nodejs-target?)
`(do ~#body)))
(defmacro code-for-browser
[& body]
(when-not (nodejs-target?)
`(do ~#body)))
(code-for-nodejs
(def my-variable "Compiled for nodejs")
(println "Hello from nodejs"))
(code-for-browser
(def my-variable "Compiled for browser")
(println "Hello from browser"))
Here is up to date code working on org.clojure/clojurescript {:mvn/version "1.11.60"}
(ns contrib.cljs-target
#?(:cljs (:require-macros [contrib.cljs-target]))
#?(:cljs (:require [goog.object :as object])))
; preferred runtime check for target through public API https://cljs.github.io/api/cljs.core/STARtargetSTAR
#?(:cljs (defn nodejs? [] (= cljs.core/*target* "nodejs")))
#?(:cljs (defn browser? [] (= cljs.core/*target* "default")))
; undocumented hack, only works in macros. https://stackoverflow.com/a/47499855
#?(:clj (defn- cljs-target [] (get-in #cljs.env/*compiler* [:options :closure-defines 'cljs.core/*target*])))
(defmacro do-nodejs [& body] (if (= "nodejs" (cljs-target)) `(do ~#body)))
(defmacro do-browser [& body] (if-not (= "nodejs" (cljs-target)) `(do ~#body)))
I used AutoIt's _ScreenCapture_Capture() before without any trouble. But on Windows 10 with a 4k resolution screen I'm using DPI scaling at 200%. _ScreenCapture_capture() now gets something 2x zoomed in and half the location I asked for.
For instance :
_ScreenCapture_Capture("c:\a.bmp", 100, 100, 200, 200)
; Path, X1, Y1, X2, Y2
Does not return a 100x100 pixel square of the screen (at 100,100 to 200,200). It returns a 100x100 pixel square (at 50,50 to 100,100) instead.
I did find a solution :
DllCall("User32.dll", "bool", "SetProcessDPIAware")
However this screws up the GUI looks. So I then found this code:
GUISetFont(8.5 * _GDIPlus_GraphicsGetDPIRatio()[0])
Func _GDIPlus_GraphicsGetDPIRatio($iDPIDef = 96)
Local $aResults[2] = [1, 1]
_GDIPlus_Startup()
Local $hGfx = _GDIPlus_GraphicsCreateFromHWND(0)
If #error Then Return SetError(1, #extended, $aResults)
#forcedef $__g_hGDIPDll, $ghGDIPDll
$aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0)
If #error Then Return SetError(2, #extended, $aResults)
Local $iDPI = $aResult[2]
Local $aresults[2] = [$iDPIDef / $iDPI, $iDPI / $iDPIDef]
_GDIPlus_GraphicsDispose($hGfx)
_GDIPlus_Shutdown()
Return $aresults
EndFunc ;==>_GDIPlus_GraphicsGetDPIRatio
Which works great for the GUI but doesn't help for _ScreenCapture_Capture() calls. Seems I can either have a good looking- or a functioning program, not both.
How could I combine these two solutions to get both a good GUI and a functioning program? If I knew how to do the opposite of :
DllCall("User32.dll", "bool", "SetProcessDPIAware")
Then when I need to capture a screen portion I could turn on compatibility, then immediately turn it off when done capturing. But I don't know how to 'UNsetprocessdpiaware'.
If you are using Windows 10 A update (10.0.14393) you can spin up a separate thread and make the thread alone Per Monitor DPI aware, and leave your main GUI as dpi unaware.
See
SetThreadDpiAwarenessContext function
If you are building using a version of visual studio before 2015 you can declare a pointer to the function prototype
DPI_AWARENESS_CONTEXT WINAPI SetThreadDpiAwarenessContext(
_In_ DPI_AWARENESS_CONTEXT dpiContext
);
and use GetProcAddress to test for the presence of the function before you call it. Anything in that thread will give you raw physical information if you used
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
Note that this function is not available on Windows 10 10.0.10586. You must test for its availability.
I'm trying to create my first "real program" in haskell (something that solves integrals if polynomials) but I'm completely stumped with this part of it:
I want to make something very simple a bit like GHCi:
> user input
program output
> user input
program output
> user input
program output
>
except that my program output is images (using LaTeX to turn mathematical expressions into PNGs) - so I can't do this using System.IO. I think it will be possible with gtk2hs which I've managed to install but I can't figure out how to make this input/output dialogue.
Please show me how it's done if you have the time. Thanks a lot!
We managed to come up with the following solution, thanks to ClaudiusMaximus.
module Main where
import Graphics.UI.Gtk
main = do
initGUI
----------------
win <- windowNew
onDestroy win mainQuit
vb <- vBoxNew False 3
log <- vBoxNew False 2
sc <- scrolledWindowNew Nothing Nothing
scrolledWindowSetPolicy sc PolicyNever PolicyAutomatic
sw <- layoutNew Nothing Nothing
en <- entryNew
----------------
scrolledWindowAddWithViewport sc log
boxPackStart vb sc PackGrow 0
boxPackStart vb en PackNatural 0
set win [ containerChild := vb ]
en `onEntryActivate` do
txt <- entryGetText en
entrySetText en ""
l <- labelNew (Just txt)
boxPackStart log l PackNatural 0
widgetShowAll log
Just ran <- scrolledWindowGetVScrollbar sc
adj <- rangeGetAdjustment ran
max <- adjustmentGetUpper adj
adjustmentSetValue adj max
----------------
widgetShowAll win
mainGUI
I think you should first implement the backend, i.e. the code for parsing a command and creating the output image. If that works, you could then implement the GUI. Basically, you need something light a text entry for input and an text and drawing widget for output. As GUI programming is (IMHO) not trivial, you should first look at some GTK/gtk2hs tutorials / introductions.
I'm able to open a zip entry and tweak the contents, but I can't figure out how to save them.
The API for CL ZIP is wanting.
Specs:
ZIP
Quicklisp
MacPorts CLISP 2.49
Aquamacs 2.1 (Emacs 23.2)
Mac OS X 10.6.4
MacBook Pro 5,1
; Removes newlines at the beginning of PRE tags in Sigil-edited ePub files.
;
; See http://code.google.com/p/sigil/issues/detail?id=655
;
; Andrew Pennebaker
; 16 Nov 2010
; Requires Quicklisp.
; http://www.quicklisp.org/
(ql:quickload "zip")
(ql:quickload "cl-ppcre")
(defvar *epub* nil)
(defvar *epub-contents* nil)
(defvar *epub-out* nil)
(defun load-epub (filename)
(setq *epub* (zip:open-zipfile filename)))
(defun close-epub ()
(zip:close-zipfile *epub*)
(setq *epub* nil)
(setq *epub-contents* nil))
(defun gather-epub-contents ()
(zip:do-zipfile-entries (name entry *epub*)
(push name *epub-contents*)))
(defun is-html-file (name)
(if (cl-ppcre:scan ".+\\.htm[l]?$" name) t nil))
(defun entry-name-to-html (name)
(flexi-streams:octets-to-string
(zip:zipfile-entry-contents
(zip:get-zipfile-entry name *epub*))))
(defun clean (html)
(values
(cl-ppcre:regex-replace-all
"<pre[^>]*>(\\s)*"
(cl-ppcre:regex-replace-all "\\s+</pre>" html "</pre>")
"<pre>")))
As per the documentation of the Common Lisp ZIP library, you have to obtain a separate handle to write to the zip file. Probably you can extract the contents to a folder, tweak the contents and compress the whole folder with a single call to (zip path-name source-folder).
Using a temp file, you're able to unzip, modify, and rezip.
See sigil-clean.cl