newlisp-redis / redis.lsp

;; @module redis
;; @description newLISP bindings for the Redis database ( )
;; @version 0.1
;; @author Nikhil Marathe <> 2010
;; @homepage @link
;; This module provides bindings to Redis. It communicates
;; with the Redis server and returns values in appropriate
;; lisp-y types.
;; @example
;; (setf 'redis (redis:connect))
;; (redis:ping redis)
;; => "+PONG"

(context 'redis)

(constant 'CRLF "\r\n")
(constant 'BUFSIZE 4096)

(constant 'inline-commands 
  '("ping" "bgsave" "get" "quit" "auth" "exists" "type" "select" "dbsize"))

(define (make-inline-command command)
  (letex ((fname (sym command)) (cmd command))
        (define (fname r)
          (letn ( (args-as-strings (map (fn (x) (string x)) (args)))
                  (command-string (join (cons (upper-case cmd) args-as-strings) " ")) )
              (:query r (append command-string redis:CRLF))))))

(context MAIN)

;; @syntax (redis <host> <port>)
;; Creates a new connection to a Redis instance
;; @return a new connection object or nil on error
(define (redis:redis (host "localhost") (port 6379))
  (let (sock (net-connect host port))
    (if (nil? sock)
      (list redis sock ""))))

(define (redis:query r command-str)
  (net-send (r 1) (append command-str redis:CRLF))
  (net-receive (r 1) buf redis:BUFSIZE)
  (write-buffer (r 2) buf)
  (:handle-reply r))

(define (redis:handle-reply r , reply)
  (while (> (length (r 2)) 0)
    (setf reply
        (case (first (r 2))
          ("+" (:handle-single-reply r))
          ("-" (:handle-error r))
          ("$" (:handle-bulk-reply r))
          ("*" (:handle-multi-bulk-reply r))
          (":" (:handle-integer-reply r))
          (true (:handle-unknown-reply r))))
    (setf (r 2) ((reply 1) (r 2)))
    (reply 0)))

(define (redis:handle-single-reply r)
  (let (pos (find redis:CRLF (r 2)))
    (if (nil? pos)
      (list (0 pos (r 2)) (+ pos (length redis:CRLF))))))

(define (redis:ping r)
  (:query r "PING"))

(define (redis:bgsave r)
  (:query r "BGSAVE"))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.