String comparison mistake - string

I tried to write a set of functions that check the expiration date for a domain name:
(ql:quickload 'inferior-shell)
(defun whois-lookup (site)
(let ((request (format nil "whois ~a" site)))
(inferior-shell:run/ss request)))
(defun match-expiration-string (input)
(let ((test-string "Registrar Registration Expiration Date:"))
(string> input test-string)))
(defun domain-expiration-date (site)
(with-input-from-string (input (whois-lookup site))
(loop for line = (read-line input nil nil)
while line do
(when (match-expiration-string line)
(format t "~A~%~t~A ~%" site line)))))
I'd call it like this: (domain-expiration-date "startpage.com").
Unfortunately, instead of just displaying the relevant line, it shows all of them.
match-expiration-string seems to be working correctly, so I have no idea what the problem is.
CL-USER> (match-expiration-string "Registrar Registration Expiration Date: 2016-05")
39 (6 bits, #x27, #o47, #b100111)
CL-USER> (match-expiration-string "Registrar Registration Expiration ")
NIL

As suggested by jkiiski, it works with a regular expression:
(defun match-expiration-string (input)
(let ((test-string "Registrar Registration Expiration Date:"))
(ppcre:scan test-string input)))
==>
CL-USER> (domain-expiration-date "startpage.com")
startpage.com
Registrar Registration Expiration Date: 2018-10-10T04:00:00Z
NIL
Like Joshua Taylor says, you don't need regex, only search. I also noticed that "Registrar Registration Expiration Date:" wasn't in every whois response, so I modified the search (and made place in case I needed other search strings for other types of domains):
(defun match-expiration-string (input)
(let ((inclusion-strings '("Expiration Date:"))
(exclusion-strings '("Registrar Registration Expiration Date:")))
(when (some #'(lambda (s) (search s input))
inclusion-strings)
(notany #'(lambda (s) (search s input))
exclusion-strings))))

Related

iterating through a list to look up data, and construct a string

Elisp newbie, looking for help with this.
I have this variable:
(setq bibtex-completion-additional-search-fields '(tags keywords))
I then have a function, which, if this variable is set, then needs to iterate through those field names, and look them up in a data record, concatenate the resulting values into a string, which it returns.
Here's what the data looks like:
("2009-03-01 Zukin, Sharon and Trujillo, Valerie and Frase, Peter and Jackson, Danielle and Recuber, Tim and Walker, Abraham gentrification New Retail Capital and Neighborhood Change: Boutiques and Gentrification in New York City article zukin_new_2009"
("date" . "2009-03-01")
("author" . "Zukin, Sharon and Trujillo, Valerie and Frase, Peter and Jackson, Danielle and Recuber, Tim and Walker, Abraham")
("tags" . "gentrification, retail")
("title" . "New {{Retail Capital}} and {{Neighborhood Change}}: {{Boutiques}} and {{Gentrification}} in {{New York City}}")
("=type=" . "article")
("=key=" . "zukin_new_2009"))
This is what I have for the function ATM, which I know is wrong. But I can't wrap my head around how to do this in elisp (I have more experience with Python and Ruby).
(defun bibtex-completion--get-extra-search-data (candidate)
"Return extended search metadata as string."
(if bibtex-completion-additional-search-fields
; if the data is present, pull its value(s), join into a single string
; TODO FIX ME, this is wrong
(format "%s" (cl-loop
for field in bibtex-completion-additional-search-fields
collect
(cdr (assoc field (cdr candidate)))
))))
So with the example data above, the function should return that string "gentrification, retail". And if that record were to have a keyword field with "foo", the return string would be "gentrification, retail, foo" (or could just be space-separated; not sure it matters).
First, the keys in your data structure are strings, not symbols. So, you could change your lookup fields,
(setq bibtex-completion-additional-search-fields '("tags" "keywords"))
but, using symbols as the cars in the candidate data structure is probably better (efficiency-wise I believe).
The canonical elisp for joining list into string is
(mapconcat #'identity ...),
(mapconcat
#'identity
(delq nil
(cl-loop for field in bibtex-completion-additional-search-fields
collect (cdr (assoc field (cdr candidate)))))
", ")

Input text reagent component value formatting

I'm trying to format the value of an input "text" reagent component without success. I expected that, after changing the value of the ratom variable, the value of the component will be formatted at re-render.
I used cl-format to format number with space thousand separator. I works well at first load, but not after change the price value.
Is it possible to format the price value of this example after saving the new value?
(ns shopping.app
(:require [reagent.core :as r]
[cljs.pprint :refer [cl-format]]))
(defonce shoppinglist (r/atom (sorted-map
1 {:id 1 :name "Bread" :price 20},
2 {:id 2 :name "Milk" :price 12})))
(defn update-item! [fn & args]
(apply swap! shoppinglist fn args))
(defn shopping-item [{:keys [id name price]} item]
(let [rreadonly (r/atom true)
rprice (r/atom price)]
(fn [{:keys [id name price]} item]
[:div
[:label id]
[:label (str " | " name)]
[:input { :type "text"
:readOnly #rreadonly
:value (cl-format nil "~,,' :d" #rprice)
:on-change #(reset! rprice (-> % .-target .-value))}]
[:button { :id "button-edit"
:hidden (not #rreadonly)
:on-click #(swap! rreadonly not)}
"Edit"]
[:button { :id "button-delete"
:hidden (not #rreadonly)
:on-click #(update-item! dissoc id)}
"Delete"]
[:button { :id "button-save"
:hidden #rreadonly
:on-click #(do
(update-item! assoc id (assoc {} :id id :name name :price (js/parseInt #rprice)))
(swap! rreadonly not))}
"Save"]
[:button { :id "button-reset"
:hidden #rreadonly
:on-click #(do (reset! rprice price)
(update-item! assoc id (assoc {} :id id :name name :price (js/parseInt #rprice)))
(swap! rreadonly not))}
"Reset"]])))
(defn shopping-list []
[:div.container
(doall (for [item (vals #shoppinglist)]
^{:key (:id item)} [:div
[shopping-item item]]))])
(defn init
"Initialize components."
[]
(let [container (.getElementById js/document "container")]
(r/render-component
[shopping-list]
container)))
This does not work because you are creating a cycle:
on-change sets the value of the rprice atom to a string, but in this expression (cl-format nil "~,,' :d" #rprice) #rprice should be a number
when you set value of the input to some formatted value, next time you type something the on-change will see this formatted value instead of the raw input you had before, so then the contents of rprice will be set to the formatted value, a string
So if you set rstring to the raw number or the formatted string, after a cycle it will always be the formatted string.
Unfortunately formatting the input as you type is a bit complex and you'll probably need a library. Maybe reagent-forms supports it: https://github.com/reagent-project/reagent-forms, if not, there are other React libraries that do.

Search in current folder with helm-do-grep

I have so small problem about in Emacs. I bind helm-do-grep command for Emacs. It's really useful.
I want to search something in current folder.
I searched some codes about that both of them are working but I don't have ability to fix them like what I want.
If you fix them for me I'll be happy thank you.
(defvar my/book-notes-directory "~/Dropbox/books")
(defun my/helm-do-grep-book-notes ()
"Search my book notes."
(interactive)
(helm-do-grep-1 (list my/book-notes-directory)))
(defun my-dir-locals-dir ()
"Return the directory local variables directory.
Code taken from `hack-dir-local-variables'."
(let ((variables-file (dir-locals-find-file (or (buffer-file-name) default-directory)))
(dir-name nil))
(cond,
((stringp variables-file)
(setq dir-name (file-name-directory variables-file)))
((consp variables-file)
(setq dir-name (nth 0 variables-file))))
dir-name))
How about something like this?
(defun my/helm-do-grep-current-directory-tree ()
"Recursively search current directory.
If a parent directory has a `dir-locals-file', use that as the
root instead."
(interactive)
(let ((variables-file (dir-locals-find-file
(or (buffer-file-name) default-directory))))
(helm-do-grep-1
(list
(cond
((stringp variables-file)
(file-name-directory variables-file))
((consp variables-file)
(nth 0 variables-file))
(t default-directory)))
t nil '("*"))))
By the way, if you ask on http://emacs.stackexchange.com , you might get better answers. (And faster, too!) =)

How to add perl-mode.el to .emacs?

If I do M-x load-file RET /root/.elisp/perl-mode.el RET then this perl-mode.el get loaded correctly.
If I in .emacs add any of these, it doesn't work
(load "/root/.elisp/perl-mode.el")
(load-file "/root/.elisp/perl-mode.el")
I am using emacs 24.1.1.
The error I get is
File mode specification error: (void-function setq-local)
Question
What is the correct way to load perl-mode.el from .emacs?
The macro setq-local was introduced in Emacs 24.3, so this version of perl-mode is too new for the Emacs you're currently running (24.1).
You could upgrade Emacs, or you could just put the definition of setq-local into your .emacs (from here):
(defmacro setq-local (var val)
"Set variable VAR to value VAL in current buffer."
;; Can't use backquote here, it's too early in the bootstrap.
(list 'set (list 'make-local-variable (list 'quote var)) val))

CLIPS simple percentage defrule

At the end, when the program is supposed to print the percentage certainties, the program hangs. What might be wrong? It has to be the calculate-percentage rule, since when removed, the non-percentaged data is printed.
(defmodule PRINT-RESULTS (import MAIN ?ALL))
(defrule PRINT-RESULTS::calculate-percentages
?var <- (religion (name ?religion) (aspects $?aspects) (certainty ?certainty))
=>
(modify ?var (certainty =(*(/ ?certainty 700)100))))
(defrule PRINT-RESULTS::print-religion
?rel <- (religion (name ?religion) (aspects $?aspects) (certainty ?certainty))
=>
(retract ?rel)
(printout t crlf RELIGION: " "
?religion crlf ASPECTS: " "
?aspects crlf CERTAINTY: " "
?certainty crlf))
It appears that you are being caught in an infinite loop. When you modify a deftemplate instance, you are replacing the original with the modified instance, which in your situation will match calculate-percentages again and again. So you need to prevent this infinite loop of rule matches.
Since you are using modules, consider calculating your certainty in a module other than PRINT-RESULTS (I'll refer to the other module as UPDATE-CERTAINTY). Then in the then part of your calculate-percentages rule, you can pop the UPDATE-CERTAINTY module to prevent the rule from matching the modified fact.
Alternately, you can use an additional slot in your facts to indicate whether the computation has been done on the fact (in this example the status slot):
(defrule PRINT-RESULTS::calculate-percentages
?var <- (religion (name ?religion) (status ~final) (aspects $?aspects) (certainty ?certainty))
=>
(modify ?var (status final) (certainty =(*(/ ?certainty 700)100))))

Resources