Unclear behavior of the defun macro - elisp

Good afternoon. The defun macro places the procedure code in the functional cell of the symbol and, if no errors are found, prints the name of the symbol in the mini-buffer.
(defun InsertSsulku ()
"Вставка текста ссылки на якорь-ноду в точку"
(interactive)
(let* ((karta '(keymap "Вставка ссылок"
("Решения" menu-item "Решения"
(keymap "Решения"
("#ref{сбрнкФйлвРквдств, текст-ссылки}" menu-item "#anchor{сбрнкФйлвРквдств}" fint-function :key-sequence nil)))
("Скрипты" menu-item "Скрипты"
(keymap "Скрипты"
("#ref{Родительский скрипт, текст ссылки}" menu-item "#anchor{Родительский скрипт}" fint-function :key-sequence nil)
("#ref{Дочерний скрипт, текст ссылки}" menu-item "#anchor{Дочерний скрипт}" fint-function :key-sequence nil)))))
(выбзнч (x-popup-menu (list '(0 0) (selected-frame))
karta)))
(insert (nth (- (length выбзнч) 1) выбзнч))))
The next question is, why does the procedure begin to run when defined?

The next question is, why does the procedure begin to run when defined?
It doesn't. What do you mean by that?

Related

Need to extend elisp function

All,
I must suck at eLisp. Banged this first function out in no time.
(defun sort-lines-reverse (beg end)
"sort lines in reverse order"
(interactive
(if (use-region-p)
(list (region-beginning) (region-end))
(list (point-min) (point-max))))
(if (and beg end)
(sort-lines 1 beg end))
)
works perfectly. Hosed this next one
(defun sort-numeric-fields-reverse (field beg end)
"sort numeric fields in reverse order"
(interactive
(if (use-region-p)
(list (read-number "Field number: " 1) (region-beginning) (region-end))
(list (read-number "Field number: " 1) (point-min) (point-max)))
(message "calling if")
(if (and beg end)
((message "inside if")
(sort-numeric-fields field beg end)
(reverse-region beg end))
)
))
No runs no hits no errors. Don't see a single message displayed in messages. I do get my field number prompt.
A snippet of randomly generated test data if one so wishes.
8 412086510
8 744308263
8 1482781895
8 995992436
1 1021762533
1 897682569
1 963686690
1 166565707
1 2096612583
1 829723388
1 587753131
1 264251710
32 139885828
32 781244288
Adding insult to injury in my KDE Neon environment the C-M-x to bring up the lisp debugger doesn't do squat.
The only real difference between these two functions is in this one I have to prompt for a field number. Inside the if I run 2 functions instead of one. After getting the first one to work the second should have been a cakewalk.
Help would be appreciated.
Two issues:
missing ) at the end of interactive, after (if (use-region-p) ...
missing progn in (if (and beg end)...
(progn is superfluous because if has been replaced by when.)
Corrected version:
(defun sort-numeric-fields-reverse (field beg end)
"sort numeric fields in reverse order"
(interactive
(if (use-region-p)
(list (read-number "Field number: " 1) (region-beginning) (region-end))
(list (read-number "Field number: " 1) (point-min) (point-max))))
(message "calling if")
(when (and beg end)
(message "inside if")
(sort-numeric-fields field beg end)
(reverse-region beg end)))
EDIT: Code changed: if-progn replaced with when according to hint from #phils.
Hint: using an adequate editor makes the typing easy and gives you control over parentheses.

How to extract element from html in Racket?

I want to extract the urls in reddit, my code is
#lang racket
(require net/url)
(require html)
(define reddit (string->url "http://www.reddit.com/r/programming/search?q=racket&sort=relevance&restrict_sr=on&t=all"))
(define in (get-pure-port reddit #:redirections 5))
(define response-html (read-html-as-xml in))
(define content-0 (list-ref response-html 0))
(close-input-port in)
The content-0 above is
(element
(location 0 0 15)
(location 0 0 82)
...
I'm wondering how to extract specific content from it.
Usually it's more convenient to deal with HTML as x-expressions instead of the html module's structs.
Also you should probably use call/input-url to handle closing the port automatically.
You can combine both of these ideas by defining a read-html-as-xexpr function and using it like this:
#lang racket/base
(require html
net/url
xml)
(define (read-html-as-xexpr in) ;; input-port? -> xexpr?
(caddr
(xml->xexpr
(element #f #f 'root '()
(read-html-as-xml in)))))
(define reddit (string->url "http://www.reddit.com/r/programming/search?q=racket&sort=relevance&restrict_sr=on&t=all"))
(call/input-url reddit
get-pure-port
read-html-as-xexpr)
That will return a big x-expression like:
'(html
((lang "en") (xml:lang "en") (xmlns "http://www.w3.org/1999/xhtml"))
(head
()
(title () "programming: search results")
(meta
((content " reddit, reddit.com, vote, comment, submit ")
(name "keywords")))
(meta
((content "reddit: the front page of the internet") (name "description")))
(meta ((content "origin") (name "referrer")))
(meta ((content "text/html; charset=UTF-8") (http-equiv "Content-Type")))
... snip ...
How to extract specific pieces of that?
For simple HTML where I don't expect the overall structure to change, I will often just use match.
However a more correct and robust way to go about it is to use the xml/path module.
UPDATE: I noticed your question started by asking about extracting URLs. Here's the example updated to use se-path*/list to get all the href attributes of all the <a> elements:
#lang racket/base
(require html
net/url
xml
xml/path)
(define (read-html-as-xexprs in) ;; (-> input-port? xexpr?)
(caddr
(xml->xexpr
(element #f #f 'root '()
(read-html-as-xml in)))))
(define reddit (string->url "http://www.reddit.com/r/programming/search?q=racket&sort=relevance&restrict_sr=on&t=all"))
(define xe (call/input-url reddit
get-pure-port
read-html-as-xexprs))
(se-path*/list '(a #:href) xe)
Result:
'("#content"
"http://www.reddit.com/r/announcements/"
"http://www.reddit.com/r/Art/"
"http://www.reddit.com/r/AskReddit/"
"http://www.reddit.com/r/askscience/"
"http://www.reddit.com/r/aww/"
"http://www.reddit.com/r/blog/"
"http://www.reddit.com/r/books/"
"http://www.reddit.com/r/creepy/"
"http://www.reddit.com/r/dataisbeautiful/"
"http://www.reddit.com/r/DIY/"
"http://www.reddit.com/r/Documentaries/"
"http://www.reddit.com/r/EarthPorn/"
"http://www.reddit.com/r/explainlikeimfive/"
"http://www.reddit.com/r/Fitness/"
"http://www.reddit.com/r/food/"
... snip ...

elisp: create dynamic menu with easy-menu and evaluate part of code during creation and not when called

I'm trying to create a dynamic menu for my own compiling plugin, but I have hit a wall. This is the code that I have at the moment:
(defun mme-tools-create-menu ()
(easy-menu-define mme-tools-menu erlang-mode-map "MME-Tools-Menu"
'("MME-Tools"
("Current Subsystem"
["Run gmake" mme-tools-build]
["Build beams" mme-tools-build-beam]
["Run Posttest" mme-tools-build-posttest]
["Run Move" mme-tools-build-move])
("Build Subsystem")))
(dolist (path mmepaths)
(if (string-match "code" path)
(let* ((ss (file-name-base path))
(uss (upcase ss)))
(easy-menu-add-item mme-tools-menu '("Build Subsystem")
[uss (mme-tools-build-path-subsystem " -j10 beam" (getenv ss))])))))
What I want the code to do is to make a sub-menu called "Build Subsystem" and fill it with entries. But no entries are created. Any help would be appreciated.
I'd suggest you do something like
(easy-menu-define mme-tools-menu erlang-mode-map "MME-Tools-Menu"
`("MME-Tools"
("Current Subsystem"
["Run gmake" mme-tools-build]
["Build beams" mme-tools-build-beam]
["Run Posttest" mme-tools-build-posttest]
["Run Move" mme-tools-build-move])
("Build Subsystem"
,#(mapcar (lambda (path)
(when (string-match "code" path)
(let* ((ss (file-name-base path))
(uss (upcase ss)))
(vector uss `(mme-tools-build-path-subsystem " -j10 beam" (getenv ',ss))))))))))
I suspect you might be looking for something like this, but it's hard to know without seeing more code. You should be able to debug this yourself, using macroexpand etc. until you get a proper set of arguments to pass to easy-menu-define.
Wrt Stefan's code, this adds the missing mapcar second arg, as you mentioned, and it removes the backquote before (mme-tools-build-path-subsystem...) (just a guess).
(easy-menu-define
mme-tools-menu
erlang-mode-map "MME-Tools-Menu"
`("MME-Tools"
("Current Subsystem"
["Run gmake" mme-tools-build]
["Build beams" mme-tools-build-beam]
["Run Posttest" mme-tools-build-posttest]
["Run Move" mme-tools-build-move])
("Build Subsystem"
,#(mapcar (lambda (path)
(when (string-match "code" path)
(let* ((ss (file-name-base path))
(uss (upcase ss)))
(vector uss
(mme-tools-build-path-subsystem
" -j10 beam" (getenv ',ss))))))
mmepaths))))

exception: current-continuation-marks: no corresponding prompt in the continuation: #<continuation-prompt-tag:web>

why do i get exception on (redirect/get) in this program
#lang web-server
(require web-server/formlets web-server/page) (struct app (nm) #:mutable)
(define (start req) (render-main-page req))
this function is to be used by most pages and generates comlete page xexpr by calling each given piece of page generator functions, each of which may embed their urls
(define (render-page embed/url a-title blocks)
(response/xexpr `(html (head (title ,a-title)
(body ,#(map (lambda (block) (block embed/url)) blocks))))))
this is piece of first page generator function
(define (render-action-panel embed/url action)
`(a ([href ,(embed/url action)]) "New"))
this is first page
(define/page (render-main-page)
(local [(define (new-handler req) (render-app-page req (app "new value")))
(define (panel-block embed/url) (render-action-panel embed/url new-handler))]
(render-page embed/url "Title" (list panel-block))))
this is piece of second page generator function (represents form)
(define (add-app-formlet an-app) (formlet (#%# ,{=> input-string nm}) nm))
(define (render-app-form embed/url an-app save-handler)
`(div (form ([action ,(embed/url save-handler)][method "POST"])
(span ,#(formlet-display (add-app-formlet an-app) ))
(span (input ([type "submit"][value "Save"]))))));)
the second form,
save handler throws exception when trying do post-redirect-get
(define/page (render-app-page an-app)
(local [(define (save-handler req)
(render-app-page
(redirect/get)
(set-app-nm! an-app (formlet-process (add-app-formlet an-app) req))))
(define (form-block embed/url)
(render-app-form embed/url an-app save-handler ))
]
(render-page embed/url "Title - form: " (list form-block))))
(require web-server/servlet-env)
(serve/servlet start)
Which redirect/get are you using?
The one from web-server/lang/servlet (which should be used with #lang web-server) is different than the one from web-server/servlet (which should be used with #lang racket (and friends))
This error message means that you are using the one from web-server/servlet.
FWIW, web-server/page cannot be used with #lang web-server because it is just a simple macro over the send/suspend/dispatch from web-server/servlet.

Extracting URLs from an Emacs buffer?

How can I write an Emacs Lisp function to find all hrefs in an HTML file and extract all of the links?
Input:
<html>
<a href="http://www.stackoverflow.com" _target="_blank">StackOverFlow&lt/a>
<h1>Emacs Lisp</h1>
<a href="http://news.ycombinator.com" _target="_blank">Hacker News&lt/a>
</html>
Output:
http://www.stackoverflow.com|StackOverFlow
http://news.ycombinator.com|Hacker News
I've seen the re-search-forward function mentioned several times during my search. Here's what I think that I need to do based on what I've read so far.
(defun extra-urls (file)
...
(setq buffer (...
(while
(re-search-forward "http://" nil t)
(when (match-string 0)
...
))
I took Heinzi's solution and came up with the final solution that I needed. I can now take a list of files, extract all URL's and titles, and place the results in one output buffer.
(defun extract-urls (fname)
"Extract HTML href url's,titles to buffer 'new-urls.csv' in | separated format."
(setq in-buf (set-buffer (find-file fname))); Save for clean up
(beginning-of-buffer); Need to do this in case the buffer is already open
(setq u1 '())
(while
(re-search-forward "^.*<a href=\"\\([^\"]+\\)\"[^>]+>\\([^<]+\\)</a>" nil t)
(when (match-string 0) ; Got a match
(setq url (match-string 1) ) ; URL
(setq title (match-string 2) ) ; Title
(setq u1 (cons (concat url "|" title "\n") u1)) ; Build the list of URLs
)
)
(kill-buffer in-buf) ; Don't leave a mess of buffers
(progn
(with-current-buffer (get-buffer-create "new-urls.csv"); Send results to new buffer
(mapcar 'insert u1))
(switch-to-buffer "new-urls.csv"); Finally, show the new buffer
)
)
;; Create a list of files to process
;;
(mapcar 'extract-urls '(
"/tmp/foo.html"
"/tmp/bar.html"
))
If there is at most one link per line and you don't mind some very ugly regular expression hacking, run the following code on your buffer:
(defun getlinks ()
(beginning-of-buffer)
(replace-regexp "^.*<a href=\"\\([^\"]+\\)\"[^>]+>\\([^<]+\\)</a>.*$" "LINK:\\1|\\2")
(beginning-of-buffer)
(replace-regexp "^\\([^L]\\|\\(L[^I]\\)\\|\\(LI[^N]\\)\\|\\(LIN[^K]\\)\\).*$" "")
(beginning-of-buffer)
(replace-regexp "
+" "
")
(beginning-of-buffer)
(replace-regexp "^LINK:\\(.*\\)$" "\\1")
)
It replaces all links with LINK:url|description, deletes all lines containing anything else, deletes empty lines, and finally removes the "LINK:".
Detailed HOWTO: (1) Correct the bug in your example html file by replacing <href with <a href, (2) copy the above function into Emacs scratch, (3) hit C-x C-e after the final ")" to load the function, (4) load your example HTML file, (5) execute the function with M-: (getlinks).
Note that the linebreaks in the third replace-regexp are important. Don't indent those two lines.
You can use the 'xml library, examples of using the parser are found here. To parse your particular file, the following does what you want:
(defun my-grab-html (file)
(interactive "fHtml file: ")
(let ((res (car (xml-parse-file file)))) ; 'car because xml-parse-file returns a list of nodes
(mapc (lambda (n)
(when (consp n) ; don't operate on the whitespace, xml preserves whitespace
(let ((link (cdr (assq 'href (xml-node-attributes n)))))
(when link
(insert link)
(insert "|")
(insert (car (xml-node-children n))) ;# grab the text for the link
(insert "\n")))))
(xml-node-children res))))
This does not recursively parse the HTML to find all the links, but it should get you started in the direction of the general solution.

Resources