Jak załadować mój skrypt do REPL node.js?

141

Mam skrypt foo.jszawierający pewne funkcje, którymi chcę się bawić w REPL.

Czy istnieje sposób, aby węzeł wykonał mój skrypt, a następnie wskoczył do REPL ze wszystkimi zadeklarowanymi wartościami globalnymi, tak jak mogę za pomocą python -i foo.pylub ghci foo.hs?

hugomg
źródło

Odpowiedzi:

186

Nadal nie ma nic wbudowanego, które zapewniałoby dokładnie taką funkcjonalność, którą opisujesz. Jednak alternatywa dla używania requirego do używania .loadpolecenia w REPL, na przykład:

.load foo.js

Ładuje plik wiersz po wierszu, tak jakbyś wpisał go w REPL. W przeciwieństwie do requiretego zanieczyszcza historię REPL za pomocą załadowanych poleceń. Ma jednak tę zaletę, że jest powtarzalny, ponieważ nie jest przechowywany w pamięci podręcznej require.

To, co jest lepsze dla ciebie, zależy od twojego przypadku użycia.


Edycja: ma ograniczone zastosowanie, ponieważ nie działa w trybie ścisłym, ale trzy lata później dowiedziałem się, że jeśli twój skrypt nie ma 'use strict', możesz użyć evaldo załadowania skryptu bez zanieczyszczania historii REPL:

var fs = require('fs');
eval(fs.readFileSync('foo.js').toString())
vossad01
źródło
A jeśli chcę wrzucić do odpowiedzi w wywołaniu zwrotnym asynchronicznym?
Chet
2
@Chet Piszesz nowe pytanie StackOverflow, jeśli Twoje pytanie nie pasuje do istniejącego :-)
vossad01
@Chet możesz. Załadować inny plik za pomocą (async () => {więcej kodu}) (); i będzie miał te same globalne.
nurettin
Wskazówka, jeśli korzystasz z macOS (może też innych). Możesz wpisać „.load” (zwróć uwagę na spację) do REPL i przeciągnij / upuść plik do terminala z Findera, aby dodać poprawną ścieżkę do polecenia. Jest to przydatne, jeśli pliki, z którymi pracujesz, są o kilka poziomów w dół.
jamesnotjim
37

zawsze używam tego polecenia

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

działa dokładnie tak samo, jak w Pythonie bez żadnych pakietów.

George Shalvashvili
źródło
1
czy ktoś wie, jak to działa w Windows cmd? Mam to działające w bash, ale nie windows.
Sharpiro,
@Sharpiro: Jeśli zainstalujesz Git, możesz zainstalować mini-UNIX na swoim komputerze z systemem Windows. Mam na myśli normalną dystrybucję Gita dla Windows.
Juan Lanus,
Jedyną rzeczą, która jest w tym denerwująca, jest to, że Node.js wydrukuje monit repl, a następnie uruchomi skrypt, dzięki czemu wszelkie dane wyjściowe zostaną zablokowane po tym monicie. stackoverflow.com/a/45893494/3538165 nie ma tego problemu, ale w tym rozwiązaniu funkcje muszą być jawnie przypisane do zmiennych, aby trafiły do ​​przestrzeni nazw replik, więc też niezbyt dobre.
Radon Rosborough
10

Stworzyłem Vorpal.js , który rozwiązuje ten problem, zmieniając Twój węzeł w interaktywny CLI. Obsługuje rozszerzenie REPL, które przenosi Cię do REPL w kontekście uruchomionej aplikacji.

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

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

Następnie możesz uruchomić aplikację i spadnie ona do REPL.

$ node myapp.js repl
myapp> repl: 
dthree
źródło
8

Innym sposobem jest zdefiniowanie tych funkcji jako globalnych.

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

Następnie załaduj plik w REPL jako:

node -r ./file.js

Następnie funkcja helloWorldjest dostępna bezpośrednio w REPL.

Ashish Chaudhary
źródło
8

Stworzyłem replpad, ponieważ zmęczyło mnie wielokrotne ładowanie skryptu.

Po prostu zainstaluj go przez: npm install -g replpad

Następnie użyj go, uruchamiając: replpad

Jeśli chcesz, aby obserwował wszystkie pliki w bieżącym i wszystkich podkatalogach i przesyłał je do odpowiedzi, gdy się zmienią, wykonaj: replpad .

Obejrzyj filmy w witrynie, aby lepiej zrozumieć, jak to działa, i poznaj inne fajne funkcje, takie jak te:

  • Uzyskaj dostęp do dokumentów modułu podstawowego w repl za pośrednictwem dox()funkcji, która jest dodawana do każdej funkcji podstawowej, tjfs.readdir.dox()
  • uzyskaj dostęp do readmes modułu użytkownika w repl za pomocą dox()funkcji, która jest dodawana do każdego modułu zainstalowanego przez npm, tjmarked.dox()
  • uzyskać dostęp do podświetlonego kodu źródłowego funkcji , informacji o tym, gdzie funkcja została zdefiniowana (plik, numer linii) oraz komentarzy funkcji i / lub jsdocs, jeśli to możliwe, poprzez srcwłaściwość dodawaną do każdej funkcji, tj.express.logger.src
  • scriptie talkie wspornik (patrz.talkpoleceń)
  • dodaje polecenia i skróty klawiaturowe
  • vim key bindings
  • obsługa map kluczowych
  • parens dopasowujące za pomocą wtyczki match token
  • dołącza kod wprowadzony w repl z powrotem do pliku za pomocą skrótu klawiaturowego lub .appendpolecenia

Zobacz: https://github.com/thlorenz/replpad

Thorsten Lorenz
źródło
Musiałem CXX=clang++ npm install replpadobejść błądg++: error: unrecognized command line option '-stdlib=libc++'
ShadSterling,
Ale kiedy go uruchomię, zawodzi# # Fatal error in ../deps/v8/src/api.cc, line 1248 # Check failed: !value_obj->IsJSReceiver() || value_obj->IsTemplateInfo(). # Illegal instruction: 4
ShadSterling,
5

Dlaczego nie załadować pliku do interaktywnej repliki węzła?

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

Następnie możesz dodać skrypty do package.json

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

testowano przy użyciu węzła 8.1.2

lfender6445
źródło
2
dlaczego nie tylko node -i -r "./build/main/index.js"?
Bernardo Dal Corno
4

Obecnie nie możesz tego zrobić bezpośrednio, ale możesz mylib = require('./foo.js')w REPL. Pamiętaj, że metody są eksportowane, a nie deklarowane jako globalne.

Ricardo Tomasi
źródło
Uważam, że jest to lepsze niż .load my_work.js, pomimo wymagania kilku dodatkowych exports.working_var = ...deklaracji, ponieważ barf REPL na niektórych rodzajach doskonale poprawnych skryptów javascript, takich jak komentarze wielowierszowe (przynajmniej w mojej readlinekonfiguracji).
brązowy
4

replpad jest fajny, ale aby szybko i łatwo załadować plik do węzła, zaimportować jego zmienne i rozpocząć odpowiedź, możesz dodać następujący kod na końcu pliku .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]);
    })();
}

Teraz, jeśli twój plik jest src.js, uruchomienie node src.jsuruchomi węzeł, załaduje plik, uruchomi REPL i skopiuje wszystkie obiekty zadeklarowane jako varna najwyższym poziomie, a także wszystkie wyeksportowane globale. W if (require.main === module)gwarantuje, że ten kod nie zostanie wykonane, jeśli src.jsjest włączone za pośrednictwem requirerachunku. W rzeczywistości możesz dodać dowolny kod, który chcesz, aby był wykonywany, gdy uruchamiasz src.jsautonomicznie do celów debugowania w ifinstrukcji.

user1936097
źródło
4

Oto wersja funkcji bash odpowiedzi George'a :

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

Jeśli umieścisz to w swoim ~/.bash_profile, możesz używać go jak aliasu, tj .:

noderepl foo.js
Eliot
źródło
2
Używam tego od miesięcy i podczas przechodzenia do nowego środowiska powłoki straciłem niektóre ustawienia i musiałem je ponownie wyśledzić. Więc skoro tu jestem, pomyślałem, że będę ci wdzięczny za tę naprawdę przydatną funkcję.
Xaekai
3

Kolejna sugestia, której tutaj nie widzę: wypróbuj ten mały kod

#!/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

Następnie możesz po prostu uruchomić ten skrypt i dołączy on foojako zmienną

krukowaty
źródło
1

Stara odpowiedź

type test.js|node -i

Otworzy węzeł REPL i wpisze wszystkie wiersze z test.js do REPL, ale z jakiegoś powodu węzeł zakończy pracę po zakończeniu pliku

Innym problemem jest to, że funkcje nie zostaną podniesione.

Lepsza odpowiedź

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

Wtedy wszystkie wartości globalne zadeklarowane bez zmiennej w test2.js będą dostępne w REPL

nie wiem, dlaczego zmienna o zasięgu globalnym nie będzie dostępna

Żyd
źródło
8
Proszę dodać wyjaśnienie do swojej odpowiedzi
mechnicov
Wygląda na to, typeże nie działa bash. Aby uzyskać lepszą odpowiedź, wydaje się, że możesz po prostu obejść się node -r noderc.jsbez ręcznego uruchamiania repl. Ale musisz przypisać do globalbezpośrednio w skrypcie funkcji / var. Powinien istnieć sposób na odpowiednie „vm.runInContext”, aby pobrać więcej wartości ze skryptu.
Gavin Haynes