منبع اصلی نوشتار زیر در این لینک قرار دارد

تبدیل دستورات تایپ شده فارسی به انگلیسی – bash و zsh

یه معضل بزرگ من، این بود که مثلا داشتم فارسی مینوشتم، بعد میرفتم توی ترمینال یادم میرفت کیبرد رو دوباره انگلیسی کنم. تا میومدم به خودم بجنبم کلی تایپ کرده بودم :( آی حرصم میگرفت! بعد مهدی فتاحی، بابای آریوس یه پیشنهادی داد بهم برای آریوس. ولی خوب این مغز من استاد زیرآبی رفتنه، یه چیز دیگه به ذهنم رسید -البته در راستای همون پیشنهاد- که پیاده سازی اولیش اینه که میخوام تو این پست دربارش بنویسم.

خیلی پیش میاد که یه دستور اشتباهی زده بشه. خوب اونها مهم نیست :) مشکل دستوراتیه که درستن، ولی با زبان اشتباهی تایپ میشن. خوب راه حل چیه؟
توی zsh و همچنین bash میتونیم یک تابع تغریف کنیم که هنگامی که دستوری زده میشه و وجود نداره، اون تابع اجرا بشه. این تابع (که اصطلاحا هوک هم بهش میگن) با آرگومانی که حاوی دستور اجرا شدست فراخوانی میشه. توی zsh اسم این تابع باید command_not_found_handler و توی bash باید باشه command_not_found_handle -توی zsh اسم تابع یه r در انتها اضافه داره-

یعنی الان توی .zshrc بنویسید :

command_not_found_handler() {
	echo "Sorry but $1 not found." 
}

بعد با دستور source ~/.zshrc اون رو لود کنید (یا اینکه ترمینال رو ببندید و دوباره باز کنید، فرق نمیکنه) و بعد یه دستور اشتباه بزنید، این پیغام به شما نشون داده میشه.
– برای bash فقط کافیه اسم فایل رو اصلاح کنید و اون r رو بردارید، و بعد بذاریدش تو .bashrc . دیگه از این به بعد حرفی درباره بش نمیزنم، جز این تغییرات کوچک باقیش فرقی نداره.

حالا اینجاست که ایده رو باید پیاده کنیم. یه اسکریپت ساده که کل حروف فارسی رو با انگلیسی عوض کنه و دستور جدید رو چک کنه، اگر وجود داشت، اجراش کنه. یک چنین اسکریپتی :

command_not_found_handler() {
  persian=( ض ص ث ق ف غ ع ه خ ح ج چ ش س ی ب ل ا ت ن م ک گ ظ ط ز ر ذ د پ و ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۰ ! ٬ ٫ ﷼ ٪ × ، ؛ )
  english=( q w e r t y u i o p \[ \] a s d f g h j k l \; \' z x c v b n m , 1 2 3 4 5 6 7 8 9 0 ! @ \# \$ % \^ \& \" )
  len=<code>echo ${#english[*]}</code>
  arg=$@
  prog=$1
  arg=${arg/$prog/}
  for ((i=1 ; i &lt; $len ; i++)) do
    arg=${arg//${persian[$i]}/${english[$i]}}
    prog=${prog//${persian[$i]}/${english[$i]}}
  done
  
  /usr/bin/which --skip-alias &quot;$prog&quot; &amp;&gt; /dev/null
  if [ &quot;$?&quot; = &quot;0&quot; ];then
	  <code>echo $prog$arg</code>
      return 0
  else
      return 127
  fi
}

دو تا آرایه متناظر از حروف فارسی و انگلیسی که قراره با هم ترکیب بشن وجود داره. اسم برنامه در $1 قرار میگیره و اسم برنامه بعلاوه آرگومانها در $@ . چون قراره که بررسی بشه که آیا برنامه وجود داره یا نه، لازمه که حتما اسم برنامه جداگانه وجود داشته باشه به همین خاطره که یه prog داریم و یه arg. بعدشم که سادست. یه جایگزینی ساده و نه چندان بهینه. متاسفانه نتونستم راهی پیدا کنم که bash یه دفعه همه این جابجایی رو با هم انجام بده.

گام بعدی، بررسی اینه که آیا این برنامه وجود داره یا نه. شاید تعجب کرده باشید که چرا آدرس کامل which رو دادم. در این مورد، zsh خودش یه which داره که متاسفانه ناقصه و نمیدونم چه اصراری بر اجرای اون داره :)) اینه که از which اصلی گنو استفاده میکنم.
نکته اینه که ما نمیتونیم (یا من نمیدونم چطوری میشه) یک alias رو اجرا کنیم. پس اونها رو هم باید جزو غلطها در نظر بگیریم (که خیلی هم جالب نیست! حتما یه راهی براش پیدا میکنم!) و به همین دلیل which با اون آرگومان skip-aliases اجرا شده (که متاسفانه which خود zsh از این پشتیبانی نمیکنه) اگه وجود داشته باشه برنامه، بازگشتی صفره که توی if همین چک شده. و بعد هم دستور توی یک subshell اجرا شده.
اگر پیدا نشه، بازگشتی ۱۲۷ به سیستم حالی میکنه که پیدا نشد، و تو خطای خودتو بده.
فعلا همین :))) و برای من که تا الان خیلی مفید بوده :) بعدا قصد دارم برای آریوس تکمیل ترش کنم. خیلی تکمیل تر.

– دوستی که خودشو me معرفی کرده یه مشکلی رو گزارش دادن، و اون هم اینه که در bash وقتی شما دستوری رو اشتباه میزنی، خطایی نشون داده نمیشه. کافیه که برای bash دقیقا قبل از خط return 127 تو یه خط جدید اینو بنویسید :

      echo "command not found : $1"

– الان متوجه شدم که این صدمین نوشته ایه که توی این وبلاگ منتشر میکنم :)))



برچسب ها : , , , , , , , , ,