Как мне загрузить мой скрипт в REPL node.js?

137

У меня есть сценарий foo.js, содержащий некоторые функции, с которыми я хочу поиграть в REPL.

Есть ли способ заставить узел выполнить мой скрипт, а затем перейти в REPL со всеми объявленными глобальными переменными, как я могу с помощью python -i foo.pyили ghci foo.hs?

hugomg
источник

Ответы:

179

По-прежнему нет ничего встроенного, чтобы обеспечить точную функциональность, которую вы описываете. Однако в качестве альтернативы его использованию requireможно использовать .loadкоманду в REPL, например:

.load foo.js

Он загружает файл построчно, как если бы вы ввели его в REPL. В отличие от requireэтого, история REPL засоряется загруженными вами командами. Тем не менее, он имеет то преимущество, что его можно повторять, потому что он не кэшируется, как require.

Что лучше для вас, будет зависеть от вашего варианта использования.


Изменить: он имеет ограниченную применимость, потому что он не работает в строгом режиме, но три года спустя я узнал, что если в вашем скрипте его нет 'use strict', вы можете использовать его evalдля загрузки своего скрипта, не загрязняя историю REPL:

var fs = require('fs');
eval(fs.readFileSync('foo.js').toString())
vossad01
источник
Что, если я захочу перейти к ответу внутри асинхронного обратного вызова?
Chet
2
@Chet Вы напишите новый вопрос на StackOverflow, если ваш вопрос не соответствует уже существующему :-)
vossad01
@Chet, вы можете загрузить другой файл с помощью (async () => {more code}) (); и он будет использовать одни и те же глобалы.
nurettin
Подсказка, если вы используете macOS (может быть, и другие). Вы можете ввести «.load» (обратите внимание на пробел) в REPL и перетащить файл в Терминал из Finder, чтобы добавить правильный путь к вашей команде. Это удобно, если файлы, с которыми вы работаете, находятся на несколько уровней ниже.
jamesnotjim
35

я всегда использую эту команду

node -i -e "$(< yourScript.js)"

работает точно так же, как в Python без каких-либо пакетов.

Георгий Шалвашвили
источник
1
Кто-нибудь знает, как заставить это работать в Windows cmd? У меня он работает в bash, но не в окнах.
Sharpiro
@Sharpiro: если вы устанавливаете Git, у вас есть возможность установить mini-UNIX на свой ПК с Windows. Я имею в виду нормальный дистрибутив Git для Windows.
Хуан Ланус
Единственное, что здесь раздражает, - это то, что Node.js распечатает приглашение repl, а затем запустит ваш скрипт, поэтому любой вывод застревает после приглашения. stackoverflow.com/a/45893494/3538165 не имеет этой проблемы, но для этого решения функции должны быть явно назначены переменным, чтобы они попали в пространство имен repl, так что это тоже не очень хорошо.
Радон Росборо
10

Я сделал Vorpal.js , который решает эту проблему, превращая добавление узла в интерактивный интерфейс командной строки. Он поддерживает расширение REPL, которое переводит вас в REPL в контексте вашего запущенного приложения.

var vorpal = require('vorpal')();
var repl = require('vorpal-repl');

vorpal
  .delimiter('myapp>')
  .use(repl)
  .show()
  .parse(process.argv); 

Затем вы можете запустить приложение, и оно перейдет в REPL.

$ node myapp.js repl
myapp> repl: 
dthree
источник
8

Другой способ - определить эти функции как глобальные.

global.helloWorld = function() { console.log("Hello World"); }

Затем предварительно загрузите файл в REPL как:

node -r ./file.js

После этого к функции helloWorldможно будет получить доступ прямо в REPL.

Ашиш Чаудхари
источник
8

Я создал replpad, так как устал многократно перезагружать скрипт.

Просто установите его через: npm install -g replpad

Затем используйте его, запустив: replpad

Если вы хотите, чтобы он просматривал все файлы в текущем и всех подкаталогах и передавал их в ответ при изменении, выполните: replpad .

Посмотрите видео на сайте, чтобы лучше понять, как это работает, и узнать о некоторых других приятных функциях, таких как:

  • доступ к документации основного модуля в repl через dox()функцию, которая добавляется к каждой основной функции, т.е.fs.readdir.dox()
  • получить доступ к файлам readmes пользовательского модуля в ответе через dox()функцию, которая добавляется к каждому модулю, установленному через npm, т.е.marked.dox()
  • доступ к выделенному исходному коду функции , информации о том, где функция была определена (файл, номер) и комментариям функции и / или jsdocs, где это возможно, через srcсвойство, которое добавляется к каждой функции, т. е.express.logger.src
  • scriptie рация поддержки (см.talkкоманда)
  • добавляет команды и сочетания клавиш
  • привязки клавиш vim
  • поддержка ключевых карт
  • сопоставление пар с помощью плагина совпадения токенов
  • добавляет код, введенный в ответ, обратно в файл с помощью сочетания клавиш или .appendкоманды

См .: https://github.com/thlorenz/replpad

Торстен Лоренц
источник
Мне пришлось CXX=clang++ npm install replpadобойти ошибкуg++: error: unrecognized command line option '-stdlib=libc++'
ShadSterling
Но потом, когда я запустил его, он не # # Fatal error in ../deps/v8/src/api.cc, line 1248 # Check failed: !value_obj->IsJSReceiver() || value_obj->IsTemplateInfo(). # Illegal instruction: 4
сработал
5

Почему бы не загрузить файл в интерактивный узел repl?

node -h
-e, --eval script          evaluate script
-i, --interactive          always enter the REPL even if stdin

node -e 'var client = require("./build/main/index.js"); console.log("Use `client` in repl")' -i

Затем вы можете добавить в package.json скрипты

"repl": "node -e 'var client = require(\"./build/main/index.js\"); console.log(\"Use `client` in repl\")' -i",

протестировано с использованием узла v8.1.2

lfender6445
источник
2
почему не просто node -i -r "./build/main/index.js"?
З. Кулла
4

В настоящее время вы не можете сделать это напрямую, но можете mylib = require('./foo.js')в REPL. Помните, что методы экспортируются, а не объявляются как глобальные.

Рикардо Томази
источник
Я считаю, что это предпочтительнее .load my_work.js, несмотря на то , что требуются некоторые дополнительные exports.working_var = ...объявления, потому что REPL блокирует некоторые виды совершенно допустимого javascript, например многострочные комментарии (по крайней мере, с моей readlineконфигурацией).
chbrown
4

replpad это круто, но для быстрого и простого способа загрузить файл в узел, импортировать его переменные и запустить ответ, вы можете добавить следующий код в конец вашего .js файла

if (require.main === module){
    (function() {
        var _context = require('repl').start({prompt: '$> '}).context;
        var scope = require('lexical-scope')(require('fs').readFileSync(__filename));
        for (var name in scope.locals[''] )
            _context[scope.locals[''][name]] = eval(scope.locals[''][name]);
        for (name in scope.globals.exported)
            _context[scope.globals.exported[name]] = eval(scope.globals.exported[name]);
    })();
}

Теперь, если ваш файл src.jsзапущен node src.js, запускается узел, загружается файл, запускается REPL и копируются все объекты, объявленные как varна верхнем уровне, а также любые экспортированные глобальные объекты . В if (require.main === module)гарантирует , что этот код не будет выполняться , если src.jsвключен через requireзаявление. Фактически, вы можете добавить любой код, который вы хотите исполнять, когда вы работаете в src.jsавтономном режиме для целей отладки внутри ifоператора.

user1936097
источник
4

Вот версия ответа Джорджа с функцией bash :

noderepl() {
    FILE_CONTENTS="$(< $1 )"
    node -i -e "$FILE_CONTENTS"
}

Если вы поместите это в свой, ~/.bash_profileвы можете использовать его как псевдоним, то есть:

noderepl foo.js
Элиот
источник
2
Я использую это уже несколько месяцев, и при переходе к новой среде оболочки я потерял некоторые из своих настроек, и мне пришлось снова отслеживать это. Итак, раз уж я здесь, я подумал, что буду благодарен вам за эту действительно полезную функцию.
Xaekai
3

Еще одно предложение, которого я здесь не вижу: попробуйте этот небольшой фрагмент кода

#!/usr/bin/env node
'use strict';

const repl = require('repl');
const cli = repl.start({ replMode: repl.REPL_MODE_STRICT });
cli.context.foo = require('./foo'); // injects it into the repl

Затем вы можете просто запустить этот скрипт, и он будет включен fooв качестве переменной

Corvid
источник
1

Старый ответ

type test.js|node -i

Откроет узел REPL и введет все строки из test.js в REPL, но по какой-то причине узел закроется после завершения файла

Другая проблема в том, что функции не будут подняты.

Лучший ответ

node -e require('repl').start({useGlobal:true}); -r ./test2.js

Тогда все глобальные переменные, объявленные без var в test2.js, будут доступны в REPL

не уверен, почему var a в глобальной области не будет доступен

еврей
источник
8
Пожалуйста, добавьте пояснение к вашему ответу
mechnicov