├── Step1.png
├── Step2.png
├── Step3.png
├── Excel-REPL.v12.suo
├── Spreadsheet Snapshot.png
├── Excel-REPL
├── nrepl
│ ├── clojure
│ │ ├── tools
│ │ │ ├── nrepl
│ │ │ │ ├── server.clj
│ │ │ │ ├── debug.clj
│ │ │ │ ├── middleware
│ │ │ │ │ ├── pr_values.clj
│ │ │ │ │ ├── load_file.clj
│ │ │ │ │ ├── interruptible_eval.clj
│ │ │ │ │ └── session.clj
│ │ │ │ ├── ack.clj
│ │ │ │ ├── misc.clj
│ │ │ │ ├── sync_channel.clj
│ │ │ │ ├── middleware.clj
│ │ │ │ ├── transport.clj
│ │ │ │ └── bencode.clj
│ │ │ └── nrepl.clj
│ │ └── data
│ │ │ ├── drawbridge_client.clj
│ │ │ └── json.clj
│ ├── excel_repl
│ │ ├── util.clj
│ │ ├── formatting.clj
│ │ ├── schedule_udf.clj
│ │ ├── coerce_db.clj
│ │ ├── interop.clj
│ │ └── udf.clj
│ └── clr_http
│ │ └── lite
│ │ ├── util.clj
│ │ ├── core.clj
│ │ ├── cookies.clj
│ │ └── client.clj
├── SampleClipboard.txt
├── Excel-REPL.csproj.user
├── packages.config
├── Excel-REPL-AddIn.dna
├── Python.cs
├── DB.cs
├── Class1.cs
├── excel-repl.clj
├── Excel-REPL.csproj
└── MainClass.cs
├── Install Instructions.txt
├── default dependencies.txt
├── Excel-REPL.sln
└── readme.md
/Step1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/whamtet/Excel-REPL/HEAD/Step1.png
--------------------------------------------------------------------------------
/Step2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/whamtet/Excel-REPL/HEAD/Step2.png
--------------------------------------------------------------------------------
/Step3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/whamtet/Excel-REPL/HEAD/Step3.png
--------------------------------------------------------------------------------
/Excel-REPL.v12.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/whamtet/Excel-REPL/HEAD/Excel-REPL.v12.suo
--------------------------------------------------------------------------------
/Spreadsheet Snapshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/whamtet/Excel-REPL/HEAD/Spreadsheet Snapshot.png
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/server.clj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/whamtet/Excel-REPL/HEAD/Excel-REPL/nrepl/clojure/tools/nrepl/server.clj
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/excel_repl/util.clj:
--------------------------------------------------------------------------------
1 | (ns excel-repl.util)
2 | (import System.Windows.Forms.Clipboard)
3 |
4 | (defn comma-interpose [s] (apply str (interpose ", " s)))
5 | (defn line-interpose [s] (apply str (interpose "\r\n" s)))
6 |
7 | (defn to-clipboard [s]
8 | (Clipboard/SetText s))
9 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/excel_repl/formatting.clj:
--------------------------------------------------------------------------------
1 | (ns excel-repl.formatting)
2 |
3 | (import ClojureExcel.MainClass)
4 | (import System.Windows.Forms.MessageBox)
5 |
6 | (defn f [x]
7 | ;(future
8 | (MyRibbon/SetOutput (map #(.ToUpper %) x)))
9 | ;)
10 |
11 | (set! MainClass/format_code f)
12 |
--------------------------------------------------------------------------------
/Excel-REPL/SampleClipboard.txt:
--------------------------------------------------------------------------------
1 | Version:0.9
2 | StartHTML:0000000213
3 | EndHTML:0000002410
4 | StartFragment:0000000249
5 | EndFragment:0000002374
6 | SourceURL:http://excel-repl.net
7 |
8 |
9 | {0}
10 |
11 |
12 | {1}
13 |
14 |
--------------------------------------------------------------------------------
/Install Instructions.txt:
--------------------------------------------------------------------------------
1 | MANUAL INSTALLATION
2 |
3 | If you lack administrator privileges for the automatic installer, you can still install Excel-REPL manually. Copy the contents of Debug into
4 |
5 | C:\Users\USER\AppData\Roaming\Microsoft\AddIns
6 |
7 | where USER is your home folder.
8 |
9 | Next open Microsoft Excel and select Options, AddIns. Add Excel-REPL and it will auto-load every time in the future.
10 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/debug.clj:
--------------------------------------------------------------------------------
1 | (ns clojure.tools.nrepl.debug)
2 |
3 | (def ^{:private true} pr-agent (agent *out*))
4 |
5 | (defn- write-out [out & args]
6 | (binding [*out* out]
7 | (pr "Thd " (-> System.Threading.Thread/CurrentThread (.ManagedThreadId)) ": ")
8 | (apply prn args)
9 | out))
10 |
11 | (defn prn-thread [& args]
12 | (send pr-agent write-out args))
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Excel-REPL/Excel-REPL.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ShowAllFiles
5 |
6 |
7 | Program
8 | C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE
9 | "Z:\Downloads\Excel-REPL\Excel-REPL\bin\Debug\Excel-REPL-AddIn.xll"
10 |
11 |
--------------------------------------------------------------------------------
/Excel-REPL/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/excel_repl/schedule_udf.clj:
--------------------------------------------------------------------------------
1 | (ns excel-repl.schedule-udf)
2 |
3 | ;;ok, two strategies
4 | ;;for ns we will concatenate a list of namespaces to compile
5 | ;;ExportUDFS will invoke a fixed function that compiles them
6 |
7 | ;;for in-macro-context we shall concatenate a list of fuctions to execute
8 | ;;INVOKEMacroContext shall execute them all and return the last result
9 |
10 | (def nss (ref []))
11 | (def fns (ref []))
12 |
13 | (defn add-ns [ns]
14 | (dosync
15 | (alter nss conj ns)))
16 |
17 | (defn add-curr-ns []
18 | (add-ns *ns*))
19 |
20 | (defn add-fn [fn]
21 | (dosync
22 | (alter fns conj fn)))
23 |
24 | (defn get-ns []
25 | (dosync
26 | (let [a @nss]
27 | (ref-set nss [])
28 | a)))
29 |
30 | (defn get-fns []
31 | (dosync
32 | (let [a @fns]
33 | (ref-set fns [])
34 | a)))
35 |
--------------------------------------------------------------------------------
/default dependencies.txt:
--------------------------------------------------------------------------------
1 | Microsoft.CSharp
2 | System
3 | System.Core
4 | System.Data
5 | System.Data.DataSetExtensions
6 | System.Xml
7 | System.Xml.Linq
8 |
9 | ExcelDNA
10 | ========
11 | ExcelDna.Integration
12 |
13 | Clojure
14 | =======
15 | Clojure
16 | Microsoft.Dynamic
17 | Microsoft.Scripting
18 |
19 | NetOffice Excel
20 | ===============
21 |
22 | NetOffice
23 | OfficeApi
24 | VBIDEApi
25 | ExcelApi
26 | Microsoft.Office.Interop.Excel
27 |
28 | Misc
29 | ====
30 | System.Web
31 | System.Drawing
32 | System.Windows.Forms
33 |
34 | DotNetZip
35 | =========
36 | Iconic.Zip
37 |
38 | Official .NET driver for MongoDB
39 | ================================
40 |
41 | MongoDB.Bson
42 | MongoDB.Driver
43 |
44 | NOTE!!!!
45 | Set ExcelDna.Integration reference to CopyLocal=True
46 | so that it may be loaded
--------------------------------------------------------------------------------
/Excel-REPL/Excel-REPL-AddIn.dna:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Excel-REPL/Python.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Scripting.Hosting;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace clojureexcel
9 | {
10 | public class Python
11 | {
12 | private static ScriptEngine engine;
13 | private static ScriptScope scope;
14 |
15 | static Python()
16 | {
17 | }
18 | private static void Init()
19 | {
20 | engine = IronPython.Hosting.Python.CreateEngine();
21 | scope = engine.CreateScope();
22 | var paths = engine.GetSearchPaths();
23 | paths.Add("C:\\Program Files (x86)\\Excel-REPL\\Excel-REPL\\Lib");
24 | paths.Add("C:\\Anaconda\\Lib");
25 | paths.Add("C:\\Program Files (x86)\\Excel-REPL\\Excel-REPL\\python");
26 | paths.Add("C:\\Users\\xuehuit\\Documents\\Visual Studio 2012\\Projects\\Excel-REPL\\Excel-REPL\\python");
27 | engine.SetSearchPaths(paths);
28 |
29 | String initCode = @"
30 | from pygments import highlight
31 | from pygments.lexers import ClojureLexer
32 | from pygments.formatters import HtmlFormatter
33 |
34 | clojureLexer = ClojureLexer()
35 | htmlFormatter = HtmlFormatter()
36 |
37 | def raw(code):
38 | return highlight(code, clojureLexer, htmlFormatter)";
39 |
40 | engine.Execute(initCode, scope);
41 | }
42 |
43 |
44 | public static dynamic Eval(String input)
45 | {
46 | return engine.Execute(input, scope);
47 | }
48 |
49 | public static String Html(String code)
50 | {
51 | code = String.Format("raw(\"\"\"{0}\"\"\")", code);
52 | return Eval(code);
53 | }
54 |
55 | public static String Css()
56 | {
57 | return Eval("htmlFormatter.get_style_defs()");
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/Excel-REPL/DB.cs:
--------------------------------------------------------------------------------
1 | using clojure.lang;
2 | using MongoDB.Bson;
3 | using MongoDB.Bson.Serialization.Attributes;
4 | using MongoDB.Driver.Builders;
5 | using System;
6 | using System.Text;
7 |
8 | public static class DB
9 | {
10 | private static IFn read_string = clojure.clr.api.Clojure.var("clojure.core", "read-string");
11 | private static IFn pr_str = clojure.clr.api.Clojure.var("clojure.core", "pr-str");
12 | public static MongoDB.Driver.MongoClient Connect(String s)
13 | {
14 | var client = new MongoDB.Driver.MongoClient(s);
15 | return client;
16 | }
17 | //mongodb://[username:password@]hostname[:port][/[database][?options]]
18 | public static MongoDB.Driver.MongoClient Connect(String host, int port)
19 | {
20 | return new MongoDB.Driver.MongoClient(String.Format("mongodb://{0}:{1}", host, port));
21 | }
22 | public static MongoDB.Driver.MongoClient Connect()
23 | {
24 | return new MongoDB.Driver.MongoClient();
25 | }
26 |
27 | public static void Set(MongoDB.Driver.MongoClient c, String k, BsonDocument v)
28 | {
29 | var db = c.GetServer().GetDatabase("db");
30 | var coll = db.GetCollection(k);
31 | Entity entity = new Entity { data = v, _id = k};
32 | coll.Save(entity);
33 | }
34 | public static Object Get(MongoDB.Driver.MongoClient c, String k)
35 | {
36 | var db = c.GetServer().GetDatabase("db");
37 | var coll = db.GetCollection(k);
38 | var query = Query.EQ(e => e._id, k);
39 | var entity = coll.FindOne(query);
40 | var v = entity.GetElement("data");
41 | //return read_string.invoke(v.Value.ToString());
42 | return v.Value;
43 | }
44 |
45 | public class Entity
46 | {
47 | [BsonId]
48 | public string _id { get; set; }
49 |
50 | public BsonDocument data { get; set; }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Excel-REPL/Class1.cs:
--------------------------------------------------------------------------------
1 | using clojure.lang;
2 | using ExcelDna.Integration;
3 | using System;
4 | using System.Windows.Forms;
5 | using System.Threading;
6 | //using System.Text.RegularExpressions;
7 |
8 | public class Class1
9 | {
10 | private static IFn ifn_list;
11 |
12 | public Class1(IFn foo)
13 | {
14 | foo;
15 | }
16 |
17 | private void Poo() { }
18 |
19 | private static Object cleanValue(object o)
20 | {
21 | if (o == null)
22 | {
23 | return "";
24 | }
25 | if (o is bool)
26 | {
27 | return o;
28 | }
29 | if (o is Ratio)
30 | {
31 | return ((Ratio)o).ToDouble(null);
32 | }
33 | if (o is sbyte
34 | || o is byte
35 | || o is short
36 | || o is ushort
37 | || o is int
38 | || o is uint
39 | || o is long
40 | || o is ulong
41 | || o is float
42 | || o is double
43 | || o is decimal)
44 | {
45 | return o;
46 | }
47 | else
48 | {
49 | return o.ToString();
50 | }
51 | }
52 |
53 | public static Object RaggedArray(Object arrayCandidate)
54 | {
55 | var input = arrayCandidate as Object[,];
56 | if (input == null)
57 | {
58 | return arrayCandidate;
59 | }
60 | int m = input.GetUpperBound(0) + 1;
61 | int n = input.GetUpperBound(1) + 1;
62 | Object[][] output = new Object[m][];
63 | for (int i = 0; i < m; i++)
64 | {
65 | Object[] row = new Object[n];
66 | for (int j = 0; j < n; j++)
67 | {
68 | row[j] = input[i, j];
69 | }
70 | output[i] = row;
71 | }
72 | return output;
73 | }
74 |
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/middleware/pr_values.clj:
--------------------------------------------------------------------------------
1 |
2 | (ns ^{:author "Chas Emerick"}
3 | clojure.tools.nrepl.middleware.pr-values
4 | (:require [clojure.tools.nrepl.transport :as t]
5 | [clojure.tools.nrepl.debug :as debug]) ;DM: Added
6 | (:use [clojure.tools.nrepl.middleware :only (set-descriptor!)])
7 | (:import clojure.tools.nrepl.transport.Transport))
8 |
9 | (defn pr-values
10 | "Middleware that returns a handler which transforms any :value slots
11 | in messages sent via the request's Transport to strings via `pr`,
12 | delegating all actual message handling to the provided handler.
13 |
14 | Requires that results of eval operations are sent in messages in a
15 | :value slot."
16 | [h]
17 | (fn [{:keys [op ^Transport transport] :as msg}]
18 | (h (assoc msg :transport (let [wt (reify Transport
19 | (recv [this] (.recv transport))
20 | (recv [this timeout] (.recv transport timeout))
21 | (send [this resp]
22 | #_(debug/prn-thread "pr-values - sending on to " (.GetHashCode transport))
23 | (.send transport
24 | (if-let [[_ v] (find resp :value)]
25 | (let [repr (System.IO.StringWriter.)] ;;; java.io.StringWriter.
26 | (assoc resp :value (do (if *print-dup*
27 | (print-dup v repr)
28 | (print-method v repr))
29 | (str repr))))
30 | resp))
31 | this))]
32 | #_(debug/prn-thread "pr-values - reify, wrapping " (.GetHashCode wt) " around " (.GetHashCode transport))
33 | wt)
34 | ))))
35 |
36 | (set-descriptor! #'pr-values
37 | {:requires #{}
38 | :expects #{}
39 | :handles {}})
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/ack.clj:
--------------------------------------------------------------------------------
1 |
2 | (ns clojure.tools.nrepl.ack
3 | (:require [clojure.tools.nrepl :as repl]
4 | [clojure.tools.nrepl.transport :as t])
5 | (:import (clojure.lang Future FutureTimeoutException))) ;DM: (java.util.concurrent Future TimeUnit TimeoutException)
6 |
7 | ; could be a lot fancier, but it'll do for now
8 | (def ^{:private true} ack-port-promise (atom nil))
9 |
10 | (defn reset-ack-port!
11 | []
12 | (reset! ack-port-promise (promise))
13 | ; save people the misery of ever trying to deref the empty promise in their REPL
14 | nil)
15 |
16 | (defn wait-for-ack
17 | "Waits for a presumably just-launched nREPL server to connect and
18 | deliver its port number. Returns that number if it's delivered
19 | within `timeout` ms, otherwise nil. Assumes that `ack`
20 | middleware has been applied to the local nREPL server handler.
21 |
22 | Expected usage:
23 |
24 | (reset-ack-port!)
25 | (start-server already-running-server-port)
26 | => (wait-for-ack)
27 | 59872 ; the port of the server started via start-server"
28 | [timeout]
29 | (let [^Future f (future @@ack-port-promise)]
30 | (try
31 | ; no deref with timeout in 1.2
32 | (.get f timeout) ;DM: remove TimeUnit/MILLISECONDS
33 | (catch FutureTimeoutException e)))) ;DM: TimeoutException
34 |
35 | (defn handle-ack
36 | [h]
37 | (fn [{:keys [op port transport] :as msg}]
38 | (if (not= op "ack")
39 | (h msg)
40 | (try
41 | (deliver @ack-port-promise port)
42 | (t/send transport {:status :done})))))
43 |
44 | ; TODO could stand to have some better error handling around all of this
45 | (defn send-ack
46 | [my-port ack-port]
47 | (with-open [transport (repl/connect :port ack-port)]
48 | (let [client (repl/client transport 1000)]
49 | ; consume response from the server, solely to let that side
50 | ; finish cleanly without (by default) spewing a SocketException when
51 | ; the ack client goes away suddenly
52 | (dorun (repl/message client {:op :ack :port my-port})))))
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/misc.clj:
--------------------------------------------------------------------------------
1 | (ns ^{:doc "Misc utilities used in nREPL's implementation (potentially also useful
2 | for anyone extending it)."
3 | :author "Chas Emerick, modified for ClojureCLR by David Miller"}
4 | clojure.tools.nrepl.misc)
5 |
6 | (try
7 | (require 'clojure.tools.logging)
8 | (defmacro log [& args] `(clojure.tools.logging/error ~@args))
9 | (catch Exception t ;;; Throwable
10 | ;(println "clojure.tools.logging not available, falling back to stdout/err")
11 | (defn log
12 | [ex & msgs]
13 | (let [ex (when (instance? Exception ex) ex) ;;; Throwable
14 | msgs (if ex msgs (cons ex msgs))]
15 | (binding [*out* *err*]
16 | (apply println "ERROR:" msgs)
17 | (when ex (println (.StackTrace ^Exception ex)))))))) ;;; (.printStackTrace ^Throwable ex)))))))
18 |
19 | (defmacro returning
20 | "Executes `body`, returning `x`."
21 | [x & body]
22 | `(let [x# ~x] ~@body x#))
23 |
24 | (defn uuid
25 | "Returns a new UUID string."
26 | []
27 | (str (Guid/NewGuid))) ;;; java.util.UUID/randomUUID
28 |
29 | (defn response-for
30 | "Returns a map containing the :session and :id from the \"request\" `msg`
31 | as well as all entries specified in `response-data`, which can be one
32 | or more maps (which will be merged), *or* key-value pairs.
33 |
34 | (response-for msg :status :done :value \"5\")
35 | (response-for msg {:status :interrupted})
36 |
37 | The :session value in `msg` may be any Clojure reference type (to accommodate
38 | likely implementations of sessions) that has an :id slot in its metadata,
39 | or a string."
40 | [{:keys [session id]} & response-data]
41 | {:pre [(seq response-data)]}
42 | (let [{:keys [status] :as response} (if (map? (first response-data))
43 | (reduce merge response-data)
44 | (apply hash-map response-data))
45 | response (if (not status)
46 | response
47 | (assoc response :status (if (coll? status)
48 | status
49 | #{status})))
50 | basis (merge (when id {:id id})
51 | ; AReference should make this suitable for any session implementation?
52 | (when session {:session (if (instance? clojure.lang.AReference session)
53 | (-> session meta :id)
54 | session)}))]
55 | (merge basis response)))
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/data/drawbridge_client.clj:
--------------------------------------------------------------------------------
1 | (ns clojure.data.drawbridge-client
2 | (:require [clojure.data.json :as json]
3 | [clojure.tools.nrepl :as nrepl]
4 | [clr-http.lite.client :as http]
5 | )
6 | (:import ClojureExcel.MainClass
7 | System.IO.StreamReader
8 | ))
9 |
10 | ;DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond
11 | (defn time-millis []
12 | (/ (.Ticks DateTime/Now) TimeSpan/TicksPerMillisecond))
13 |
14 | (defn ring-client-transport
15 | "Returns an nREPL client-side transport to connect to HTTP nREPL
16 | endpoints implemented by `ring-handler`.
17 |
18 | This fn is implicitly registered as the implementation of
19 | clojure.tools.nrepl/url-connect for `http` and `https` schemes;
20 | so, once this namespace is loaded, any tool that uses url-connect
21 | will use this implementation for connecting to HTTP and HTTPS
22 | nREPL endpoints."
23 | [url]
24 | (let [incoming (MainClass/GetCollection); a bit of a hack
25 | fill #(when-let [responses (->> %
26 | StreamReader.
27 | line-seq
28 | rest
29 | drop-last
30 | (remove empty?)
31 | (map json/read-str)
32 | (remove nil?)
33 | seq)]
34 | (doseq [response responses]
35 | (.Add incoming response)))
36 |
37 | session-cookies (atom nil)
38 |
39 | http (fn [& [msg]]
40 | (let [
41 | req-map (merge {:as :stream
42 | :cookies @session-cookies}
43 | (when msg {:form-params msg}))
44 | {:keys [cookies body] :as resp} ((if msg http/post http/get)
45 | url
46 | req-map)]
47 | (println "cookies" cookies)
48 | (swap! session-cookies merge cookies)
49 | (fill body)))
50 | poll #(MainClass/TakeItem incoming)
51 | ]
52 | (clojure.tools.nrepl.transport.FnTransport.
53 | (fn read [timeout]
54 | (let [t (time-millis)]
55 | (or (poll)
56 | (when (pos? timeout)
57 | (http)
58 | (recur (- timeout (- (time-millis) t)))))))
59 | http
60 | (fn close []))))
61 |
62 |
63 | ;(.removeMethod nrepl/url-connect "http")
64 | ;(.removeMethod nrepl/url-connect "https")
65 |
66 | (.addMethod nrepl/url-connect "http" #'ring-client-transport)
67 | (.addMethod nrepl/url-connect "https" #'ring-client-transport)
68 |
69 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clr_http/lite/util.clj:
--------------------------------------------------------------------------------
1 | (ns clr-http.lite.util
2 | "Helper functions for the HTTP client."
3 | (:require [clojure.clr.io :as io])
4 | (:import
5 | System.Text.Encoding
6 | System.IO.MemoryStream
7 | System.IO.Stream
8 | System.IO.Compression.GZipStream
9 | System.IO.Compression.CompressionMode
10 | System.IO.Compression.DeflateStream
11 | ))
12 |
13 | (assembly-load-with-partial-name "System.Web")
14 | (import System.Web.HttpUtility)
15 |
16 | (defn utf8-bytes
17 | "Returns the UTF-8 bytes corresponding to the given string."
18 | [^String s]
19 | (.GetBytes Encoding/UTF8 s))
20 |
21 | (defn utf8-string
22 | "Returns the String corresponding to the UTF-8 decoding of the given bytes."
23 | [b]
24 | (if (string? b)
25 | b
26 | (.GetString Encoding/UTF8 b)))
27 |
28 | (defn url-decode
29 | "Returns the form-url-decoded version of the given string, using either a
30 | specified encoding or UTF-8 by default."
31 | [encoded & [encoding]]
32 | (HttpUtility/UrlDecode encoded (or encoding Encoding/UTF8)))
33 |
34 | (defn url-encode
35 | "Returns an UTF-8 URL encoded version of the given string."
36 | [unencoded]
37 | (HttpUtility/UrlEncode unencoded Encoding/UTF8))
38 |
39 | (defn base64-encode
40 | "Encode an array of bytes into a base64 encoded string."
41 | [unencoded]
42 | (Convert/ToBase64String unencoded))
43 |
44 | (defn to-byte-array
45 | "Returns a byte array for the InputStream provided."
46 | [is]
47 | (with-open [os (MemoryStream.)]
48 | (io/copy is os)
49 | (.ToArray os)))
50 |
51 | (defn gunzip
52 | "Returns a gunzip'd version of the given byte array."
53 | [b]
54 | (when b
55 | (if (instance? Stream b)
56 | (GZipStream. b CompressionMode/Decompress)
57 | (with-open [
58 | is (GZipStream. (MemoryStream. b) CompressionMode/Decompress)
59 | ]
60 | (to-byte-array is)))))
61 |
62 | (defn gzip
63 | "gzips binary array"
64 | [b]
65 | (when b
66 | (with-open [compressIntoMs (MemoryStream.)]
67 | (with-open [gzs (GZipStream. compressIntoMs CompressionMode/Compress)]
68 | (.Write gzs b 0 (.Length b)))
69 | (.ToArray compressIntoMs))))
70 |
71 | (defn inflate
72 | "Returns a zlip inflated version of a the given byte array."
73 | [b]
74 | (when b
75 | (with-open [
76 | is (DeflateStream. (MemoryStream. b) CompressionMode/Decompress)
77 | ]
78 | (to-byte-array is))))
79 |
80 | (defn deflate
81 | "Deflates binary array"
82 | [b]
83 | (when b
84 | (with-open [
85 | mem-stream (MemoryStream.)
86 | ]
87 | (with-open [deflate-stream (DeflateStream. mem-stream CompressionMode/Compress)]
88 | (.Write deflate-stream b 0 (.Length b)))
89 | (.ToArray mem-stream))))
90 |
91 | (defmacro doto-set
92 | "Similar to doto however sets Csharp properties instead"
93 | [new & rest]
94 | (let [x (gensym)]
95 | `(let [~x ~new]
96 | ~@(for [[a b] rest]
97 | `(set! (~a ~x) ~b))
98 | ~x)))
99 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/excel_repl/coerce_db.clj:
--------------------------------------------------------------------------------
1 | (ns excel-repl.coerce-db
2 | (:use [clojure.data.json :only [write-str read-str]]
3 | )
4 | (:import [clojure.lang IPersistentMap Keyword IPersistentCollection Ratio Symbol]
5 | [System.Collections IEnumerable IDictionary IList]
6 | ; [java.util Map List Set]
7 | ; [com.mongodb DBObject BasicDBObject BasicDBList]
8 | ; [com.mongodb.gridfs GridFSFile]
9 | ; [com.mongodb.util JSON]
10 | ))
11 |
12 | (assembly-load "MongoDB.Bson")
13 | (import '[MongoDB.Bson BsonArray BsonInt32 BsonInt64 BsonBoolean
14 | BsonDateTime BsonDouble BsonNull BsonRegularExpression
15 | BsonString BsonSymbol BsonDocument BsonElement
16 | BsonValue BsonExtensionMethods
17 | ])
18 |
19 |
20 |
21 | (defprotocol ConvertibleFromMongo
22 | (mongo->clojure [o]))
23 |
24 | (extend-protocol ConvertibleFromMongo
25 | BsonDocument
26 | (mongo->clojure [^BsonDocument m]
27 | (into {}
28 | (map #(vector (mongo->clojure (.Name %)) (mongo->clojure (.Value %))) (seq m))))
29 | BsonArray
30 | (mongo->clojure [^IEnumerable l]
31 | (mapv mongo->clojure l))
32 | Object
33 | (mongo->clojure [o] o)
34 | nil
35 | (mongo->clojure [o] o)
36 | BsonInt32
37 | (mongo->clojure [o] (int o))
38 | BsonInt64
39 | (mongo->clojure [o] (long o))
40 | BsonBoolean
41 | (mongo->clojure [o] (.Value o))
42 | BsonDateTime
43 | (mongo->clojure [o] (str o))
44 | BsonDouble
45 | (mongo->clojure [o] (.Value o))
46 | BsonNull
47 | (mongo->clojure [o])
48 | BsonRegularExpression
49 | (mongo->clojure [o] (-> o .Pattern re-pattern))
50 | String
51 | (mongo->clojure [o]
52 | (let [s (str o)]
53 | (if (.StartsWith s ":")
54 | (keyword (.Substring s 1))
55 | s)))
56 | BsonString
57 | (mongo->clojure [o]
58 | (let [s (str o)]
59 | (if (.StartsWith s ":")
60 | (keyword (.Substring s 1))
61 | s)))
62 | BsonSymbol
63 | (mongo->clojure [o] (-> o str symbol))
64 | )
65 |
66 |
67 | ;; ;;; Converting data from Clojure into data objects suitable for Mongo
68 |
69 | (defprotocol ConvertibleToMongo
70 | (clojure->mongo [o]))
71 |
72 | (extend-protocol ConvertibleToMongo
73 | IPersistentMap
74 | (clojure->mongo [m]
75 | (let [out (BsonDocument.)]
76 | (doseq [[k v] m]
77 | (.Add out (str k) (clojure->mongo v)))
78 | out))
79 | IPersistentCollection
80 | (clojure->mongo [m] (BsonArray. (map clojure->mongo m)))
81 | Keyword
82 | (clojure->mongo [^Keyword o]
83 | (BsonString. (str o)))
84 | nil
85 | (clojure->mongo [o] BsonNull/Value)
86 | Object
87 | (clojure->mongo [o] (BsonValue/Create o))
88 | Ratio
89 | (clojure->mongo [o] (BsonValue/Create (.ToDouble o nil)))
90 | Symbol
91 | (clojure->mongo [o] (-> o str BsonValue/Create))
92 | Int64
93 | (clojure->mongo [o] (BsonInt64. o))
94 | )
95 |
--------------------------------------------------------------------------------
/Excel-REPL/excel-repl.clj:
--------------------------------------------------------------------------------
1 | ;no ns. this will be evaluated in clojure.core for simplicity
2 |
3 | (import System.Environment)
4 | (import System.IO.Directory)
5 | (import System.Windows.Forms.MessageBox)
6 |
7 | (import ExcelDna.Integration.ExcelReference)
8 | (import ExcelDna.Integration.XlCall)
9 | (import ClojureExcel.MainClass)
10 |
11 | ;(import NetOffice.ExcelApi.Application)
12 |
13 | (require '[clojure.repl :as r])
14 | (require 'clojure.pprint)
15 | (require '[clojure.string :as string])
16 | (require 'clojure.walk)
17 |
18 | (defn show
19 | "Show MessageBox"
20 | [x]
21 | (MessageBox/Show x))
22 |
23 | (defn get-cd
24 | "returns current directory as a string"
25 | []
26 | (Directory/GetCurrentDirectory))
27 |
28 | (defn set-cd
29 | "sets current directory as a string"
30 | [new-d]
31 | (Directory/SetCurrentDirectory new-d))
32 |
33 | (defn get-load-path []
34 | (set (string/split (Environment/GetEnvironmentVariable "CLOJURE_LOAD_PATH") #";")))
35 |
36 | (defn set-load-path! [s]
37 | (let [
38 | new-path (apply str (interpose ";" s))
39 | ]
40 | (Environment/SetEnvironmentVariable "CLOJURE_LOAD_PATH" new-path)
41 | new-path))
42 |
43 | (defn append-load-path!
44 | "appends file string to clojure load path"
45 | [new-path]
46 | (set-load-path! (conj (get-load-path) new-path)))
47 |
48 | (defn split-lines [s]
49 | (string/split s #"\n"))
50 |
51 | (defmacro with-out-strs
52 | "evaluates expression and returns list of lines printed"
53 | [x]
54 | `(split-lines (with-out-str ~x)))
55 |
56 | (defmacro source
57 | "function source returned as string"
58 | [x]
59 | `(with-out-strs (r/source ~x)))
60 |
61 | (defmacro doc
62 | "function docstring"
63 | [x]
64 | `(with-out-strs (r/doc ~x)))
65 |
66 | (defmacro pprint
67 | "pprint to string"
68 | [x]
69 | `(with-out-strs (clojure.pprint/pprint ~x)))
70 |
71 | (defmacro time-str
72 | "times evaluation of expression x"
73 | [x]
74 | `(with-out-strs (time ~x)))
75 |
76 |
77 | (def letters "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
78 | (def letter->val (into {} (map-indexed (fn [i s] [s i]) letters)))
79 |
80 | (defn letter->val2
81 | "column number of excel coumn A, AZ etc"
82 | [[s t :as ss]]
83 | (if t
84 | (apply + 26
85 | (map *
86 | (map letter->val (reverse ss))
87 | (map #(Math/Pow 26 %) (range))))
88 | (letter->val s)))
89 |
90 | (defn col-num
91 | "column number of reference in form A4 etc"
92 | [s]
93 | (if (string? s)
94 | (letter->val2 (re-find #"[A-Z]+" s))
95 | (second s)))
96 |
97 | (defn row-num
98 | [s]
99 | (if (string? s)
100 | (dec (int (re-find #"[0-9]+" s)))
101 | (first s)))
102 |
103 | (defn get-values
104 | "Returns values at ref which is of the form A1 or A1:B6.
105 | Single cell selections are returned as a value, 2D selections as an Object[][] array"
106 | [sheet ref]
107 | (let [
108 | refs (if (.Contains ref ":") (string/split ref #":") [ref ref])
109 | [i id] (map row-num refs)
110 | [j jd] (map col-num refs)
111 | value (.GetValue (ExcelReference. i id j jd sheet))
112 | ]
113 | (if (.Contains ref ":")
114 | (MainClass/RaggedArray value)
115 | value)))
116 |
117 | ;;otha stuff
118 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clr_http/lite/core.clj:
--------------------------------------------------------------------------------
1 | (ns clr-http.lite.core
2 | "Core HTTP request/response implementation."
3 | (:require [clojure.clr.io :as io]
4 | [clr-http.lite.util :as util]
5 | [clr-http.lite.cookies :as cookies]
6 | )
7 | (:import
8 | System.Net.WebRequest
9 | System.Net.CookieContainer))
10 |
11 | (defn safe-conj [a b]
12 | (if (vector? a)
13 | (conj a b)
14 | [a b]))
15 |
16 | (defn parse-headers
17 | "Takes a URLConnection and returns a map of names to values.
18 |
19 | If a name appears more than once (like `set-cookie`) then the value
20 | will be a vector containing the values in the order they appeared
21 | in the headers."
22 | [conn]
23 | (let [headers (.Headers conn)]
24 | (apply merge-with
25 | safe-conj
26 | (for [header (.Headers conn)]
27 | {header (.Get headers header)}))))
28 |
29 | (defn- coerce-body-entity
30 | "Coerce the http-entity from an HttpResponse to either a byte-array, or a
31 | stream that closes itself and the connection manager when closed."
32 | [{:keys [as]} conn]
33 | (let [ins (.GetResponseStream conn)]
34 | (if (or (= :stream as) (nil? ins))
35 | ins
36 | (util/to-byte-array ins))))
37 |
38 | (defn request
39 | "Executes the HTTP request corresponding to the given Ring request map and
40 | returns the Ring response map corresponding to the resulting HTTP response.
41 | Note that where Ring uses InputStreams for the request and response bodies,
42 | the clj-http uses ByteArrays for the bodies."
43 | [{:keys [request-method scheme server-name server-port uri query-string
44 | headers content-type character-encoding body socket-timeout
45 | cookies save-request? follow-redirects] :as req}]
46 | (let [http-url (str (name scheme) "://" server-name
47 | (when server-port (str ":" server-port))
48 | uri
49 | (when query-string (str "?" query-string)))
50 | request (WebRequest/Create http-url)
51 | Headers (.Headers request)
52 | ;^CookieContainer cookie-container (.CookieContainer request)
53 | cookie-container (CookieContainer.)
54 | ]
55 | (when (and content-type character-encoding)
56 | (set! (.ContentType request) (str content-type
57 | "; charset="
58 | character-encoding)))
59 | (when (and content-type (not character-encoding))
60 | (set! (.ContentType request) content-type))
61 | (doseq [[h v] headers]
62 | (.Add Headers h v))
63 | (when (false? follow-redirects)
64 | (set! (.AllowAutoRedirect request) false))
65 | (set! (.Method request) (.ToUpper (name request-method)))
66 | (when socket-timeout
67 | (set! (.ReadWriteTimeout request) socket-timeout))
68 | (doseq [cookie (map cookies/map->cookie cookies)]
69 | (if (empty? (.Domain cookie))
70 | (set! (.Domain cookie) server-name))
71 | (.Add cookie-container cookie))
72 | (set! (.CookieContainer request) cookie-container)
73 | (when body
74 | (with-open [out (.GetRequestStream request)]
75 | (io/copy body out)))
76 | (try
77 | (let [
78 | response (.GetResponse request)
79 | ]
80 | (merge {:headers (parse-headers response)
81 | :status (-> response .StatusCode int)
82 | :body (when-not (= request-method :head)
83 | (coerce-body-entity req response))
84 | :cookies (into {} (map cookies/cookie->map (.Cookies response)))
85 | }
86 | (when save-request?
87 | {:request (-> req
88 | (dissoc :save-request?)
89 | (assoc :http-url http-url))})))
90 | (catch Exception e
91 | {:status 500
92 | :body (str e)}))))
93 |
--------------------------------------------------------------------------------
/Excel-REPL.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Excel-REPL", "Excel-REPL\Excel-REPL.csproj", "{2EB259F1-F88C-44C2-8B63-F61522F43595}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApplication1", "ConsoleApplication1\ConsoleApplication1.csproj", "{C0515150-373D-416A-A2AD-904F08A21979}"
9 | EndProject
10 | Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Setup2", "Setup2\Setup2.vdproj", "{0FC739F3-17D8-42F0-9747-579693D2C1AC}"
11 | EndProject
12 | Project("{6141683F-8A12-4E36-9623-2EB02B2C2303}") = "Setup5", "Setup5\Setup5.isproj", "{EB97A841-84D8-494C-A778-828120AC86FA}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | CD_ROM|Any CPU = CD_ROM|Any CPU
17 | Debug|Any CPU = Debug|Any CPU
18 | DVD-5|Any CPU = DVD-5|Any CPU
19 | Release|Any CPU = Release|Any CPU
20 | SingleImage|Any CPU = SingleImage|Any CPU
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU
24 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.CD_ROM|Any CPU.Build.0 = Release|Any CPU
25 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU
28 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.DVD-5|Any CPU.Build.0 = Debug|Any CPU
29 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU
32 | {2EB259F1-F88C-44C2-8B63-F61522F43595}.SingleImage|Any CPU.Build.0 = Release|Any CPU
33 | {C0515150-373D-416A-A2AD-904F08A21979}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU
34 | {C0515150-373D-416A-A2AD-904F08A21979}.CD_ROM|Any CPU.Build.0 = Release|Any CPU
35 | {C0515150-373D-416A-A2AD-904F08A21979}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {C0515150-373D-416A-A2AD-904F08A21979}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {C0515150-373D-416A-A2AD-904F08A21979}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU
38 | {C0515150-373D-416A-A2AD-904F08A21979}.DVD-5|Any CPU.Build.0 = Debug|Any CPU
39 | {C0515150-373D-416A-A2AD-904F08A21979}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {C0515150-373D-416A-A2AD-904F08A21979}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {C0515150-373D-416A-A2AD-904F08A21979}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU
42 | {C0515150-373D-416A-A2AD-904F08A21979}.SingleImage|Any CPU.Build.0 = Release|Any CPU
43 | {0FC739F3-17D8-42F0-9747-579693D2C1AC}.CD_ROM|Any CPU.ActiveCfg = Release
44 | {0FC739F3-17D8-42F0-9747-579693D2C1AC}.CD_ROM|Any CPU.Build.0 = Release
45 | {0FC739F3-17D8-42F0-9747-579693D2C1AC}.Debug|Any CPU.ActiveCfg = Debug
46 | {0FC739F3-17D8-42F0-9747-579693D2C1AC}.DVD-5|Any CPU.ActiveCfg = Debug
47 | {0FC739F3-17D8-42F0-9747-579693D2C1AC}.DVD-5|Any CPU.Build.0 = Debug
48 | {0FC739F3-17D8-42F0-9747-579693D2C1AC}.Release|Any CPU.ActiveCfg = Release
49 | {0FC739F3-17D8-42F0-9747-579693D2C1AC}.SingleImage|Any CPU.ActiveCfg = Release
50 | {0FC739F3-17D8-42F0-9747-579693D2C1AC}.SingleImage|Any CPU.Build.0 = Release
51 | {EB97A841-84D8-494C-A778-828120AC86FA}.CD_ROM|Any CPU.ActiveCfg = CD_ROM
52 | {EB97A841-84D8-494C-A778-828120AC86FA}.CD_ROM|Any CPU.Build.0 = CD_ROM
53 | {EB97A841-84D8-494C-A778-828120AC86FA}.Debug|Any CPU.ActiveCfg = DVD-5
54 | {EB97A841-84D8-494C-A778-828120AC86FA}.Debug|Any CPU.Build.0 = DVD-5
55 | {EB97A841-84D8-494C-A778-828120AC86FA}.DVD-5|Any CPU.ActiveCfg = DVD-5
56 | {EB97A841-84D8-494C-A778-828120AC86FA}.DVD-5|Any CPU.Build.0 = DVD-5
57 | {EB97A841-84D8-494C-A778-828120AC86FA}.Release|Any CPU.ActiveCfg = SingleImage
58 | {EB97A841-84D8-494C-A778-828120AC86FA}.Release|Any CPU.Build.0 = SingleImage
59 | {EB97A841-84D8-494C-A778-828120AC86FA}.SingleImage|Any CPU.ActiveCfg = SingleImage
60 | {EB97A841-84D8-494C-A778-828120AC86FA}.SingleImage|Any CPU.Build.0 = SingleImage
61 | EndGlobalSection
62 | GlobalSection(SolutionProperties) = preSolution
63 | HideSolutionNode = FALSE
64 | EndGlobalSection
65 | EndGlobal
66 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/sync_channel.clj:
--------------------------------------------------------------------------------
1 | ;-
2 | ; Copyright (c) David Miller. All rights reserved.
3 | ; The use and distribution terms for this software are covered by the
4 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
5 | ; which can be found in the file epl-v10.html at the root of this distribution.
6 | ; By using this software in any fashion, you are agreeing to be bound by
7 | ; the terms of this license.
8 | ; You must not remove this notice, or any other, from this software.
9 |
10 |
11 | (ns #^{:author "David Miller"
12 | :doc "A simple synchronous channel"}
13 | clojure.tools.nrepl.sync-channel
14 | (:refer-clojure :exclude (take)))
15 |
16 | ;; Reason for existence
17 | ;;
18 | ;; The original (ClojureJVM) FnTransport code uses a java.util.concurrent.SynchronousQueue.
19 | ;; However, in that use there is a single producer and a single consumer.
20 | ;; The CLR does not supply such a construct.
21 | ;; (The closest equivalent would be a System.Collections.Concurrent.BlockingCollection with zero capacity,
22 | ;; but that class only allows capacity greater than zero.)
23 | ;;
24 | ;; Rather then do a full-blown implementation of a synchronous queue,
25 | ;; something along the lines of Doug Lea's C# implementation
26 | ;; http://code.google.com/p/netconcurrent/source/browse/trunk/src/Spring/Spring.Threading/Threading/Collections/SynchronousQueue.cs
27 | ;; we can go with a much simpler construct - a synchronous channel between producer and consumer
28 | ;; that blocks either one if the other is not waiting.
29 |
30 | (defprotocol SyncChannel
31 | "A synchronous channel (single-threaded on producer and consumer)"
32 | (put [this value] "Put a value to this channel (Producer)")
33 | (take [this] "Get a value from this channel (Consumer)")
34 | (poll [this] [this timeout] "Get a value from this channel if one is available (within the designated timeout period)"))
35 |
36 |
37 | (definterface ITakeValue
38 | (takeValue []))
39 |
40 | ;; SimpleSyncChannel assumes there is a single producer thread and a single consumer thread.
41 | (deftype SimpleSyncChannel [#^:volatile-mutable value
42 | #^:volatile-mutable c-waiting?
43 | #^:volatile-mutable p-waiting?
44 | lock]
45 | SyncChannel
46 | (put [this v]
47 | (when (nil? v)
48 | (throw (NullReferenceException. "Cannot put nil on SyncChannel")))
49 | (locking lock
50 | (when p-waiting?
51 | (throw (Exception. "Producer not single-threaded")))
52 | (set! value v)
53 | (System.Threading.Monitor/Pulse lock)
54 | (set! p-waiting? true)
55 | (System.Threading.Monitor/Wait lock)
56 | (set! p-waiting? false)))
57 |
58 | (poll [this]
59 | (locking lock
60 | (when c-waiting?
61 | (throw (Exception. "Consumer not single-threaded")))
62 | (when-not (nil? value)
63 | (.takeValue ^ITakeValue this))))
64 |
65 | (poll [this timeout]
66 | (locking lock
67 | (when c-waiting?
68 | (throw (Exception. "Consumer not single-threaded")))
69 | (if (nil? value)
70 | (do
71 | (set! c-waiting? true)
72 | (let [result
73 | (when (System.Threading.Monitor/Wait lock (int timeout))
74 | (.takeValue ^ITakeValue this))]
75 | (set! c-waiting? false)
76 | result))
77 | (.takeValue ^ITakeValue this))))
78 |
79 | (take [this]
80 | (locking lock
81 | (when c-waiting?
82 | (throw (Exception. "Consumer not single-threaded")))
83 | (when (nil? value)
84 | (set! c-waiting? true)
85 | (System.Threading.Monitor/Wait lock)
86 | (set! c-waiting? false))
87 | (.takeValue ^ITakeValue this)))
88 |
89 | ITakeValue
90 | (takeValue [this]
91 | (let [curval value]
92 | (set! value nil)
93 | (System.Threading.Monitor/Pulse lock)
94 | curval)))
95 |
96 | (defn make-simple-sync-channel []
97 | (SimpleSyncChannel. nil false false (Object.)))
98 |
99 |
100 | (comment
101 |
102 | (def prn-agent (agent nil))
103 | (defn sprn [& strings] (send-off prn-agent (fn [v] (apply prn strings))))
104 | (defn f [n]
105 | (let [sc (make-simple-sync-channel)
106 | p (agent nil)
107 | c (agent nil)]
108 | (send c (fn [v] (dotimes [i n] (sprn (str "Consumer " i)) (sprn (str "====> "(take sc))))))
109 | (send p (fn [v] (dotimes [i n] (sprn (str "Producer " i)) (put sc i))))
110 | [p c sc]))
111 | )
112 |
113 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/middleware/load_file.clj:
--------------------------------------------------------------------------------
1 | (ns ^{:author "Chas Emerick"}
2 | clojure.tools.nrepl.middleware.load-file
3 | (:require [clojure.tools.nrepl.middleware.interruptible-eval :as eval])
4 | (:use [clojure.tools.nrepl.middleware :as middleware :only (set-descriptor!)]))
5 |
6 | ; need to hold file contents "out of band" so as to avoid JVM method
7 | ; size limitations (cannot eval an expression larger than some size
8 | ; [64k?]), so the naive approach of just interpolating file contents
9 | ; into an expression to be evaluated doesn't work
10 | ; see http://code.google.com/p/counterclockwise/issues/detail?id=429
11 | ; and http://groups.google.com/group/clojure/browse_thread/thread/f54044da06b9939f
12 | (defonce ^{:private true
13 | :doc "An atom that temporarily holds the contents of files to
14 | be loaded."} file-contents (atom {}))
15 |
16 | (defn- load-large-file-code
17 | "A variant of `load-file-code` that returns an
18 | expression that will only work if evaluated within the same process
19 | where it was called. Here to work around the JVM method size limit
20 | so that (by default, for those tools using the load-file middleware)
21 | loading files of any size will work when the nREPL server is running
22 | remotely or locally."
23 | [file file-path file-name]
24 | ; mini TTL impl so that any code orphaned by errors that occur
25 | ; between here and the evaluation of the Compiler/load expression
26 | ; below are cleaned up on subsequent loads
27 | (let [t (Environment/TickCount) ;DM: System/currentTimeMillis
28 | file-key ^{:t t} [file-path (gensym)]]
29 | (swap! file-contents
30 | (fn [file-contents]
31 | (let [expired-keys
32 | (filter
33 | (comp #(and %
34 | (< 100000000 (- (Environment/TickCount) %))) ;DM: (< 10000 (- (System/currentTimeMillis) %)) -- need to switch to ticks
35 | :t meta)
36 | (keys file-contents))]
37 | (assoc (apply dissoc file-contents expired-keys)
38 | file-key file))))
39 | (binding [*print-length* nil
40 | *print-level* nil]
41 | (pr-str `(try
42 | (clojure.lang.Compiler/load
43 | (System.IO.StringReader. (@@(var file-contents) '~file-key)) ;DM: java.io.StringReader.
44 | ~file-path
45 | ~file-name)
46 | (finally
47 | (swap! @(var file-contents) dissoc '~file-key)))))))
48 |
49 | (defn ^{:dynamic true} load-file-code
50 | "Given the contents of a file, its _source-path-relative_ path,
51 | and its filename, returns a string of code containing a single
52 | expression that, when evaluated, will load those contents with
53 | appropriate filename references and line numbers in metadata, etc.
54 |
55 | Note that because a single expression is produced, very large
56 | file loads will fail due to the JVM method size limitation.
57 | In such cases, see `load-large-file-code'`."
58 | [file file-path file-name]
59 | (Console/WriteLine "LOADFILE: {0} {1} {2}" file file-path file-name)
60 | (apply format
61 | "(clojure.lang.Compiler/load (System.IO.StringReader. %s) nil %s %s)" ;DM: java.io.StringReader. Add nil (load needs four args)
62 | (map (fn [item]
63 | (binding [*print-length* nil
64 | *print-level* nil]
65 | (pr-str item)))
66 | [file file-path file-name])))
67 |
68 | (defn wrap-load-file
69 | "Middleware that evaluates a file's contents, as per load-file,
70 | but with all data supplied in the sent message (i.e. safe for use
71 | with remote REPL environments).
72 |
73 | This middleware depends on the availability of an :op \"eval\"
74 | middleware below it (such as interruptible-eval)."
75 | [h]
76 | (fn [{:keys [op file file-name file-path] :as msg}]
77 | (if (not= op "load-file")
78 | (h msg)
79 | (h (assoc msg
80 | :op "eval"
81 | :code ((if (thread-bound? #'load-file-code)
82 | load-file-code
83 | load-large-file-code)
84 | file file-path file-name))))))
85 |
86 | (set-descriptor! #'wrap-load-file
87 | {:requires #{}
88 | :expects #{"eval"}
89 | :handles {"load-file"
90 | {:doc "Loads a body of code, using supplied path and filename info to set source file and line number metadata. Delegates to underlying \"eval\" middleware/handler."
91 | :requires {"file" "Full contents of a file of code."}
92 | :optional {"file-path" "Source-path-relative path of the source file, e.g. clojure/java/io.clj"
93 | "file-name" "Name of source file, e.g. io.clj"}
94 | :returns (-> (meta #'eval/interruptible-eval)
95 | ::middleware/descriptor
96 | :handles
97 | (get "eval")
98 | :returns)}}})
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clr_http/lite/cookies.clj:
--------------------------------------------------------------------------------
1 | (ns clr-http.lite.cookies
2 | (:require
3 | [clojure.string :as string]
4 | [clr-http.lite.util :as util]
5 | )
6 | (:import
7 | System.Net.Cookie
8 | System.Net.CookieCollection
9 | ))
10 |
11 | (defn compact-map
12 | "Removes all map entries where value is nil."
13 | [m]
14 | (reduce #(if (get m %2) (assoc %1 %2 (get m %2)) %1)
15 | (sorted-map) (sort (keys m))))
16 |
17 | (defn cookie->map
18 | "Converts a ClientCookie object into a tuple where the first item is
19 | the name of the cookie and the second item the content of the
20 | cookie."
21 | [cookie]
22 | [(.Name cookie)
23 | (compact-map
24 | {:comment (.Comment cookie)
25 | :comment-url (if (.CommentUri cookie) (str (.CommentUri cookie)))
26 | :discard (.Discard cookie)
27 | :domain (.Domain cookie)
28 | :expires (let [expires (.Expires cookie)]
29 | (if-not (= (DateTime. 0) expires) expires))
30 | :path (.Path cookie)
31 | :ports (let [ports
32 | (filter identity (map #(try (Int32/Parse %) (catch Exception e))
33 | (-> cookie .Port (string/replace "\"" "") (string/split #","))))]
34 | (if-not (empty? ports) ports))
35 | :secure (.Secure cookie)
36 | :value (try
37 | (util/url-decode (.Value cookie))
38 | (catch Exception _ (.Value cookie)))
39 | :version (.Version cookie)})])
40 |
41 | (defn map->cookie
42 | [[cookie-name value]]
43 | (if (map? value)
44 | (let [
45 | {:keys [value comment comment-url discard domain expires path ports secure version]} value
46 | cookie
47 | (util/doto-set
48 | (Cookie. (name cookie-name) (-> value name util/url-encode))
49 | (.Comment comment)
50 | (.Discard (if (nil? discard) true discard))
51 | (.Domain domain)
52 | (.Path path)
53 | (.Secure (boolean secure))
54 | (.Version (or version 0))
55 | )]
56 | (if comment-url (set! (.CommentUri cookie) (Uri. comment-url)))
57 | (if ports (set! (.Port cookie) (->> ports (interpose ",") (apply str) pr-str)))
58 | (if expires (set! (.Discard cookie) expires))
59 | cookie)
60 | (Cookie. (name cookie-name) (-> value name util/url-encode))))
61 |
62 | #_(defn decode-cookie
63 | "Decode the Set-Cookie string into a cookie seq."
64 | [set-cookie-str]
65 | (if-not (string/blank? set-cookie-str)
66 | ;; I just want to parse a cookie without providing origin. How?
67 | (let [domain (string/lower-case (str (gensym)))
68 | origin (CookieOrigin. domain 80 "/" false)
69 | [cookie-name cookie-content] (-> (cookie-spec)
70 | (.parse (BasicHeader.
71 | "set-cookie"
72 | set-cookie-str)
73 | origin)
74 | first
75 | to-cookie)]
76 | [cookie-name
77 | (if (= domain (:domain cookie-content))
78 | (dissoc cookie-content :domain) cookie-content)])))
79 |
80 | #_(defn decode-cookies
81 | "Converts a cookie string or seq of strings into a cookie map."
82 | [cookies]
83 | (reduce #(assoc %1 (first %2) (second %2)) {}
84 | (map decode-cookie (if (sequential? cookies) cookies [cookies]))))
85 |
86 | #_(defn decode-cookie-header
87 | "Decode the Set-Cookie header into the cookies key."
88 | [response]
89 | (if-let [cookies (get (:headers response) "set-cookie")]
90 | (assoc response
91 | :cookies (decode-cookies cookies)
92 | :headers (dissoc (:headers response) "set-cookie"))
93 | response))
94 |
95 | #_(defn cookie-response
96 | "Adds cookies map to server response"
97 | [response]
98 | (if-let [^CookieCollection cookies (.Cookies response)]
99 | (assoc response :cookies (seq cookies))
100 | response))
101 |
102 | #_(defn encode-cookie
103 | "Encode the cookie into a string used by the Cookie header."
104 | [cookie]
105 | (when-let [header (-> (cookie-spec)
106 | (.formatCookies [(to-basic-client-cookie cookie)])
107 | first)]
108 | (.getValue ^org.apache.http.Header header)))
109 |
110 | #_(defn encode-cookies
111 | "Encode the cookie map into a string."
112 | [cookie-map] (string/join ";" (map encode-cookie (seq cookie-map))))
113 |
114 | #_(defn encode-cookie-header
115 | "Encode the :cookies key of the request into a Cookie header."
116 | [request]
117 | (if (:cookies request)
118 | (-> request
119 | (assoc-in [:headers "Cookie"] (encode-cookies (:cookies request)))
120 | (dissoc :cookies))
121 | request))
122 |
123 | #_(defn cookie-request
124 | "Adds cookies to request based on request map"
125 | [request]
126 | ;have to look into this one
127 | )
128 |
129 | #_(defn wrap-cookies
130 | [client]
131 | #_(fn [request]
132 | (let [response (client (encode-cookie-header request))]
133 | (decode-cookie-header response))))
134 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/excel_repl/interop.clj:
--------------------------------------------------------------------------------
1 | (ns excel-repl.interop)
2 |
3 | (import ExcelDna.Integration.ExcelReference)
4 | (import ExcelDna.Integration.XlCall)
5 | (import ClojureExcel.MainClass)
6 |
7 | (assembly-load "ExcelApi")
8 | (import NetOffice.ExcelApi.Application)
9 |
10 | (require '[clojure.string :as str])
11 |
12 | (defn comma-interpose [s] (apply str (interpose ", " s)))
13 | (defn line-interpose [s] (apply str (interpose "\r\n" s)))
14 |
15 |
16 | (def letters "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
17 | (def letter->val (into {} (map-indexed (fn [i s] [s i]) letters)))
18 |
19 | (defn letter->val2
20 | "column number of excel coumn A, AZ etc"
21 | [[s t :as ss]]
22 | (if t
23 | (apply + 26
24 | (map *
25 | (map letter->val (reverse ss))
26 | (map #(Math/Pow 26 %) (range))))
27 | (letter->val s)))
28 |
29 | (defn col-num
30 | "column number of reference in form A4 etc"
31 | [s]
32 | (if (string? s)
33 | (letter->val2 (re-find #"[A-Z]+" s))
34 | (second s)))
35 |
36 | (defn row-num
37 | [s]
38 | (if (string? s)
39 | (dec (int (re-find #"[0-9]+" s)))
40 | (first s)))
41 |
42 | ;;DEPRECATED!!
43 | ;;WRITING TO THE WORKBOOK RANDOMLY CRASHES IT.
44 | #_(defn insert-value
45 | "Inserts val at ref."
46 | [sheet ref val]
47 | (let [
48 | i (row-num ref)
49 | j (col-num ref)
50 | ref (ExcelReference. i i j j sheet)
51 | ]
52 | (.SetValue ref val)))
53 |
54 | (defn split-str [s]
55 | (map #(str "\"" (apply str %) "\"") (partition-all 250 s)))
56 |
57 | (defn concatenated-str [s]
58 | (format "CONCATENATE(%s)" (comma-interpose (split-str s))))
59 |
60 | (defn excel-pr-str [s]
61 | (if (string? s) (concatenated-str (.Replace s "\"" "\"\"")) s))
62 |
63 | (defn formula-str
64 | "Generates Excel formula string =f(arg1, \"arg2\"...).
65 | Long strings a split via =CONCATENATE to conform to the Excel 255 character limit"
66 | [f & args]
67 | (format "=%s(%s)" f (comma-interpose (map excel-pr-str args))))
68 |
69 |
70 | (defn regularize-array
71 | "ensures array is rectangular"
72 | [arr]
73 | (let [
74 | n (apply max (map count arr))
75 | extend #(take n (concat % (repeat nil)))
76 | ]
77 | (map extend arr)))
78 |
79 |
80 | ;;DEPRECATED!!
81 | ;;WRITING TO THE WORKBOOK RANDOMLY CRASHES IT.
82 | #_(defn insert-values
83 | "Inserts 2d array of values at ref."
84 | [sheet ref values]
85 | (let [
86 | values (regularize-array values)
87 | m (count values)
88 | n (count (first values))
89 | values (-> values to-array-2d MainClass/RectangularArray)
90 | i (row-num ref)
91 | j (col-num ref)
92 | id (+ i m -1)
93 | jd (+ j n -1)
94 | ref (ExcelReference. i id j jd sheet)
95 | ]
96 | (-> ref (.SetValue values))))
97 |
98 | (defn get-values
99 | "Returns values at ref which is of the form A1 or A1:B6.
100 | Single cell selections are returned as a value, 2D selections as an Object[][] array"
101 | [sheet ref]
102 | (let [
103 | refs (if (.Contains ref ":") (str/split ref #":") [ref ref])
104 | [i id] (map row-num refs)
105 | [j jd] (map col-num refs)
106 | value (.GetValue (ExcelReference. i id j jd sheet))
107 | ]
108 | (if (.Contains ref ":")
109 | (MainClass/RaggedArray value)
110 | value)))
111 |
112 | ;;DEPRECATED!!
113 | ;;WRITING TO THE WORKBOOK RANDOMLY CRASHES IT.
114 | #_(defn insert-formula
115 | "Takes a single formula and inserts it into one or many cells.
116 | Use this instead of insert-values when you have a formula.
117 | Because Excel-REPL abuses threads the formulas may be stale when first inserted.
118 | "
119 | [sheet ref formula]
120 | (let [
121 | refs (if (.Contains ref ":") (str/split ref #":") [ref ref])
122 | [i id] (map row-num refs)
123 | [j jd] (map col-num refs)
124 | ref (ExcelReference. i id j jd sheet)
125 | ]
126 | (XlCall/Excel XlCall/xlcFormulaFill (object-array [formula ref]))))
127 |
128 | ;;DEPRECATED!!
129 | ;;WRITING TO THE WORKBOOK RANDOMLY CRASHES IT.
130 | #_(defn add-sheet
131 | "Adds new sheet to current workbook."
132 | [name]
133 | (let [
134 | sheets (-> (Application/GetActiveInstance) .ActiveWorkbook .Worksheets)
135 | existing-names (set (map #(.Name %) sheets))
136 | name (if (existing-names name)
137 | (loop [i 1]
138 | (let [new-name (format "%s (%s)" name i)]
139 | (if (existing-names new-name)
140 | (recur (inc i))
141 | new-name))) name)
142 | sheet (.Add sheets)
143 | ]
144 | (set! (.Name sheet) name)))
145 |
146 | (defn require-sheet [v]
147 | "Require excel spreadsheet. V is of form
148 | [sheet A C D]
149 | [sheet A C D :as alias]
150 | A C D are the columns containing source code"
151 | (let [
152 | sheet-name (first v)
153 | [_as alias-name] (take-last 2 v)
154 | [alias-name cols]
155 | (if (= :as _as)
156 | [alias-name (drop 1 (drop-last 2 v))]
157 | [sheet-name (drop 1 v)])
158 | ns-aliases (-> *ns* ns-aliases keys set)
159 | ]
160 | (if-not (ns-aliases alias-name)
161 | (let [
162 | source
163 | (apply str
164 | (flatten
165 | (for [col cols]
166 | (line-interpose
167 | (filter string?
168 | (map first
169 | (get-values (str sheet-name) (format "%s1:%s200" col col))))))))
170 | ]
171 | (MainClass/my_eval source (str sheet-name))
172 | (require (vector sheet-name :as alias-name))))))
173 |
174 | ;;DEPRECATED!!
175 | ;;WRITING TO THE WORKBOOK RANDOMLY CRASHES IT.
176 | #_(defmacro clear-contents
177 | "Clears an m by n grid at sheet, ref.
178 | Must be called inside udf/in-macro-context"
179 | [sheet ref m n]
180 | `(interop/insert-values ~sheet ~ref
181 | (let [
182 | row# (repeat ~n nil)
183 | rows# (repeat ~m row#)
184 | ]
185 | rows#)))
186 |
187 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/excel_repl/udf.clj:
--------------------------------------------------------------------------------
1 | (ns excel-repl.udf)
2 |
3 | (import System.CodeDom.Compiler.CompilerParameters)
4 | (import Microsoft.CSharp.CSharpCodeProvider)
5 | (import System.Reflection.BindingFlags)
6 | (import ClojureExcel.MainClass)
7 | (import System.Windows.Forms.MessageBox)
8 |
9 | (assembly-load "ExcelApi")
10 | (import NetOffice.ExcelApi.Application)
11 |
12 | (require '[excel-repl.schedule-udf :as schedule-udf])
13 | (require '[excel-repl.util :as util])
14 |
15 | (def loaded-classes (MainClass/AssemblyPaths));convenience method because Stack Overflow gave the example in C#
16 | (defn load-path [s] (some #(if (.Contains % s) %) loaded-classes))
17 |
18 | (defn my-compile [code]
19 | (let [
20 | cp (CompilerParameters.)
21 | ]
22 | (set! (.GenerateExecutable cp) false)
23 | (set! (.GenerateInMemory cp) true)
24 | (-> cp .ReferencedAssemblies (.Add (load-path "System.Windows.Forms.dll")))
25 | (-> cp .ReferencedAssemblies (.Add (load-path "Clojure.dll")))
26 | (-> cp .ReferencedAssemblies (.Add (load-path "ExcelDna.Integration.dll")))
27 | ; (-> cp .ReferencedAssemblies (.Add (load-path "System.dll")))
28 | ; (-> cp .ReferencedAssemblies (.Add "Z:\\Documents\\Visual Studio 2013\\Projects\\Excel-REPL\\ProcessOutput\\bin\\Debug"))
29 | (-> cp .ReferencedAssemblies (.Add (load-path "System.Core.dll")))
30 | (.CompileAssemblyFromSource
31 | (CSharpCodeProvider.)
32 | cp (into-array [code]))))
33 |
34 | (def to-clean {"?" "_QMARK_" "!" "_BANG_" ">" "_GT_" "<" "_LT_" "-" "_"})
35 |
36 | (defn clean-str [s]
37 | (reduce (fn [s [old new]] (.Replace s old new)) (.ToLower (str s)) to-clean))
38 |
39 |
40 | (defn dirty-arglist? [l]
41 | (some #(or (= '& %) (map? %)) l))
42 |
43 | (defn filter-arglists [v]
44 | (let [
45 | {:keys [name arglists doc export async]} (meta v)
46 | arglists (remove dirty-arglist? arglists)
47 | ]
48 | (if (and (not-empty arglists) export) [(clean-str name) arglists doc async (var-get v)])))
49 |
50 | (defn filter-ns-interns [ns]
51 | (filter identity (map filter-arglists (vals (ns-interns ns)))))
52 |
53 | (defn filter-all-interns []
54 | (mapcat filter-ns-interns (schedule-udf/get-ns)))
55 |
56 | (defn emit-static-method [method-name name arglist doc async]
57 | (let [
58 | doc (format "[ExcelFunction(Description=@\"%s\")]" (or doc ""))
59 | f #(if (vector? %)
60 | (if (vector? (first %))
61 | "Object[,] "
62 | "Object[] ")
63 | "Object ")
64 | arg-types (map f arglist)
65 | clean-args (map #(if (vector? %) (gensym) (clean-str %)) arglist)
66 | arglist1 (util/comma-interpose (map str arg-types clean-args))
67 | clean-args2 (map (fn [original-arg cleaned]
68 | (if (and (vector? original-arg) (vector? (first original-arg)))
69 | (format "RaggedArray(%s)" cleaned)
70 | cleaned)) arglist clean-args)
71 | arglist2 (util/comma-interpose clean-args2)
72 | arglist3 (util/comma-interpose clean-args)
73 |
74 | invoke-body (format "try { return cleanValue(%s.invoke(%s)); } catch (Exception e) {return e.ToString();}" name arglist2)
75 | invoke-body (if async
76 | (format "return ExcelAsyncUtil.Run(\"\", new Object[]{%s}, delegate
77 | {
78 | %s
79 | });" arglist3 invoke-body)
80 | invoke-body)
81 | ]
82 | (format "%s
83 | public static object %s(%s)
84 | {
85 | %s
86 | }" doc method-name arglist1 invoke-body)))
87 |
88 | (defn emit-static-methods [[name arglists doc async]]
89 | (let [
90 | method-names (if (= 1 (count arglists))
91 | [(.ToUpper name)]
92 | (map #(str (.ToUpper name) (count %)) arglists))]
93 | (util/line-interpose (map #(emit-static-method %1 name %2 doc async) method-names arglists))))
94 |
95 | (defn class-str
96 | ([d]
97 | (let [
98 | fns (map first d)
99 | fn-str (util/comma-interpose fns)
100 | construct-fn-str (util/comma-interpose (map #(str "IFn " %) fns))
101 | construct-body-str (apply str (map #(format " Class1.%s = %s;\r\n" % %) fns))
102 | static-methods (util/line-interpose (map emit-static-methods d))
103 |
104 | s (MainClass/ResourceSlurp "Class1.cs")
105 | s (.Replace s "ifn_list" fn-str)
106 | s (.Replace s "IFn foo" construct-fn-str)
107 | s (.Replace s "foo;" construct-body-str)
108 | s (.Replace s " private void Poo() { }" static-methods)
109 | ]
110 | s)))
111 |
112 | (defn get-methods [t]
113 | (.GetMethods t (enum-or BindingFlags/Public BindingFlags/Static)))
114 |
115 | (defn export-udfs []
116 | (let [d (filter-all-interns)]
117 | (if (not-empty d)
118 | (let [
119 | _ (-> d class-str util/to-clipboard)
120 | t (-> d class-str my-compile .CompiledAssembly .GetTypes first)
121 | types (map last d)
122 | constructor-args (object-array types)
123 | ]
124 | (Activator/CreateInstance t constructor-args)
125 | (MainClass/RegisterMethods (get-methods t))))))
126 |
127 | (defn export-fns []
128 | (schedule-udf/add-curr-ns)
129 | (.Run (Application/GetActiveInstance) "ExportUdfs"))
130 |
131 | (defmacro in-macro-context
132 | "Evaluates body within an Excel macro context so that cell values can be set without throwing an exception."
133 | [& body]
134 | `(do
135 | (schedule-udf/add-fn
136 | (fn [] ~@body))
137 | (.Run (NetOffice.ExcelApi.Application/GetActiveInstance) "InvokeAnonymousMacros")))
138 |
139 | (defn invoke-anonymous-macros []
140 | (or (last (map #(%) (schedule-udf/get-fns))) "Result Empty"))
141 |
142 | (set! MainClass/export_udfs export-udfs)
143 | ;(set! MainClass/invoke_anonymous_macros invoke-anonymous-macros)
144 |
145 | (defn split-words [n s]
146 | (loop [
147 | todo s
148 | sb (StringBuilder.)
149 | i 0
150 | done []]
151 | (if-let [c (first todo)]
152 | (do
153 | (.Append sb c)
154 | (if (and (> i n) (= \space c))
155 | (recur (rest s) (StringBuilder.) 0 (conj done (str sb)))
156 | (recur (rest s) sb (inc i) done)))
157 | (let [
158 | last-line (str sb)
159 | ]
160 | (if (= "" last-line)
161 | done
162 | (conj done last-line))))))
163 |
164 |
165 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Excel REPL
2 |
3 | Boost your productivity with a full Clojure programming environment in Microsoft Excel
4 |
5 | Excel REPL makes it easy to start a ClojureCLR Repl from within Excel. Simply install it as an Excel Add-In to provide a few additional Excel Functions
6 |
7 | ## Download
8 |
9 | [Installer](https://github.com/whamtet/Excel-REPL/releases/download/0.1/Excel-REPL.exe) (requires administrator permissions).
10 |
11 | There is a [Manual Installer](https://github.com/whamtet/Excel-REPL/releases/download/0.1/Excel-REPL.zip) if you lack administrator permissions on your machine.
12 |
13 | ## Usage
14 |
15 | Select output column
16 |
17 | 
18 |
19 | Type ```=Load(A:A)``` where A is the input column. Press CTRL+SHIFT+ENTER, not just enter.
20 |
21 | 
22 |
23 | Create your first bug. Excel-REPL splits the stack trace down the output column.
24 |
25 | NB: Excel 2003 or earlier does not support entire column selection. Type ```=Load(A1:A200)``` instead.
26 |
27 | 
28 |
29 | ## Demo Spreadsheet.
30 |
31 | Download [Excel-REPL.xlsx](https://github.com/whamtet/Excel-REPL/releases/download/0.1/Excel-REPL.xlsx) for a quick demo.
32 | If this doesn't work correctly you must have an installation error. Please contact the author straight away.
33 |
34 | ## Export
35 |
36 | ```clojure
37 | (defn ^:export f [] ...)
38 |
39 | (defn ^:export g ([] "No Args") ([x] "One Arg"))
40 |
41 | (defn ^:export h [single-cell-argument [_ :as excel-array-argument]] ...)
42 |
43 | (defn ^:export i [[[_] :as two-d-array] ...)
44 |
45 | (require 'excel-repl.udf)
46 | (excel-repl.udf/export-fns) ;exports the above functions
47 | ```
48 |
49 | `excel-repl.udf/export-fns` will export as Excel user defined functions all functions with `^:export` metadata in the current namespace. Functions with a single arglist are simply exported as their name. Multiarity functions include the arity. In the example above f will export `=F()` and g will export `=G0()` and `=G1(x)`.
50 |
51 | Excel REPL assumes all arguments are passed as single cell selections (A1, B6 etc). To indicate that an argument should be an array selection declare that argument with vector destructuring. For 2D arrays use double destructuring.
52 |
53 | `excel-repl.udf/export-fns` abuses Excel slightly and may fail on the first one or two invocations in a given session.
54 |
55 | ## Asynchronous Export
56 |
57 | ```clojure
58 | (defn ^:export ^:async f [x] ...)
59 | ```
60 | Asynchronous export caches on arguments to f.
61 |
62 | ## Read workbook
63 |
64 | You may read values directly from the workbook
65 |
66 | ```clojure
67 | (require '[excel-repl.interop :as interop])
68 |
69 | (interop/get-values "MySheet" "A6")
70 | (interop/get-values "AnotherSheet" "A6:B7")
71 |
72 | ```
73 | Please see [interop.clj](https://github.com/whamtet/Excel-REPL/blob/master/Excel-REPL/nrepl/excel_repl/interop.clj) for the functions to manipulate the worksheet.
74 |
75 | ## Returning 1D and 2D arrays
76 |
77 | If `Load` returns a 1 or 2 dimensional collection you may paste it into a range of Excel Cells. To do so
78 |
79 | 1) Drag from the top left hand corner the number of cells for your output
80 |
81 | 2) Click in the formula bar and enter your formula
82 |
83 | 3) Press Control + Shift + Enter instead of simply enter
84 |
85 | WARNING: Only `Load` can be used in this way. If you return exported functions in this way Excel will crash.
86 |
87 | ## Error Messages
88 |
89 | Errors are caught and returned as text within the output cells. The stacktrace is split down the column so select multiple cells for output as mentioned above.
90 |
91 | ## Auxiliary Methods
92 |
93 | Excel REPL adds useful functions and macros to clojure.core that are useful when interacting with a worksheet. Please see [excel-repl.clj](https://github.com/whamtet/Excel-REPL/blob/master/Excel-REPL/excel-repl.clj) for details.
94 |
95 | If you wish to pull stuff off the net straight into your worksheet [clr-http-lite](https://github.com/whamtet/clr-http-lite) is included
96 |
97 | ```clojure
98 |
99 | (require '[clr-http.lite.client :as client])
100 |
101 | (client/get "http://google.com")
102 | => {:status 200
103 | :headers {"date" "Sun, 01 Aug 2010 07:03:49 GMT"
104 | "cache-control" "private, max-age=0"
105 | "content-type" "text/html; charset=ISO-8859-1"
106 | ...}
107 | :body "..."}
108 |
109 | ```
110 |
111 | ## Database
112 |
113 | Excel REPL provides convenience methods for connecting directly to a mongo database
114 |
115 | ```clojure
116 | (require '[excel-repl.coerce-db :as coerce-db])
117 |
118 | (defonce connection (DB/Connect))
119 |
120 | (DB/Set connection "test-values" (coerce-db/clojure->mongo {:hi "there"} ))
121 | (-> connection (DB/Get "test-values") coerce-db/mongo->clojure str); {:hi "there"}
122 | ```
123 |
124 | ## NREPL
125 |
126 | Excel REPL uses ClojureCLR which has less support than the main JVM implementation. You may wish to connect to an external Clojure repl. Both HTTP and TCP connections are supported.
127 |
128 | ```clojure
129 | (require '[clojure.tools.nrepl :as nrepl])
130 | (require '[clojure.data.drawbridge-client :as drawbridge-client]) ;Adds Http support to Nrepl
131 |
132 | (def timeout 10000); 10 seconds
133 | (def tcp-client (nrepl/client (nrepl/url-connect "nrepl://localhost:50000")) timeout)
134 | (def http-client (nrepl/client (nrepl/url-connect "http://some.server/drawbridge-client")) timeout)
135 |
136 | (defn remote-eval-str
137 | "evaluates string on remote repl"
138 | [code-str]
139 | (-> tcp-client
140 | (nrepl/message {:op "eval" :code code-str})
141 | nrepl/response-values))
142 |
143 | (defmacro remote-eval [& body]
144 | `(first (remote-eval-str (nrepl/code ~@body))))
145 |
146 | (remote-eval (+ 1 2)); 3
147 | ```
148 |
149 | For information about connecting to a Clojure repl via Http, visit [Drawbridge](https://github.com/cemerick/drawbridge).
150 |
151 | ## NREPL Server
152 |
153 | You may also use Excel-REPL as an nrepl server. This makes it easy to push data over to the spreadsheet
154 |
155 | ```clojure
156 | (require '[clojure.tools.nrepl.server :as server])
157 | (defonce server (server/start-server))
158 | ```
159 |
160 | ## Build
161 |
162 | The build process is a bit of a manual hack. Please contact the author if you want help with this.
163 |
164 | ## System Requirements
165 |
166 | Excel Repl works with Microsoft Excel 97+ (that's quite old) and Microsoft .NET 4.0 or 4.5.
167 |
168 | ## Gotchas
169 |
170 | Be careful when spitting. Excel sometimes runs the code several times, creating a race condition. Use the following pattern
171 |
172 | ```clojure
173 | (defonce o (Object.))
174 | (locking o (spit my-file contents))
175 | ```
176 |
--------------------------------------------------------------------------------
/Excel-REPL/Excel-REPL.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {2EB259F1-F88C-44C2-8B63-F61522F43595}
8 | Library
9 | Properties
10 | Excel_REPL
11 | Excel-REPL
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\Clojure.1.7.0\lib\net40\Clojure.dll
35 | True
36 |
37 |
38 | Z:\Downloads\clojure-clr\bin\4.0\Release\clojure.clr.io.clj.dll
39 |
40 |
41 | ..\packages\NetOffice.Excel.1.7.3.0\lib\net45\ExcelApi.dll
42 | True
43 |
44 |
45 | ..\packages\ExcelDna.Integration.0.33.9\lib\ExcelDna.Integration.dll
46 | True
47 |
48 |
49 | ..\packages\DotNetZip.1.9.3\lib\net20\Ionic.Zip.dll
50 |
51 |
52 | ..\packages\Clojure.1.7.0\lib\net40\Microsoft.Dynamic.dll
53 | True
54 |
55 |
56 | True
57 |
58 |
59 | ..\packages\Clojure.1.7.0\lib\net40\Microsoft.Scripting.dll
60 | True
61 |
62 |
63 | ..\packages\NetOffice.Core.1.7.3.0\lib\net45\NetOffice.dll
64 | True
65 |
66 |
67 | ..\packages\NetOffice.Core.1.7.3.0\lib\net45\OfficeApi.dll
68 | True
69 |
70 |
71 | ..\packages\NetOffice.Outlook.1.7.3.0\lib\net45\OutlookApi.dll
72 | True
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | ..\packages\NetOffice.Core.1.7.3.0\lib\net45\VBIDEApi.dll
86 | True
87 |
88 |
89 |
90 |
91 | Code
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | PreserveNewest
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | xcopy "Z:\Downloads\Excel-REPL\packages\ExcelDNA.AddIn.0.33.9\tools\ExcelDna.xll" "$(TargetDir)Excel-REPL-AddIn.xll*" /C /Y
111 | xcopy "$(TargetDir)Excel-REPL-AddIn.dna*" "$(TargetDir)Excel-REPL-AddIn64.dna*" /C /Y
112 | xcopy "Z:\Downloads\Excel-REPL\packages\ExcelDNA.AddIn.0.33.9\tools\ExcelDna64.xll" "$(TargetDir)Excel-REPL-AddIn64.xll*" /C /Y
113 | Z:\Downloads\Excel-REPL\packages\ExcelDNA.AddIn.0.33.9\tools\ExcelDnaPack.exe "$(TargetDir)Excel-REPL-AddIn.dna" /Y
114 | Z:\Downloads\Excel-REPL\packages\ExcelDNA.AddIn.0.33.9\tools\ExcelDnaPack.exe "$(TargetDir)Excel-REPL-AddIn64.dna" /Y
115 |
116 |
123 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/middleware.clj:
--------------------------------------------------------------------------------
1 | (ns clojure.tools.nrepl.middleware
2 | (:require clojure.tools.nrepl
3 | [clojure.tools.nrepl.transport :as transport]
4 | [clojure.tools.nrepl.misc :as misc]
5 | [clojure.set :as set])
6 | (:refer-clojure :exclude (comparator)))
7 |
8 | (defn- var-name
9 | [^clojure.lang.Var v]
10 | (str (.ns v) \/ (.sym v)))
11 |
12 | (defn- wrap-conj-descriptor
13 | [descriptor-map h]
14 | (fn [{:keys [op descriptors] :as msg}]
15 | (h (if-not (= op "describe")
16 | msg
17 | (assoc msg :descriptors (merge descriptor-map descriptors))))))
18 |
19 | (defn set-descriptor!
20 | "Sets the given [descriptor] map as the ::descriptor metadata on
21 | the provided [middleware-var], after assoc'ing in the var's
22 | fully-qualified name as the descriptor's \"implemented-by\" value."
23 | [middleware-var descriptor]
24 | (let [descriptor (-> descriptor
25 | (assoc :implemented-by (-> middleware-var var-name symbol))
26 | (update-in [:expects] (fnil conj #{}) "describe"))]
27 | (alter-meta! middleware-var assoc ::descriptor descriptor)
28 | (alter-var-root middleware-var #(comp (partial wrap-conj-descriptor
29 | (:handles descriptor)) %))))
30 |
31 | (defn- safe-version
32 | [m]
33 | (into {} (filter (fn [[_ v]] (or (number? v) (string? v))) m)))
34 |
35 | (defn- java-version
36 | []
37 | (let [version-string (.ToString Environment/Version) ;;; (System/getProperty "java.version")
38 | version-seq (re-seq #"\d+" version-string)
39 | ;; add detailed version info only if we found four numbers in the version string
40 | version-map (if (<= 3 (count version-seq))
41 | (zipmap [:major :minor :incremental :update] version-seq)
42 | {})]
43 | (assoc version-map :version-string version-string)))
44 |
45 | (defn wrap-describe
46 | [h]
47 | (fn [{:keys [op descriptors verbose? transport] :as msg}]
48 | (if (= op "describe")
49 | (transport/send transport (misc/response-for msg
50 | {:ops (if verbose?
51 | descriptors
52 | (into {} (map #(vector (key %) {}) descriptors)))
53 | :versions {:nrepl (safe-version clojure.tools.nrepl/version)
54 | :clojure (safe-version
55 | (assoc *clojure-version* :version-string (clojure-version)))
56 | :java {:version-string (safe-version (java-version))}}
57 | :status :done}))
58 | (h msg))))
59 |
60 | (set-descriptor! #'wrap-describe
61 | {:handles {"describe"
62 | {:doc "Produce a machine- and human-readable directory and documentation for the operations supported by an nREPL endpoint."
63 | :requires {}
64 | :optional {"verbose?" "Include informational detail for each \"op\"eration in the return message."}
65 | :returns {"ops" "Map of \"op\"erations supported by this nREPL endpoint"
66 | "versions" "Map containing version maps (like *clojure-version*, e.g. major, minor, incremental, and qualifier keys) for values, component names as keys. Common keys include \"nrepl\" and \"clojure\"."}}}})
67 | ; eliminate implicit expectation of "describe" handler; this is the only
68 | ; special case introduced by the conj'ing of :expects "describe" by set-descriptor!
69 | (alter-meta! #'wrap-describe update-in [::descriptor :expects] disj "describe")
70 |
71 | (defn- dependencies
72 | [set start dir]
73 | (let [ops (start dir)
74 | deps (set/select
75 | (comp seq (partial set/intersection ops) :handles)
76 | set)]
77 | (when (deps start)
78 | (throw (ArgumentException. ;DM: IllegalArgumentException
79 | (format "Middleware %s depends upon itself via %s"
80 | (:implemented-by start)
81 | dir))))
82 | (concat ops
83 | (mapcat #(dependencies set % dir) deps))))
84 |
85 | (defn- comparator
86 | [{a-requires :requires a-expects :expects a-handles :handles}
87 | {b-requires :requires b-expects :expects b-handles :handles}]
88 | (or (->> (into {} [[[a-requires b-handles] -1]
89 | [[a-expects b-handles] 1]
90 | [[b-requires a-handles] 1]
91 | [[b-expects a-handles] -1]])
92 | (map (fn [[sets ret]]
93 | (and (seq (apply set/intersection sets)) ret)))
94 | (some #{-1 1}))
95 | 0))
96 |
97 | (defn- extend-deps
98 | [middlewares]
99 | (let [descriptor #(-> % meta ::descriptor)
100 | middlewares (concat middlewares
101 | (->> (map descriptor middlewares)
102 | (mapcat (juxt :expects :requires))
103 | (mapcat identity)
104 | (filter var?)))]
105 | (doseq [m (remove descriptor middlewares)]
106 | (binding [*out* *err*]
107 | (printf "[WARNING] No nREPL middleware descriptor in metadata of %s, see clojure.tools.middleware/set-descriptor!" m)
108 | (println)))
109 | (let [middlewares (set (for [m middlewares]
110 | (-> (descriptor m)
111 | ; only conj'ing m here to support direct reference to
112 | ; middleware dependencies in :expects and :requires,
113 | ; e.g. interruptable-eval's dep on
114 | ; clojure.tools.nrepl.middleware.pr-values/pr-values
115 | (update-in [:handles] (comp set #(conj % m) keys))
116 | (assoc :implemented-by m))))]
117 | (set (for [m middlewares]
118 | (reduce
119 | #(update-in % [%2] into (dependencies middlewares % %2))
120 | m #{:expects :requires}))))))
121 |
122 | (defn- conj-sorted
123 | [stack comparator x]
124 | (let [comparisons (->> stack
125 | (map-indexed #(vector % (comparator x %2)))
126 | (remove (comp zero? second)))
127 | lower (ffirst (filter (comp neg? second) comparisons))
128 | upper (ffirst (reverse (filter (comp pos? second) comparisons)))
129 | ; default conj'ing at the end, a good default for descriptor-less middlewares
130 | [before after] (split-at (or (and upper (inc upper)) lower (count stack)) stack)]
131 | (into [] (concat before [x] after))))
132 |
133 | ;; TODO throw exception when the stack doesn't satisfy the requirements of the descriptors involved
134 | (defn linearize-middleware-stack
135 | [middlewares]
136 | (->> middlewares
137 | extend-deps
138 | (sort-by (comp count (partial apply concat) (juxt :expects :requires)))
139 | reverse
140 | (reduce #(conj-sorted % comparator %2) [])
141 | (map :implemented-by)))
142 |
143 | ;;; documentation utilities ;;;
144 |
145 | ; oh, kill me now
146 | (defn- markdown-escape
147 | [^String s]
148 | (System.Text.RegularExpressions.Regex/Replace s "([*_])" "\\\\$1")) ;DM: (.replaceAll s "([*_])" "\\\\$1")
149 |
150 | (defn- message-slot-markdown
151 | [msg-slot-docs]
152 | (apply str (for [[k v] msg-slot-docs]
153 | (format "* `%s` %s\n" (pr-str k) (markdown-escape v)))))
154 |
155 | (defn- describe-markdown
156 | "Given a message containing the response to a verbose :describe message,
157 | generates a markdown string conveying the information therein, suitable for
158 | use in e.g. wiki pages, github, etc.
159 |
160 | (This is currently private because markdown conversion surely shouldn't
161 | be part of the API here...?)"
162 | [{:keys [ops versions]}]
163 | (apply str "# Supported nREPL operations
164 |
165 | generated from a verbose 'describe' response (nREPL v"
166 | (:version-string clojure.tools.nrepl/version)
167 | ")\n\n## Operations"
168 | (for [[op {:keys [doc optional requires returns]}] ops]
169 | (str "\n\n### `" (pr-str op) "`\n\n"
170 | (markdown-escape doc) "\n\n"
171 | "###### Required parameters\n\n"
172 | (message-slot-markdown requires)
173 | "\n\n###### Optional parameters\n\n"
174 | (message-slot-markdown optional)
175 | "\n\n###### Returns\n\n"
176 | (message-slot-markdown returns)))))
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clr_http/lite/client.clj:
--------------------------------------------------------------------------------
1 | (ns clr-http.lite.client
2 | "Batteries-included HTTP client."
3 | (:require [clojure.string :as str]
4 | [clojure.clr.io :as io]
5 | [clr-http.lite.core :as core]
6 | [clr-http.lite.util :as util])
7 | (:import
8 | System.Text.Encoding
9 | System.Text.UTF8Encoding
10 | )
11 | (:refer-clojure :exclude (get)))
12 |
13 | (def str->encoding
14 | (into {}
15 | (for [encoding (Encoding/GetEncodings)]
16 | [(.Name encoding) (.GetEncoding encoding)])))
17 |
18 | (defn update [m k f & args]
19 | (assoc m k (apply f (m k) args)))
20 |
21 | (defn parse-url [url]
22 | (let [uri (Uri. url)]
23 | {:scheme (-> uri .Scheme keyword)
24 | :server-name (.Host uri)
25 | :server-port (.Port uri)
26 | :uri (.LocalPath uri)
27 | :user-info (.UserInfo uri)
28 | :query-string (let [q (.Query uri)]
29 | (if-not (empty? q) (.Substring q 1)))}))
30 |
31 | (def unexceptional-status?
32 | #{200 201 202 203 204 205 206 207 300 301 302 303 307})
33 |
34 | (defn wrap-exceptions [client]
35 | (fn [req]
36 | (let [{:keys [status] :as resp} (client req)]
37 | (if (or (not (clojure.core/get req :throw-exceptions true))
38 | (unexceptional-status? status))
39 | resp
40 | (throw (Exception. (pr-str resp)))
41 | #_(throw+ resp "clj-http: status %s" (:status %))))))
42 |
43 | (declare wrap-redirects)
44 |
45 | (defn follow-redirect [client req resp]
46 | (let [url (get-in resp [:headers "location"])]
47 | ((wrap-redirects client) (assoc req :url url))))
48 |
49 | (defn wrap-redirects [client]
50 | (fn [{:keys [request-method follow-redirects] :as req}]
51 | (let [{:keys [status] :as resp} (client req)]
52 | (cond
53 | (= false follow-redirects)
54 | resp
55 | (and (#{301 302 307} status) (#{:get :head} request-method))
56 | (follow-redirect client req resp)
57 | (and (= 303 status) (= :head request-method))
58 | (follow-redirect client (assoc req :request-method :get) resp)
59 | :else
60 | resp))))
61 |
62 | (defn wrap-decompression [client]
63 | (fn [req]
64 | (if (get-in req [:headers "Accept-Encoding"])
65 | (client req)
66 | (let [req-c (update req :headers assoc "Accept-Encoding" "gzip, deflate")
67 | resp-c (client req-c)]
68 | (case (or (get-in resp-c [:headers "Content-Encoding"])
69 | (get-in resp-c [:headers "content-encoding"]))
70 | "gzip" (update resp-c :body util/gunzip)
71 | "deflate" (update resp-c :body util/inflate)
72 | resp-c)))))
73 |
74 | (defn wrap-output-coercion [client]
75 | (fn [{:keys [as] :as req}]
76 | (let [{:keys [body] :as resp} (client req)]
77 | (if body
78 | (cond
79 | (keyword? as)
80 | (condp = as
81 | ;; Don't do anything for streams
82 | :stream resp
83 | ;; Don't do anything when it's a byte-array
84 | :byte-array resp
85 | ;; Automatically determine response type
86 | :auto
87 | (assoc resp
88 | :body
89 | (let [typestring (get-in resp [:headers "content-type"])]
90 | (cond
91 | (.startsWith (str typestring) "text/")
92 | (if-let [charset (second (re-find #"charset=(.*)"
93 | (str typestring)))]
94 | (.GetString (Activator/CreateInstance (str->encoding charset UTF8Encoding)) body)
95 | (util/utf8-string body))
96 | :else
97 | (util/utf8-string body))))
98 | ;; No :as matches found
99 | (update-in resp [:body] util/utf8-string))
100 | ;; Try the charset given if a string is specified
101 | (string? as)
102 | (update-in resp [:body] #(.GetString (Activator/CreateInstance (str->encoding as UTF8Encoding)) %))
103 | ;; Return a regular UTF-8 string body
104 | :else
105 | (update-in resp [:body] util/utf8-string))
106 | resp))))
107 |
108 | (defn wrap-input-coercion [client]
109 | (fn [{:keys [body body-encoding length] :as req}]
110 | (let [
111 | encoding (str->encoding body-encoding UTF8Encoding)
112 | ]
113 | (if body
114 | (cond
115 | (string? body)
116 | (client (assoc req
117 | :body (.GetBytes (Activator/CreateInstance encoding) body)
118 | :character-encoding (or body-encoding "UTF-8")))
119 | :else
120 | (client req))
121 | (client req)))))
122 |
123 | (defn content-type-value [type]
124 | (if (keyword? type)
125 | (str "application/" (name type))
126 | type))
127 |
128 | (defn wrap-content-type [client]
129 | (fn [{:keys [content-type] :as req}]
130 | (if content-type
131 | (client (update-in req [:content-type] content-type-value))
132 | (client req))))
133 |
134 | (defn wrap-accept [client]
135 | (fn [{:keys [accept] :as req}]
136 | (if accept
137 | (client (-> req
138 | (dissoc :accept)
139 | (assoc-in [:headers "Accept"]
140 | (content-type-value accept))))
141 | (client req))))
142 |
143 | (defn accept-encoding-value [accept-encoding]
144 | (str/join ", " (map name accept-encoding)))
145 |
146 | (defn wrap-accept-encoding [client]
147 | (fn [{:keys [accept-encoding] :as req}]
148 | (if accept-encoding
149 | (client (-> req (dissoc :accept-encoding)
150 | (assoc-in [:headers "Accept-Encoding"]
151 | (accept-encoding-value accept-encoding))))
152 | (client req))))
153 |
154 | (defn generate-query-string [params]
155 | (str/join "&"
156 | (mapcat (fn [[k v]]
157 | (if (sequential? v)
158 | (map #(str (util/url-encode (name %1))
159 | "="
160 | (util/url-encode (str %2)))
161 | (repeat k) v)
162 | [(str (util/url-encode (name k))
163 | "="
164 | (util/url-encode (str v)))]))
165 | params)))
166 |
167 | (defn wrap-query-params [client]
168 | (fn [{:keys [query-params] :as req}]
169 | (if query-params
170 | (client (-> req (dissoc :query-params)
171 | (assoc :query-string
172 | (generate-query-string query-params))))
173 | (client req))))
174 |
175 | (defn basic-auth-value [basic-auth]
176 | (let [basic-auth (if (string? basic-auth)
177 | basic-auth
178 | (str (first basic-auth) ":" (second basic-auth)))]
179 | (str "Basic " (util/base64-encode (util/utf8-bytes basic-auth)))))
180 |
181 | (defn wrap-basic-auth [client]
182 | (fn [req]
183 | (if-let [basic-auth (:basic-auth req)]
184 | (client (-> req
185 | (dissoc :basic-auth)
186 | (assoc-in [:headers "Authorization"]
187 | (basic-auth-value basic-auth))))
188 | (client req))))
189 |
190 | (defn parse-user-info [user-info]
191 | (when user-info
192 | (str/split user-info #":")))
193 |
194 | (defn wrap-user-info [client]
195 | (fn [req]
196 | (if-let [[user password] (parse-user-info (:user-info req))]
197 | (client (assoc req :basic-auth [user password]))
198 | (client req))))
199 |
200 | (defn wrap-method [client]
201 | (fn [req]
202 | (if-let [m (:method req)]
203 | (client (-> req
204 | (dissoc :method)
205 | (assoc :request-method m)))
206 | (client req))))
207 |
208 | (defn wrap-form-params [client]
209 | (fn [{:keys [form-params request-method] :as req}]
210 | (if (and form-params (= :post request-method))
211 | (client (-> req
212 | (dissoc :form-params)
213 | (assoc :content-type
214 | (content-type-value
215 | :x-www-form-urlencoded)
216 | :body (generate-query-string form-params))))
217 | (client req))))
218 |
219 | (defn wrap-url [client]
220 | (fn [req]
221 | (if-let [url (:url req)]
222 | (client (-> req (dissoc :url) (merge (parse-url url))))
223 | (client req))))
224 |
225 | #_(defn wrap-unknown-host [client]
226 | (fn [{:keys [ignore-unknown-host?] :as req}]
227 | (try
228 | (client req)
229 | (catch UnknownHostException e
230 | (if ignore-unknown-host?
231 | nil
232 | (throw e))))))
233 |
234 | (defn wrap-request
235 | "Returns a battaries-included HTTP request function coresponding to the given
236 | core client. See client/client."
237 | [request]
238 | (-> request
239 | wrap-query-params
240 | wrap-user-info
241 | wrap-url
242 | wrap-redirects
243 | wrap-decompression
244 | wrap-input-coercion
245 | wrap-output-coercion
246 | wrap-exceptions
247 | wrap-basic-auth
248 | wrap-accept
249 | wrap-accept-encoding
250 | wrap-content-type
251 | wrap-form-params
252 | wrap-method
253 | ;wrap-unknown-host
254 | ))
255 |
256 | (def #^{:doc
257 | "Executes the HTTP request corresponding to the given map and returns
258 | the response map for corresponding to the resulting HTTP response.
259 |
260 | In addition to the standard Ring request keys, the following keys are also
261 | recognized:
262 | * :url
263 | * :method
264 | * :query-params
265 | * :basic-auth
266 | * :content-type
267 | * :accept
268 | * :accept-encoding
269 | * :as
270 |
271 | The following additional behaviors over also automatically enabled:
272 | * Exceptions are thrown for status codes other than 200-207, 300-303, or 307
273 | * Gzip and deflate responses are accepted and decompressed
274 | * Input and output bodies are coerced as required and indicated by the :as
275 | option."}
276 | request
277 | (wrap-request #'core/request))
278 |
279 | (defn get
280 | "Like #'request, but sets the :method and :url as appropriate."
281 | [url & [req]]
282 | (request (merge req {:method :get :url url})))
283 |
284 | (defn head
285 | "Like #'request, but sets the :method and :url as appropriate."
286 | [url & [req]]
287 | (request (merge req {:method :head :url url})))
288 |
289 | (defn post
290 | "Like #'request, but sets the :method and :url as appropriate."
291 | [url & [req]]
292 | (request (merge req {:method :post :url url})))
293 |
294 | (defn put
295 | "Like #'request, but sets the :method and :url as appropriate."
296 | [url & [req]]
297 | (request (merge req {:method :put :url url})))
298 |
299 | (defn delete
300 | "Like #'request, but sets the :method and :url as appropriate."
301 | [url & [req]]
302 | (request (merge req {:method :delete :url url})))
303 |
304 | (defmacro with-connection-pool
305 | "This macro is a no-op, but left in to support backward-compatibility
306 | with clj-http."
307 | [opts & body]
308 | `(do
309 | ~@body))
310 |
--------------------------------------------------------------------------------
/Excel-REPL/nrepl/clojure/tools/nrepl/transport.clj:
--------------------------------------------------------------------------------
1 | (ns ^{:author "Chas Emerick"}
2 | clojure.tools.nrepl.transport
3 | (:require [clojure.tools.nrepl.bencode :as be]
4 | [clojure.clr.io :as io] ;DM: clojure.java.io
5 | [clojure.tools.nrepl.debug :as debug]
6 | [clojure.tools.nrepl.sync-channel :as sc] ;DM: Added
7 | clojure.main ;Matt: Added
8 | (clojure walk set))
9 | (:use [clojure.tools.nrepl.misc :only (returning uuid)])
10 | (:refer-clojure :exclude (send))
11 | (:import (System.IO Stream EndOfStreamException) ;DM: (java.io InputStream OutputStream PushbackInputStream
12 | (clojure.lang PushbackInputStream PushbackTextReader) ;DM: PushbackReader IOException EOFException)
13 | (System.Net.Sockets Socket SocketException) ;DM: (java.net Socket SocketException)
14 | (System.Collections.Concurrent ;DM: (java.util.concurrent SynchronousQueue LinkedBlockingQueue
15 | |BlockingCollection`1[System.Object]|) ;DM: BlockingQueue TimeUnit)
16 | ; clojure.tools.nrepl.transport.Transport ;DM: Added
17 | clojure.lang.RT ))
18 |
19 | (defprotocol Transport
20 | "Defines the interface for a wire protocol implementation for use
21 | with nREPL."
22 | (recv [this] [this timeout]
23 | "Reads and returns the next message received. Will block.
24 | Should return nil the a message is not available after `timeout`
25 | ms or if the underlying channel has been closed.")
26 | (send [this msg] "Sends msg. Implementations should return the transport."))
27 |
28 | (deftype FnTransport [recv-fn send-fn close]
29 | Transport
30 | ;; TODO this keywordization/stringification has no business being in FnTransport
31 | (send [this msg] #_(debug/prn-thread "FnTransport:: send " msg) (-> msg clojure.walk/stringify-keys send-fn) this)
32 | (recv [this] #_(debug/prn-thread "FnTransprot:: recv ") (.recv this Int32/MaxValue)) ;DM: Long/MAX_VALUE
33 | (recv [this timeout] #_(debug/prn-thread "FnTransport:: recv [" timeout "]") (clojure.walk/keywordize-keys (recv-fn timeout)))
34 | System.IDisposable ;DM: java.io.Closeable
35 | (Dispose [this] #_(debug/prn-thread "FnTranpsort:: Dispose " (.GetHashCode this)) (close))) ;DM: (close [this] (close))) TODO: This violates good IDisposable practice
36 |
37 | (defn fn-transport
38 | "Returns a Transport implementation that delegates its functionality
39 | to the 2 or 3 functions provided."
40 | ([read write] (fn-transport read write nil))
41 | ([read write close]
42 | (let [read-queue (sc/make-simple-sync-channel) ;DM: (SynchronousQueue.)
43 | msg-pump (future (try
44 | (while true
45 | #_(debug/prn-thread "fn-transport:: ready to read")
46 | (sc/put read-queue (read)) ;DM: .put
47 | #_(debug/prn-thread "fn-transport:: put to queue")) ;DEBUG
48 | (catch Exception t ;DM: Throwable
49 | #_(debug/prn-thread "fn-transport:: caught exception!!!!")
50 | (sc/put read-queue t))))] ;DM: .put
51 | (FnTransport.
52 | (let [failure (atom nil)]
53 | #(if @failure
54 | (throw @failure)
55 | (let [msg (sc/poll read-queue % )] ;DM: .poll, remove TimeUnit/MILLISECONDS
56 | #_(debug/prn-thread "fn-transport:: read from queue: " (let [mstr (str msg)] (if (< (count mstr) 75) mstr (subs mstr 0 75)))) ;DEBUG
57 | (if (instance? Exception msg) ;DM: Throwable
58 | (do #_(debug/prn-thread "fn-transport:: read Exception: " (let [mstr (str msg)] (if (< (count mstr) 75) mstr (subs mstr 0 75)))) (reset! failure msg) (throw msg))
59 | msg))))
60 | write
61 | (fn [] (close) #_(future-cancel msg-pump))))))
62 |
63 | (defmulti #^{:private true} > input
82 | (map (fn [[k v]] [k ( "))) ;DM: .write
141 | session-id (atom nil)
142 | read-msg #(let [code (read r)]
143 | (merge {:op "eval" :code [code] :ns @cns :id (str "eval" (uuid))}
144 | (when @session-id {:session @session-id})))
145 | read-seq (atom (cons {:op "clone"} (repeatedly read-msg)))
146 | write (fn [{:strs [out err value status ns new-session id] :as msg}]
147 | (when new-session (reset! session-id new-session))
148 | (when ns (reset! cns ns))
149 | (doseq [^String x [out err value] :when x]
150 | (.Write w x)) ;DM: .write
151 | (when (and (= status #{:done}) id (.startsWith ^String id "eval"))
152 | (prompt true))
153 | (.Flush w)) ;DM: .flush
154 | read #(let [head (promise)]
155 | (swap! read-seq (fn [s]
156 | (deliver head (first s))
157 | (rest s)))
158 | @head)]
159 | (fn-transport read write
160 | (when s
161 | (swap! read-seq (partial cons {:session @session-id :op "close"}))
162 | #(.Close s)))))) ;DM: .close
163 |
164 | (defn tty-greeting
165 | "A greeting fn usable with clojure.tools.nrepl.server/start-server,
166 | meant to be used in conjunction with Transports returned by the
167 | `tty` function.
168 |
169 | Usually, Clojure-aware client-side tooling would provide this upon connecting
170 | to the server, but telnet et al. isn't that."
171 | [transport]
172 | (send transport {:out (str ";; Clojure " (clojure-version)
173 | \newline "user=> ")}))
174 |
175 | (deftype QueueTransport [^|System.Collections.Concurrent.BlockingCollection`1[System.Object]| in
176 | ^|System.Collections.Concurrent.BlockingCollection`1[System.Object]| out] ;DM: ^BlockingQueue
177 | clojure.tools.nrepl.transport.Transport
178 | (send [this msg] (.Add out msg) this) ;DM: .put
179 | (recv [this] (.Take in)) ;DM: .take
180 | (recv [this timeout] (let [x nil] (.TryTake in (by-ref x) (int timeout)) x))) ;DM: .poll, removed TimeUnit/MILLISECONDS, added (int .), let, ref
181 |
182 | (defn piped-transports
183 | "Returns a pair of Transports that read from and write to each other."
184 | []
185 | (let [a (|System.Collections.Concurrent.BlockingCollection`1[System.Object]|.) ;DM: LinkedBlockingQueue
186 | b (|System.Collections.Concurrent.BlockingCollection`1[System.Object]|.)] ;DM: LinkedBlockingQueue
187 | [(QueueTransport. a b) (QueueTransport. b a)]))
188 |
--------------------------------------------------------------------------------
/Excel-REPL/MainClass.cs:
--------------------------------------------------------------------------------
1 | using clojure.lang;
2 | using ExcelDna.Integration;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.IO;
8 | using System.Text.RegularExpressions;
9 | using System.Reflection;
10 | using System.Collections.Concurrent;
11 | using System.Windows.Forms;
12 | using System.Threading;
13 |
14 | namespace ClojureExcel
15 | {
16 | public class MainClass : ExcelDna.Integration.CustomUI.ExcelRibbon, IExcelAddIn
17 | {
18 | public void AutoClose() { }
19 | public void AutoOpen()
20 | {
21 | Init();
22 | ExcelIntegration.RegisterUnhandledExceptionHandler(
23 | ex => "!!! EXCEPTION: " + ex.ToString());
24 | }
25 |
26 | private static Object GetFirst(Object o)
27 | {
28 | return ((Object[,])o)[0, 0];
29 | }
30 |
31 | public static IFn export_udfs, format_code;
32 |
33 | public static void ExportUdfs()
34 | {
35 | try
36 | {
37 | export_udfs.invoke();
38 | }
39 | catch (Exception e)
40 | {
41 | MessageBox.Show(e.ToString());
42 | }
43 | }
44 | //referenced by excel-repl.udf
45 | public static Object AssemblyPaths()
46 | {
47 | var assemblies = AppDomain.CurrentDomain
48 | .GetAssemblies()
49 | .Where(a => !a.IsDynamic)
50 | .Select(a => a.Location);
51 | return assemblies;
52 | }
53 | //referenced by excel-repl.udf
54 | public static void RegisterMethods(MethodInfo[] methods)
55 | {
56 | List l = new List();
57 | foreach (MethodInfo info in methods)
58 | {
59 | l.Add(info);
60 | }
61 | Integration.RegisterMethods(l);
62 | }
63 |
64 | private static void Init()
65 | {
66 | try
67 | {
68 | string path = Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)).FullName;
69 | if (Environment.OSVersion.Version.Major >= 6)
70 | {
71 | path = Directory.GetParent(path).ToString();
72 | }
73 |
74 |
75 | String clojureSrc = ResourceSlurp("excel-repl.clj");
76 | GetFirst(my_eval2(clojureSrc, "clojure.core"));
77 | clojureSrc = ResourceSlurp("interop.clj");
78 | my_eval2(clojureSrc, "excel-repl.interop");
79 | }
80 | catch (Exception e)
81 | {
82 | msg = e.ToString();
83 | }
84 | }
85 | public static String ResourceSlurp(String resource)
86 | {
87 | return (String)slurp.invoke(Assembly.GetExecutingAssembly().GetManifestResourceStream("Excel_REPL." + resource));
88 | }
89 | //used by drawbridge-client
90 | public static BlockingCollection