search


Homework: Implementing search
Mon Jun 18 00:00:00 UTC 2018

This blog has a search icon on the upper right but it is not functional. We will implement this in a series of steps assigned as homework. The contents of the blog are stored in EDN text files in public/blog-entries directory. EDN is Clojure's form of S-expressions . HTML/XML/JSON are all forms of s-expressions. When you write Clojure code, you are writing EDN s-expressions.

We can implement this search feature without dependency on the web browser. We will implement this feature at the Clojure REPL then integrated with the web interface once the feature is implemented and bug free. This is called REPL driven development

Start emacs
% cd lambdakids
 % emacs

Once emacs is started, start the repl with

M-x cider-jack-in

You will see something like this


;; Connected to nREPL server - nrepl://localhost:35562
;; CIDER 0.17.0 (AndalucĂ­a), nREPL 0.2.13
;; Clojure 1.9.0, Java 1.8.0_151
;;     Docs: (doc function-name)
;;           (find-doc part-of-name)
;;   Source: (source function-name)
;;  Javadoc: (javadoc java-object-or-class)
;;     Exit: 
;;  Results: Stored in vars *1, *2, *3, an exception in *e;
;; ======================================================================
;; If you're new to CIDER it is highly recommended to go through its
;; manual first. Type  to view it.
;; In case you're seeing any warnings you should consult the manual's
;; "Troubleshooting" section.
;;
;; Here are few tips to get you started:
;;
;; * Press  to see a list of the keybindings available (this
;;   will work in every Emacs buffer)
;; * Press <,> to quickly invoke some REPL command
;; * Press  to switch between the REPL and a Clojure file
;; * Press  to jump to the source of something (e.g. a var, a
;;   Java method)
;; * Press  to view the documentation for something (e.g.
;;   a var, a Java method)
;; * Enable `eldoc-mode' to display function & method signatures in the minibuffer.
;; * Print CIDER's refcard and keep it close to your keyboard.
;;
;; CIDER is super customizable - try  to
;; get a feel for this. If you're thirsty for knowledge you should try
;; .
;;
;; If you think you've encountered a bug (or have some suggestions for
;; improvements) use  to report it.
;;
;; Above all else - don't panic! In case of an emergency - procure
;; some (hard) cider and enjoy it responsibly!
;;
;; You can remove this message with the  command.
;; You can disable it from appearing on start by setting
;; `cider-repl-display-help-banner' to nil.
;; ======================================================================
WARNING: clj-refactor and refactor-nrepl are out of sync.
Their versions are 2.3.1 and n/a, respectively.
You can mute this warning by changing cljr-suppress-middleware-warnings.
user> 

Reading a file

Let's read the content of the file public/blog-entries/search.blog using slurp


user>  (def blog (slurp "public/blog-entries/search.blog"))
#'user/blog
user>
user> (prn blog)
"{:blog/title \"Homework: Implementing search\"\n :blog/date #inst \"2018-06-18\"\n :blog/content [:div\n                [:p \"This blog has a search icon on the upper right \
but it is not functional. As a homework assignment, implement the search feature.\"\n                 \"The contents of the blog are stored in \" [:a {:href \"https://github.\
com/edn-format/edn\"} \"EDN\"] \"text files in public/blog-entries directory.\"\n                 \"EDN is Clojure's form of \" [:a {:href \"https://en.wikipedia.org/wiki/S-e\
xpression\"} \"S-expressions\"] \". HTML/XML/JSON are all forms of\"\n                 \"s-expressions. When you write Clojure code, you are writing EDN s-expressions.\"]\n\n\
                [:p \"Before we continue, there's an incompatability withthe latest cider-0.17 and clj-refactor packages. To fix this,  update your emacs init.el as \"]\n    \
                            \n                [:pre\n                 [:code.bash.hljs\n                  \"% wget -c https://bit.ly/2LZKmkx -O ~/.emacs.d/init.el\"]]\n\n                [:p \
                            \"We can implement this search feature without anything replated to the web.  We will implement this feature at the Clojure REPL then integrated\"\n                 \"with th\
                            e web interface once the feature is implemented and bug free.\"]\n\n                [:pre\n                 [:code.bash.hljs\n                  \"% cd lambdakids\\n\"\n      \
                                        \"% emacs\"]]\n\n                [:p \"Once emacs is started, start the repl with\"]\n                [:pre\n                 [:code.bash.hljs\n                  \
                                        \"M-x cider-jack-in\"]]\n\n                [:p \"You will see something like this\"]\n                [:pre\n                 [:code.bash.hljs\n                  (slurp \"pub\
                                        lic/cider-console.txt\")\n\n                  ]]\n\n                [:p \"Perform some experiment at the REPL\"\n                 ]\n\n                [:pre\n                \
                                         [:code.clojure.hljs\n                  \"(def blog (slurp \\\"public/blog-entries/search.blog\\\"))\"]]\n                \n                ]\n \n \n\n }\n"
                                         nil

user> (type blog)
java.lang.String

Notice that the type of blog is a String

Convert a String into EDN data structures

We have the blog in the form of a Clojure EDN string but to leverage the processing power of Clojure, we will convert it into EDN data structures using read-string

user> (def search-blog (read-string blog))
 user> (type search-blog)
 clojure.lang.PersistentArrayMap

search-blog is now an EDN data structure whereas blog is an EDN string. In particular search-blog is a Clojure Map. We can now use functions that operate on Maps for example keys

user> (keys search-blog)
 (:blog/title :blog/date :blog/content)

We can access the blog title

user> (:blog/title search-blog)
 "Homework: Implementing search"
Your assignment

You need to do some research on your own to complete this assignment. The key to this is asking the right questions so that you can google it. Feel free to reach out to me to ask questions or if anything is confusing or not clear.

  • Write a predicate function
    (defn txt-exits-in? [file-name txt])
    txt-exists-in? returns true if txt is a substring in the file given by file-name and false otherwise. It should be case insensitive. For example,
    (txt-exists-in? "public/blog-entries/search.blog" "EDN") => true
     (txt-exists-in? "public/blog-entries/search.blog" "edn") => true
     (txt-exists-in? "public/blog-entries/functions.blog" "haha") => false
    
  • Write a function
    (defn search [txt])
    search should return a vector of file-names of all files in public/blog-entries where txt is a substring in that file
    (search "EDN") => ["search.blog", "chp.blog"]
    

Once you've implemented these two functions. We can connect it to the web to implement search of the blog