How to store string from user input using a widget in emacs? - emacs

I have created a widget with an editable-field.
(widget-create 'editable-field
:size 13
:format "name: %v \n"
"Type in your name")
How can I now store only the user input?
I tried setq before widget-create
but it stores the entire widget definition.

I was able to store the user input using the notify field in the widget creation.
(widget-create 'editable-field
:size 13
:format "name: %v \n"
;;"Type in your name"
:notify (lambda (widget &rest ignore)
(setq *name* (widget-value widget)))
)

Related

How to pass the variable name as a string to a function? (ClojureScript)

Description of the situation
I want to make a form template for an element, but they must be dynamically created. The meta data involved in the Component should use the variable-name passed as it's meta-data.
Code
For example,
In the view,
(ns my.app
(:require [my.app.templating :as template])
(defn view-component [nOperacaoExtrato]
[:<>
(template/temp-form nOperacaoExtrato)])
The templating function,
(ns my.app.templating)
(defn temp-form
"Template input"
[dado]
#_(js/console.log (str "meta-data: " (meta #'dado)))
(let [nome-var (:name (meta #'dado))]
[:div.col
[:label
{:for (str "form1_" nome-var)}
"Natureza do Dispendio"]
[:p
{:class "form-control",
:id (str "form1_" nome-var)
:name (str "form1" nome-var)}
dado]]))
The result should be, something like this (because the variable passed is nOperacaoExtrato):
[:div.col
[:label
{:for "form1_re-fin-n-operacao-extrato-prop"}
"Nº da Operação no Extrato"]
[:p
{:class "form-control",
:id "form1_re-fin-n-operacao-extrato-prop",
:name "form1_re-fin-n-operacao-extrato-prop"}
(h/preencher-str nOperacaoExtrato)]]
The issue:
Both of these return null.
(meta #'data)
(meta data)
``
You should probably convert this function to a macro. Let me show you fellow Portuguese speaker:
src/cljs/user.cljc
(ns cljs.user)
(defn temp-form-fn
"Template input"
[dado nome-var]
[:div.col
[:label
{:for (str "form1_" nome-var)}
"Natureza do Dispendio"]
[:p
{:class "form-control",
:id (str "form1_" nome-var)
:name (str "form1" nome-var)}
dado]])
#?
(:clj
(defmacro temp-form
[dado]
`(temp-form-fn ~dado ~(name dado))))
Then in the repl:
cljs.user> (require '[cljs.user :refer-macros [temp-form]])
nil
cljs.user> (let [nOperacaoExtrato 1234]
(temp-form nOperacaoExtrato))
[:div.col
[:label {:for "form1_nOperacaoExtrato"} "Natureza do Dispendio"]
[:p
{:class "form-control",
:id "form1_nOperacaoExtrato",
:name "form1nOperacaoExtrato"}
1234]]

Why isn't my macro functioning in the same way as handwritten code?

So I have 2 router functions for learning to work with clack in common lisp. One is written without macros, and the other is written with macros that expand to match the first function, but only the non-macro version is working. The code below has (:use :trivia) from (ql:quickload 'trivia).
This one is written without any macros, and works:
(defun router (env)
(match env
((guard (property :path-info path)
(equalp "/" path))
(home env))
((guard (property :path-info path)
(equalp "/live/clicked" path))
(live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404 page not found"))))))
I decided I didn't like those guard clauses taking up so much space in the function definition, so I rewrote the function:
(defun router (env)
(match env
(route "/" (home env))
(route "/live/clicked" (live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404 page not found"))))))
route is defined as so:
(defmacro route (valid-path &body body)
(let ((path (gensym)))
`((guard (property :path-info ,path)
(equalp ,valid-path ,path))
,#body)))
With this new router function and macro, the function is always short-circuiting on the first clause. When macroexpanding the 2 (route ...) clauses, I receive this output, matching the function I wrote:
* `(defun router (env)
(match env
,(macroexpand '(route "/" (home env)))
,(macroexpand '(route "/live/clicked" (live-clicked env)))
((property :path-info path)
`(404 nil (,(format nil "404")))))))
(DEFUN ROUTER (ENV)
(MATCH ENV
((GUARD (PROPERTY :PATH-INFO #:G120) (EQUALP "/" #:G120)) (HOME ENV))
((GUARD (PROPERTY :PATH-INFO #:G121) (EQUALP "/live/clicked" #:G121)) (LIVE-CLICKED ENV))
((PROPERTY :PATH-INFO PATH) `(404 NIL (,(FORMAT NIL "404")))))
(home env) and (live-clicked env) are functions that return something similar to (backquote (200 nil (,(*form generating html*)))). env is the state of the web request, but in this instance it only needs to be (list :path-info "/live/clicked")
First of all, macroexpand should be
used for interactive debugging rather than in production code.
Its use inside defun (almost) never makes sense.
Second, to understand your second router, you should macroexpand its body
rather than the defun, i.e.,
(macroexpand '(match env
(route "/" (home env))
(route "/live/clicked" (live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404"))))))
You will see that route is not expanded because it is not in a "function position".
What you need to expand your route before match is expanded, i.e., you probably want a
wrapper around match (I removed gensym because you indicated in the comments that it is really
not necessary):
(defmacro my-match (what &body clauses)
(labels ((handle-clause (clause)
(if (eq (car clause) 'route)
(apply #'route (rest clause))
clause))
(route (valid-path &rest body)
`((guard (property :path-info path)
(equalp ,valid-path path))
,#body)))
`(match ,what ,#(mapcar #'handle-clause clauses))))
and then
(defun router (env)
(my-match env
(route "/" (home env))
(route "/live/clicked" (live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404 page not found"))))))
Testing:
(macroexpand '(my-match env
(route "/" (home env))
(route "/live/clicked" (live-clicked env))
((property :path-info path)
`(404 nil (,(format nil "404"))))))
==>
(MATCH ENV ((GUARD (PROPERTY :PATH-INFO PATH) (EQUALP "/" PATH)) (HOME ENV))
((GUARD (PROPERTY :PATH-INFO PATH) (EQUALP "/live/clicked" PATH))
(LIVE-CLICKED ENV))
((PROPERTY :PATH-INFO PATH) `(404 NIL (,(FORMAT NIL "404")))))
T
The pattern matcher you are using, Trivia, has a defpattern macro. That's what you must use to define a macro against the pattern language itself, rather than defmacro.

Generating inline javascript with cl-who, parenscript and hunchentoot

I'm trying to generate inline javascript, but I have to put the parenscript code inside (:script) and (str) tags using cl-who. ps, ps*, ps-inline and ps-inline* don't seem to make much difference to the generated js.
Is the usual way to write a macro to avoid code duplication, or is there a better way?
Here's my program:
(in-package #:ps-test)
(defmacro standard-page ((&key title) &body body)
`(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
(:html
:lang "en"
(:head
(:meta :http-equiv "Content-Type"
:content "text/html;charset=utf-8")
(:title ,title)
(:link :type "text/css"
:rel "stylesheet"
:href "/style.css"))
(:body
,#body))))
(defun main ()
(with-html-output (*standard-output* nil :indent t :prologue nil)
(standard-page (:title "Parenscript test")
(:div (str "Hello worldzors"))
(:script :type "text/javascript"
(str (ps (alert "Hello world as well")))))))
(define-easy-handler (docroot :uri "/") ()
(main))
(defun start-ps-test ()
(setf (html-mode) :html5)
(setf *js-string-delimiter* #\")
(start (make-instance 'hunchentoot:easy-acceptor :port 8080)))
(defun stop-ps-test ()
(stop *server*))
(defvar *server* (start-ps-test))
Macros are fine in this use case.
The trick is that macros are expanded in a specific order. Say
you define a js macro: when macroexpansion encounters
with-html-output, the inner call to your macros (js (alert "Ho Ho Ho")) looks like a function call, and is left as-is in the generated
code. If your js macro then expands into (:script ...), then the system will complain that :script is an unknown function (assuming you
didn't actually name a function like that). You should emit an
enclosing (who:htm ...) expression to interpret the code using
CL-WHO's code walker.
(defmacro js (code)
`(who:htm
(:script :type "text/javascript" (who:str (ps:ps ,code)))))
This only works in the context of an enclosing with-html-output.
For inline Javascript, you don't want to have a <script> tag around it,
and you can generally simply use ps-inline:
(who:with-html-output (*standard-output*)
(:a :href (ps:ps-inline (void 0))
"A link where the usual HREF behavior is canceled."))
;; prints:
;;
;; <a href='javascript:void(0)'>A link where the usual HREF behavior is canceled.</a>
But feel free to use a macro if you often do the same thing:
(defmacro link (&body body)
`(who:htm (:a :href #.(ps:ps-inline (void 0)) ,#body)))
(who:with-html-output (*standard-output*) (link "Link"))
;; prints:
;;
;; <a href='javascript:void(0)'>Link</a>

Sending email in emacs w/ request package and mailgun

I am trying to write an elisp function to send email using a mailgun account.
Here is what I have tried:
(require 'request)
(defun send-mail (api-key from-url to-name to-address subject message)
"Sends an email using Mailgun account"
(request
(concat "https://api.mailgun.net/v3/" from-url "/messages")
:type "POST"
:data '(("from" . (concat "Mailgun Sandbox <postmaster#" from-url ">"))
("to" . (concat to-name " <" to-address ">"))
("subject" . subject)
("text" . message))
:headers '(("api" . api-key))
:parser 'json-read
:success (function*
(lambda (&key data &allow-other-keys)
(message "I sent: %S" (assoc-default 'form data))))))
I am getting the error "Wrong type argument: integerp, concat" from the "from" section in :data. Not sure what I am doing wrong, or if this is even the correct approach to be taking.
In this section:
:data '(("from" . (concat "Mailgun Sandbox <postmaster#" from-url ">"))
("to" . (concat to-name " <" to-address ">"))
("subject" . subject)
("text" . message))
you are quoting the entire list literally with a single quote ('), but you actually want the concat function calls to be evaluated before that.
You can use a backquote instead, and put a comma before the parts that should be evaluated:
:data `(("from" . ,(concat "Mailgun Sandbox <postmaster#" from-url ">"))
("to" . ,(concat to-name " <" to-address ">"))
("subject" . subject)
("text" . message))
The question lawlist linked to in the comments explains this in more detail.

Elisp help. Why does the following snippet fail?

I'm trying to write a little script that notifies me when someone talks to me in erc. So I need to write a funcion that recieves what I presume are two strings, nick and msg so I can hook it. But my test function fails. I have tested growl-notify and the format s-expresions and they work fine but I cant get test to work. I have no idea why is it failing. Any pointers?
(defun growl-notify (&key message)
"Use growl for notifications"
(start-process "growlnotify" "growlnotifications" "growlnotify" "-m " message))
(defun test (nick msg)
(growlnotify :message (format "%s: %s" nick msg)))
(test "Ppop" "something")
It gives the following backtrack, hope it helps.
Debugger entered--Lisp error: (void-function growlnotify)
(growlnotify :message (format "%s: %s" nick msg))
test("oi" "poi")
eval((test "oi" "poi") nil)
eval-last-sexp-1(t)
eval-last-sexp(t)
eval-print-last-sexp()
call-interactively(eval-print-last-sexp nil nil)
recursive-edit()
debug(error (wrong-number-of-arguments (lambda (&key message) "Use growl for notifications" (start-process "growlnotify" "growlnotifications" "growlnotify" "-m " message)) 3))
The error message is Debugger entered--Lisp error: (void-function growlnotify), which tells you that growlnotify isn't defined as a function.
If you look at your code, you'll see that you defined it like this: (defun growl-notify (&key message), which defines a function called growl-notify. A simple typo.