Line by line reader in cljs
(ns cljs-line-reader.core | |
(:refer-clojure :exclude [flush]) | |
(:require clojure.string | |
[cljs.core.async :refer [>!]]) | |
(:require-macros [cljs.core.async.macros :refer [go]])) | |
(def fs (js/require "fs")) | |
(def stream (js/require "stream")) | |
(def ^:const eol (.-EOL (js/require "os"))) ;;eg "\n" or "\r\n" | |
(defn- transform [chunk encoding done] | |
(this-as this | |
(let [data (if (.-_lastLineData this) | |
(str (.-_lastLineData this) chunk) | |
(str chunk)) | |
lines (clojure.string/split data (js/RegExp. eol "g"))] | |
(set! (.-_lastLineData this) (last lines)) | |
(doseq [line (butlast lines)] | |
(.push this line)) | |
(done)))) | |
(defn- flush [done] | |
(this-as this | |
(if (.-_lastLineData this) | |
(.push this (.-_lastLineData this))) | |
(set! (.-_lastLineData this) nil) | |
(done))) | |
(defn read-file-cb [file-name cb] | |
(let [line-reader (.Transform stream #js {:objectMode true}) | |
source (.createReadStream fs file-name)] | |
(set! (.-_transform line-reader) transform) | |
(set! (.-_flush line-reader) flush) | |
(.pipe source line-reader) | |
(.on line-reader "readable" | |
(fn [] | |
(when-let [line (.read line-reader)] | |
(cb (str line)) ;;callback with each line | |
(recur)))) | |
nil)) | |
(defn read-file-chan [file-name out-chan] | |
(let [line-reader (.Transform stream #js {:objectMode true}) | |
source (.createReadStream fs file-name)] | |
(set! (.-_transform line-reader) transform) | |
(set! (.-_flush line-reader) flush) | |
(.pipe source line-reader) | |
(.on line-reader "readable" | |
(fn [] | |
(go | |
(loop [] | |
(when-let [line (.read line-reader)] | |
(>! out-chan (str line)) ;;push line to chan | |
(recur)))))) | |
nil)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment