قراءة السطر
المصدر: lib/readline.js
يوفر مُعامل node:readline
واجهة لقراءة البيانات من دفق قابل للقراءة (مثل process.stdin
) سطرًا واحدًا في كل مرة.
لاستخدام واجهات برمجة التطبيقات القائمة على الوعود:
import * as readline from 'node:readline/promises'
const readline = require('node:readline/promises')
لاستخدام واجهات برمجة التطبيقات المتزامنة وواجهات برمجة التطبيقات القائمة على المُنعطفات:
import * as readline from 'node:readline'
const readline = require('node:readline')
يوضح المثال البسيط التالي الاستخدام الأساسي لمعامل node:readline
.
import * as readline from 'node:readline/promises'
import { stdin as input, stdout as output } from 'node:process'
const rl = readline.createInterface({ input, output })
const answer = await rl.question('What do you think of Node.js? ')
console.log(`Thank you for your valuable feedback: ${answer}`)
rl.close()
const readline = require('node:readline')
const { stdin: input, stdout: output } = require('node:process')
const rl = readline.createInterface({ input, output })
rl.question('What do you think of Node.js? ', answer => {
// TODO: تسجيل الإجابة في قاعدة بيانات
console.log(`Thank you for your valuable feedback: ${answer}`)
rl.close()
})
بمجرد استدعاء هذا الرمز، لن ينتهي تطبيق Node.js حتى يتم إغلاق readline.Interface
لأن الواجهة تنتظر استلام البيانات على دفق input
.
فئة: InterfaceConstructor
مضاف في: v0.1.104
- يمتد: <EventEmitter>
يتم إنشاء مثيلات فئة InterfaceConstructor
باستخدام طريقة readlinePromises.createInterface()
أو readline.createInterface()
. يرتبط كل مثال بدفق إدخال واحد input
قابل للقراءة ودفق إخراج واحد output
قابل للكتابة. يتم استخدام دفق output
لطباعة المطالبات لإدخال المستخدم الذي يصل إلى دفق input
ويتم قراءته منه.
حدث: 'close'
مضاف في: v0.1.98
يُصدر حدث 'close'
عندما يحدث أحد الأمور التالية:
- يتم استدعاء طريقة
rl.close()
ويكون مثيلInterfaceConstructor
قد تخلى عن التحكم في تدفقات الإدخالinput
والإخراجoutput
؛ - تتلقى دفق الإدخال
input
حدث'end'
الخاص به؛ - تتلقى دفق الإدخال
input
+ للإشارة إلى نهاية الإرسال (EOT)؛ - تتلقى دفق الإدخال
input
+ للإشارة إلىSIGINT
ولا يوجد مستمع لحدث'SIGINT'
مسجل على مثيلInterfaceConstructor
.
يتم استدعاء دالة المستمع بدون تمرير أي وسيطات.
يُكتمل مثيل InterfaceConstructor
بمجرد إصدار حدث 'close'
.
حدث: 'line'
مضاف في: v0.1.98
يُصدر حدث 'line'
كلما تلقى دفق الإدخال input
إدخال نهاية السطر (\n
، \r
، أو \r\n
). يحدث هذا عادةً عندما يضغط المستخدم أو .
كما يتم إصدار حدث 'line'
إذا تم قراءة بيانات جديدة من دفق وينتهي هذا الدفق بدون علامة نهاية سطر نهائية.
يتم استدعاء دالة المستمع مع سلسلة تحتوي على سطر واحد من الإدخال المستقبَل.
rl.on('line', input => {
console.log(`Received: ${input}`)
})
حدث: 'history'
مضاف في: v15.8.0، v14.18.0
يُصدر حدث 'history'
كلما تغيرت مصفوفة السجل.
يتم استدعاء دالة المستمع مع مصفوفة تحتوي على مصفوفة السجل. ستُعكس جميع التغييرات، الأسطر المضافة والأسطر المُزالة بسبب historySize
و removeHistoryDuplicates
.
الهدف الأساسي هو السماح للمستمع بالاحتفاظ بالسجل. من الممكن أيضًا أن يغيّر المستمع كائن السجل. قد يكون هذا مفيدًا لمنع إضافة أسطر معينة إلى السجل، مثل كلمة المرور.
rl.on('history', history => {
console.log(`Received: ${history}`)
})
حدث: 'pause'
مضاف في: v0.7.5
يُصدر حدث 'pause'
عندما يحدث أحد الأمور التالية:
- يتم إيقاف دفق الإدخال
input
. - لا يتم إيقاف دفق الإدخال
input
ويتلقى حدث'SIGCONT'
. (انظر الأحداث'SIGTSTP'
و'SIGCONT'
.)
يتم استدعاء دالة المستمع بدون تمرير أي وسيطات.
rl.on('pause', () => {
console.log('Readline paused.')
})
حدث: 'resume'
تم الإضافة في: v0.7.5
يتم إرسال حدث 'resume'
كلما تم استئناف دفق input
.
يتم استدعاء دالة المُستمع بدون تمرير أي وسيطات.
rl.on('resume', () => {
console.log('Readline resumed.')
})
حدث: 'SIGCONT'
تم الإضافة في: v0.7.5
يتم إرسال حدث 'SIGCONT'
عندما يتم إرجاع عملية Node.js التي تم نقلها مسبقًا إلى الخلفية باستخدام + (أي SIGTSTP
) إلى المقدمة باستخدام fg(1p)
.
إذا تم إيقاف دفق input
قبل طلب SIGTSTP
، فلن يتم إرسال هذا الحدث.
يتم استدعاء دالة المُستمع بدون تمرير أي وسيطات.
rl.on('SIGCONT', () => {
// `prompt` سيُعيد استئناف الدفق تلقائيًا
rl.prompt()
})
حدث 'SIGCONT'
غير مدعوم على Windows.
حدث: 'SIGINT'
تم الإضافة في: v0.3.0
يتم إرسال حدث 'SIGINT'
كلما تلقى دفق input
إدخالًا، يُعرف عادةً باسم SIGINT
. إذا لم تكن هناك مُستمعات لحدث 'SIGINT'
مسجلة عندما يتلقى دفق input
إشارة SIGINT
، فسيتم إرسال حدث 'pause'
.
يتم استدعاء دالة المُستمع بدون تمرير أي وسيطات.
rl.on('SIGINT', () => {
rl.question('Are you sure you want to exit? ', answer => {
if (answer.match(/^y(es)?$/i)) rl.pause()
})
})
حدث: 'SIGTSTP'
تم الإضافة في: v0.7.5
يتم إرسال حدث 'SIGTSTP'
عندما يتلقى دفق input
إدخالًا +، يُعرف عادةً باسم SIGTSTP
. إذا لم تكن هناك مُستمعات لحدث 'SIGTSTP'
مسجلة عندما يتلقى دفق input
إشارة SIGTSTP
، فسيتم إرسال عملية Node.js إلى الخلفية.
عندما يتم استئناف البرنامج باستخدام fg(1p)
، سيتم إرسال حدثي 'pause'
و 'SIGCONT'
. ويمكن استخدام هذين الحدثين لاستئناف دفق input
.
لن يتم إرسال حدثي 'pause'
و 'SIGCONT'
إذا تم إيقاف input
قبل إرسال العملية إلى الخلفية.
يتم استدعاء دالة المُستمع بدون تمرير أي وسيطات.
rl.on('SIGTSTP', () => {
// هذا سيُلغي SIGTSTP ويمنع البرنامج من الانتقال إلى الخلفية.
console.log('Caught SIGTSTP.')
})
حدث 'SIGTSTP'
غير مدعوم على Windows.
rl.close()
مضاف في: v0.1.98
تقوم طريقة rl.close()
بإغلاق مثيل InterfaceConstructor
والتخلي عن التحكم في تدفقات الإدخال (input
) والإخراج (output
). عند استدعائها، سيتم إصدار حدث 'close'
.
إن استدعاء rl.close()
لا يوقف على الفور الأحداث الأخرى (بما في ذلك 'line'
) من أن يتم إصدارها بواسطة مثيل InterfaceConstructor
.
rl.pause()
مضاف في: v0.3.4
تقوم طريقة rl.pause()
بإيقاف تدفق الإدخال (input
) مؤقتًا، مما يسمح باستئنافه لاحقًا إذا لزم الأمر.
إن استدعاء rl.pause()
لا يوقف على الفور الأحداث الأخرى (بما في ذلك 'line'
) من أن يتم إصدارها بواسطة مثيل InterfaceConstructor
.
rl.prompt([preserveCursor])
مضاف في: v0.1.98
preserveCursor
<boolean> إذا كانتtrue
، تمنع إعادة تعيين موضع المؤشر إلى0
.
تقوم طريقة rl.prompt()
بكتابة prompt
المُهيأ لمثيلات InterfaceConstructor
في سطر جديد في output
لتزويد المستخدم بموقع جديد لتقديم الإدخال.
عند استدعائها، ستستأنف rl.prompt()
تدفق الإدخال (input
) إذا تم إيقافه مؤقتًا.
إذا تم إنشاء InterfaceConstructor
مع تعيين output
إلى null
أو undefined
، فلن يتم كتابة الموجه.
rl.resume()
مضاف في: v0.3.4
تقوم طريقة rl.resume()
باستئناف تدفق الإدخال (input
) إذا تم إيقافه مؤقتًا.
rl.setPrompt(prompt)
مضاف في: v0.1.98
prompt
<string>
تقوم طريقة rl.setPrompt()
بتعيين الموجه الذي سيتم كتابته إلى output
كلما تم استدعاء rl.prompt()
.
rl.getPrompt()
مضاف في: v15.3.0، v14.17.0
- المُرجَع: <string> سلسلة الموجه الحالية
تقوم طريقة rl.getPrompt()
بإرجاع الموجه الحالي الذي تستخدمه rl.prompt()
.
rl.write(data[, key])
مضاف في: v0.1.98
تقوم طريقة rl.write()
بكتابة data
أو تسلسل مفاتيح مُحدد بواسطة key
إلى output
. يتم دعم وسيطة key
فقط إذا كان output
عبارة عن وحدة طرفية نصية TTY. راجع ربطات مفاتيح TTY للحصول على قائمة بتركيبات المفاتيح.
إذا تم تحديد key
، فسيتم تجاهل data
.
عند استدعائها، ستستأنف rl.write()
تدفق الإدخال (input
) إذا تم إيقافه مؤقتًا.
إذا تم إنشاء InterfaceConstructor
مع تعيين output
إلى null
أو undefined
، فلن يتم كتابة data
و key
.
rl.write('Delete this!')
// محاكاة Ctrl+U لحذف السطر المكتوب سابقًا
rl.write(null, { ctrl: true, name: 'u' })
ستقوم طريقة rl.write()
بكتابة البيانات إلى إدخال readline
Interface
كما لو تم تقديمها من قبل المستخدم.
rl[Symbol.asyncIterator]()
[History]
الإصدار | التغييرات |
---|---|
v11.14.0, v10.17.0 | لم يعد دعم Symbol.asyncIterator تجريبيًا. |
v11.4.0, v10.16.0 | تمت الإضافة في: v11.4.0, v10.16.0 |
- الإرجاع: <AsyncIterator>
إنشاء كائن AsyncIterator
الذي يتكرر عبر كل سطر في دفق الإدخال كسلسلة. تسمح هذه الطريقة بالتكرار غير المتزامن لأشياء InterfaceConstructor
من خلال حلقات for await...of
.
لا يتم إعادة توجيه الأخطاء في دفق الإدخال.
إذا تم إنهاء الحلقة باستخدام break
أو throw
أو return
، فسيتم استدعاء rl.close()
. بعبارة أخرى، فإن التكرار فوق InterfaceConstructor
سيستهلك دائمًا دفق الإدخال بالكامل.
الأداء ليس على قدم المساواة مع واجهة برمجة التطبيقات التقليدية لحدث 'line'
. استخدم 'line'
بدلاً من ذلك للتطبيقات الحساسة للأداء.
async function processLineByLine() {
const rl = readline.createInterface({
// ...
})
for await (const line of rl) {
// كل سطر في إدخال readline سيكون متاحًا تباعًا هنا كـ
// `line`.
}
}
سيبدأ readline.createInterface()
في استهلاك دفق الإدخال بمجرد استدعائه. قد يؤدي وجود عمليات غير متزامنة بين إنشاء الواجهة والتكرار غير المتزامن إلى فقدان الأسطر.
rl.line
[History]
الإصدار | التغييرات |
---|---|
v15.8.0, v14.18.0 | ستكون القيمة دائمًا سلسلة، وليس غير معرفة. |
v0.1.98 | تمت الإضافة في: v0.1.98 |
بيانات الإدخال الحالية التي تتم معالجتها بواسطة العقدة.
يمكن استخدام هذا عند جمع الإدخال من دفق TTY لاسترداد القيمة الحالية التي تم معالجتها حتى الآن، قبل إصدار حدث line
. بمجرد إصدار حدث line
، ستكون هذه الخاصية سلسلة فارغة.
كن على دراية بأن تعديل القيمة أثناء وقت تشغيل مثيل قد يكون له عواقب غير مقصودة إذا لم يتم التحكم في rl.cursor
أيضًا.
إذا لم يتم استخدام دفق TTY للإدخال، فاستخدم حدث 'line'
.
إحدى حالات الاستخدام الممكنة ستكون كما يلي:
const values = ['lorem ipsum', 'dolor sit amet']
const rl = readline.createInterface(process.stdin)
const showResults = debounce(() => {
console.log('\n', values.filter(val => val.startsWith(rl.line)).join(' '))
}, 300)
process.stdin.on('keypress', (c, k) => {
showResults()
})
rl.cursor
مضاف في: v0.1.98
موضع المؤشر بالنسبة إلى rl.line
.
سيتعقب هذا المكان الذي يهبط فيه المؤشر الحالي في سلسلة الإدخال، عند قراءة الإدخال من دفق TTY. يحدد موضع المؤشر جزء سلسلة الإدخال الذي سيتم تعديله أثناء معالجة الإدخال، بالإضافة إلى العمود الذي سيتم عرض مؤشر المحطة الطرفية فيه.
rl.getCursorPos()
مضاف في: v13.5.0، v12.16.0
- يعيد: <Object>
يعيد الموضع الحقيقي للمؤشر بالنسبة إلى مطالبة الإدخال + السلسلة. يتم تضمين سلاسل الإدخال الطويلة (التفاف) بالإضافة إلى مطالبات متعددة الأسطر في الحسابات.
واجهة برمجة التطبيقات للوعود
مضاف في: v17.0.0
[مستقر: 1 - تجريبي]
مستقر: 1 استقرار: 1 - تجريبي
الفئة: readlinePromises.Interface
مضاف في: v17.0.0
يتم إنشاء مثيلات من فئة readlinePromises.Interface
باستخدام طريقة readlinePromises.createInterface()
. يرتبط كل مثال بدفق input
قابل للقراءة واحد وبدفق output
قابل للكتابة واحد. يتم استخدام دفق output
لطباعة مطالبات إدخال المستخدم التي تصل إلى دفق input
، ويتم قراءتها منه.
rl.question(query[, options])
مضاف في: v17.0.0
query
<string> عبارة أو استعلام لكتابته إلىoutput
، تُضاف قبل المطالَب.options
<Object>signal
<AbortSignal> يسمح بشكل اختياري بإلغاءquestion()
باستخدامAbortSignal
.
قيمة الإرجاع: <Promise> وعد يتم الوفاء به بإدخال المستخدم استجابةً لـ
query
.
تعرض طريقة rl.question()
query
بكتابتها إلى output
، وتنتظر إدخال المستخدم على input
، ثم تقوم باستدعاء دالة callback
بإعطاء الإدخال المُقدم كأول وسيطة.
عند النداء، ستستأنف rl.question()
تدفق input
إذا تم إيقافه مؤقتًا.
إذا تم إنشاء readlinePromises.Interface
مع تعيين output
إلى null
أو undefined
، فلن يتم كتابة query
.
إذا تم استدعاء السؤال بعد rl.close()
، فإنه يُرجع وعدًا مرفوضًا.
مثال على الاستخدام:
const answer = await rl.question('ما هو طعامك المفضل؟ ')
console.log(`أوه، إذن طعامك المفضل هو ${answer}`)
استخدام AbortSignal
لإلغاء سؤال.
const signal = AbortSignal.timeout(10_000)
signal.addEventListener(
'abort',
() => {
console.log('انتهى وقت سؤال الطعام')
},
{ once: true }
)
const answer = await rl.question('ما هو طعامك المفضل؟ ', { signal })
console.log(`أوه، إذن طعامك المفضل هو ${answer}`)
Class: readlinePromises.Readline
مضاف في: v17.0.0
new readlinePromises.Readline(stream[, options])
مضاف في: v17.0.0
stream
<stream.Writable> تدفق TTY.options
<Object>autoCommit
<boolean> إذا كانتtrue
، فلا حاجة إلى استدعاءrl.commit()
.
rl.clearLine(dir)
مضاف في: v17.0.0
dir
<عدد صحيح>-1
: إلى اليسار من المؤشر1
: إلى اليمين من المؤشر0
: السطر بأكمله
قيمة الإرجاع: this
تضيف طريقة rl.clearLine()
إلى القائمة الداخلية للإجراءات المعلقة إجراءً يمسح السطر الحالي للـ stream
المرتبط في اتجاه محدد يتم تحديده بواسطة dir
. اتصل بـ rl.commit()
لرؤية تأثير هذه الطريقة، ما لم يتم تمرير autoCommit: true
إلى المُنشئ.
rl.clearScreenDown()
مضاف في: v17.0.0
- قيمة الإرجاع: this
تضيف طريقة rl.clearScreenDown()
إلى القائمة الداخلية للإجراءات المعلقة إجراءً يمسح stream
المرتبط من الموضع الحالي للمؤشر إلى الأسفل. اتصل بـ rl.commit()
لرؤية تأثير هذه الطريقة، ما لم يتم تمرير autoCommit: true
إلى المُنشئ.
rl.commit()
مضاف في: v17.0.0
- قيمة الإرجاع: <وعد>
ترسل طريقة rl.commit()
جميع الإجراءات المعلقة إلى stream
المرتبط وتُمسح القائمة الداخلية للإجراءات المعلقة.
rl.cursorTo(x[, y])
مضاف في: v17.0.0
x
<عدد صحيح>y
<عدد صحيح>- قيمة الإرجاع: this
تضيف طريقة rl.cursorTo()
إلى القائمة الداخلية للإجراءات المعلقة إجراءً ينقل المؤشر إلى الموضع المحدد في stream
المرتبط. اتصل بـ rl.commit()
لرؤية تأثير هذه الطريقة، ما لم يتم تمرير autoCommit: true
إلى المُنشئ.
rl.moveCursor(dx, dy)
مضاف في: v17.0.0
dx
<عدد صحيح>dy
<عدد صحيح>- قيمة الإرجاع: this
تضيف طريقة rl.moveCursor()
إلى القائمة الداخلية للإجراءات المعلقة إجراءً ينقل المؤشر بشكل نسبي إلى موضعه الحالي في stream
المرتبط. اتصل بـ rl.commit()
لرؤية تأثير هذه الطريقة، ما لم يتم تمرير autoCommit: true
إلى المُنشئ.
rl.rollback()
مضاف في: v17.0.0
- قيمة الإرجاع: this
تقوم طرق rl.rollback
بمسح القائمة الداخلية من الإجراءات المعلقة بدون إرسالها إلى stream
المرتبط.
readlinePromises.createInterface(options)
مضاف في: v17.0.0
options
<Object>input
<stream.Readable> تدفق قابل للقراءة للاستماع إليه. هذا الخيار مطلوب.output
<stream.Writable> تدفق قابل للكتابة لكتابة بيانات readline إليه.completer
<Function> دالة اختيارية تُستخدم لإكمال علامات التبويب تلقائيًا.terminal
<boolean>true
إذا كان يجب التعامل مع تدفقاتinput
وoutput
مثل TTY، وكتابة أكواد ANSI/VT100 المُهربة إليها. الافتراضي: التحقق منisTTY
على تدفقoutput
عند إنشاء مثيل.history
<string[]> القائمة الأولية لسطور التاريخ. هذا الخيار منطقي فقط إذا تم تعيينterminal
علىtrue
من قبل المستخدم أو عن طريق فحص داخلي لـoutput
، وإلا فلن يتم تهيئة آلية تخزين التاريخ على الإطلاق. الافتراضي:[]
.historySize
<number> الحد الأقصى لعدد سطور التاريخ المُحتفظ بها. لإلغاء تمكين التاريخ، عيّن هذه القيمة على0
. هذا الخيار منطقي فقط إذا تم تعيينterminal
علىtrue
من قبل المستخدم أو عن طريق فحص داخلي لـoutput
، وإلا فلن يتم تهيئة آلية تخزين التاريخ على الإطلاق. الافتراضي:30
.removeHistoryDuplicates
<boolean> إذا كانtrue
، عندما يُضاف سطر إدخال جديد إلى قائمة التاريخ يُكرر سطرًا أقدم، فهذا سيُزيل السطر الأقدم من القائمة. الافتراضي:false
.prompt
<string> سلسلة المطالبة التي سيتم استخدامها. الافتراضي:'\> '
.crlfDelay
<number> إذا تجاوز التأخير بين\r
و\n
crlfDelay
ميلي ثانية، فسيتم التعامل مع كل من\r
و\n
كمدخل منفصل لنهاية السطر. سيتم إجبارcrlfDelay
على رقم لا يقل عن100
. يمكن تعيينه علىInfinity
، وفي هذه الحالة سيتم دائمًا اعتبار\r
متبوعًا بـ\n
فاصل سطر واحد (وهو ما قد يكون معقولاً لـ قراءة الملفات باستخدام فاصل سطر\r\n
). الافتراضي:100
.escapeCodeTimeout
<number> المدة التي سينتظرهاreadlinePromises
حرفًا (عند قراءة تسلسل مفتاح غامض بالميلي ثانية، وهو ما يمكن أن يشكل كل من تسلسل مفتاح كامل باستخدام الإدخال الذي تم قراءته حتى الآن ويمكنه أخذ إدخال إضافي لإكمال تسلسل مفتاح أطول). الافتراضي:500
.tabSize
<integer> عدد المسافات التي تساوي علامة التبويب (الحد الأدنى 1). الافتراضي:8
.
قيمة الإرجاع: <readlinePromises.Interface>
تقوم طريقة readlinePromises.createInterface()
بإنشاء مثيل جديد من readlinePromises.Interface
.
import { createInterface } from 'node:readline/promises'
import { stdin, stdout } from 'node:process'
const rl = createInterface({
input: stdin,
output: stdout,
})
const { createInterface } = require('node:readline/promises')
const rl = createInterface({
input: process.stdin,
output: process.stdout,
})
بمجرد إنشاء مثيل readlinePromises.Interface
، تكون الحالة الأكثر شيوعًا هي الاستماع إلى حدث 'line'
:
rl.on('line', line => {
console.log(`Received: ${line}`)
})
إذا كانت قيمة terminal
هي true
لهذا المثيل، فسيكون لتدفق output
أفضل توافق إذا عرّف خاصية output.columns
وأصدر حدث 'resize'
على output
إذا أو عندما تتغير الأعمدة (process.stdout
يفعل هذا تلقائيًا عندما يكون TTY).
استخدام دالة completer
تأخذ دالة completer
السطر الحالي الذي أدخله المستخدم كوسيط، وتعيد مصفوفة تحتوي على مُدخلين:
- مصفوفة تحتوي على مُدخِلات مُطابقة للإكمال.
- السلسلة الفرعية التي تم استخدامها للمطابقة.
على سبيل المثال: [[substr1, substr2, ...], originalsubstring]
.
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ')
const hits = completions.filter(c => c.startsWith(line))
// عرض جميع عمليات الإكمال إذا لم يتم العثور على أي شيء
return [hits.length ? hits : completions, line]
}
يمكن لدالة completer
أيضًا إعادة <Promise>، أو أن تكون غير متزامنة:
async function completer(linePartial) {
await someAsyncWork()
return [['123'], linePartial]
}
واجهة برمجة التطبيقات للاستدعاء العكسي
تمت الإضافة في: v0.1.104
الفئة: readline.Interface
[السجل]
الإصدار | التغييرات |
---|---|
v17.0.0 | الآن ترث الفئة readline.Interface من Interface . |
v0.1.104 | تمت الإضافة في: v0.1.104 |
يتم إنشاء مثيلات فئة readline.Interface
باستخدام طريقة readline.createInterface()
. كل مثيل مرتبط بتيار إدخال input
واحد قابل للقراءة وتيار إخراج output
واحد قابل للكتابة. يتم استخدام تيار output
لطباعة مطالبات إدخال المستخدم التي تصل إلى تيار input
، ويتم قراءتها منه.
rl.question(query[, options], callback)
تمت الإضافة في: v0.3.3
query
<string> عبارة أو استعلام لكتابته إلىoutput
، يتم وضعه قبل المطالبة.options
<Object>signal
<AbortSignal> يسمح بشكل اختياري بإلغاءquestion()
باستخدامAbortController
.
callback
<Function> دالة استدعاء عكسي يتم استدعاؤها مع إدخال المستخدم استجابةً لـquery
.
تُعرض طريقة rl.question()
الاستعلام query
من خلال كتابته إلى output
، وتنتظر إدخال المستخدم الذي سيتم توفيره على input
، ثم تستدعي دالة callback
وتمرر الإدخال المُقدم كوسيط أول.
عند استدعائها، ستستأنف rl.question()
تيار input
إذا تم إيقافه مؤقتًا.
إذا تم إنشاء readline.Interface
مع تعيين output
إلى null
أو undefined
، فلن يتم كتابة query
.
لا تتبع دالة callback
المُمررة إلى rl.question()
النمط النموذجي المتمثل في قبول كائن Error
أو null
كوسيط أول. يتم استدعاء callback
مع الإجابة المُقدمة كوسيط وحيد.
سيتم إرسال خطأ إذا تم استدعاء rl.question()
بعد rl.close()
.
مثال على الاستخدام:
rl.question('What is your favorite food? ', answer => {
console.log(`Oh, so your favorite food is ${answer}`)
})
باستخدام AbortController
لإلغاء سؤال.
const ac = new AbortController()
const signal = ac.signal
rl.question('What is your favorite food? ', { signal }, answer => {
console.log(`Oh, so your favorite food is ${answer}`)
})
signal.addEventListener(
'abort',
() => {
console.log('The food question timed out')
},
{ once: true }
)
setTimeout(() => ac.abort(), 10000)
readline.clearLine(stream, dir[, callback])
[History]
الإصدار | التغييرات |
---|---|
v18.0.0 | يُلقي تمرير مُستدعي غير صالح إلى وسيطة callback الآن ERR_INVALID_ARG_TYPE بدلاً من ERR_INVALID_CALLBACK . |
v12.7.0 | يتم الكشف عن مُستدعي و قيمة الإرجاع لـ write() للدفق. |
v0.7.7 | تمت الإضافة في: v0.7.7 |
stream
<stream.Writable>dir
<number>-1
: إلى اليسار من المؤشر1
: إلى اليمين من المؤشر0
: السطر بأكمله
callback
<Function> يتم استدعاؤه بمجرد اكتمال العملية.القيمة المُرجعه: <boolean>
false
إذا كانstream
يرغب في أن تنتظر شفرة الاستدعاء حتى يتم إصدار حدث'drain'
قبل متابعة كتابة بيانات إضافية؛ خلاف ذلكtrue
.
طريقة readline.clearLine()
تقوم بمسح السطر الحالي من دفق TTY المُعطى في الاتجاه المحدد بواسطة dir
.
readline.clearScreenDown(stream[, callback])
[History]
الإصدار | التغييرات |
---|---|
v18.0.0 | يُلقي تمرير مُستدعي غير صالح إلى وسيطة callback الآن ERR_INVALID_ARG_TYPE بدلاً من ERR_INVALID_CALLBACK . |
v12.7.0 | يتم الكشف عن مُستدعي و قيمة الإرجاع لـ write() للدفق. |
v0.7.7 | تمت الإضافة في: v0.7.7 |
stream
<stream.Writable>callback
<Function> يتم استدعاؤه بمجرد اكتمال العملية.- القيمة المُرجعه: <boolean>
false
إذا كانstream
يرغب في أن تنتظر شفرة الاستدعاء حتى يتم إصدار حدث'drain'
قبل متابعة كتابة بيانات إضافية؛ خلاف ذلكtrue
.
طريقة readline.clearScreenDown()
تقوم بمسح دفق TTY المُعطى من الموضع الحالي للمؤشر إلى الأسفل.
readline.createInterface(options)
[السجل]
الإصدار | التغييرات |
---|---|
v15.14.0، v14.18.0 | أصبح خيار signal مدعومًا الآن. |
v15.8.0، v14.18.0 | أصبح خيار history مدعومًا الآن. |
v13.9.0 | أصبح خيار tabSize مدعومًا الآن. |
v8.3.0، v6.11.4 | إزالة الحد الأقصى لخيار crlfDelay . |
v6.6.0 | أصبح خيار crlfDelay مدعومًا الآن. |
v6.3.0 | أصبح خيار prompt مدعومًا الآن. |
v6.0.0 | يمكن أن يكون خيار historySize مساويًا لـ 0 الآن. |
v0.1.98 | تمت الإضافة في: v0.1.98 |
options
<Object>input
<stream.Readable> تدفق قابل للقراءة للاستماع إليه. هذا الخيار مطلوب.output
<stream.Writable> تدفق قابل للكتابة لكتابة بيانات readline إليه.completer
<Function> دالة اختيارية تُستخدم لإكمال علامات التبويب تلقائيًا.terminal
<boolean>true
إذا كان يجب التعامل مع تياراتinput
وoutput
مثل TTY، وكتابة رموز الإفلات ANSI/VT100 إليها. الافتراضي: التحقق منisTTY
على دفقoutput
عند إنشاء مثيل.history
<string[]> القائمة الأولية لسطور التاريخ. يكون هذا الخيار منطقيًا فقط إذا تم تعيينterminal
علىtrue
بواسطة المستخدم أو بواسطة فحص داخلي لـoutput
، وإلا فلن يتم تهيئة آلية تخزين التاريخ على الإطلاق. الافتراضي:[]
.historySize
<number> الحد الأقصى لعدد أسطر التاريخ التي يتم الاحتفاظ بها. لإلغاء تمكين التاريخ، عيّن هذه القيمة على0
. يكون هذا الخيار منطقيًا فقط إذا تم تعيينterminal
علىtrue
بواسطة المستخدم أو بواسطة فحص داخلي لـoutput
، وإلا فلن يتم تهيئة آلية تخزين التاريخ على الإطلاق. الافتراضي:30
.removeHistoryDuplicates
<boolean> إذا كانtrue
، فعندما يتم إضافة سطر إدخال جديد إلى قائمة التاريخ يكرر سطرًا أقدم، فسيتم إزالة السطر الأقدم من القائمة. الافتراضي:false
.prompt
<string> سلسلة المطالبة التي سيتم استخدامها. الافتراضي:'\> '
.crlfDelay
<number> إذا تجاوز التأخير بين\r
و\n
crlfDelay
ميلي ثانية، فسيتم التعامل مع كل من\r
و\n
كمدخل منفصل لنهاية السطر. سيتم إجبارcrlfDelay
على رقم لا يقل عن100
. يمكن تعيينه علىInfinity
، وفي هذه الحالة سيتم اعتبار\r
متبوعًا بـ\n
دائمًا فاصل سطر واحد (وهو أمر معقول لـ قراءة الملفات باستخدام فاصل سطر\r\n
). الافتراضي:100
.escapeCodeTimeout
<number> المدة التي ينتظرهاreadline
حرفًا (عند قراءة تسلسل مفتاح غامض بالميلي ثانية، وهو ما يمكن أن يشكل تسلسل مفتاح كامل باستخدام الإدخال المقروء حتى الآن ويمكنه أخذ إدخال إضافي لإكمال تسلسل مفتاح أطول). الافتراضي:500
.tabSize
<integer> عدد المسافات التي تساوي علامة التبويب (الحد الأدنى 1). الافتراضي:8
.signal
<AbortSignal> يسمح بإغلاق الواجهة باستخدام AbortSignal. سيؤدي إلغاء الإشارة داخليًا إلى استدعاءclose
على الواجهة.
الإرجاع: <readline.Interface>
إن طريقة readline.createInterface()
تُنشئ مثيلًا جديدًا لـ readline.Interface
.
import { createInterface } from 'node:readline'
import { stdin, stdout } from 'node:process'
const rl = createInterface({
input: stdin,
output: stdout,
})
const { createInterface } = require('node:readline')
const rl = createInterface({
input: process.stdin,
output: process.stdout,
})
بمجرد إنشاء مثيل readline.Interface
، فإن الحالة الأكثر شيوعًا هي الاستماع إلى حدث 'line'
:
rl.on('line', line => {
console.log(`Received: ${line}`)
})
إذا كان terminal
يساوي true
لهذا المثال، فسوف يحصل دفق output
على أفضل توافق إذا عرّف خاصية output.columns
وأصدر حدث 'resize'
على output
إذا أو عندما تتغير الأعمدة (process.stdout
يفعل ذلك تلقائيًا عندما يكون TTY).
عند إنشاء readline.Interface
باستخدام stdin
كمدخل، فلن ينتهي البرنامج حتى يتلقى حرف EOF. للخروج دون انتظار إدخال المستخدم، اتصل بـ process.stdin.unref()
.
استخدام دالة completer
تأخذ دالة completer
السطر الحالي الذي أدخله المستخدم كوسيطة، وتعيد Array
يحتوي على مُدخلين:
Array
يحتوي على المُدخَلات المُطابقة للإكمال.- السلسلة الفرعية التي تم استخدامها للمطابقة.
على سبيل المثال: [[substr1, substr2, ...], originalsubstring]
.
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ')
const hits = completions.filter(c => c.startsWith(line))
// عرض جميع عمليات الإكمال إذا لم يتم العثور على أي منها
return [hits.length ? hits : completions, line]
}
يمكن استدعاء دالة completer
بشكل غير متزامن إذا كانت تقبل وسيطتين:
function completer(linePartial, callback) {
callback(null, [['123'], linePartial])
}
readline.cursorTo(stream, x[, y][, callback])
[History]
الإصدار | التغييرات |
---|---|
v18.0.0 | يؤدي تمرير مُنعطف غير صالح إلى وسيطة callback الآن إلى طرح ERR_INVALID_ARG_TYPE بدلاً من ERR_INVALID_CALLBACK . |
v12.7.0 | تم الكشف عن مُنعطف و قيمة الإرجاع لـ write() للدفق. |
v0.7.7 | تمت الإضافة في: v0.7.7 |
stream
<stream.Writable>x
<number>y
<number>callback
<Function> يتم استدعاء هذه الدالة بمجرد اكتمال العملية.- القيمة المُرجعّة: <boolean>
false
إذا كانstream
يرغب في أن ينتظر رمز الاستدعاء حدث'drain'
قبل المتابعة في كتابة بيانات إضافية؛ وإلاtrue
.
تُنقل طريقة readline.cursorTo()
المؤشر إلى الموضع المحدد في دفق TTY معين.
readline.moveCursor(stream, dx, dy[, callback])
[History]
الإصدار | التغييرات |
---|---|
v18.0.0 | يؤدي تمرير مُنعطف غير صالح إلى وسيطة callback الآن إلى طرح ERR_INVALID_ARG_TYPE بدلاً من ERR_INVALID_CALLBACK . |
v12.7.0 | تم الكشف عن مُنعطف و قيمة الإرجاع لـ write() للدفق. |
v0.7.7 | تمت الإضافة في: v0.7.7 |
stream
<stream.Writable>dx
<number>dy
<number>callback
<Function> يتم استدعاء هذه الدالة بمجرد اكتمال العملية.- القيمة المُرجعّة: <boolean>
false
إذا كانstream
يرغب في أن ينتظر رمز الاستدعاء حدث'drain'
قبل المتابعة في كتابة بيانات إضافية؛ وإلاtrue
.
تُنقل طريقة readline.moveCursor()
المؤشر بشكل نسبي إلى موضعه الحالي في دفق TTY معين.
readline.emitKeypressEvents(stream[, interface])
مضاف في: v0.7.7
stream
<stream.Readable>interface
<readline.InterfaceConstructor>
تتسبب طريقة readline.emitKeypressEvents()
في بدء تدفق قابل للقراءة المعطى في إصدار أحداث 'keypress'
التي تتوافق مع الإدخال المستلم.
اختياريًا، يحدد interface
مثيلًا لـ readline.Interface
يتم تعطيل الإكمال التلقائي له عند الكشف عن إدخال تم نسخه ولصقه.
إذا كان stream
عبارة عن TTY، فيجب أن يكون في الوضع الخام.
يتم استدعاء هذا تلقائيًا بواسطة أي مثيل readline على مُدخله input
إذا كان input
عبارة عن محطة طرفية. إن إغلاق مثيل readline
لا يوقف input
من إصدار أحداث 'keypress'
.
readline.emitKeypressEvents(process.stdin)
if (process.stdin.isTTY) process.stdin.setRawMode(true)
مثال: واجهة سطر أوامر صغيرة
يوضح المثال التالي استخدام فئة readline.Interface
لتنفيذ واجهة سطر أوامر صغيرة:
import { createInterface } from 'node:readline'
import { exit, stdin, stdout } from 'node:process'
const rl = createInterface({
input: stdin,
output: stdout,
prompt: 'OHAI> ',
})
rl.prompt()
rl.on('line', line => {
switch (line.trim()) {
case 'hello':
console.log('world!')
break
default:
console.log(`Say what? I might have heard '${line.trim()}'`)
break
}
rl.prompt()
}).on('close', () => {
console.log('Have a great day!')
exit(0)
})
const { createInterface } = require('node:readline')
const rl = createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'OHAI> ',
})
rl.prompt()
rl.on('line', line => {
switch (line.trim()) {
case 'hello':
console.log('world!')
break
default:
console.log(`Say what? I might have heard '${line.trim()}'`)
break
}
rl.prompt()
}).on('close', () => {
console.log('Have a great day!')
process.exit(0)
})
مثال: قراءة تدفق الملف سطرًا بسطر
حالة استخدام شائعة لـ readline
هي استهلاك ملف إدخال سطرًا في كل مرة. أسهل طريقة للقيام بذلك هي الاستفادة من واجهة برمجة التطبيقات fs.ReadStream
بالإضافة إلى حلقة for await...of
:
import { createReadStream } from 'node:fs'
import { createInterface } from 'node:readline'
async function processLineByLine() {
const fileStream = createReadStream('input.txt')
const rl = createInterface({
input: fileStream,
crlfDelay: Infinity,
})
// ملاحظة: نستخدم خيار crlfDelay للتعرف على جميع حالات CR LF
// ('\r\n') في input.txt كفاصل سطر واحد.
for await (const line of rl) {
// سيتوفر كل سطر في input.txt تباعًا هنا كـ `line`.
console.log(`Line from file: ${line}`)
}
}
processLineByLine()
const { createReadStream } = require('node:fs')
const { createInterface } = require('node:readline')
async function processLineByLine() {
const fileStream = createReadStream('input.txt')
const rl = createInterface({
input: fileStream,
crlfDelay: Infinity,
})
// ملاحظة: نستخدم خيار crlfDelay للتعرف على جميع حالات CR LF
// ('\r\n') في input.txt كفاصل سطر واحد.
for await (const line of rl) {
// سيتوفر كل سطر في input.txt تباعًا هنا كـ `line`.
console.log(`Line from file: ${line}`)
}
}
processLineByLine()
بدلاً من ذلك، يمكن للمرء استخدام حدث 'line'
:
import { createReadStream } from 'node:fs'
import { createInterface } from 'node:readline'
const rl = createInterface({
input: createReadStream('sample.txt'),
crlfDelay: Infinity,
})
rl.on('line', line => {
console.log(`Line from file: ${line}`)
})
const { createReadStream } = require('node:fs')
const { createInterface } = require('node:readline')
const rl = createInterface({
input: createReadStream('sample.txt'),
crlfDelay: Infinity,
})
rl.on('line', line => {
console.log(`Line from file: ${line}`)
})
في الوقت الحالي، قد تكون حلقة for await...of
أبطأ قليلاً. إذا كان تدفق async
/ await
والسرعة كلاهما ضروريان، فيمكن تطبيق نهج مختلط:
import { once } from 'node:events'
import { createReadStream } from 'node:fs'
import { createInterface } from 'node:readline'
;(async function processLineByLine() {
try {
const rl = createInterface({
input: createReadStream('big-file.txt'),
crlfDelay: Infinity,
})
rl.on('line', line => {
// معالجة السطر.
})
await once(rl, 'close')
console.log('File processed.')
} catch (err) {
console.error(err)
}
})()
const { once } = require('node:events')
const { createReadStream } = require('node:fs')
const { createInterface } = require('node:readline')
;(async function processLineByLine() {
try {
const rl = createInterface({
input: createReadStream('big-file.txt'),
crlfDelay: Infinity,
})
rl.on('line', line => {
// معالجة السطر.
})
await once(rl, 'close')
console.log('File processed.')
} catch (err) {
console.error(err)
}
})()
اختصارات لوحة المفاتيح لـTTY
اختصارات لوحة المفاتيح | الوصف | الملاحظات |
---|---|---|
+ + | حذف السطر من اليسار | لا يعمل على لينكس وماك ويندوز |
+ + | حذف السطر من اليمين | لا يعمل على ماك |
+ | إرسال SIGINT أو إغلاق مثيل readline | |
+ | حذف من اليسار | |
+ | حذف من اليمين أو إغلاق مثيل readline في حالة كان السطر الحالي فارغًا / EOF | لا يعمل على ويندوز |
+ | حذف من الموقع الحالي إلى بداية السطر | |
+ | حذف من الموقع الحالي إلى نهاية السطر | |
+ | نسخ (استدعاء) النص المحذوف سابقًا | يعمل فقط مع النص المحذوف بواسطة + أو + |
+ | التنقل بين النصوص المحذوفة سابقًا | متوفر فقط عندما يكون آخر ضغطة مفتاح + أو + |
+ | الانتقال إلى بداية السطر | |
+ | الانتقال إلى نهاية السطر | |
+ | الرجوع حرفًا واحدًا | |
+ | التقدم حرفًا واحدًا | |
+ | مسح الشاشة | |
+ | عنصر التاريخ التالي | |
+ | عنصر التاريخ السابق | |
+ | التراجع عن التغيير السابق | أي ضغطة مفتاح تُصدر رمز المفتاح 0x1F ستؤدي هذا الإجراء. في العديد من المحطات الطرفية، على سبيل المثال xterm ، يتم ربط هذا بـ + . |
+ | إعادة التغيير السابق | لا تحتوي العديد من المحطات الطرفية على اختصار لوحة مفاتيح لإعادة التنفيذ افتراضيًا. لقد اخترنا رمز المفتاح 0x1E لإجراء إعادة التنفيذ. في xterm ، يتم ربطه بـ + افتراضيًا. |
+ | نقل العملية قيد التشغيل إلى الخلفية. اكتب fg واضغط على للرجوع. | لا يعمل على ويندوز |
+ أو + | حذف للخلف إلى حدود الكلمة | + لا يعمل على لينكس وماك وويندوز |
+ | حذف للأمام إلى حدود الكلمة | لا يعمل على ماك |
+ أو + | كلمة يسار | + لا يعمل على ماك |
+ أو + | كلمة يمين | + لا يعمل على ماك |
+ أو + | حذف كلمة يمين | + لا يعمل على ويندوز |
+ | حذف كلمة يسار | لا يعمل على ماك |