Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी कोड की 25 पंक्तियों में एक शेल लिखना

यदि आप Linux या Mac का उपयोग करते हैं, तो हर बार जब आप कोई टर्मिनल खोलते हैं तो आप एक शेल एप्लिकेशन का उपयोग कर रहे होते हैं।

शेल एक इंटरफ़ेस है जो आपके सिस्टम में कमांड निष्पादित करने में आपकी सहायता करता है।

शेल पर्यावरण चर को होस्ट करता है और इसमें कमांड इतिहास और स्वतः पूर्णता जैसी उपयोगी विशेषताएं होती हैं।

अगर आप उस तरह के व्यक्ति हैं जो यह सीखना पसंद करते हैं कि चीजें कैसे काम करती हैं, तो यह पोस्ट आपके लिए एकदम सही होगी!

शेल कैसे काम करता है?

अपना खुद का शेल एप्लिकेशन बनाने के लिए आइए सोचें कि शेल वास्तव में क्या है:

सबसे पहले, एक प्रॉम्प्ट होता है, आमतौर पर आपके वर्तमान उपयोगकर्ता और वर्तमान निर्देशिका जैसी कुछ अतिरिक्त जानकारी के साथ, फिर आप एक कमांड टाइप करते हैं और जब आप एंटर दबाते हैं तो परिणाम आपकी स्क्रीन पर प्रदर्शित होते हैं।

हाँ, यह बहुत बुनियादी लगता है, लेकिन क्या यह आपको कुछ याद नहीं दिलाता?

अगर आप pry के बारे में सोच रहे हैं तो आप सही हैं!

आपके ऑपरेटिंग सिस्टम के लिए मूल रूप से एक आरईपीएल (रीड-एवल-प्रिंट-लूप) में एक शेल।

यह जानते हुए कि हम आपके शेल का अपना पहला संस्करण लिख सकते हैं :

prompt = "> "

print prompt

while (input = gets.chomp)
  break if input == "exit"

  system(input)
  print prompt
end

यह हमें एक न्यूनतम, लेकिन कार्यात्मक खोल देगा। हम एक पुस्तकालय का उपयोग करके इसे बेहतर बना सकते हैं जिसका उपयोग कई अन्य आरईपीएल जैसे अनुप्रयोग करते हैं।

उस लाइब्रेरी को Readline . कहा जाता है ।

रीडलाइन लाइब्रेरी का उपयोग करना

रीडलाइन रूबी मानक पुस्तकालय का हिस्सा है, इसलिए स्थापित करने के लिए कुछ भी नहीं है, आपको बस require की आवश्यकता है यह।

Readline . का उपयोग करने के लाभों में से एक यह है कि यह हमारे लिए स्वचालित रूप से एक कमांड इतिहास रख सकता है।

यह कमांड प्रॉम्प्ट और कई अन्य चीजों को प्रिंट करने का भी ध्यान रख सकता है।

यहाँ हमारे शेल का v2 है, इस बार Readline . का उपयोग करते हुए :

require 'readline'

while input = Readline.readline("> ", true)
  break if input == "exit"

  system(input)
end

यह बहुत अच्छा है, हमने दो puts से छुटकारा पा लिया है शीघ्र और अब हमारे पास Readline . से कुछ शक्तिशाली क्षमताओं तक पहुंच है . उदाहरण के लिए, हम किसी शब्द को हटाने के लिए कीबोर्ड शॉर्टकट का उपयोग कर सकते हैं (CTRL + W ) या इतिहास भी खोजें (CTRL + R )!

आइए पूरा इतिहास प्रिंट करने के लिए एक नया कमांड जोड़ें:

require 'readline'

while input = Readline.readline("> ", true)
  break                       if input == "exit"
  puts Readline::HISTORY.to_a if input == "hist"

  # Remove blank lines from history
  Readline::HISTORY.pop if input == ""

  system(input)
end
<ब्लॉककोट>

मजेदार तथ्य:यदि आप इस कोड को pry में आज़माते हैं तो आपको pry का कमांड इतिहास मिल जाएगा! इसका कारण यह है कि pry भी Readline . का उपयोग कर रहा है , और Readline::HISTORY साझा स्थिति है।

अब आप hist type टाइप कर सकते हैं अपना आदेश इतिहास प्राप्त करने के लिए 🙂

स्वतः-पूर्णता जोड़ना

अपने पसंदीदा शेल की स्वतः-पूर्णता सुविधा के लिए धन्यवाद, आप बहुत सारी टाइपिंग को बचाने में सक्षम होंगे। रीडलाइन इस सुविधा को आपके शेल में एकीकृत करना वास्तव में आसान बनाता है।

आइए अपने इतिहास के आदेशों को स्वतः पूर्ण करके प्रारंभ करें।

उदाहरण :

comp = proc { |s| Readline::HISTORY.grep(/^#{Regexp.escape(s)}/) }

Readline.completion_append_character = " "
Readline.completion_proc = comp

## rest of the code goes here ##
जाता है।

इस कोड के साथ आप <tab> . दबाकर पहले से टाइप किए गए कमांड को स्वतः पूर्ण करने में सक्षम होना चाहिए चाभी। अब इसे एक कदम आगे बढ़ाते हैं और निर्देशिका स्वतः पूर्णता जोड़ें।

उदाहरण :

comp = proc do |s|
  directory_list = Dir.glob("#{s}*")

  if directory_list.size > 0
    directory_list
  else
    Readline::HISTORY.grep(/^#{Regexp.escape(s)}/)
  end
end

completion_proc संभावित उम्मीदवारों की सूची लौटाता है, इस मामले में हमें केवल Dir.glob का उपयोग करके यह जांचने की आवश्यकता है कि टाइप की गई स्ट्रिंग निर्देशिका नाम का हिस्सा है या नहीं . रीडलाइन बाकी का ख्याल रखेगी!

सिस्टम विधि को लागू करना

अब आपके पास इतिहास और स्वत:पूर्णता के साथ एक कार्यशील शेल होना चाहिए, कोड की 25 पंक्तियों के लिए बहुत बुरा नहीं है 🙂

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

यह system . द्वारा किया जाता है विधि, सी में यह विधि सिर्फ आपके आदेश को /bin/sh . पर भेजती है , जो एक शेल एप्लिकेशन है। आइए देखें कि आप किस तरह /bin/sh को लागू कर सकते हैं रूबी में करता है।

<ब्लॉककोट>

नोट :यह केवल Linux / Mac पर काम करेगा

सिस्टम विधि:

def system(command)
  fork {
    exec(command)
  }
end

यहाँ क्या होता है कि fork वर्तमान प्रक्रिया की एक नई प्रतिलिपि बनाता है, फिर इस प्रक्रिया को उस कमांड से बदल दिया जाता है जिसे हम exec के माध्यम से चलाना चाहते हैं तरीका। यह Linux प्रोग्रामिंग में एक बहुत ही सामान्य पैटर्न है।

यदि आप फोर्क नहीं करते हैं तो वर्तमान प्रक्रिया को बदल दिया जाता है, जिसका अर्थ है कि जब आप कमांड चला रहे हैं (ls , cd या कुछ और) किया जाता है तो आपका रूबी प्रोग्राम इसके साथ समाप्त हो जाएगा।

आप इसे यहां होते हुए देख सकते हैं:

def system(command)
  exec(command)
end

system('ls')

# This code will never run!
puts "after system"

निष्कर्ष

इस पोस्ट में आपने सीखा कि शेल एक REPL जैसा इंटरफ़ेस है (सोचें irb / pry ) आपके सिस्टम के साथ बातचीत करने के लिए। आपने शक्तिशाली Readline . का उपयोग करके अपने स्वयं के शेल का निर्माण करना भी सीखा पुस्तकालय, जो इतिहास और स्वतः पूर्णता जैसी कई अंतर्निहित सुविधाएँ प्रदान करता है (लेकिन आपको यह परिभाषित करना होगा कि यह कैसे काम करता है)।

और उसके बाद आपने fork . के बारे में सीखा + exec लिनक्स प्रोग्रामिंग प्रोजेक्ट्स में आमतौर पर इस्तेमाल किया जाने वाला पैटर्न।

अगर आपको यह पोस्ट अच्छी लगी हो तो क्या आप मुझ पर एक एहसान कर सकते हैं और इसे अपने सभी रूबी दोस्तों के साथ साझा कर सकते हैं? यह ब्लॉग को बढ़ने में मदद करेगा और अधिक लोग सीख सकेंगे 🙂


  1. रूबी में एडब्ल्यूएस लैम्ब्डा फ़ंक्शन लिखना

    AWS लैम्ब्डा हमें ओवरहेड को कम करते हुए स्केलेबल फ़ंक्शन सेट करने की अनुमति देता है। पूरे रूबी ऑन रेल्स ऐप को लिखने, होस्ट करने और बनाए रखने के बजाय, हम अलग-अलग घटनाओं पर स्वतंत्र रूप से प्रतिक्रिया देने के लिए लैम्ब्डा फ़ंक्शन का उपयोग कर सकते हैं। यह लेख आपको एडब्ल्यूएस नवागंतुक से रूबी को अपने लै

  1. टेस्ट-कमिट-रिवर्ट:रूबी में लिगेसी कोड के परीक्षण के लिए एक उपयोगी कार्यप्रवाह

    ऐसा हम में से अधिकांश के साथ होता है। जैसे-जैसे सॉफ्टवेयर प्रोजेक्ट बढ़ते हैं, कोडबेस के कुछ हिस्से बिना व्यापक परीक्षण सूट के उत्पादन में समाप्त हो जाते हैं। जब आप कुछ महीनों के बाद कोड के उसी क्षेत्र पर फिर से नज़र डालते हैं, तो इसे समझना मुश्किल हो सकता है; इससे भी बदतर, एक बग हो सकता है, और हम न

  1. रूबी में स्थैतिक विश्लेषण

    मान लें कि आप अपने सभी तरीकों को खोजने के लिए अपने स्रोत कोड को पार्स करना चाहते हैं, जहां वे परिभाषित हैं और वे कौन से तर्क लेते हैं। आप यह कैसे कर सकते हैं? आपका पहला विचार इसके लिए एक रेगेक्सपी लिखना हो सकता है... लेकिन क्या कोई बेहतर तरीका है? हाँ! स्थिर विश्लेषण एक ऐसी तकनीक है जिसका उपय