Collect lines of a buffer - elisp

There's process output that needs to be parsed per line, into structs.
sug skProc strutils.capitalize proc (string): string{.noSideEffect.}
sug skProc strutils.quoteIfContainsWhite proc (string): string
sug skProc system.gorge proc (string, string): string
sug skProc system.of proc (T, S): bool{.noSideEffect.}
sug skProc system.definedInScope proc (expr): bool{.noSideEffect.}
sug skIterator system.items iterator (cstring): char{.inline.}
sug skProc system.ord proc (T): int{.noSideEffect.}
This data is inside a buffer. So how do I read each line and pass it
to a function which returns a parsed representation and collect all
lines in the end?
EDIT: The code for parsing the lines (not debugged):
(defstruct nimrod-sug type namespace name signature)
(defun nimrod-parse-suggestion-line (line)
(let ((split (split-string line "[\t\n]")))
(make-nimrod-sug
:type (nth 1 split)
:namespace (first (split-string (nth 2 split) "\\."))
:name (second (split-string (nth 2 split) "\\."))
:signature (nth 3 split))

With some minor changes to the parser:
(defun nimrod-parse-suggestion-line (line)
(destructuring-bind (_ type fn &rest sig) (split-string line "[[:space:]]+" t)
(make-nimrod-sug :type type
:namespace (first (split-string fn "\\."))
:name (second (split-string fn "\\."))
:signature (apply 'concat sig))))
Assuming the name of the buffer is *output*, you can parse it like so:
(with-current-buffer "*output*"
(mapcar 'nimrod-parse-suggestion-line
(split-string (buffer-string) "[\r\n]" t)))
; => ([cl-struct-nimrod-sug "skProc" "strutils" "capitalize" "proc(string):string{.noSideEffect.}"] ...)
If you're currently visiting the output buffer, you won't need the with-current-buffer wrapper.

Related

Getting the output of a process

I am trying to create a function which takes as input a path and returns the output of the ls terminal command as a string. I'm using a process and sentinel since I'll eventually want to create other functions which will take some time to execute, and I want them to run asynchronously.
(defun ls-to-string (path)
(let (ls-proc
ls-output)
(progn (setq ls-proc (start-process "" "ls-buffer" "ls" path))
(set-process-sentinel ls-proc (lambda (p e)
(if (string= e "finished\n")
(progn (set-buffer "ls-buffer")
(setq ls-output (buffer-string))
(kill-buffer "ls-buffer")
(message ls-output))))) <---- (1)
ls-output))) <---- (2)
(ls-to-string "/home")
I have (temporarily) added (message ls-output) just to show that ls-output does contain the string (1). However the return value is nil (2).

WebSocket error in common lisp

I want to make slack bot.
I can not solve this error.
(ql:quickload '(:cl-slack
:event-emitter
:websocket-driver
:jonathan
:cl-async
)
:silent t)
(defconstant +token+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
(defconstant +channel+ "xxx")
(defvar *client* (make-instance 'cl-slack.core:slack-client
:token +token+))
(let ((url (getf (jonathan:parse (cl-slack.rtm:start *client* nil)) :|url|)))
(format t url)
(defparameter *slack-bot* (wsd:make-client url)))
(defun params (id type channel text)
(jonathan:to-json (list :|id| id
:|type| type
:|channel| channel
:|text| text)))
(wsd:on :message *slack-bot*
(lambda (message)
(let ((data (jonathan:parse message)))
(format t "~A~%" data)
(when (string= (getf data :|type|) "message")
(wsd:send *slack-bot*
(params 1
"message"
(getf data :|channel|)
(getf data :|text|)))))))
(as:with-event-loop (:catch-app-errors t)
(wsd:start-connection *slack-bot*))
error is
[20:42:25] cl-async-util - handle-error: SSL verify error: 20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY

LISP - get all method names from a class

Can I get in LISP all the method names from a class?
Actually I need the methods, which have
set-
in their names.
For LispWorks:
(defun find-all-methods (class prefix)
(loop for method in (clos:specializer-direct-methods class)
for gf = (method-generic-function method)
for fname = (generic-function-name gf)
for fname-string = (when (symbolp fname) (symbol-name fname))
when (and (stringp fname-string)
(>= (length fname-string)
(length prefix))
(string= fname-string prefix
:end1 (length prefix)
:end2 (length prefix)))
collect method))
Example:
CL-USER 20 > (pprint (find-all-methods (find-class 'capi:button) "PRINT-"))
(#<STANDARD-METHOD CAPI:PRINT-COLLECTION-ITEM NIL (CAPI:BUTTON T) 40E06173D3>
#<STANDARD-METHOD CAPI:PRINT-CAPI-BUTTON NIL (CAPI:BUTTON) 40E05F9DDB>)

How can I map an unknown list of args to start-process in elisp?

I'm finally trying to learn elisp but haven't wrapped my head around how to map an unknown list of arguments to variables dynamically.
Here's a working function that passes up to three arguments to start-process. But I would like to pass an infinite number of args to the function.
(defun create-drush-buffer (command &rest a)
(if (locate-dominating-file default-directory "includes/bootstrap.inc")
(progn
(setq opt1 (car a))
(setq opt2 (cadr a))
(setq opt3 (caddr a))
(setq allopt (concat opt1 " " opt2 " " opt3))
(setq b-name (concat "*drush " command " " allopt "*"))
(if (buffer-live-p b-name)
(switch-to-buffer b-name)
(setq d-buffer (get-buffer-create b-name))
(with-current-buffer d-buffer
(goto-char (point-min))
(view-mode 1)
(hl-line-mode 1)
(if opt3
(start-process "drush" (current-buffer) drupal-drush-program
command
opt1
opt2
opt3)
(if opt2
(start-process "drush" (current-buffer)
drupal-drush-program
command
opt1
opt2)
(if opt1
(start-process "drush" (current-buffer)
drupal-drush-program
command
opt1)
(start-process "drush" (current-buffer)
drupal-drush-program
command))))
(shrink-window-if-larger-than-buffer))
(switch-to-buffer d-buffer)))
(message (concat default-directory " is not a drupal project"))))
Here's an example of a calling function I would like to work with create-drush-buffer.
(defun drush-sql-sync ()
(interactive)
(create-drush-buffer
"sql-sync"
"-y"
"-d"
"-v"
"#cu.wstage1-education"
"#cu.local-education"))
How can I achieve this and make my code less redundant? Any help with code or even steering me to relevant documentation appreciated.
You can use apply:
(apply FUNCTION &rest ARGUMENTS)
Call FUNCTION with our remaining args, using our last arg as list of
args. Then return the value FUNCTION returns. Thus, (apply '+ 1 2 '(3
4)) returns 10.
This way, you could call start-process using something like:
(apply 'start-process "drush" (current-buffer)
drupal-drush-program
command
a)
As a side note, you should not create temporary variables using setq, as this creates or modified global variables (if no local ones with the name exists). Instead, use let.
Good luck with your elisp projects!

Using syntax-table information in elisp for tokenization

I would like to use elisp to tokenize the following:
variable := "The symbol \" delimits strings"; (* Comments go here *)
as:
<variable> <:=> <The symbol \" delimits strings> <;>
based on the information from the buffer's syntax-table.
I have the symbol-table setup appropriately and am currently using the following function which operates correctly except for the string constant (either returns token or nil if point is not at an identifier or one of the operators in the regex).
(defun forward-token ()
(forward-comment (point-max))
(cond
((looking-at (regexp-opt '("=" ":=" "," ";")))
(goto-char (match-end 0))
(match-string-no-properties 0))
(t (buffer-substring-no-properties
(point)
(progn (skip-syntax-forward "w_")
(point))))))
I am an elisp novice, so any pointers are appreciated.
I don't think your skip-syntax-forward use is correct for strings.
I think you need to add a cond clause like this:
((looking-at "\"")
(let* ((here (point)) (there (scan-sexps here 1)))
(goto-char there)
(buffer-substring-no-properties
(1+ here) (1- there))))
to handle string literals.

Resources