replete-repl / replete-ios

ClojureScript REPL iOS app
Eclipse Public License 1.0
395 stars 25 forks source link

add support for source files #15

Closed mfikes closed 8 years ago

mfikes commented 9 years ago

Perhaps via iTunes file sharing.

Motivated by desire to allow macros, and a require-macros REPL special.

Could also consider JARS as being "on classpath"?

bsvingen commented 9 years ago

It's quite easy to accept files from other apps, for instance Dropbox or a Git client.

https://github.com/mfikes/replete/pull/32 accepts files, but just logs the filename.

How do we actually load them?

mfikes commented 9 years ago

@bsvingen We could have Replete work like other REPLs by implementing REPL special functions like require, etc.

For Ambly, a compiler output directory is set up on the device (usually somewhere under Private Documents makes sense), and files in the src directory on the user's computer are "on the classpath" so that a require in the Ambly REPL causes compilation to the output directory. For Replete, something very similar could be done, with the big difference being that the src directory is also on the device (perhaps instead under Documents so that they are also easily accessible via iTunes file sharing).

In short, I could see Replete working like Ambly, with the main difference being that the compiler is on the device (embedded in the JavaScript runtime).

bsvingen commented 9 years ago

@mfikes:

Could we do something simpler for now, just to get this working?

I see that you call the evaluate method on AppDelegate for the eval button - could we just call that with the content of the file?

mfikes commented 9 years ago

@bsvingen What you describe perhaps could be met via a simplistic implementation of load-file.

cljs.user=> (doc load-file)
-------------------------
load-file
REPL Special Function
  Sequentially read and evaluate the set of forms contained in the file.
nil

At a more basic level, things like ns don't even work yet in Replete, so if the file has an ns form at the top, then it is not clear to me what to do. Skip such forms? But, I could imagine some simple code might be written that succeeds in implementing load-file for simple files that just have a bunch of def forms or defn forms in it. The eval button wants a string with a single form, so the biggest trick for that simple case would be to break the file apart into separate forms to be sequentially evaluated. But... I think I've seen tricks done in REPLs where a fake outer do is placed around all of the forms, and then that larger form is passed to be evaluated as a single form.

With the above, with some simple code that might be thrown away later (see how load-file really works in the cljs.repl namespace), file loading could be supported without involving JavaScript being emitted to an output directory to be loaded, etc.

If you'd like to take a stab at something like that, I wouldn't mind. My general thoughts are that support for source files could even come in a subsequent release. In other words, look at how http://himera.herokuapp.com works today. It doesn't support namespaces, and doesn't even support printing yet, but yet it is useful for educational purposes. Replete is getting to be close to Himera, but currently has lots of minor bugs to be sorted out with its basic functionality outside of source file support. :)

mfikes commented 9 years ago

@bsvingen On second thought, I think I see what you are suggesting. When a file is sent to the app, instead of placing it on the filesystem somehow, and implementing a load-file REPL special, I think you are suggesting immediately evaluating the contents of the file. Hmm... I guess that would work too, and if later we wanted to allow the user to save the file a choice could be presented to the user: Execute it now? Or save it?

bsvingen commented 9 years ago

Yes, I'm suggesting something like that.

Doing a traditional load-file is tricky on an OS where users are not supposed to be interacting with the file system. There are two basic ways of accessing files not created by the app itself, one of them is through the document picker/document providers, the other is "open in". I started with the latter, since it requires less UI.

The main reason I think this would be useful is that it's quite limited what you can do if you have to start from scratch every time - this app can be great as a way of demonstrating Clojure, but that's a lot easier to do if you can have a few pre-written functions in a file somewhere, and easily use an external editor.

The idea then is that you should be able to write code in any iOS text editor, and then just do "open in" to have your code evaluated. I think it's perfectly reasonable that the same limitations apply to a loaded file as to the app in general, so if typing and clicking "eval" doesn't support namespaces, then neither would loading from the file.

(And just to be clear, I'm not suggesting making anything that would support loading just any old, existing ClojureScript library, I'm talking about loading a few lines you code you write specifically for Replete, but that you would prefer not having to retype or copy and paste every time.)

You are right that's it's probably a good idea to have some kind of confirmation from the user before evaluating.

(A more advanced model for the future could be one where you specify a file or a set of files from some document provider (whether iCloud, Dropbox, or even a Git repo), and where this file is loaded, and then automatically reloaded every time a file changes. Then you could easily edit code in any editor, even on a desktop computer, and have it ready to run in the app.)

I'd be happy to give it a try if you think this could be useful.

mfikes commented 9 years ago

@bsvingen Yes. Sounds good to me.

You are also right about being careful about exposing the filesystem. What you are suggesting doesn't involve storage at all :)

bsvingen commented 9 years ago

https://github.com/mfikes/replete/pull/35 is a first attempt.