2012-02-03 7 views
18

मैं टर्मिनल में चल रहे node.js प्रोग्राम से Vim खोलने में सक्षम होना चाहता हूं, कुछ सामग्री बनाएं, सहेजें और Vim से बाहर निकलें, और फिर फ़ाइल की सामग्री को पकड़ें।मैं node.js से टर्मिनल एप्लिकेशन कैसे खोलूं?

मैं इस तरह कुछ करने के लिए कोशिश कर रहा हूँ:

filename = '/tmp/tmpfile-' + process.pid 

editor = process.env['EDITOR'] ? 'vi' 
spawn editor, [filename], (err, stdout, stderr) -> 

    text = fs.readFileSync filename 
    console.log text 

हालांकि, जब इस चलाता है, यह सिर्फ टर्मिनल लटका हुआ है।

मैंने इसे exec के साथ भी आजमाया है और एक ही परिणाम मिला है।

अद्यतन:

इस तथ्य यह है कि इस प्रक्रिया को एक आदेश readline चल के साथ एक प्रॉम्प्ट पर टाइप किया से शुरू की है द्वारा जटिल है। मैंने पूरी तरह से एक फाइल में अपने नवीनतम संस्करण के प्रासंगिक भागों को निकाला। यहाँ अपनी संपूर्णता में यह है:

{spawn} = require 'child_process' 
fs = require 'fs' 
tty = require 'tty' 
rl = require 'readline' 

cli = rl.createInterface process.stdin, process.stdout, null 
cli.prompt() 

filename = '/tmp/tmpfile-' + process.pid 

proc = spawn 'vim', [filename] 

#cli.pause() 
process.stdin.resume() 

indata = (c) -> 
    proc.stdin.write c 
process.stdin.on 'data', indata 

proc.stdout.on 'data', (c) -> 
    process.stdout.write c 

proc.on 'exit',() -> 
    tty.setRawMode false 
    process.stdin.removeListener 'data', indata 

    # Grab content from the temporary file and display it 
    text = fs.readFile filename, (err, data) -> 
     throw err if err? 
     console.log data.toString() 

     # Try to resume readline prompt 
     cli.prompt() 

जिस तरह से यह ऊपर शो के रूप में काम करता है, कि यह सेकंड के एक जोड़े के लिए एक संकेत से पता चलता है, और फिर विम करने के लिए लॉन्च किया गया, लेकिन TTY में गड़बड़ है। मैं फ़ाइल को संपादित और सहेज सकता हूं, और सामग्री सही ढंग से मुद्रित की जाती है। बाहर निकलने पर टर्मिनल पर मुद्रित जंक का एक गुच्छा भी है, और रीडलाइन कार्यक्षमता बाद में टूट जाती है (कोई ऊपर/नीचे तीर नहीं, कोई टैब पूरा नहीं होता है)।

यदि मैं cli.pause() लाइन को अनमोल करता हूं, तो टीटीई विम में ठीक है, लेकिन मैं सम्मिलित मोड में फंस गया हूं, और Esc कुंजी काम नहीं करता है। अगर मैंने Ctrl-C मारा तो यह बच्चे और अभिभावक प्रक्रिया को छोड़ देता है।

+0

आप उपयोग के मामले पर कुछ प्रकाश डाला सकता है? क्या आप अपने आदेशों को चलाकर या डिस्क पर फ़ाइल लिखकर विम से बातचीत करना चाहते हैं? –

+0

क्या उपयोगकर्ता को सामग्री बनाने के लिए संपादक का उपयोग करने के लिए कहने का इरादा है? या आप 'vode' को पूरी तरह से 'node.js' के भीतर से ड्राइव करने का इरादा रखते हैं? – sarnold

+0

मैं 'vim' खोलने में सक्षम होना चाहता हूं ताकि मैं सामग्री बना सकूं, और जब समाप्त हो जाए, बाहर निकलें, और नोड अस्थायी फ़ाइल की सामग्री को पकड़ ले, जिसे मैं नोड से HTTP अनुरोध के हिस्से के रूप में भेजूंगा। – mkopala

उत्तर

9

अद्यतन: मेरा उत्तर उस समय लागू हुआ जब यह बनाया गया था, लेकिन नोड के आधुनिक संस्करणों के लिए, this other answer देखें।

सबसे पहले, स्पॉन का उपयोग सही नहीं है। यहां दस्तावेज़ हैं। http://nodejs.org/docs/latest/api/child_processes.html#child_process.spawn

आपका नमूना कोड ऐसा लगता है कि आप स्वचालित रूप से पॉप अप करने और टर्मिनल को लेने की अपेक्षा करते हैं, लेकिन ऐसा नहीं होगा। याद रखने की महत्वपूर्ण बात यह है कि भले ही आप किसी प्रक्रिया को जन्म दे सकें, यह सुनिश्चित करने के लिए आप पर निर्भर है कि प्रक्रिया से डेटा इसे आपके टर्मिनल के प्रदर्शन के लिए बनाता है।

इस मामले में, आपको stdin से डेटा लेने और इसे vim पर भेजने की आवश्यकता है, और आपको vim द्वारा डेटा आउटपुट लेने और इसे अपने टर्मिनल पर सेट करने की आवश्यकता है, अन्यथा आप कुछ भी नहीं देखेंगे। आपको टीटी को कच्चे मोड में सेट करने की भी आवश्यकता है, अन्यथा नोड कुछ प्रमुख अनुक्रमों को रोक देगा, इसलिए विम ठीक से व्यवहार नहीं करेगा।

अगला, पढ़ा नहीं FileSync। यदि आप ऐसे मामले पर आते हैं जहां आपको लगता है कि आपको सिंक विधि का उपयोग करने की आवश्यकता है, तो संभावना है कि आप कुछ गलत कर रहे हैं।

यहां एक त्वरित उदाहरण है जिसे मैंने एक साथ रखा है। मैं इसे हर मामले में काम करने के लिए झुका नहीं सकता, लेकिन इसमें ज्यादातर मामलों को शामिल करना चाहिए।

var tty = require('tty'); 
var child_process = require('child_process'); 
var fs = require('fs'); 

function spawnVim(file, cb) { 
    var vim = child_process.spawn('vim', [file]) 

    function indata(c) { 
    vim.stdin.write(c); 
    } 
    function outdata(c) { 
    process.stdout.write(c); 
    } 

    process.stdin.resume(); 
    process.stdin.on('data', indata); 
    vim.stdout.on('data', outdata); 
    tty.setRawMode(true); 

    vim.on('exit', function(code) { 
    tty.setRawMode(false); 
    process.stdin.pause(); 
    process.stdin.removeListener('data', indata); 
    vim.stdout.removeListener('data', outdata); 

    cb(code); 
    }); 
} 

var filename = '/tmp/somefile.txt'; 

spawnVim(filename, function(code) { 
    if (code == 0) { 
    fs.readFile(filename, function(err, data) { 
     if (!err) { 
     console.log(data.toString()); 
     } 
    }); 
    } 
}); 

अद्यतन

मैं seeee। मुझे नहीं लगता कि रीडलाइन इस सब के साथ संगत है जैसा कि आप दुर्भाग्य से चाहते हैं। मुद्दा यह है कि जब आप इंटरफेस बनाते हैं, तो नोड का मानना ​​है कि उस बिंदु से उस धारा से पूर्ण नियंत्रण होगा।जब हम उस डेटा को vim पर रीडायरेक्ट करते हैं, तो रीडलाइन अभी भी प्रसंस्करण कीप्रेस है, लेकिन विम भी वही काम कर रहा है।

मेरे द्वारा देखे जाने वाले एकमात्र तरीका यह है कि आप vim शुरू करने से पहले cli इंटरफ़ेस से मैन्युअल रूप से सब कुछ अक्षम कर दें।

प्रक्रिया को बढ़ाने से ठीक पहले, हमें इंटरफ़ेस को बंद करने की आवश्यकता है, और दुर्भाग्यवश मैन्युअल रूप से कीप्रेस श्रोता को हटा दें क्योंकि कम से कम इस समय, नोड स्वचालित रूप से इसे हटा नहीं देता है।

process.stdin.removeAllListeners 'keypress' 
cli.close() 
tty.setRawMode true 

फिर प्रक्रिया में 'बाहर निकलें' कॉलबैक में, आपको फिर से CreateInterface को कॉल करने की आवश्यकता होगी।

+1

यह लगभग काम कर रहा है। पहली समस्या यह है कि विम के लिए कुछ सेकंड लगते हैं, और यह टर्मिनल में केवल आधा स्क्रीन है। दूसरा, टीटीवी भी मेकअप किया गया है। टाइप करने के बाद 'iThis संपादक का एक परीक्षण है' यह 'टीटीआई आई टेस ओ वें संपादक' दिखाता है। फ़ाइल सामग्री से बाहर निकलने और प्रदर्शित करने से सही स्ट्रिंग दिखाई देती है। – mkopala

+1

मैं जिस प्रोग्राम का उपयोग कर रहा हूं वह एक एपीआई के लिए एक एकल उपयोगकर्ता कमांड लाइन क्लाइंट है, इसलिए मैंने 'readFileSync' का उपयोग किया। कॉलबैक छोड़कर कोड को थोड़ा सा सरल बनाता है। असल में, यह सभी कोड सिंक्रोनस के लिए शायद आसान होगा ... लेकिन यह अब मुझे मिला है। – mkopala

+1

फिर भी, readFileSync खराब रूप है। यदि आप नोड का उपयोग करने जा रहे हैं, तो आप इसे सही भी कर सकते हैं। मुझे नहीं पता कि यह आपके लिए इतनी अजीब क्यों दिख रहा है। क्या आप नैनो की तरह एक साधारण संपादक का उपयोग करने का प्रयास कर सकते हैं? मेरा विम निश्चित रूप से आपके से बेहतर काम करता है, लेकिन मेरी बैकस्पेस कुंजी काम नहीं करती है और मुझे लगता है कि यह काम नहीं कर रहा है, लेकिन यह नैनो में काम करता है। क्या आप उस मुद्दे को मेरे द्वारा पोस्ट किए गए सटीक कोड के साथ प्राप्त कर रहे हैं, या आपने इसे अपने कोड में एकीकृत किया है? हो सकता है कि आप जिस कोड का उपयोग कर रहे हैं उसे अधिक पोस्ट करें? – loganfsmyth

26

बस मुख्य प्रक्रिया से stdio का उत्तराधिकारी।

var editor = process.env.EDITOR || 'vi'; 

var child = child_process.spawn(editor, ['/tmp/somefile.txt'], { 
    stdio: 'inherit' 
}); 

child.on('exit', function (e, code) { 
    console.log("finished"); 
}); 

अधिक विकल्प: http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

+3

यह एक नया और बहुत आसान जवाब प्रतीत होता है! –

+0

2015 के अंत तक वर्तमान नोडजेज़ रिलीज पर यह सही समाधान है।वर्तमान में 'सही' के रूप में चिह्नित अन्य उत्तर अब काम नहीं करेगा। –

+0

मुझे लगता है कि यह एक 'वर्ग' में ऐसा करने का उदाहरण है: https://gist.github.com/56c65f8608781dbd88ef – Sukima

संबंधित मुद्दे