Giter VIP home page Giter VIP logo

paren-soup's Introduction

Clojars Project

Introduction

A library providing a ClojureScript viewer and editor that you can embed in any website. No, that was not a complete sentence. And neither is this. Be a rebel, like me, by using paren-soup. CodeMirror is nice if you want to support other languages, but why would you?

Here are the features:

To use paren-soup in your own website, just go to the releases section and download the latest files. In your HTML, link to one of the CSS files and use the following markup:

<div class="paren-soup">
  <div class="instarepl"></div>
  <div class="numbers"></div>
  <div class="content" contenteditable="true">(+ 1 1) ; put initial code here</div>
</div>
<script type="text/javascript" src="paren-soup.js"></script>
<script type="text/javascript">
  paren_soup.core.init_all();
</script>

If you just want a viewer, not an editor, leave out the contenteditable attribute. If you don’t want the instaREPL or line numbers, remove the relevant divs and they will not appear. To get the code out of the content element via JavaScript or ClojureScript, read its textContent property. There is no API to learn!

Note that by default, the prebuilt copy of paren-soup.js runs the instaREPL in a web worker in order to isolate it and allow the editor to be compiled in advanced mode. Alternatively, you can change your script tag to use "paren-soup-with-compiler.js" instead. That version will run the instaREPL directly, where it will have access to the DOM and allow multiple paren-soup instances to share instaREPL state.

If you want to use paren-soup in a ClojureScript project, add it to your project's dependencies (see version indicated at the top). Your HTML file will still need the markup shown above, except without the script tags. Instead, you can initialize it from your ClojureScript code like this:

(ns my-project.core
  (:require [paren-soup.core :as ps]))

(ps/init-all)

Development

  • Install the Clojure CLI tool
  • To develop with figwheel: clj -M:cljs:dev
  • To build the release version: clj -M:cljs:prod build
  • To install the release version: clj -M:cljs:prod install

Licensing

All files that originate from this project are dedicated to the public domain. I would love pull requests, and will assume that they are also dedicated to the public domain.

paren-soup's People

Contributors

oakes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

paren-soup's Issues

Can't press enter in microsoft edge

Currently I'm calling preventDefault when pressing enter and then manually calling (.execCommand js/document "insertHTML" false "\n"), so I get a proper newline character rather than a <br> tag. This works fine in webkit-based browsers but in Edge it has no effect.

Usage in other projects

This is a kind of beginner question and I am not sure if this is the right place to ask, but I run into problems trying to use paren-soup in another project.

I would like to use paren-soup inside devcards. I've tried the lein dep 0.1.2 , and running lein install inside the cloned repo (0.1.3) inside the project I want to use it in.

I get

Compile Error
clojure.lang.ExceptionInfo : failed compiling file:src/devc/core.cljs
clojure.lang.ExceptionInfo : Referred var cljs.tools.reader/*wrap-value-and-add-metadata?* does not exist
Error on file , line , column

I've downloaded cljs.jar and put it inside the projects root assuming that is what was needed because of: ", but you will need to build your own copy of ClojureScript until a version is released with this patch.".

But it didn't make a difference, any pointers of what to try next?

Pasting within a line removes the line break at the end of it.

I imagine this is where Nightcode editor issues go. (This is in Nightcode 2.5.6 running on Windows)
In this case, I pasted dependency info from github into the :depencencies vector and that seems to have removed the carriage return at the end of the line. You can see where the :aot bit jumped up to the end of the line.

image

image

Atom split across elements

Although atoms such as numbers usually are formatted as single HTML elements in paren-soup, a single atom is sometimes formatted as multiple HTML elements. As a consequence, the cropped state text will contain only a fragment of the atom, resulting in an incorrect parse.

This issue can be replicated from Firefox (but not Chrome) in the paren-soup demo:

  1. Type in the number 123 on say line 3 in the editor.
  2. Open the DOM inspector of the web browser to view the associated HTML element, expected to be: <span class="number">123</span>
  3. Type an arrow right, then arrow left to return the cursor to be just after the number.
  4. Type 4 to make the number 1234.
  5. In the DOM inspector, the atom is now encoded as two elements: <span class="number">123</span><span class="number">4</span>

This issue may cause unexpected rendering of atoms. For example, if a custom stylesheet declares .number elements to have a border, a number may display as two or more boxes.

Persistence across boxes

Thanks for developing this library! I'm using it to develop a computational linguistics course at UCSD, and it's a really useful tool.

Is there a way to make variable definitions persist across code boxes? It would be useful to be able to define a variable in a box earlier in the page, and then use the definition in a later box.

Doesn't recognise "%integer" in anonymous function

I have this code in paren-soup:

(defn prime? [n]
  (if (< n 2) false
    (not
      (reduce #(or % %2)
        (for [a (range 2 n)]
          (zero? (mod n a)))))))

For some reason, there's an error in the anonymous function, #(or % %2), at the %2:

Arg literal must be %, %& or %integer

But the arg literal is %integer.

The code works perfectly on clojurescript.io, which recognises the %2.

Typing affected by delimiter style

When typing with the cursor just after a delimiter, the style of the inserted character briefly is styled as the delimiter.

The challenge is that the same caret position may correspond to several insertion points in the markup. For example, if the caret is after the ( below, the insertion points can be either before or after the </span> end-tag:

<span class="delimiter">(</span>

As is, when navigating the text, if the caret is behind the ( the insertion point for typed text will be within the delimiter element. I've gone down the rabbit hole to find a solution to move the insertion point to after the delimiter element.

Various CSS hacks was a dead end - and I've tried a few. A promising quick fix was to set the delimiter span element to contenteditable=false, but there were still inconsistencies like when deleting a character after the delimiter.

Others have had similar challenges with range and carets, like this Rangy issue: timdown/rangy#366 What actually worked to expel the cursor from a marked element while keeping the caret in the same place was:

  1. Create an element with a single character text object
  2. Insert it after (or before) the marked element
  3. Move the cursor to its text
  4. Set contenteditable of the marked element to false
  5. Remove the text node.

This forces the insertion cursor to the empty element. Working at least in Firefox and Chrome, working around a long standing bug in the latter.

Calling this function from paren-soup.core during update-cursor-position! (before the highlighting) fixes the problem by expelling the insertion point from the delimiter element - at least in Chrome and Firefox:

(defn reset-insertion-cursor []
  {:post [(not (dom/get-focused-elem "delimiter"))]}
  (when-let [delimiter (dom/get-focused-elem "delimiter")]
    (let [parent (.-parentElement delimiter)
          opening? (boolean (.-nextSibling delimiter))
          element (.createElement js/document "span")
          content (.appendChild element (.createTextNode js/document "\u200B"))
          range (.getRangeAt (.getSelection js/document) 0)]
      (if (zero? (.-startOffset range))
        (let [reference (if opening? parent delimiter)] 
          (.insertBefore (.-parentElement reference) element reference))
        (let [reference (if opening? delimiter parent)]
          (js/rangy.dom.insertAfter element reference)))
      (doto range
         .deleteContents
         (.setStartAfter content)
         (.setEndAfter content)
         (.collapse false))
      (.setAttribute delimiter "contenteditable" "false")
      (.removeChild element content)))) 

Demo not up to date

Hi,
I wanted to tell you that some colors were too light in the light theme, but it seems that your repo already contains the color "gold" for numbers instead of "FFD700".
So maybe your demo uses some old code?
I tried to investigate the gh-pages branch but the files seem to be both at "Hide the scroll bars".
I'm missing something, but what?

Documentation for integrating this into an existing ClojureScript project

Assuming a start like this:

  • Add [paren-soup "2.8.6"] to your dependencies.

What comes next?

Can this be hosted as a sub section of an existing page?

How do I invoke the compiler loop from ClojureScript? (the example shows how to do it with plain HTML & Javascript)

Can I provide context such as already defined defns and defs?

Is there an example Hiccup form for generating the required HTML?

Once I know the answer to these questions I will write up some documentation and issue a PR.

Time-out unresponsive section of code?

Currently what paren-soup does with a statement is it evaluates it until the statement is finished, even when it might take a while to finish. For example:

(defn fibonacci [n]
  (if (< n 2) n
    (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))

(fibonacci 200)

Obviously that will take a long time to finish, but the whole section that I tested the code on became unresponsive. Is it better to either time the function out after a certain period of time, or to listen for a change to the statement (e.g. a backspace on the 200 to become 20) for re-evaluation?

Requiring results in could not analyze error

I am using ClojureScript 1.9.229 and paren-soup 2.10.3.
Requiring paren-soup results in:
No such namespace: clojure.spec.alpha, could not locate clojure/spec/alpha.cljs, clojure/spec/alpha.cljc, or Closure namespace "clojure.spec.alpha"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.