add simple startup file support to REPL (.coffeerc) #1996

Open
wants to merge 5 commits into
from

Projects

None yet

7 participants

@codelahoma

When starting REPL, loads and runs the file .coffeerc if present in the current directory.

@michaelficarra
Collaborator

Why the working directory and not ~?

@michaelficarra michaelficarra and 1 other commented on an outdated diff Jan 2, 2012
src/repl.coffee
@@ -34,7 +35,7 @@ backlog = ''
# The main REPL function. **run** is called every time a line of code is entered.
# Attempt to evaluate the command. If there's an exception, print it out instead
# of exiting.
-run = (buffer) ->
+run = (buffer, echo_output=true) ->
@michaelficarra
michaelficarra Jan 2, 2012

camelCase variables

@paulmillr
paulmillr Jan 2, 2012

and a space before and after the operator

@jashkenas
Owner

What exactly are you using this for, given that the current REPL isn't exactly configurable?

@codelahoma

@michaelficarra The use case that prompted me to add this was that I was working on a project and needing to execute a common series of statements each time I started the REPL.

@jashkenas Using as described above, but now that @michaelficarra has mentioned it, I'm going to add ~ as well so I can define helper functions that I'd like to have present in all REPL instances.

@michaelficarra
Collaborator

@codelahoma: Ah, that seems useful. It'd be nice to have CoffeeScript = require './lib/coffee-script' executed when I run the REPL in the coffee-script directory.

@jashkenas: #1661 (comment)

@michaelficarra
Collaborator

@codelahoma: process.env.USERPROFILE is undefined for me. This'll cause a lookup to `undefined/.coffeerc'. That's not desirable.

@michaelficarra michaelficarra commented on an outdated diff Jan 2, 2012
src/repl.coffee
@@ -120,5 +124,11 @@ repl.on 'close', ->
repl.on 'line', run
+for dir in [process.env['USERPROFILE'], process.env['HOME'], process.cwd()]
+ fs.readFile path.normalize("#{dir}/.coffeerc"),
@michaelficarra
michaelficarra Jan 2, 2012

should use path.join dir, '.coffeerc'

@michaelficarra michaelficarra commented on an outdated diff Jan 2, 2012
src/repl.coffee
@@ -120,5 +124,11 @@ repl.on 'close', ->
repl.on 'line', run
+for dir in [process.env['USERPROFILE'], process.env['HOME'], process.cwd()]
@michaelficarra
michaelficarra Jan 2, 2012

You don't need to use dynamic member access on constant strings.

for dir in [process.env.HOME or process.env.USERPROFILE, process.cwd()]

@michaelficarra michaelficarra commented on an outdated diff Jan 2, 2012
src/repl.coffee
@@ -34,7 +37,7 @@ backlog = ''
# The main REPL function. **run** is called every time a line of code is entered.
# Attempt to evaluate the command. If there's an exception, print it out instead
# of exiting.
-run = (buffer) ->
+run = (buffer, echoOutput = true) ->
@michaelficarra
michaelficarra Jan 2, 2012

edit: ignore this, see comment below

I don't like the name echoOutput. Ideally, we would take a function and pass the "output" to that, defaulting it to a process.stdout writer. But that's a lot of code for a function that's not even part of our public API. So maybe printOutput or writeOutput? And yes is preferred to true where it makes sense in this project.

@michaelficarra michaelficarra and 1 other commented on an outdated diff Jan 2, 2012
src/repl.coffee
@@ -120,5 +124,11 @@ repl.on 'close', ->
repl.on 'line', run
+for dir in [process.env['USERPROFILE'], process.env['HOME'], process.cwd()]
+ fs.readFile path.normalize("#{dir}/.coffeerc"),
+ (err, data) ->
+ unless err
+ run data, false
@michaelficarra
michaelficarra Jan 2, 2012

I don't like how this runs the code through the REPL function. That's not right. Use CoffeeScript.eval instead and revert the changes to run.

@codelahoma
codelahoma Jan 2, 2012

This would repeat a good chunk of run's code, which isn't DRY.

Any opposition to factoring out the common code into its own method?

@michaelficarra
michaelficarra Jan 2, 2012

Which chunk? It would look like this:

for dir in [process.env.HOME or process.env.USERPROFILE, process.cwd()]
  filename = path.join dir, '.coffeerc'
  fs.readFile file, (err, data) ->
    return if err
    CoffeeScript.eval data, { filename, modulename: '.coffeerc' }

We don't want _ to have the completion value of the last line in .coffeerc or allow .coffeercs to end in \, right? I don't see anything duplicated other than the single reference to CoffeeScript.eval.

@codelahoma
codelahoma Jan 2, 2012

Okay, not exactly a chunk.

My thought was that a wrapper function could isolate the try/eval/catch/stacktrace logic in a single place. It could then be used in both run and the .coffeerc logic without the clutter of exception handling.

This, of course, assumes we want an exception in .coffeerc to be non-fatal, and behave the same as an exception currently does in the REPL.

replEval = (code, options = {}) ->
  try
    CoffeeScript.eval code, options
  catch err
    error err
@michaelficarra
michaelficarra Jan 2, 2012

Nope, I'd say you just let the error float to the top. Or do that. Whatever.

edit: edited. Or whatever.

@codelahoma

@michaelficarra Thanks for all the feedback. I'll get it cleaned up.

@codelahoma codelahoma switch to readFileSync to prevent race
~/.coffeerc should be evaluated before ./coffeerc, so
that project specific values can override defaults.
186ff26
@TrevorBurnham
Collaborator

@codelahoma Are you familiar with the -r flag? You can just put the configuration you need in start.coffee and run

coffee -r './start.coffee'

to require start.coffee before the REPL starts up; anything start.coffee attaches to the global object will be available from the REPL environment.

Also, the .whateverrc naming convention doesn't really make sense for such a file, does it? Typically, such files run on system/shell startup.

@jashkenas
Owner

Awesome -- I didn't remember (know) that the -r flag can be used with the REPL. That's a much, much better solution than a magical file name. Thanks for the note, Trevor.

@jashkenas jashkenas closed this Jan 3, 2012
@michaelficarra
Collaborator

@jashkenas: I don't think the -r flag is a replacement for the automagic loading of a .coffeerc file. I think the whole point was to not have to specify anything when starting the REPL. You can define defaults that you set once and don't have to think about again. You're free to run coffee bare.

@jashkenas
Owner

I don't think that automagic code loading defaults are a good idea for any aspect of the coffee command ... compiling, printing, REPL ... whatever.

It's not as fully flexible as you may want, if you're doing something really custom. -r provides you a simple hook to write your own enhanced REPL, in whatever script you like.

@michaelficarra
Collaborator

Ah, oh well. At least it was a good exercise for @codelahoma, and we now have this code and discussion on record.

@codelahoma

The behavior and filename directly correspond to IRB's .irbrc. Python does the same with whatever file the PYTHONSTARTUP environmental variable specifies. This is not an unusual feature for a REPL at all.

@TrevorBurnham
Collaborator

@codelahoma Ah, I was unaware of .irbrc. I stand corrected.

@jashkenas
Owner

In your .bashrc ...

alias coffeerepl='coffee -r /path/to/my/special/stuff.coffee'
@michaelficarra
Collaborator

-r doesn't check for existence

$ coffee -r {.,~}/.cofferc

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: Cannot find module './.cofferc'
    at Function._resolveFilename (module.js:334:11)
    at Function._load (module.js:279:25)
    at Module.require (module.js:357:17)
    at require (module.js:368:17)
    at /home/michael/projects/coffee-script/lib/coffee-script/command.js:192:7
    at Object.run (/home/michael/projects/coffee-script/lib/coffee-script/command.js:50:23)
    at Object.<anonymous> (/home/michael/projects/coffee-script/bin/coffee:7:41)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
@codelahoma

I'll not beat a dead horse.

Like @michaelficarra said, it was a good exercise.

<stagewhisper>even though recreating the behavior from the shell will take more than an alias, especially on Windows</stagewhisper>

@thedufer

As far as I can tell, the -r option is no longer supported. Can we re-open this?

@michaelficarra
Collaborator

Sure. Also, there's now precedent with the .coffee_history file.

@michaelficarra michaelficarra reopened this Sep 5, 2013
@jasonkarns

If a .coffeerc file is used, I implore you to follow the XDG spec and not use ~/.coffeerc but $XDG_CONFIG_HOME/coffee

http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment