কম্পিউটার

রুবি কোডের 25 লাইনে একটি শেল লেখা

আপনি যদি লিনাক্স বা ম্যাক ব্যবহার করেন, প্রতিবার আপনি একটি টার্মিনাল খুললে আপনি একটি শেল অ্যাপ্লিকেশন ব্যবহার করছেন৷

একটি শেল হল একটি ইন্টারফেস যা আপনাকে আপনার সিস্টেমে কমান্ড চালাতে সাহায্য করে।

শেল এনভায়রনমেন্ট ভেরিয়েবল হোস্ট করে এবং কমান্ড ইতিহাস এবং স্বয়ংক্রিয়-সম্পূর্ণতার মতো দরকারী বৈশিষ্ট্য রয়েছে।

আপনি যদি এমন ব্যক্তি হন যে জিনিসগুলি কীভাবে কাজ করে তা শিখতে পছন্দ করেন তবে এই পোস্টটি আপনার জন্য উপযুক্ত হবে!

একটি শেল কিভাবে কাজ করে?

আমাদের নিজস্ব শেল অ্যাপ্লিকেশন তৈরি করতে আসুন একটি শেল আসলে কী তা নিয়ে চিন্তা করি:

প্রথমে, একটি প্রম্পট থাকে, সাধারণত আপনার বর্তমান ব্যবহারকারী এবং বর্তমান ডিরেক্টরির মতো কিছু অতিরিক্ত তথ্য সহ, তারপর আপনি একটি কমান্ড টাইপ করেন এবং যখন আপনি এন্টার টিপুন তখন ফলাফলগুলি আপনার স্ক্রিনে প্রদর্শিত হয়৷

হ্যাঁ, এটি বেশ মৌলিক শোনাচ্ছে, কিন্তু এটি কি আপনাকে কিছু মনে করিয়ে দেয় না?

আপনি যদি pry এর কথা ভাবছেন তাহলে আপনি ঠিক!

আপনার অপারেটিং সিস্টেমের জন্য মূলত একটি REPL (Read-Eval-Print-Loop) এর একটি শেল৷

জেনে যে আমরা আপনার শেলের প্রথম সংস্করণ লিখতে পারি :

prompt = "> "

print prompt

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

  system(input)
  print prompt
end

এটি আমাদের একটি ন্যূনতম, কিন্তু কার্যকরী শেল দেবে। আমরা একটি লাইব্রেরি ব্যবহার করে এটিকে উন্নত করতে পারি যা অন্য অনেক REPL-এর মতো অ্যাপ্লিকেশন ব্যবহার করে।

সেই লাইব্রেরিটিকে 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 টাইপ করতে পারেন আপনার কমান্ড ইতিহাস পেতে 🙂

স্বয়ংক্রিয়-সম্পূর্ণতা যোগ করা হচ্ছে

আপনার প্রিয় শেলের স্বয়ংক্রিয়-সম্পূর্ণ বৈশিষ্ট্যের জন্য ধন্যবাদ আপনি প্রচুর টাইপিং সংরক্ষণ করতে সক্ষম হবেন। রিডলাইন আপনার শেলটিতে এই বৈশিষ্ট্যটি একত্রিত করা সত্যিই সহজ করে তোলে৷

আমাদের ইতিহাস থেকে স্বয়ংক্রিয়ভাবে সম্পূর্ণ করার কমান্ড দিয়ে শুরু করা যাক।

উদাহরণ :

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 দ্বারা সম্পন্ন হয় পদ্ধতি, C তে এই পদ্ধতিটি আপনার কমান্ড পাঠায় /bin/sh , যা একটি শেল অ্যাপ্লিকেশন। চলুন দেখি কিভাবে আপনি কি /bin/sh বাস্তবায়ন করতে পারেন রুবিতে করে।

দ্রষ্টব্য :এটি শুধুমাত্র Linux / Mac 🙂

এ কাজ করবে৷

সিস্টেম পদ্ধতি:

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

এখানে যা ঘটে তা হল fork বর্তমান প্রক্রিয়াটির একটি নতুন অনুলিপি তৈরি করে, তারপরে এই প্রক্রিয়াটি কমান্ড দ্বারা প্রতিস্থাপিত হয় যা আমরা exec এর মাধ্যমে চালাতে চাই। পদ্ধতি এটি লিনাক্স প্রোগ্রামিং এর একটি খুব সাধারণ প্যাটার্ন।

আপনি যদি কাঁটাচামচ না করেন তবে বর্তমান প্রক্রিয়াটি প্রতিস্থাপিত হয়, যার অর্থ হল আপনি যখন কমান্ডটি চালাচ্ছেন (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. RuboCop সহ রুবি কোড লিন্টিং এবং স্বয়ংক্রিয় ফর্ম্যাটিং

  2. রুবিতে AWS Lambda ফাংশন লেখা

  3. টেস্ট-কমিট-রিভার্ট:রুবিতে লিগ্যাসি কোড পরীক্ষা করার জন্য একটি দরকারী কর্মপ্রবাহ

  4. রুবি মধ্যে স্ট্যাটিক বিশ্লেষণ