Permalink
Browse files

Merge remote branch 'arthuredelstein/web-edit' into cljs_in_cljs

  • Loading branch information...
2 parents e4d2d35 + f0cbeb9 commit 85bec1e3f2210c92d251b8299ff2d8b25f862ba2 @kanaka committed Jan 3, 2009
Showing with 432 additions and 33 deletions.
  1. +3 −0 .gitmodules
  2. +54 −0 src/cljs/webconsole.cljs
  3. +86 −0 src/cljs/webedit.cljs
  4. +2 −32 src/cljs/webrepl2.cljs
  5. +26 −0 src/cljs/webrepl3.cljs
  6. +6 −0 web/build2.sh
  7. +6 −0 web/build3.sh
  8. +221 −0 web/repl3.html
  9. +27 −1 web/stylesheets/himera.css
  10. +1 −0 web/vendor/codemirror
View
3 .gitmodules
@@ -1,3 +1,6 @@
[submodule "web/vendor/jq-console"]
path = web/vendor/jq-console
url = https://github.com/replit/jq-console
+[submodule "web/vendor/codemirror"]
+ path = web/vendor/codemirror
+ url = https://github.com/marijnh/CodeMirror.git
View
54 src/cljs/webconsole.cljs
@@ -0,0 +1,54 @@
+(ns webconsole
+ (:require [cljs.repl :as repl]))
+
+(defn start-prompt
+ "Starts a new REPL prompt and optionally pre-populates user input field
+ with initial-text."
+ ([jqconsole initial-text]
+ (let [prompt-label (str "\n" (repl/prompt))
+ continue-label (str (apply str (repeat (- (count prompt-label) 4) " "))
+ "...")]
+ (.SetPromptLabel jqconsole prompt-label continue-label)
+ (.Prompt jqconsole "true"
+ (fn [input]
+ (repl/eval-print input)
+ (start-prompt jqconsole))
+ #(if (repl/complete-form? %)
+ false
+ 0))
+ (when-not (empty? initial-text)
+ (.SetPromptText jqconsole initial-text)))
+ jqconsole)
+ ([jqconsole] (start-prompt jqconsole nil)))
+
+(defn cancel-input
+ "Cancel the REPL prompt and write a message to output."
+ [jqconsole message]
+ (let [prompt-text (.GetPromptText jqconsole false)]
+ (doto jqconsole
+ .ClearPromptText
+ .AbortPrompt
+ (.Write message "jqconsole-output"))
+ prompt-text))
+
+(defn register-shortcuts [jqconsole shortcut-map]
+ (doseq [[key callback] shortcut-map]
+ (.RegisterShortcut jqconsole key callback)))
+
+(defn console
+ "Create and initialize the REPL console, with a shortcut-map that
+ maps keys to callback functions."
+ [console-selector]
+ (repl/init)
+ (let [jqconsole
+ (.jqconsole (js/$ console-selector)
+ "ClojureScript-in-ClojureScript Web REPL"
+ "\n>>> "
+ "")]
+ (.SetIndentWidth jqconsole 1)
+ ;; Setup the print function
+ (set! *out* #(.Write jqconsole %))
+ (set! *rtn* #(.Write jqconsole % "jqconsole-output"))
+ (set! *err* #(.Write jqconsole % "jqconsole-message-error"))
+ (set! *print-fn* #(*out* %1))
+ (start-prompt jqconsole)))
View
86 src/cljs/webedit.cljs
@@ -0,0 +1,86 @@
+(ns webedit
+ (:require [cljs.repl :as repl]))
+
+
+;; file storage
+
+(defn store-item
+ "Writes text at key in localStorage."
+ [key text]
+ (-> js/window .-localStorage (.setItem key text)))
+
+(defn load-item
+ "Reads text at key in localStorage."
+ [key]
+ (-> js/window .-localStorage (.getItem key)))
+
+;; editor keys
+
+(defn- map->js [m]
+ (let [out (js-obj)]
+ (doseq [[k v] m]
+ (aset out (name k) v))
+ out))
+
+(defn str-contains? [s x]
+ (not= (.indexOf s x) -1))
+
+(defn mac? []
+ (str-contains? (str (.-platform js/navigator)) "Mac"))
+
+(def command-prefix (if (mac?) "Cmd" "Ctrl"))
+
+(defn register-shortcuts [editor key-map]
+ (let [js-key-map
+ (->> (for [[k callback] key-map]
+ [(str command-prefix "-" k) callback])
+ (into {})
+ map->js)]
+ (.addKeyMap editor js-key-map)))
+
+;; show/hide editor
+
+(def editor-visible (atom false))
+
+(def editor-visible-key "__editor_visible")
+
+(defn update-editor-visibility [show?]
+ (let [container (js/$ "#editor-container")]
+ (if show?
+ (.slideDown container 100)
+ (.slideUp container 100))))
+
+(defn store-editor-visibility [show?]
+ (store-item editor-visible-key (str show?)))
+
+(defn update-link [show?]
+ (.html (js/$ "#toggle-editor")
+ (str (if show? "Hide" "Show")
+ " file editor")))
+
+(defn add-updating-watch [reference fun]
+ (add-watch reference fun (fn [_ _ _ value] (fun value))))
+
+(defn setup-editor-toggling []
+ (add-updating-watch editor-visible update-editor-visibility)
+ (add-updating-watch editor-visible store-editor-visibility)
+ (add-updating-watch editor-visible update-link)
+ (.click (js/$ "#toggle-editor") #(swap! editor-visible not))
+ (reset! editor-visible (= "true" (load-item editor-visible-key))))
+
+;; main editor function
+
+(defn editor []
+ (let [eval-cmd (str command-prefix "-E")]
+ (setup-editor-toggling)
+ (.html (js/$ "#tiny-note")
+ (str "Press " eval-cmd
+ " to evaluate file in REPL."))
+ (doto
+ (.fromTextArea js/CodeMirror
+ (.getElementById js/document "editor")
+ (map->js {:mode "clojure"
+ :lineNumbers true
+ :matchBrackets true}))
+ (.setValue (or (load-item "scratch")
+ ";; Develop your clojurescript program here")))))
View
34 src/cljs/webrepl2.cljs
@@ -1,39 +1,9 @@
(ns webrepl
- (:require [cljs.repl :as repl]))
-
-(defn start-prompt []
- (let [prompt-label (str "\n" (repl/prompt))
- continue-label (str (apply str (repeat (- (count prompt-label) 5) " "))
- "... ")]
- (.SetPromptLabel js/jqconsole prompt-label continue-label)
- (.Prompt js/jqconsole "true"
- (fn [input]
- (repl/eval-print input)
- (start-prompt))
- #(if (repl/complete-form? %)
- false
- 0))))
+ (:require webconsole))
(.ready (js/jQuery js/document)
(fn []
- (repl/init)
-
- ;; setup the REPL console
- (set! js/jqconsole
- (.jqconsole (js/jQuery "#console")
- "ClojureScript-in-ClojureScript Web REPL"
- "\n>>> "
- ""))
- (.SetIndentWidth js/jqconsole 1)
-
- ;; Setup the print function
- (set! *out* #(.Write js/jqconsole %))
- (set! *rtn* #(.Write js/jqconsole % "jqconsole-output"))
- (set! *err* #(.Write js/jqconsole % "jqconsole-message-error"))
- (set! *print-fn* #(*out* %1))
-
- (start-prompt)
-
+ (webconsole/console "#console" {})
;; print,evaluate,print some example forms
;(pep "(+ 1 2)")
;(pep "(let [sqr #(* % %)] (sqr 8))")
View
26 src/cljs/webrepl3.cljs
@@ -0,0 +1,26 @@
+(ns webrepl
+ (:require [cljs.repl :as repl]
+ [webconsole :as webconsole]
+ [webedit :as webedit]))
+
+(defn evaluate-file
+ "Evaluates the editor's file in the REPL console."
+ [editor console]
+ (let [text (.getValue editor)
+ prompt-text (webconsole/cancel-input console "Evaluating file...\n")]
+ (repl/eval-print text)
+ (webedit/store-item "scratch" text)
+ (webconsole/start-prompt console prompt-text)))
+
+(defn start-app []
+ (let [editor (webedit/editor)
+ console (webconsole/console "#console")]
+ (webconsole/register-shortcuts console
+ {"E" #(this-as this-console
+ (evaluate-file editor this-console))})
+ (webedit/register-shortcuts editor
+ {"E" #(evaluate-file % console)})))
+
+(.ready (js/jQuery js/document) start-app)
+
+
View
6 web/build2.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+cd $(dirname ${0})
+
+echo "Building webrepl2.js"
+time ../bin/cljsc ../src/cljs/webrepl2.cljs > webrepl2.js
View
6 web/build3.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+cd $(dirname ${0})
+
+echo "Building webrepl3.js"
+time ../bin/cljsc ../src/cljs/webrepl3.cljs > webrepl3.js
View
221 web/repl3.html
@@ -0,0 +1,221 @@
+<!--
+Copyright (c) 2013 Joel Martin
+Copyright (c) 2012 Fogus, Jen Myers and Relevance Inc.
+All rights reserved. The use and distribution terms for this software
+are covered by the Eclipse Public License 1.0
+(http://opensource.org/licenses/eclipse-1.0.php) which can be found in
+the file COPYING the root of this distribution. By using this
+software in any fashion, you are agreeing to be bound by the terms of
+this license. You must not remove this notice, or any other, from
+this software.
+-->
+
+<html>
+<head>
+ <!--<script type="text/javascript" src="javascript/jquery-1.4.2.min.js"></script>-->
+ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
+ <script type="text/javascript" src="vendor/jq-console/jqconsole.min.js"></script>
+ <script src="vendor/codemirror/lib/codemirror.js"></script>
+ <link rel="stylesheet" href="vendor/codemirror/lib/codemirror.css">
+ <script src="vendor/codemirror/mode/clojure/clojure.js"></script>
+ <script src="vendor/codemirror/addon/edit/matchbrackets.js"></script>
+ <script type="text/javascript" src="out/goog/base.js"></script>
+ <script type="text/javascript" src="webrepl3.js"></script>
+ <script type="text/javascript">
+ goog.require('webrepl');
+ </script>
+ <link rel="stylesheet" type="text/css" href="stylesheets/base.css" />
+ <link rel="stylesheet" type="text/css" href="stylesheets/layout.css" />
+ <link rel="stylesheet" type="text/css" href="stylesheets/skeleton.css" />
+ <link rel="stylesheet" type="text/css" href="stylesheets/himera.css" />
+ <style type="text/css" media="screen">
+ </style>
+ <title>ClojureScript-in-ClojureScript REPL</title>
+</head>
+<body>
+
+ <div class="container">
+ <h1 id="title"><a href="http://www.clojurescript.net"/>ClojureScript.net</a></h1>
+
+ <h2>ClojureScript Web REPL</h2>
+
+ <div id="editor-container" class="sixteen columns">
+ <div id="tiny-note" class="tiny-note"></div>
+ <textarea class="editor" id="editor">;; Develop your clojurescript program here.
+;; Ctrl+E/Cmd+E evaluates file in the REPL.</textarea>
+ </div>
+
+ <div id="console-container" class="sixteen columns">
+ <div class="console" id="console"></div>
+ </div>
+ <div class="eight columns">
+ <h3><span style="cursor: pointer" class="doc-link" id="toggle-editor">Show file editor</a></h3>
+ </div>
+ <div class="eight columns">
+ <div class="source">
+ <a href="http://github.com/kanaka/clojurescript">View source on Github <img src="images/github-icon.png" /></a></p>
+ </div><!-- /source -->
+ </div>
+
+ <div class="rule sixteen columns"></div>
+
+ <div class="sixteen columns">
+ <h3>ClojureScript at a glance - <a href="http://appletree.or.kr/quick_reference_cards/Others/ClojureScript%20Cheat%20Sheet.pdf" class="doc-link">PDF</a> | <a href="http://clojuredocs.org/" class="doc-link">Searchable docs</a> | <a href="synonym.html" class="doc-link">Translations from JavaScript</a></h3>
+ </div>
+
+ <div class="cheat-box-container eight columns">
+ <div class="cheat-box">
+ <h4>Datatypes</h4>
+ <table>
+ <tr class="row-one">
+ <td class="row-label">Map</td>
+ <td>{:key1 :val1, :key2 :val2}</td>
+ </tr>
+ <tr>
+ <td class="row-label">Vectors</td>
+ <td>[1 2 3 4 :a :b :c 1 2]</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">Sets</td>
+ <td>#{:a :b :c 1 2 3}</td>
+ </tr>
+ <tr>
+ <td class="row-label">Scalars</td>
+ <td>a-symbol, :a-keyword, "a string"</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">Arrays</td>
+ <td>(array 1 2 3)</td>
+ </tr>
+ </table>
+ </div><!-- /cheat-box -->
+ <div class="cheat-box">
+ <h4>Functions</h4>
+ <table>
+ <tr class="row-one">
+ <td class="row-label">Calling</td>
+ <td>(<span class="ebnf">&lt;function&gt;</span>
+ <span class="ebnf">&lt;args*&gt;</span>)</td>
+ </tr>
+ <tr>
+ <td class="row-label">Defining named functions</td>
+ <td>(defn <span class="ebnf">&lt;name&gt;</span>
+ [<span class="ebnf">&lt;args*&gt;</span>]
+ <span class="ebnf">|constraints|</span>
+ <span class="ebnf">&lt;actions*&gt;</span>)</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">Anonymous function</td>
+ <td>(fn <span class="ebnf">|name|</span>
+ [<span class="ebnf">&lt;args*&gt;</span>]
+ <span class="ebnf">|constraints|</span>
+ <span class="ebnf">&lt;actions*&gt;</span>)</td>
+ </tr>
+ <tr>
+ <td class="row-label">Anonymous inline function</td>
+ <td>#(<span class="ebnf">&lt;action&gt;</span>
+ <span class="ebnf">|%,%2,%3, or %&|</span>)</td>
+ </tr>
+ </table>
+ </div><!-- /cheat-box -->
+ <div class="cheat-box">
+ <h4>Useful Macros</h4>
+ <table>
+ <tr class="row-one">
+ <td class="row-label">Conditionals</td>
+ <td>if if-let cond condp and or when when-let</td>
+ </tr>
+ <tr>
+ <td class="row-label">Nesting, chaining, and Interop</td>
+ <td>-> ->> doto .. .</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">Defining things</td>
+ <td>def defn fn let binding defmulti defmethod deftype defrecord reify this-as</td>
+ </tr>
+ </table>
+ </div>
+ </div><!-- /cheat-box-container -->
+
+ <div class="cheat-box-container eight columns">
+ <div class="cheat-box">
+ <h4>Useful Functions</h4>
+ <table>
+ <tr class="row-one">
+ <td class="row-label">Math</td>
+ <td>+ - * / quot rem mod inc dec max min</td>
+ </tr>
+ <tr>
+ <td class="row-label">Comparison</td>
+ <td>= == not= < > <= >=</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">Predicates</td>
+ <td>nil? identical? zero? pos? neg? even? odd? true? false?</td>
+ </tr>
+ <tr>
+ <td class="row-label">Data processing</td>
+ <td>map reduce filter partition split-at split-with</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">Data create</td>
+ <td>vector vec hash-map set for list list*</td>
+ </tr>
+ <tr>
+ <td class="row-label">Data inspection</td>
+ <td>first rest get get-in keys vals count get nth contains? find</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">Data manipulation</td>
+ <td>seq into conj cons assoc assoc-in dissoc zipmap merge merge-with select-keys update-in</td>
+ </tr>
+ <tr>
+ <td class="row-label">Arrays</td>
+ <td>first rest get get-in keys vals count get nth contains? find</td></td>
+ </tr>
+ </table>
+ </div><!-- /cheat-box -->
+ <div class="cheat-box">
+ <h4>JavaScript Interop</h4>
+ <table>
+ <tr class="row-one">
+ <td class="row-label">Method call</td>
+ <td>(.the-method target-object args...)</td>
+ </tr>
+ <tr>
+ <td class="row-label">Property access</td>
+ <td>(.-property target-object -property)</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">Property setting</td>
+ <td>(set! (.-title js/document) "Hi!")</td>
+ </tr>
+ <tr>
+ <td class="row-label">Direct JavaScript</td>
+ <td>(js/alert "Hello Cleveland!")</td>
+ </tr>
+ <tr class="row-one">
+ <td class="row-label">External library use</td>
+ <td>(.text (js/jQuery "#title") "ClojureScript Rocks!")</td>
+ </tr>
+ </table>
+ </div>
+ </div><!-- /cheat-box-container -->
+
+ <div class="rule sixteen columns"></div>
+
+ <div class="column footer-logo">
+ <div>Cljs-in-Cljs &copy; 2013 Joel Martin</div>
+ <div>Himera design &copy; 2012-2013 <a ref="http://www.fogus.me">Fogus</a>, <a href="http://jenmyers.net/">Jen Myers</a> and <a href="http://www.thinkrelevance.com">Relevance Inc.</a></div>
+ </div>
+
+ <ul class="footer-links">
+ <li><a href="http://clojure.org/">Clojure.org</a></li>
+ <li><a href="https://github.com/kanaka/clojurescript">Cljs-in-Cljs</a></li>
+ <li><a href="https://github.com/clojure/clojurescript">ClojureScript</a></li>
+ <li><a href="http://clojuredocs.org/">Clojure Docs</a></li>
+ </ul>
+
+ </div><!-- / container -->
+</body>
+</html>
View
28 web/stylesheets/himera.css
@@ -85,6 +85,32 @@ ul.footer-links {
color: #333;
}
+.tiny-note {
+ font-size: small;
+}
+
+/* Editor ---------------------------------------------- */
+
+.CodeMirror {
+ position: relative;
+ height: 320px;
+ background: #fbfbf8;
+ border-radius: 5px;
+ -moz-border-radius: 5px;
+ border: 1px solid #d5ceb4;
+}
+
+/* Console --------------------------------------------- */
+
+#console {
+ position: relative;
+ height: 220px;
+ background: #fbfbf8;
+ border-radius: 5px;
+ -moz-border-radius: 5px;
+ border: 1px solid #d5ceb4;
+}
+
/* Console --------------------------------------------- */
/* The console container element */
#console {
@@ -148,7 +174,7 @@ ul.footer-links {
.jqconsole-inner {
/*width:580px;*/
- height:300px;
+ height:200px;
margin: 10px 10px;
overflow:auto;
text-align:left;
1 web/vendor/codemirror
@@ -0,0 +1 @@
+Subproject commit a61e3518a834e43e18c8da2cd9dac563b90533e9

0 comments on commit 85bec1e

Please sign in to comment.