Zsh এ কীভাবে আপনার নিজের শেল ফাংশনটি সংজ্ঞায়িত এবং লোড করবেন


54

আমার নিজের শেল ফাংশনগুলি zsh এ সংজ্ঞায়িত করতে এবং চালাতে আমার খুব কষ্ট হচ্ছে। আমি অফিসিয়াল ডকুমেন্টেশনের নির্দেশাবলী অনুসরণ করে প্রথমে সহজ উদাহরণ দিয়ে চেষ্টা করেছি, কিন্তু আমি এটি কার্যকর করতে ব্যর্থ হয়েছি।

আমার একটি ফোল্ডার রয়েছে:

~/.my_zsh_functions

এই ফোল্ডারে আমি ব্যবহারকারীর অনুমতি functions_1সহ একটি ফাইল কল করেছি rwx। এই ফাইলে আমার নীচের শেল ফাংশনটি সংজ্ঞায়িত হয়েছে:

my_function () {
echo "Hello world";
}

আমি FPATHফোল্ডারের পথ অন্তর্ভুক্ত করার জন্য সংজ্ঞায়িত করেছি ~/.my_zsh_functions:

export FPATH=~/.my_zsh_functions:$FPATH

আমি নিশ্চিত করতে পারি যে ফোল্ডারটি .my_zsh_functionsফাংশনের পথে echo $FPATHবা এর সাথে রয়েছেecho $fpath

তবে, আমি যদি তখন শেল থেকে নিম্নলিখিতটি চেষ্টা করি:

> autoload my_function
> my_function

আমি পাই:

zsh: my_test_function: ফাংশন সংজ্ঞা ফাইল পাওয়া যায় নি

কল করতে সক্ষম হওয়ার জন্য আমার আরও কিছু করার দরকার আছে my_function?

হালনাগাদ:

উত্তরগুলি এখনও পর্যন্ত zsh ফাংশনগুলির সাথে ফাইলটি স্যুরসিংয়ের পরামর্শ দেয়। এটি বোঝা যায়, তবে আমি কিছুটা বিভ্রান্ত হয়ে পড়েছি। Zsh- কে এই ফাইলগুলি কোথায় রয়েছে তা জানা উচিত নয় FPATH? তখন কী উদ্দেশ্য autoload?


আপনার $ ZDOTDIR সঠিকভাবে সংজ্ঞায়িত হয়েছে তা নিশ্চিত করুন। zsh.sourceforge.net/Intro/intro_3.html
ramonovski

2
$ ZDOTDIR এর মান এই সমস্যার সাথে সম্পর্কিত নয়। ভেরিয়েবল নির্ধারণ করে যেখানে zsh ব্যবহারকারীর কনফিগারেশন ফাইলগুলি সন্ধান করছে। যদি এটি সেট না করা থাকে instead পরিবর্তে হোম ব্যবহার করা হয়, যা প্রায় প্রত্যেকের জন্যই সঠিক মান।
ফ্রাঙ্ক তেরবেক

উত্তর:


94

Zsh এ, ফাংশন অনুসন্ধানের পথ (p fpath) ডিরেক্টরিগুলির একটি সেট সংজ্ঞায়িত করে, যার মধ্যে এমন ফাইল রয়েছে যা এতে থাকা ফাংশনটি প্রথমবারের জন্য প্রয়োজন হলে স্বয়ংক্রিয়ভাবে লোড হওয়ার জন্য চিহ্নিত করা যেতে পারে।

জেডএসের অটোলয়েডিং ফাইলগুলির দুটি মোড রয়েছে: জেডএসের নেটিভ উপায় এবং অন্য মোড যা ksh এর অটোলয়েডিংয়ের অনুরূপ। যদি KSH_AUTOLOAD বিকল্পটি সেট করা থাকে তবে পরবর্তীটি সক্রিয় থাকে। জেডএসের নেটিভ মোডটি ডিফল্ট এবং আমি এখানে অন্যভাবে আলোচনা করব না (ksh- স্টাইলের অটোলয়েডিং সম্পর্কে বিশদ জন্য "ম্যান zshmisc" এবং "ম্যান zshoptions" দেখুন)।

ঠিক আছে. বলুন যে আপনি একটি ডিরেক্টরি `~ / .zfunc 'পেয়েছেন এবং আপনি এটি ফাংশন অনুসন্ধানের পথের অংশ হতে চান, আপনি এটি করুন:

fpath=( ~/.zfunc "${fpath[@]}" )

এটি অনুসন্ধানের পথের সামনের অংশে আপনার ব্যক্তিগত ডিরেক্টরি যুক্ত করে । এটি গুরুত্বপূর্ণ যদি আপনি নিজের সাথে zsh এর ইনস্টলেশন থেকে ফাংশনগুলিকে ওভাররাইড করতে চান (যেমন আপনি যখন শেলের একটি পুরানো ইনস্টলড সংস্করণ সহ zsh এর সিভিএস সংগ্রহস্থল থেকে `_git) এর মতো একটি আপডেট সমাপ্তির ফাংশন ব্যবহার করতে চান)।

এটাও লক্ষণীয় যে, p p fpath 'থেকে ডিরেক্টরিগুলি পুনরাবৃত্তভাবে অনুসন্ধান করা হয় না। আপনি যদি নিজের ব্যক্তিগত ডিরেক্টরিটি পুনরাবৃত্তভাবে অনুসন্ধান করতে চান তবে আপনাকে নিজের যত্ন নিতে হবে, এটির মতো (নীচের স্নিপেটটির জন্য T EXTENDED_GLOB 'বিকল্পটি সেট করা দরকার):

fpath=(
    ~/.zfuncs
    ~/.zfuncs/**/*~*/(CVS)#(/N)
    "${fpath[@]}"
)

এটি প্রশিক্ষণহীন চোখের কাছে ক্রিপ্টিক দেখতে পারে তবে "সিভিএস" নামক ডিরেক্টরিগুলি উপেক্ষা করার সময় এটি সত্যই `~ / .zfunc 'এর নীচে সমস্ত ডিরেক্টরি যুক্ত করে (যা দরকারী, যদি আপনি পুরো চেকআউট করার পরিকল্পনা করছেন zsh এর সিভিএস থেকে আপনার ব্যক্তিগত অনুসন্ধানের পথে ফাংশন ট্রি)।

আসুন ধরে নেওয়া যাক আপনি একটি ফাইল পেয়েছেন ~ ~ / .zfunc / হ্যালো 'যাতে নিম্নলিখিত লাইনটি রয়েছে:

printf 'Hello world.\n'

আপনাকে এখন যা করতে হবে তা হ'ল ফাংশনটিকে তার প্রথম রেফারেন্সের মধ্যে স্বয়ংক্রিয়ভাবে লোড করার জন্য চিহ্নিত করা :

autoload -Uz hello

"আপনি কি জিজ্ঞাসা করেন?" ঠিক আছে, এটি কেবলমাত্র বিকল্পগুলির একটি সেট যা 'অটোল্যাড' দ্বারা সঠিক কাজটি করবে, অন্যথায় কী অপশন সেট করা হচ্ছে না কেন। ফাংশনটি লোড হওয়ার সময় `ইউ 'উপন্যাসের প্রসারকে অক্ষম করে এবং` কেএসএইচ_আউটলোড' যে কোনও কারণেই সেট করা থাকলেও sh z 'zsh-style অটোলেডিংয়ের জন্য বাধ্য করে।

এটির যত্ন নেওয়া হওয়ার পরে, আপনি আপনার নতুন 'হ্যালো' ফাংশনটি ব্যবহার করতে পারেন:

zsh% হ্যালো
ওহে বিশ্ব.

এই ফাইলগুলিকে সোর্স করার বিষয়ে একটি শব্দ: এটি ঠিক ভুল । আপনি যদি সেই source ~ / .zfunc / হ্যালো 'ফাইলটি উত্স করেন তবে এটি কেবল "হ্যালো ওয়ার্ল্ড" মুদ্রণ করবে। একদা. বেশি কিছু না. কোন ফাংশন সংজ্ঞায়িত করা হবে না। এবং তদ্ব্যতীত, ধারণাটি কেবল তখন প্রয়োজন হয় যখন ফাংশনের কোডটি লোড করা হয় । 'অটোল্যাড' কল করার পরে ফাংশনের সংজ্ঞাটি পড়ে না । প্রয়োজন অনুযায়ী ফাংশনটি কেবল অটোলয়েড হিসাবে চিহ্নিত হয়েছে।

এবং পরিশেষে, $ FPATH এবং $ fpath সম্পর্কে একটি নোট: জেডএস সেগুলি সংযুক্ত পরামিতি হিসাবে ধরে রাখে। লোয়ার কেস প্যারামিটারটি একটি অ্যারে। উপরের কেস সংস্করণটি একটি স্ট্রিং স্কেলার, এতে লিঙ্কযুক্ত অ্যারে থেকে এন্ট্রিগুলির মধ্যে প্রবেশ করে কোলন যোগ হয়। এটি সম্পন্ন হয়েছে, কারণ স্কেলারগুলির একটি তালিকা পরিচালনা করা অ্যারেগুলি ব্যবহার করা আরও প্রাকৃতিক, এছাড়াও স্কেলার পরামিতি ব্যবহার করে এমন কোডের পিছনে সামঞ্জস্যতা বজায় রাখাও। আপনি যদি $ FPATH (স্কেলারটি) ব্যবহার করতে চান তবে আপনার সাবধান হওয়া দরকার:

FPATH=~/.zfunc:$FPATH

কাজ করবে, যখন নিম্নলিখিতগুলি কাজ করবে না:

FPATH="~/.zfunc:$FPATH"

কারণটি হ'ল ডাবল উদ্ধৃতিতে টিলডে সম্প্রসারণ করা হয় না। এটি সম্ভবত আপনার সমস্যার উত্স। যদি echo $FPATHএকটি টিলড প্রিন্ট করে এবং প্রসারিত পথ না হয় তবে এটি কার্যকর হবে না। নিরাপদ থাকতে, আমি এই জাতীয় টিলার পরিবর্তে $ হোম ব্যবহার করব:

FPATH="$HOME/.zfunc:$FPATH"

বলা হচ্ছে, আমি এই ব্যাখ্যার শীর্ষে যেমনটি করেছি ঠিক তেমন অ্যারে প্যারামিটার ব্যবহার করব।

আপনার $ FPATH প্যারামিটারও রফতানি করা উচিত নয়। এটি কেবল বর্তমান শেল প্রক্রিয়া দ্বারা প্রয়োজনীয়, এটির কোনও শিশু দ্বারা নয়।

হালনাগাদ

P p fpath 'এ ফাইলগুলির বিষয়বস্তু সম্পর্কে:

Zsh- স্টাইল অটোলয়েডিং সহ, কোনও ফাইলের বিষয়বস্তু হ'ল এটি নির্ধারিত ফাংশনের মূল উপাদান। সুতরাং একটি লাইনযুক্ত "হ্যালো" নামের একটি ফাইল echo "Hello world."সম্পূর্ণ "হ্যালো" নামক একটি ফাংশন সংজ্ঞায়িত করে। আপনি hello () { ... }কোডটি চারপাশে নির্বিঘ্ন করতে পারেন তবে তা অতিমাত্রায় হবে।

যদিও দাবি করা যায় যে একটি ফাইলের মধ্যে কেবল একটি ফাংশন থাকতে পারে তবে তা সম্পূর্ণ সঠিক নয়।

বিশেষত যদি আপনি ফাংশন ভিত্তিক সমাপ্তি সিস্টেম (কমপিস) থেকে কিছু ফাংশনটি দেখে থাকেন তবে আপনি দ্রুত বুঝতে পারবেন যে এটি একটি ভুল ধারণা। আপনি একটি ফাংশন ফাইলে অতিরিক্ত ফাংশন সংজ্ঞায়িত করতে মুক্ত। আপনি যে কোনও প্রারম্ভিককরণের জন্য নির্দ্বিধায় রয়েছেন, যা আপনাকে প্রথমবার ফাংশনটি বলা হওয়ার দরকার হতে পারে। তবে, আপনি যখন করবেন তখন আপনি সর্বদা একটি ফাংশন সংজ্ঞায়িত করবেন যা ফাইলের মতো ফাইলের মতো নামকরণ করা হবে এবং ফাইলটির শেষে সেই ফাংশনটি কল করবে , সুতরাং এটি প্রথমবার সঞ্চালিত হয় যখন ফাংশনটি রেফারেন্স করা হয়।

যদি - উপ-ফাংশন সহ - আপনি ফাইলটির মধ্যে ফাইলের মতো কোনও ফাংশন সংজ্ঞায়িত করেননি, তবে আপনি এতে ফাংশন সংজ্ঞাযুক্ত ফাংশনটি সমাপ্ত করবেন (অর্থাত্ ফাইলের উপ-ফাংশনগুলির সাথে)। আপনি যখন ফাইলটির মতো নামকরণ করা ফাংশনটি কল করবেন তখন আপনি কার্যকরভাবে আপনার সমস্ত উপ-ফাংশন সংজ্ঞায়িত করবেন। সাধারণত, আপনি যা চান তা তাই নয় , সুতরাং আপনি কোনও ফাংশনটিকে নতুন করে সংজ্ঞায়িত করতে চাইবেন, এটি ফাইলের মধ্যে ফাইলের মতো নামকরণ করা হবে।

আমি একটি সংক্ষিপ্ত কঙ্কাল অন্তর্ভুক্ত করব, এটি আপনাকে কীভাবে কাজ করে তার একটি ধারণা দেবে:

# Let's again assume that these are the contents of a file called "hello".

# You may run arbitrary code in here, that will run the first time the
# function is referenced. Commonly, that is initialisation code. For example
# the `_tmux' completion function does exactly that.
echo initialising...

# You may also define additional functions in here. Note, that these
# functions are visible in global scope, so it is paramount to take
# care when you're naming these so you do not shadow existing commands or
# redefine existing functions.
hello_helper_one () {
    printf 'Hello'
}

hello_helper_two () {
    printf 'world.'
}

# Now you should redefine the "hello" function (which currently contains
# all the code from the file) to something that covers its actual
# functionality. After that, the two helper functions along with the core
# function will be defined and visible in global scope.
hello () {
    printf '%s %s\n' "$(hello_helper_one)" "$(hello_helper_two)"
}

# Finally run the redefined function with the same arguments as the current
# run. If this is left out, the functionality implemented by the newly
# defined "hello" function is not executed upon its first call. So:
hello "$@"

আপনি যদি এই নির্বোধ উদাহরণটি চালনা করেন তবে প্রথম রানটি দেখতে এমন দেখাবে:

zsh% হ্যালো
initialising ...
ওহে বিশ্ব.

এবং পরপর কলগুলি এর মতো দেখতে পাবেন:

zsh% হ্যালো
ওহে বিশ্ব.

আমি আশা করি এটি পরিষ্কার হয়ে যায়।

(এই জটিল কৌশলগুলি ব্যবহার করে এমন আরও জটিল বাস্তব-বিশ্বের উদাহরণগুলির মধ্যে একটি zsh এর ফাংশন ভিত্তিক সমাপ্তি সিস্টেমের ইতিমধ্যে উল্লিখিত ` _tmux 'ফাংশন।)


ধন্যবাদ ফ্র্যাঙ্ক! আমি অন্যান্য উত্তরে পড়েছি যে আমি প্রতি ফাইলের জন্য একটি ফাংশনই সংজ্ঞায়িত করতে পারি, এটি কি ঠিক? আমি লক্ষ্য করেছি আপনি বাক্য গঠন ব্যবহার করেননি my_function () { }আপনার Hello worldউদাহরণ। যদি সিনট্যাক্সের প্রয়োজন না হয়, কখন এটি ব্যবহার করা কার্যকর হবে?
আমিলিও ভাজকেজ-রেইনা

1
আমি সেই উত্তরগুলিও উত্তর দেওয়ার জন্য মূল উত্তরটি প্রসারিত করেছি।
ফ্রাঙ্ক টারবেক

"আপনি সর্বদা ফাংশনটি সংজ্ঞায়িত করবেন যা ফাইলের ফাইলের মতো নামকরণ করা হবে এবং ফাইলটির শেষে সেই ফাংশনটি কল করবে" কেন?
Hibou57

Hibou57: (পাশাপাশি: এটি একটি টাইপো, "একটি ফাংশন সংজ্ঞায়িত" হওয়া উচিত, এটি এখন ঠিক করা হয়েছে।) আমি ভেবেছিলাম যে এটি স্পষ্ট ছিল, যখন আপনি কোড স্নিপেট বিবেচনার পরে অনুসরণ করবেন। যাইহোক, আমি এমন একটি অনুচ্ছেদ যুক্ত করেছি যা কারণটিকে আরও আক্ষরিক অর্থে বানান করে।
ফ্রাঙ্ক টারবেক

ধন্যবাদ আপনার সাইট থেকে আরও তথ্য এখানে
টিমো

5

কোনও fpathউপাদান দ্বারা চিহ্নিত ডিরেক্টরিতে ফাইলের নামটি এটি সংজ্ঞায়িত অটোলোডেবল ফাংশনটির নামের সাথে মেলে।

আপনার ফাংশনটির নামকরণ করা হয়েছে my_functionএবং ~/.my_zsh_functionsএটি আপনার ডিরেক্টরিতে রয়েছে fpathতাই আপনার সংজ্ঞাটি my_functionফাইলে থাকা উচিত ~/.my_zsh_functions/my_function

আপনার প্রস্তাবিত ফাইল নাম ( functions_1) এর বহুবচনটি নির্দেশ করে যে আপনি ফাইলটিতে একাধিক ফাংশন রাখার পরিকল্পনা করেছিলেন। এটি কীভাবে fpathএবং অটোলয়েডিংয়ের কাজ নয়। আপনার প্রতি ফাইলটিতে একটি ফাংশন সংজ্ঞা থাকা উচিত।


2

দিতে source ~/.my_zsh_functions/functions1টার্মিনাল এবং The মূল্যায়ন my_function, এখন আপনি ফাংশন কল করতে সক্ষম হবে


2
ধন্যবাদ, কিন্তু কি ভূমিকা FPATHএবং autoloadতারপর? আমারও কেন ফাইলটি উত্স করতে হবে? আমার আপডেট হওয়া প্রশ্নটি দেখুন।
18:37 এমেলেও ওয়াজকেজ-রেইনা

1

আপনি আপনার $ ZDOTDIR / .zshrc এর মতো আপনার সমস্ত ফাংশন সহ একটি ফাইল "লোড" করতে পারেন:

source $ZDOTDIR/functions_file

অথবা একটি বিন্দু ব্যবহার করতে পারে ""। পরিবর্তে "উত্স"।


1
ধন্যবাদ, কিন্তু কি ভূমিকা FPATHএবং autoloadতারপর? আমারও কেন ফাইলটি উত্স করতে হবে? আমার আপডেট হওয়া প্রশ্নটি দেখুন।
18:36 এমেলেও ওয়াজকেজ-রেইনা

0

সোর্সিং স্পষ্টভাবে সঠিক পদ্ধতির নয়, যেহেতু আপনি যা চান বলে মনে হচ্ছে তা হচ্ছে অলস সূচনাপ্রাপ্ত কার্যাদি have এটা কি autoloadজন্য। আপনি কীভাবে পরে যাবেন তা এখানে কীভাবে সম্পাদন করা যায় তা এখানে।

আপনার মধ্যে ~/.my_zsh_functions, আপনি বলেছেন যে আপনি my_functionসেই ইকোসকে "হ্যালো ওয়ার্ল্ড" নামে একটি ফাংশন রাখতে চান । তবে, আপনি এটি একটি ফাংশন কলে মুড়ে দিন, যা এটি কীভাবে কাজ করে না। পরিবর্তে, আপনাকে একটি ফাইল কল করতে হবে ~/.my_zsh_functions/my_function। এটিতে, কেবল echo "Hello world"কোনও ফাংশন মোড়কে নয় put আপনি যদি সত্যিই আবরণটি পছন্দ করেন তবে আপনি এর মতো কিছু করতেও পারেন।

# ~/.my_zsh_functions/my_function
__my_function () {
    echo "Hello world";
}
# you have to call __my_function
# if this is how you choose to do it
__my_function

এরপরে, আপনার .zshrcফাইলে, নিম্নলিখিতগুলি যুক্ত করুন:

fpath=(~/.my_zsh_functions $fpath);
autoload -U ~/.my_zsh_functions/my_function

আপনি যখন একটি নতুন জেডএসএইচ শেল লোড করেন, টাইপ করুন which my_function। আপনার এটি দেখতে হবে:

my_function () {
    # undefined
    builtin autoload -XU
}

জেডএসএইচ আপনার সাথে সবেমাত্র আমার_ফানশনটি বন্ধ করে দিয়েছে autoload -X। এখন, চালান my_functionতবে কেবল টাইপিং my_function। আপনার Hello worldপ্রিন্ট আউট দেখতে হবে এবং এখন যখন আপনি চালাবেন তখন আপনাকে which my_functionএইভাবে ভরাট ফাংশনটি দেখতে হবে:

my_function () {
    echo "Hello world"
}

এখন, আসল যাদুটি তখনই আসে যখন আপনি ~/.my_zsh_functionsকাজ করতে আপনার পুরো ফোল্ডারটি সেট আপ করেন autoload। আপনি যদি এই ফোল্ডারে ফেলেছেন এমন প্রতিটি ফাইল যদি এইভাবে কাজ করতে চান তবে আপনি যা রেখেছেন .zshrcতাতে কিছু পরিবর্তন করুন:

# add ~/.my_zsh_functions to fpath, and then lazy autoload
# every file in there as a function
fpath=(~/.my_zsh_functions $fpath);
autoload -U fpath[1]/*(.:t)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.