List buffers associated with files? - list

I'm very new to using lisp, so I'm sorry if this is a trivial question. I haven't been able to find solutions after a while googling, though I'm sure that this is fault on my part.
So. I'm trying to write a command which will revert all open buffers. Simple. I just do
(setq revert-without-query (buffer-list))
(mapc 'revert-buffer (buffer-list))`
Unfortunately, this ends up failing if there are any buffers which aren't associated with files- which is to say, always.
Doing C-x C-b to list-buffers prints something like
CRM Buffer Size Mode File
init.el 300 Emacs-lisp ~/.spacemacs.d/init.el
%scratch% 30 Test
Ok. Easy enough. If I was allowed to mix lisp and python, I'd do something like
(setq revert-without-query [b for b in buffer-list if b.File != ""])
;; Or would I test for nil? Decisions, decisions...
Upon some digging, I found that there exists remove-if. Unfortunately, being completely new to lisp, I have no idea how to access the list, their attributes, or... well... anything. Mind helping me out?

One possibility would be checking buffer-file-name which will return nil if the buffer isn't visiting a file, eg.
(cl-loop for buf in (buffer-list)
if (buffer-file-name buf)
collect buf)
or
(cl-remove-if-not 'buffer-file-name (buffer-list))

You probably want to revert dired directories also. Any type of buffer can have its own specialized revert (see revert-buffer-function). So you probably want to check for both buffer-file-name and dired-directory being non-nil.
(dolist (b (buffer-list))
(when (buffer-live-p b)
(with-current-buffer b
(when (or buffer-file-name dired-directory)
(revert-buffer 'ignore-auto 'noconfirm)))))
You can also use the ignore-errors hammer, but you're probably better off fixing corner cases as you encounter them.

Related

Null pointer exception when trying to write to file using riemann

I am trying to set up multiple logging streams for riemann. I have decided to use the simple Clojure file write function to set up additional streams. However, the file is written to as soon as riemann is reloaded but results in a null pointer exception when the relevant event is called and the file needs to be written to.
(where (and (or (tagged "source1") (host "shubham"))
(not (= (:installation_id event) "default")))
(smap (fn [event] (prepare-influx-event event {:time-unit :nanoseconds}))
influx
)
(let [wrtr (io/writer "/var/log/riemann/test.txt" :append true)]
(.write wrtr "Listen please1\n")
(.close wrtr))
;;(spit "/var/log/riemann/test.txt" "Listen please2\n" :append true)
)
the riemann config contains a Clojure expression that is run when riemann starts. The result of running this expsreassion, that is the thing that evaluating it returns, is then used to process all the events. Riemann's config file is a function, which returns a function that will do the actual work. (insert yo'dog memes here)
In this case, when riemann loads that last expression it, while it's getting ready to run, it will open the file, write to it, close it. then it will take the result of closing it and treat that as the function to handle events.
the result of closing a file is null, so it will later try to "run" that null as a function and a NPE results.
you likely want an smap around the let, or just remove the close as you want riemann to keep this file open the whole time it runs. depending on what your going for you may consider making the call to smap above be the last expression inside the let.
below this line is purely my opinion, and not part of the answer:
you almost certainly want to use a proper logging-thing to log stuff to disk on the riemann host. These hosts tend to run for a long time uninterrupted (i tend to leave them a couple years) and if you have it writing to a single file, that file will eventually encounter physics (full disk, size limit etc.) and then if you ssh in and delete it, no space will be freed because riemann will still have the file open. This somehow seems to always happen during some event where you'd really rather monitoring was working. Using a thing with log-rotation is generally a good idea.

Support for ANSI escape sequence cursor moving

I'm making a simple ASCII animation, and I need the ability to place the cursor at an arbitrary point in the console screen.
While searching, I found this blog that shows this can be achieved by doing:
(print (str (char 27) "[2J")) ; clear screen
(print (str (char 27) "[;H")) ; move cursor to the top left corner of the screen
, which uses ANSI escape sequences.
The first line works as expected, but unfortunately, I haven't been able to find a console that allows for the second line to move the cursor.
After looking up how ANSI escape sequences work, I wrote up this function to ease it's use:
(defn move-cursor-to [x y]
(print (str (char 27) "[" y ";" x "H")))
But when I run (move-cursor-to 10 10), the output is wrong in every "console" I've tried:
IntelliJ/Cursive's REPL ignores it outright; printing nothing.
IntelliJ's Terminal prints the escape character as a ?, and literally prints the rest (?[10;10H)
The Window's 10 command prompt prints something similar to IntelliJ's Terminal, except the ? it prints is inside a box.
Am I doing something wrong? Is there a way to get this to work in the standard Windows 10 command prompt?
I wrote this to fill in the blanks in the meantime:
(defn move-cursor-to [x y]
(let [r #(apply str (repeat % %2))]
(print (str (r y \newline)
(r x \space)))))
but this is a poor solution. It requires clearing the screen prior to use, which for anything beyond a simple animation is unacceptable.
There is an easier way!
There is a much easier way to do this. Have a look at
the clojure-lanterna library.
This library will allow you to address an arbitrary location on a screen. It can
either use a terminal emulator or it can create a swing based window.
Another advantage of using this library is that it also incorporates support for
a virtual window or virtual screen, which can make your output appear to be
much smoother and reduces potential flicker.
The library also has support for ANSI colour codes and a few other nice
features.
Cursive only implements a limited subset of ANSI commands. In particular, most of the caret movement commands don't work. Feel free to file an issue for this, but fixing it is likely to be low priority since it's quite tricky to do in a REPL output pane.

How do I interactively read the input text for this Emacs function?

I am new to Emacs functions. Today is my first attempt to create a function.
I know that count-matches will tell me how many times a regex appears in the rest of the buffer, but most of the time I need to count from the beginning of the buffer. So I tried this:
(defun count-matches-for-whole-buffer (text-to-count)
"Opens the ~/.emacs.d/init.el file"
(interactive "sText-to-count:")
(beginning-of-buffer)
(count-matches text-to-count))
I put this in ~/.emacs.d/init.el and then do "eval-buffer" on that buffer.
So now I have access to this function. And if I run it, it will ask me for text to search for.
But the function only gets as far as this line:
beginning-of-buffer
I never get the count. Why is that?
Two things.
You should use (goto-char (point-min)) instead of beginning-of-buffer.
count-matches will not display messages when called from lisp code unless you provide a parameter indicating so.
Try this code:
(defun count-matches-for-whole-buffer (text-to-count)
(interactive "sText-to-count:")
(count-matches text-to-count (point-min) (point-max) t))

Getting a dump of all the user-created functions defined in a repl session in clojure

Is there a way to get a dump of all the source code I have entered into a repl session. I have created a bunch of functions using (defn ...) but did it 'on the fly' without entering them in a text file (IDE) first.
Is there a convenience way to get the source back out of the repl session?
I note that:
(dir user)
will give me a printed list of type:
user.proxy$java.lang.Object
so I can't appear to get that printed list into a Seq for mapping a function like 'source' over. And even if I could then:
(source my-defined-fn)
returns "source not found"...even though I personally entered it in to the repl session.
Any way of doing this? Thanks.
Sorry, but I suspect the answer is no :-/
The best you get is scrolling up in the repl buffer to where you defined it. The source function works by looking in the var's metadata for the file and line number where the functions code is (or was last time it was evaluated), opening the file, and printing the lines. It looks like this:
...
(when-let [filepath (:file (meta v))]
(when-let [strm (.getResourceAsStream (RT/baseLoader) filepath)]
(with-open [rdr (LineNumberReader. (InputStreamReader. strm))]
(dotimes [_ (dec (:line (meta v)))] (.readLine rdr))
...
Not including the full source in the metadata was done on purpose to save memory in the normal case, though it does make it less convenient here.

How to clear SML Buffer in Emacs when using SML mode.

I am using Emacs with SML mode. Sometimes I need to clean the SML buffer. How can I do that.
Standard ML of New Jersey is a functional programming language that is a variant of ML. Usually it's used in EMACS with a plugin. Since I usually just kill the buffer and start a new one there wasn't the need for a clearscreen. However this might be useful:
http://www.standardml.org/Basis/manpages.html.
(let ((sml-process (get-process "sml")))
(when sml-process
(quit-process sml-process)))
(sleep-for 0.25)
(let ((sml-buffer (get-buffer "*sml*")))
(when sml-buffer
(kill-buffer sml-buffer)))