using sbcl schedule-timer with sly - timer

I want to use a timer to periodically print info to the repl (and do some other things).
SBCL 2.0.1
Emacs 26.1
sly 1.0.0-beta-3
(I can't create a sly tag...)
in sly-repl:
(defvar *timer* (make-timer (lambda ()
(write-line ".")
(force-output))))
(schedule-timer *timer* 2 :repeat-interval 1)`
and works fine - after 2 seconds, "." is printed
in timer-test.lisp:
(defvar *timer* (make-timer (lambda ()
(write-line ".")
(force-output))))
(schedule-timer *timer* 2 :repeat-interval 1)`
compiles fine
when I execute the schedule-timer form, the REPL tells me:
Timer #<TIMER {1002C5EB33}> failed to interrupt thread #<SB-THREAD:THREAD "slynk-worker" FINISHED values: T {1002C3DFA3}>.
I don't know enough about threads in SBCL to sort this out. Is there a simple way to get a scheduled timer (in a file) to output to the REPL?
with thanks for your help.

Here is a version of your code which tries to use some SWANK functionality to find out what the REPL thread is and schedule the timer in that thread. Note that this won't work with SLY as far as I can tell because SLY has different package names at least. However it may provide a clue and it's too long to be a comment.
Note also that I don't know if this is the right way of finding the REPL thread, or if the REPL thread actually persists for any length of time.
If repl-thread-maybe fails to find a candidate thread, it returns t, which causes make-timer to run the timer in its own thread. This is safe I think, but will mean that any output from the timer (assuming that's what you are after) goes somewhere other than the REPL.
Anyway, here it is for what it's worth
;;;;
;;;
(in-package :cl-user)
#-(and SBCL SWANK)
(eval-when (:compile-toplevel :load-toplevel :execute)
(error "Not SBCL / not SWANK"))
(defun repl-thread-maybe (&key (repl-thread-name "repl-thread")
(fallback-value t))
;; I have no idea if this is the right way to find the REPL thread,
;; but it kind of works.
(or (find-if (lambda (thread)
(string-equal (swank/backend:thread-name thread)
repl-thread-name))
(swank/backend:all-threads))
fallback-value))
(defparameter *timer* (make-timer (lambda ()
(write-line ".")
(force-output))
:thread (repl-thread-maybe)))
(schedule-timer *timer* 2 :repeat-interval 1)

Related

lisp package not available at read time when loading is deferred

I made a small repro for this issue using only lisp.
file1.lisp :-
(defpackage :my_package
(:use :cl))
(in-package :my_package)
(defun subscribe (x) (print x)(terpri))
(export '(subscribe))
(in-package :cl-user)
file2.lisp :-
(defun loader ()
(load "file1.lisp")
(my_package:subscribe "hello"))
(loader)
Now, running this gives the same error :-
sbcl --load file2.lisp
This is SBCL 2.1.11.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
debugger invoked on a SB-C::INPUT-ERROR-IN-LOAD in thread
#<THREAD "main thread" RUNNING {1001834103}>:
READ error during LOAD:
Package MY_PACKAGE does not exist.
Line: 3, Column: 22, File-Position: 59
Stream: #<SB-INT:FORM-TRACKING-STREAM for "file /home/omkarwagh/swarajya/scratch/file2.lisp" {10009BF613}>
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT ] Abort loading file "/home/omkarwagh/swarajya/scratch/file2.lisp".
1: [CONTINUE] Ignore runtime option --load "file2.lisp".
2: Skip rest of --eval and --load options.
3: Skip to toplevel READ/EVAL/PRINT loop.
4: [EXIT ] Exit SBCL (calling #'EXIT, killing the process).
(SB-C:COMPILER-ERROR SB-C::INPUT-ERROR-IN-LOAD :CONDITION #<SB-INT:SIMPLE-READER-PACKAGE-ERROR "Package ~A does not exist." {10018375A3}> :STREAM #<SB-INT:FORM-TRACKING-STREAM for "file /home/omkarwagh/swarajya/scratch/file2.lisp" {10009BF613}>)
4
I guess that the problem is that we don't know the package at read time because the relevant file has not been loaded yet.
So the question is, what is the recommended practice in this case?
Original question
I have a roswell script that I've attached below. I have an asdf system called "my_system" which has only one module with one file that contains only one package called "my_package".
Somehow, the asdf system is being loaded but when I try to actually use any of the functions in it, then it fails with an error saying that "my_package" is not found
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 $(readlink -f $(dirname $(readlink -f $0)))/asdf.conf "$#"
|#
(progn ;;init forms
(ros:ensure-asdf)
#+quicklisp(ql:quickload '() :silent t)
)
(defpackage :ros.script.test.3880638094
(:use :cl))
(in-package :ros.script.test.3880638094)
(require "asdf")
;(asdf:load-system "my_system")
;(print #'my_package:subscribe)
(defun main (mydir &rest argv)
(declare (ignorable argv))
(asdf:initialize-source-registry `(:source-registry :inherit-configuration (:include ,mydir)))
(asdf:load-system "my_system")
(sleep 0.2)
(print "here3")(terpri)
(print (list-all-packages))
(do-external-symbols (s (find-package :my_package)) (print s))
(print #'my_package::subscribe)(terpri)
)
;;; vim: set ft=lisp lisp:
The error is :-
Unhandled SB-C::INPUT-ERROR-IN-LOAD in thread #<SB-THREAD:THREAD "main thread" RUNNING
{1004460113}>:
READ error during LOAD:
Package MY_PACKAGE does not exist.
However, if I comment out this line :-
(print #'my_package::subscribe)(terpri)
I do in fact, see the package in the list of packages as well as the symbol in question :-
#<PACKAGE "MY_PACKAGE">
MY_PACKAGE:SUBSCRIBE
As you said, the error is signalled because the package does not exist at the read time (when the form is read as text and translated to symbols).
The most straightforward option to change the code above this is to create the symbol when function is executed, e.g., (funcall (intern "SUBSCRIBE" 'my-package)). Variant of this (using read-from-string instead of intern) can be seen in the Swank or Slynk loader.
If you use asdf (which is implied in your question), you should probably use uiop to do this for you - see uiop:symbol-call. For example, documented way to define test-op is with
:perform (test-op (o c) (symbol-call :fiveam '#:run! :foobar)))
However, most libraries structure files in such a way that this issue does not arise - the file1.lisp would be loaded before file2.lisp (e.g., using asdf system definition).

Emacs executes `c-mode-hook` twice

Here's my emacs config
(require 'cc-mode)
(defun ffy-c-mode-hook ()
"This is settings for the C/C++ mode"
(message "ffy-c-mode-hook executed")
(electric-pair-mode +1)
(electric-indent-local-mode +1)
(if electric-indent-mode
(let ((binding (key-binding (kbd "RET"))))
(local-set-key (kbd "RET") (key-binding (kbd "C-j")))
(local-set-key (kbd "C-j") binding)))
(c-toggle-hungry-state +1)
(c-set-style "gnu")
(setq c-basic-offset 4))
(add-hook 'c-mode-hook #'ffy-c-mode-hook)
Apparently c-mode-hook is executed twice, because when I open a C file I see:
user-error: Beginning of history; no preceding item
ffy-c-mode-hook executed [2 times]
Is it a feature or a bug ? No other hooks are executed multiple times AFAIK. Plus it seems that now I can't toggle features in the hook.
I looked at the variable c-mode-hook and it its value is (ffy-c-mode-hook)
The versions of Emacs and CC-mode are
GNU Emacs 24.5.1 (i686-pc-mingw32) of 2015-04-11 on LEG570
Using CC Mode version 5.32.5
Stacktrace on ffy-c-mode-hook
ffy-c-mode-hook()
run-hooks(change-major-mode-after-body-hook prog-mode-hook c-mode-common-hook c-mode-hook c-mode-hook)
apply(run-hooks (change-major-mode-after-body-hook prog-mode-hook c-mode-common-hook c-mode-hook c-mode-hook))
run-mode-hooks(c-mode-hook)
c-mode()
set-auto-mode-0(c-mode nil)
set-auto-mode()
Following my comment about the bug report http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16759 I don't think that language hooks are guaranteed to be executed once for a number of language modes. I suspect the issue is due to using define-derived-mode which is a lisp macro for defining a mode that already includes calls to hooks, this means the hooks called in the mode will be an additional execution.
You might want to try the initialization hook. The manual says:
Variable: c-initialization-hook
Hook run only once per Emacs session, when CC Mode is initialized. This is a good place to change
key bindings (or add new ones) in any of the CC Mode key maps. See
Sample Init File.
The sample it gives is here: https://www.gnu.org/software/emacs/manual/html_node/ccmode/Sample-Init-File.html#Sample-Init-File

How to add a "sleep" or "wait" to my Lua Script?

I'm trying to make a simple script for a game, by changing the time of day, but I want to do it in a fast motion. So this is what I'm talking about:
function disco ( hour, minute)
setTime ( 1, 0 )
SLEEP
setTime ( 2, 0 )
SLEEP
setTime ( 3, 0 )
end
and so on. How would I go about doing this?
Lua doesn't provide a standard sleep function, but there are several ways to implement one, see Sleep Function for detail.
For Linux, this may be the easiest one:
function sleep(n)
os.execute("sleep " .. tonumber(n))
end
In Windows, you can use ping:
function sleep(n)
if n > 0 then os.execute("ping -n " .. tonumber(n+1) .. " localhost > NUL") end
end
The one using select deserves some attention because it is the only portable way to get sub-second resolution:
require "socket"
function sleep(sec)
socket.select(nil, nil, sec)
end
sleep(0.2)
If you have luasocket installed:
local socket = require 'socket'
socket.sleep(0.2)
This homebrew function have precision down to a 10th of a second or less.
function sleep (a)
local sec = tonumber(os.clock() + a);
while (os.clock() < sec) do
end
end
wxLua has three sleep functions:
local wx = require 'wx'
wx.wxSleep(12) -- sleeps for 12 seconds
wx.wxMilliSleep(1200) -- sleeps for 1200 milliseconds
wx.wxMicroSleep(1200) -- sleeps for 1200 microseconds (if the system supports such resolution)
I know this is a super old question, but I stumbled upon it while I was working on something. Here's some code that's working for me...
time=os.time()
wait=5
newtime=time+wait
while (time<newtime)
do
time=os.time()
end
And I needed randomization so I added
math.randomseed(os.time())
math.random(); math.random(); math.random()
randwait = math.random(1,30)
time=os.time()
newtime=time+randwait
while (time<newtime)
do
time=os.time()
end
I needed something simple for a polling script, so I tried the os.execute option from Yu Hao's answer. But at least on my machine, I could no longer terminate the script with Ctrl+C. So I tried a very similar function using io.popen instead, and this one does allow early termination.
function wait (s)
local timer = io.popen("sleep " .. s)
timer:close()
end
You should read this:
http://lua-users.org/wiki/SleepFunction
There are several solutions and each one has a description, which is important to know.
This is, what I used:
function util.Sleep(s)
if type(s) ~= "number" then
error("Unable to wait if parameter 'seconds' isn't a number: " .. type(s))
end
-- http://lua-users.org/wiki/SleepFunction
local ntime = os.clock() + s/10
repeat until os.clock() > ntime
end
if you're using a MacBook or UNIX based system, use this:
function wait(time)
if tonumber(time) ~= nil then
os.execute("Sleep "..tonumber(time))
else
os.execute("Sleep "..tonumber("0.1"))
end
wait()
You can use "os.time" or "os.clock" with "while" loop, i prefer "repeat until" loop because its shorter, but they are expensive because they cost full usage of a single core.
If you need something less demanding, you can use various wrappers like wxLua that i use, but sometimes, some of them also got usage penalty, specially annoying in games, so its best to test them and get what is best for your project.
Or you can relay on OS like Windows to do sleep function, using applications that exist in system32, via Batch or PowerShell, using ">nul" to hide it with "os.execute" or "io.popen", like "ping" (localhost/127.0.0.1) with timeout, "choice" (works with XP, newer versions may be different, i prefer it), "timeout" (/nobreak may be useless because all Windows commands can be canceled with CTRL+C). Downside are limited to given OS and number limitation as well as seconds or miliseconds, running it on eg. Linux may need Wine emulation for Windows (if application are written for it). You can also use "sleep" or "start-sleep" (from PowerShell), but since Lua are standalone, most people prefer pure Lua or wrappers, and you can use what suits your project.
function wait(time)
local duration = os.time() + time
while os.time() < duration do end
end
This is probably one of the easiest ways to add a wait/sleep function to your script

Emacs lisp - problems with filename-string on win7

On Win7 with Emacs24 I encounter problems when Emacs programs want to open (pdf) files. The problems remain when I activate or deactivate openwith-mode. I either get a 'wrong-type-argument arrayp nil' message inside Emacs or Acrobat Reader is started but gives an error message 'can't open/find that file'.
I tried to debug it and always ended up in files.el.
It seems that the name of the pdf-file to be opened is constructed by concatenating the absolute filename and the file extension .pdf. However, the filename-string given to AcroRd32 appears to look like this:
AcroRd32 "c:\\absolute\file\name".pdf
This doesn't work on the command line either. I have to change it (manually) to
AcroRd32 "c:\\absolute\file\name.pdf"
or to
AcroRd32 c:\\absolute\file\name.pdf
to make it work.
I don't know if this is considered a bug, or if it is a problem only for me. I tried to change the elisp code to something like
(format "%s" (concat absolute-filename file-extension))
to get rid of those double-quotes, but to no avail. And anyway, I don't feel comfortable to mess around in a basic library like files.el, and its really hard to edebug that library since its invoked permanently.
Maybe somebody encountered the same problem and found a solution?
[I use GNU Emacs 24.0.91.1 (i386-mingw-nt6.1.7601) of 2011-11-22 on MARVIN.]
PS 1 Test Case 1
I get the following error message when I do M-x toggle-debug-on-error and then try to open a pdf file in dired:
Debugger entered--Lisp error: (wrong-type-argument arrayp nil)
file-truename(nil)
find-file-noselect-1(#<buffer test.pdf<4>> "~/.emacs.d/org/projects/sandbox/test.pdf" nil nil "~/.emacs.d/org/projects/sandbox/test.pdf" ((2816 7 . 27468) (16087 . 35227)))
find-file-noselect("c:/Users/tj2/.emacs.d/org/projects/sandbox/test.pdf" nil nil nil)
find-file("c:/Users/tj2/.emacs.d/org/projects/sandbox/test.pdf")
dired-find-file()
call-interactively(dired-find-file nil nil)
and the following message:
Openwith mode enabled
find-file-noselect-1: Wrong type argument: arrayp, nil
Does it matter that my .emacs.d is really a windows symlink (mklink) to a Dropboxfolder?
PS 2 Test Case 2
here is the message I get in the maven-compile buffer, when doing C-c C-s (LilyPond-command-view) in a ,ly buffer:
-*- mode: compilation; default-directory: "~/.emacs.d/org/projects/sandbox/" -*-
Compilation started at Tue Dec 20 09:16:28
AcroRd32 "c:/Users/tj2/.emacs.d/org/projects/sandbox/2test".pdf
Compilation exited abnormally with code 1 at Tue Dec 20 09:16:35
In the message buffer I find
Compilation exited abnormally with code 1
Error during redisplay: (invalid-regexp "Unmatched ( or \\(")
This error doesn't trigger the debugger, although I did M-x toggle-debug-on-error.
Sounds like a bug, to me. Consider reporting it: M-x report-emacs-bug.
Dunno why Michael H. sent you to a Sunrise Commander page with a tip about OpenWith. Perhaps I'm missing something in your question where you indicate that you use one of those packages?
I would suggest reporting an Emacs bug. And if you want to see more about opening Windows apps associated with file types etc. then I'd suggest consulting this page.
This seems to be a problem with openwith.el, so I don't think you'll get much help with an Emacs bug report since openwith.el is not part of Emacs.
I've found a similar error (I'm on Linux) and decided that it would be better to use a "cleaner" alternative that doesn't tweak find-file-noselect (see that page on emacs.sxe for why). The OpenWith wiki page pointed me to a less-popular little bit of glue code,
https://www.emacswiki.org/emacs/download/run-assoc.el (code)
https://www.emacswiki.org/emacs/RunAssoc (docs)
By default this package's run-associated-program is not well-integrated with the usual Emacs workflow, but here is how you can integrate it with helm-find-files (also documented at the above link).
(require 'run-assoc)
(setq associated-program-alist
'(("evince" "\\.pdf$")
("play" "\\.mp3$")))
(defun helm-find-files-maybe-run-assoc (orig-fun &rest args)
(let ((sel (helm-get-selection)))
(if (string-match (mapconcat
(lambda (x) (second x))
associated-program-alist "\\|")
(helm-get-selection))
(run-associated-program sel)
(apply orig-fun args))))
(advice-add 'helm-execute-selection-action
:around #'helm-find-files-maybe-run-assoc)

monitoring file changes in racket (like tail -f)

I would like to implement a "tail -f" like behavior in Racket. That is, I would like to read from a file, and when I hit the end, be able making something like a "blocking" (read-line file), that shall return when some other process appends a line to file.
I tried synchronizing with (read-line-evt file) but, if I am at the end of file, instead of blocking until other data is available, it returns immediately.
Is there a way to do it?
I don't think that you have any way to avoid polling the file.
Note that all of Racket's input functions consider eof a value that should be returned when it reaches the end of the input stream -- so all of the events immediately return that when the end is reached. At least I don't see anything that looks like a "wait until some input is ready, not eof".
In any case, you also have the ffi, if you know about some system call that triggers a callback instead of polling the file. AFAICT, the linux source code for tail uses inotify, so you might be able to use an old package that interfaces that from racket called mzfam. (But it's pretty old and might need some update work.)
I don't know when Racket added file system change events, but I suspect it was since this question was asked many years ago. Now you can wait on such an event and see if you can read another line (It's not fine grained enough to tell specifically that more data was appended to the file, just that something changed about it.)
An example of a basic tail -f like program to demonstrate file-system-change-evt:
;;; tail.rkt
#lang racket/base
(require racket/list racket/port)
;;; Some utility functions and macros
;; Like take but return the list if it's less than n elements long
;; instead of raising an error
(define (take* list n)
(with-handlers ([exn:fail:contract? (lambda (e) list)])
(take list n)))
;; Repeat body forever until a break is received
(define-syntax-rule (forever body ...)
(with-handlers ([exn:break? (lambda (e) (void))])
(let loop ()
body ...
(loop))))
;; Display the last N lines of a file. Could be more efficient, but
;; this part's not the point...
(define (display-last-lines port n)
(for-each displayln
(reverse
(for/fold ([lines '()])
([line (in-lines port)])
(take* (cons line lines) n)))))
;; Wait for the file's status to change and try to read lines when it does.
(define (follow-tail file)
(call-with-input-file file
(lambda (port)
(display-last-lines port 10)
(forever
(sync (filesystem-change-evt file))
(for ([line (in-lines port)])
(displayln line))))))
(module+ main
(unless (= (vector-length (current-command-line-arguments)) 1)
(displayln "Usage: racket tail.rkt FILENAME" (current-error-port))
(exit 1))
(follow-tail (string->path (vector-ref (current-command-line-arguments) 0))))
After being inspired by this question and Eli's mention of inotify in his answer, and seeing that there still wasn't a Racket package to provide access to it (I think the standard file system change code uses it internally, but it's not exposed at any low level to users), I wrote it myself. A version of the core tail function from above using it:
(require inotify)
(define (follow-tail file)
(call-with-input-file file
(lambda (port)
(display-last-lines port 10)
(call-with-inotify-instance
`((,file (IN_MODIFY)))
(lambda (inotify wds)
(forever
(sync inotify)
(for ([line (in-lines port)])
(displayln line))))))))

Resources