ฉันจะโหลดสคริปต์ของฉันลงใน node.js REPL ได้อย่างไร


141

ฉันมีสคริปต์foo.jsที่มีฟังก์ชันบางอย่างที่ฉันต้องการเล่นใน REPL

มีวิธีที่จะให้โหนดรันสคริปต์ของฉันแล้วกระโดดเข้าสู่ REPL พร้อมกับ globals ที่ประกาศทั้งหมดเช่นที่ฉันสามารถทำได้python -i foo.pyหรือghci foo.hsไม่

คำตอบ:


186

ยังไม่มีอะไรในตัวเพื่อให้มีฟังก์ชันการทำงานที่ตรงตามที่คุณอธิบาย อย่างไรก็ตามทางเลือกอื่นในการใช้requireเพื่อใช้.loadคำสั่งภายใน REPL เช่น:

.load foo.js

มันโหลดไฟล์ทีละบรรทัดเหมือนกับที่คุณพิมพ์ลงใน REPL ซึ่งแตกต่างจากrequireนี้จะทำให้ประวัติ REPL เป็นมลพิษด้วยคำสั่งที่คุณโหลด อย่างไรก็ตามมีข้อได้เปรียบในการทำซ้ำได้เนื่องจากไม่ได้แคชเหมือนrequire.

ซึ่งจะดีกว่าสำหรับคุณจะขึ้นอยู่กับกรณีการใช้งานของคุณ


แก้ไข:มีการใช้งานที่ จำกัด เนื่องจากไม่ทำงานในโหมดเข้มงวด แต่สามปีต่อมาฉันได้เรียนรู้ว่าหากสคริปต์ของคุณไม่มี'use strict'คุณสามารถใช้evalเพื่อโหลดสคริปต์ของคุณได้โดยไม่ทำให้ประวัติ REPL เสียหาย:

var fs = require('fs');
eval(fs.readFileSync('foo.js').toString())

จะเกิดอะไรขึ้นถ้าฉันต้องการวางลงในการจำลองภายในของการโทรกลับแบบ async?
Chet

2
@Chet คุณเขียนคำถาม StackOverflow ใหม่หากคำถามของคุณไม่ตรงกับคำถามที่มีอยู่ :-)
vossad01

@ เชตคุณสามารถ. โหลดไฟล์อื่นด้วย (async () => {more code}) (); และจะแบ่งปันโลกเดียวกัน
nurettin

เคล็ดลับหากคุณใช้ macOS (อาจเป็นรุ่นอื่นด้วย) คุณสามารถพิมพ์ ".load" (จดช่องว่าง) ลงใน REPL แล้วลาก / วางไฟล์ลงใน Terminal จาก Finder เพื่อเพิ่มเส้นทางที่ถูกต้องให้กับคำสั่งของคุณ สิ่งนี้มีประโยชน์หากไฟล์ที่คุณใช้งานมีหลายระดับลง
jamesnotjim

37

ฉันมักจะใช้คำสั่งนี้

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

ทำงานเหมือนกับใน Python โดยไม่มีแพ็คเกจใด ๆ


1
ไม่มีใครรู้วิธีทำให้มันทำงานใน windows cmd? ฉันทำให้มันทำงานใน bash แต่ไม่ใช่ windows
Sharpiro

@Sharpiro: หากคุณติดตั้ง Git คุณจะมีตัวเลือกในการติดตั้ง mini-UNIX ลงในพีซี Windows ของคุณ ฉันหมายถึงการกระจายปกติของ Git สำหรับ Windows
Juan Lanus

สิ่งหนึ่งที่น่ารำคาญเกี่ยวกับเรื่องนี้คือ Node.js จะพิมพ์พรอมต์การจำลองจากนั้นเรียกใช้สคริปต์ของคุณดังนั้นผลลัพธ์ใด ๆ จึงค้างหลังจากพรอมต์ stackoverflow.com/a/45893494/3538165ไม่มีปัญหานี้ แต่สำหรับฟังก์ชันโซลูชันนั้นจะต้องกำหนดให้กับตัวแปรอย่างชัดเจนเพื่อให้ลงเอยในเนมสเปซจำลองดังนั้นจึงไม่ค่อยดีนักเช่นกัน
Radon Rosborough

10

ฉันสร้างVorpal.jsซึ่งจัดการปัญหานี้โดยเปลี่ยนโหนดของคุณเพิ่มเป็น CLI แบบโต้ตอบ สนับสนุนส่วนขยาย 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: 

8

อีกวิธีหนึ่งคือการกำหนดฟังก์ชันเหล่านั้นเป็นส่วนกลาง

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

จากนั้นโหลดไฟล์ล่วงหน้าใน REPL เป็น:

node -r ./file.js

จากนั้นhelloWorldสามารถเข้าถึงฟังก์ชั่นได้โดยตรงใน REPL


8

ฉันสร้างreplpadเนื่องจากเบื่อที่จะโหลดสคริปต์ซ้ำ ๆ

เพียงติดตั้งผ่าน: npm install -g replpad

จากนั้นใช้โดยเรียกใช้: replpad

หากคุณต้องการให้มันดูไฟล์ทั้งหมดในไดเร็กทอรีปัจจุบันและไดเร็กทอรีย่อยทั้งหมดและไพพ์ไฟล์เหล่านั้นลงในเรพเมื่อเปลี่ยนให้ทำดังนี้ replpad .

ดูวิดีโอบนไซต์เพื่อรับทราบวิธีการทำงานที่ดีขึ้นและเรียนรู้เกี่ยวกับคุณสมบัติที่ดีอื่น ๆ ที่มีเช่นนี้:

  • เข้าถึงเอกสารโมดูลหลักในการจำลองผ่านdox()ฟังก์ชันที่เพิ่มให้กับทุกฟังก์ชันหลักเช่นfs.readdir.dox()
  • เข้าถึงการอ่านโมดูลผู้ใช้ในการแทนที่ผ่านdox()ฟังก์ชันที่เพิ่มให้กับทุกโมดูลที่ติดตั้งผ่าน npm เช่นmarked.dox()
  • ซอร์สโค้ดที่ไฮไลต์ของฟังก์ชันการเข้าถึงข้อมูลเกี่ยวกับตำแหน่งที่กำหนดฟังก์ชัน (ไฟล์หมายเลขผ้าลินิน) และข้อคิดเห็นเกี่ยวกับฟังก์ชันและ / หรือjsdocsหากเป็นไปได้ผ่านsrcคุณสมบัติที่เพิ่มให้กับทุกฟังก์ชันเช่นexpress.logger.src
  • การสนับสนุนscriptie-talkie (ดู.talkคำสั่ง)
  • เพิ่มคำสั่งและแป้นพิมพ์ลัด
  • การผูกคีย์เป็นกลุ่ม
  • รองรับแผนที่สำคัญ
  • parens ที่จับคู่ผ่านปลั๊กอิน match token
  • ต่อท้ายรหัสที่ป้อนในการจำลองกลับไปที่ไฟล์ผ่านแป้นพิมพ์ลัดหรือ.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
ShadSterling

5

ทำไมไม่โหลดไฟล์ลงในโหนดโต้ตอบแทน?

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


2
ทำไมไม่เพียงnode -i -r "./build/main/index.js"?
Bernardo Dal Corno

4

ขณะนี้คุณไม่สามารถทำได้โดยตรง แต่คุณสามารถทำได้mylib = require('./foo.js')ใน REPL วิธีการจำจะถูกส่งออกไม่ได้ประกาศเป็น globals


ฉันพบว่าสิ่งนี้ดีกว่า.load my_work.jsแม้ว่าจะต้องมีexports.working_var = ...การประกาศเพิ่มเติมเนื่องจาก REPL barfs บนจาวาสคริปต์ที่ถูกต้องสมบูรณ์บางประเภทเช่นความคิดเห็นหลายบรรทัด (อย่างน้อยก็ด้วย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คำสั่ง


4

นี่คือฟังก์ชัน bash ของ คำตอบของ George :

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เป็นตัวแปร


1

คำตอบเก่า

type test.js|node -i

จะเปิดโหนด REPL และพิมพ์ทุกบรรทัดจาก test.js เป็น REPL แต่ด้วยเหตุผลบางประการโหนดจะออกหลังจากจบไฟล์

ปัญหาอีกประการหนึ่งคือฟังก์ชันจะไม่ถูกยกขึ้น

ตอบดีกว่า

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

จากนั้น globals ทั้งหมดที่ประกาศโดยไม่มี var ภายใน test2.js จะพร้อมใช้งานใน REPL

ไม่แน่ใจว่าเหตุใด var a ในขอบเขตส่วนกลางจึงไม่พร้อมใช้งาน


8
โปรดเพิ่มคำอธิบายในคำตอบของคุณ
mechnicov

ดูเหมือนว่าไม่ทำงานในtype bashเพื่อให้ได้คำตอบที่ดีขึ้นดูเหมือนว่าคุณสามารถทำได้node -r noderc.jsโดยไม่ต้องเริ่มการจำลองด้วยตนเอง แต่คุณต้องกำหนดให้globalโดยตรงในสคริปต์สำหรับฟังก์ชัน / var ควรมีวิธีการ "vm.runInContext" ที่เหมาะสมเพื่อที่จะรับค่าเพิ่มเติมจากสคริปต์
Gavin Haynes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.