镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

REPL started with replServer doesn't persist history #5730

Description

@victorb

I'm trying to create a REPL via the programmatic library provided by the built-in repl package (https://nodejs.org/api/repl.html).

I'm doing something like this[1]:

var repl = require('repl')
repl.start(' > ')

And I'm expecting the commands I enter to be preserved if I open the repl once again later. Not finding that this is the case, I have been trying to setting both NODE_REPL_HISTORY and NODE_REPL_HISTORY by doing something like this process.env.NODE_REPL_HISTORY = 'somepath'. I've tried setting something to relative path, absolute path, a folder, a file, a non-existing file and a already existing file. But in all cases, the history is not persisted.

I'm not sure if I found a bug or if I'm doing something wrong but would appreciate any I can get.

  • Version: v5.8.0 but reproduced the same issue on every version down to v4.0.0, haven't tested lower versions than that...
  • Platform: Darwin Mak.localdomain 15.0.0 Darwin Kernel Version 15.0.0: Wed Aug 26 16:57:32 PDT 2015; root:xnu-3247.1.106~1/RELEASE_X86_64 x86_64
  • Subsystem: REPL

[1] In reality I'm doing something bigger, https://github.com/victorbjelkholm/trymodule, but figured a small test-case is better for troubleshooting.

Activity

  1. added
    replIssues and PRs related to the REPL subsystem.
    on Mar 15, 2016
  2. mscdex commented on Mar 15, 2016

    @mscdex
    Contributor

    FWIW I would expect programmatic REPLs to have to opt-in as far as saving history goes.

  3. victorb commented on Mar 15, 2016

    @victorb
    Author

    @mscdex That makes sense for me as well, I just would like to be able to enable it somehow, setting the environment variable would be one way, accepting it being set in opts

    PS. I can also reproduce this in a docker image (mhart/alpine-node) I frequently use for testing things.

  4. cjihrig commented on Mar 15, 2016

    @cjihrig
    Contributor

    @victorbjelkholm what if you pass terminal: true in the REPL options? Looking at the code, it looks like that causes the history to be setup.

  5. victorb commented on Mar 15, 2016

    @victorb
    Author

    @cjihrig Yeah, tried that as well but to no avail 👎

    Extended example:

    var repl = require('repl')
    
    repl.start({
      terminal: true,
      prompt: '> '
    })
  6. cjihrig commented on Mar 15, 2016

    @cjihrig
    Contributor

    Ah, yea that is only for the internal REPL, sorry.

  7. victorb commented on Mar 16, 2016

    @victorb
    Author

    @cjihrig saving history in general for programmatic repl or that specific snippet of code? (https://github.com/nodejs/node/blob/master/lib/internal/repl.js#L58-L61)

  8. victorb commented on Mar 16, 2016

    @victorb
    Author

    Seems like one option would be to use the relatively small library repl.history (https://github.com/tmpvar/repl.history) but I would much rather have it in node vanilla.

  9. cjihrig commented on Mar 16, 2016

    @cjihrig
    Contributor

    I meant that specific snippet of code that you linked to. It's exported at the top of that file as createInternalRepl(). It looks like it might not be supported for the programmatic REPL at this time.

  10. victorb commented on Mar 16, 2016

    @victorb
    Author

    Oh, I see.

    I'll leave this issue open as a feature request to enable history persistence in the programmatic repl and continue my day with using repl.history instead.

    Thanks for the help @cjihrig 👍

  11. Fishrock123 commented on Mar 16, 2016

    @Fishrock123
    Contributor

    Imo this is kind of up to the implementor. Maybe we can have it as an option? But it would be a very significant change the programatic API.

  12. lance commented on Mar 16, 2016

    @lance
    Member

    How big of a change is it really? The createInternalRepl() function just uses a boolean (an odd one, if you ask me[1]) to determine whether or not to call setupHistory(). It seems to me that this function could easily be moved to the public facing repl.js, and triggered on a similar, but probably more aptly named option. E.g. option.history = '/path/to/file.txt'.

    It's minor, but there is already a little bleed over from internal to external. I don't see a disadvantage to moving history management into the public API and simply make the createInternalRepl function much simpler - setting up command line defaults and such.

    Edit: This is a long way of saying, I'd be willing to submit a PR for this change if there's any chance of it being accepted.

    [1] The fact that writing history is a side effect of setting opts.terminal = true seems strange, but I suspect it's a vestige of the fact that this createInternalRepl is secret and only ever used by node.js at startup.

  13. lance commented on Jul 6, 2016

    @lance
    Member

    Given that we ultimately decided not to merge the PR for this, I'm going to close it. Feel free to reopen if there is demonstrated need.

  14. f0ster commented on Nov 5, 2017

    @f0ster

    Just chiming in after some research but late to the party, I would definitely use this if it were available in the stdlib ^^ :)

  15. jeffs commented on Jan 25, 2018

    @jeffs

    For others who find this issue:

    • Calling repl.start is a no-go because it misses history
    • Calling node -r ./noderc.js is a no-go because repl.repl is unavailable
      • require('repl').repl is undefined under -r, even for interactive sessions

    My work-around is to have tmux start node and send it arbitrary initialization code:

    $ cat bin/repl
    #!/bin/sh
    
    file="$HOME/path/to/my/noderc.js"
    
    stty -echo
    tmux send-keys 'node; stty echo' C-m ".load $file" C-m

    UPDATE:

    New hack: Use a command-line flag to require a module that configures the global object, and sets a callback to configure the repl once it's been initialized.

    ~ $ grep repl .bashrc
    alias repl='node --use-strict -r ~/home/git/env/etc/noderc.js'
    
    ~ $ cat ~/home/git/env/etc/noderc.js
    setTimeout(() => global.repl.repl.ignoreUndefined = true, 1000);
    
    global.jenny = [8, 6, 7, 5, 3, 0, 9];

    This has the advantage of not adding the rc file contents to .node_repl_history every time you start a REPL.

  16. joniba commented on Oct 8, 2018

    @joniba

    Any examples of how to implement loading command history into the repl that is os- and terminal-independent? I looked at repl.history but don't see how to load that history back into the repl once it loads.

  17. noinkling commented on Jan 14, 2019

    @noinkling

    I'd very much like to see this reopened. It's strange that the built-in REPL has this functionality but programmatic REPLs have no access to it and instead depend on hacky workarounds.

    Also, the workaround linked above requires extra effort in order to reimplement max history size, so it's at least a little harder than that.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues requesting new Node.js features.replIssues and PRs related to the REPL subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions