হুক ফাংশনটি একবারে চালানোর কোনও উপায় আছে কি?


15

প্রসঙ্গ

আমি ইমাস ক্লায়েন্ট / সার্ভার কনফিগারেশনেafter-make-frame-functions থিমগুলি সঠিকভাবে লোড করতে হুক ব্যবহার করছি । বিশেষত এটি কোড স্নিপেট যা আমি এটি তৈরি করতে ব্যবহার করি (এই উত্তরের উপর ভিত্তি করে ):

 (if (daemonp)
      (add-hook 'after-make-frame-functions
          (lambda (frame)
              (select-frame frame)
              (load-theme 'monokai t)
              ;; setup the smart-mode-line and its theme
              (sml/setup))) 
      (progn (load-theme 'monokai t)
             (sml/setup)))

সমস্যাটি

যখন একটি নতুন emacsclient -c/tসেশন শুরু হয় হুক মৃত্যুদন্ড কার্যকর করা হয় না শুধুমাত্র নতুন ফ্রেমে কিন্তু সমস্ত পূর্ববর্তী অস্তিত্ব ফ্রেম (অন্যান্য মধ্যে emacsclient সেশন) এবং এটি একটি খুব বিরক্তিকর ভিজ্যুয়াল ইফেক্ট (থিম ঐ সমস্ত ফ্রেম মধ্যে আবার লোড করা হয়) করে তোলে । আরও খারাপ, টার্মিনালের ক্লায়েন্টরা ইতিমধ্যে খোলা থিমের রঙটি পুরোপুরি মিশে গেছে। স্পষ্টতই এটি একই ইমাস সার্ভারের সাথে সংযুক্ত ইম্যাক্স ক্লায়েন্টগুলিতে ঘটে। এই আচরণের কারণ স্পষ্ট, হুকটি সার্ভারে চালিত হয় এবং এর সমস্ত ক্লায়েন্ট প্রভাবিত হয়।

প্রশ্নটি

এই ফাংশনটি শুধুমাত্র একবার চালানো বা হুক ব্যবহার না করে একই ফলাফল পাওয়ার কোনও উপায় আছে?


একটি আংশিক সমাধান

@ ড্র এর উত্তরের জন্য ধন্যবাদ আমার কাছে এখন এই কোডটি রয়েছে। তবে এখনও সমস্যা আছে, একবার আপনি টার্মিনালে ক্লায়েন্ট সেশন শুরু করার পরে, জিইউআই সঠিকভাবে থিমগুলি লোড করে না এবং বিপরীতে। অনেক পরীক্ষার পরে, আমি বুঝতে পেরেছিলাম যে আচরণটি নির্ভর করে প্রথমে কোন ইমাস্ক্লিভেন্টটি শুরু হয় এবং বিভিন্ন জিনিস ফেলে দেওয়ার পরে, আমি মনে করি এটি সম্ভবত রঙিন প্যালেটটি বোঝানো হয়েছে is আপনি যদি ম্যানুয়ালি থিমটি পুনরায় লোড করেন তবে সমস্ত ঠিকঠাক কাজ করে এবং এই কারণটি যখন আমার প্রাথমিক কনফিগারেশনের মতো প্রতিবার হুক দ্বারা ডাকা হয় তখন এই আচরণটি উপস্থিত হয় না not

(defun emacsclient-setup-theme-function (frame)
  (progn
    (select-frame frame)
    (load-theme 'monokai t)
    ;; setup the smart-mode-line and its theme
    (sml/setup)
    (remove-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)))

(if (daemonp)
    (add-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)
    (progn (load-theme 'monokai t)
           (sml/setup)))

চূড়ান্ত সমাধান

অবশেষে আমার সম্পূর্ণ কার্যকারী কোড রয়েছে যা আংশিক সমাধানে দেখা আচরণের সমাধান করে, এটি অর্জনের জন্য আমি মোড (টার্মিনাল বা গুই) দ্বারা একবার ফাংশনটি চালিত করি যখন প্রাসঙ্গিক ইমামস্ক্লিয়েন্ট প্রথমবারের জন্য শুরু করা হয়, তারপরে হুক থেকে ফাংশনটি সরিয়ে দিন কারণ আর দরকার নেই। এখন, আমি খুশি! :) আবার ধন্যবাদ @ ড্র!

কোড:

(setq myGraphicModeHash (make-hash-table :test 'equal :size 2))
(puthash "gui" t myGraphicModeHash)
(puthash "term" t myGraphicModeHash)

(defun emacsclient-setup-theme-function (frame)
  (let ((gui (gethash "gui" myGraphicModeHash))
        (ter (gethash "term" myGraphicModeHash)))
    (progn
      (select-frame frame)
      (when (or gui ter) 
        (progn
          (load-theme 'monokai t)
          ;; setup the smart-mode-line and its theme
          (sml/setup)
          (sml/apply-theme 'dark)
          (if (display-graphic-p)
              (puthash "gui" nil myGraphicModeHash)
            (puthash "term" nil myGraphicModeHash))))
      (when (not (and gui ter))
        (remove-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)))))

(if (daemonp)
    (add-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)
  (progn (load-theme 'monokai t)
         (sml/setup)))

1
প্রস্তাবিত শিরোনামটি সম্পাদনা করেছি। দয়া করে, রোলব্যাক নির্দ্বিধায় যদি আপনার মূল কথাটি বোঝানো না থাকে
মালবারবা

ঠিক আছে @ মালবারবা! আমি @ ড্র্রু
জো ডি কাস্ত্রো

উত্তর:


11

আমি অনুমান করছি যে আপনি " একবার মাত্র একবার হুক চালাবেন " এর উপায় আপনি খুঁজছেন না । আমি অনুমান করছি যে আপনি যখনই হুকটি চালাবেন কেবল তখনই সেই নির্দিষ্ট ফাংশনটি সম্পাদন করার উপায় খুঁজছেন।

প্রচলিত এবং সহজ, সেই প্রশ্নের উত্তর হ'ল আপনার ফাংশনটি হুক থেকে নিজেকে সরিয়ে ফেলার জন্য, আপনি চান ওয়ান-টাইম ক্রিয়াটি চালিয়ে যাওয়ার পরে। অন্য কথায় add-hookএমন একটি প্রসঙ্গে ব্যবহার করুন যেখানে আপনি জানেন যে হুক চালানো হলে ফাংশনটি সম্পাদন করা উচিত এবং ফাংশনটি তার কাজ করার পরে ফাংশনটি নিজেই নিজেকে হুক থেকে সরিয়ে ফেলতে হবে।

আপনি যদি সত্যিই যা চান তা সম্পর্কে যদি আমি সঠিকভাবে অনুমান করছি, তবে দয়া করে আপনার প্রশ্নটি এমন কিছুতে সম্পাদনা করার বিষয়ে বিবেচনা করুন " কেবল একবার হুক ফাংশন চালানোর কোনও উপায় আছে কি ?

মানক গ্রন্থাগার থেকে এখানে একটি উদাহরণ দেওয়া হয়েছে facemenu.el:

(defun facemenu-set-self-insert-face (face)
  "Arrange for the next self-inserted char to have face `face'."
  (setq facemenu-self-insert-data (cons face this-command))
  (add-hook 'post-self-insert-hook 'facemenu-post-self-insert-function))

(defun facemenu-post-self-insert-function ()
  (when (and (car facemenu-self-insert-data)
             (eq last-command (cdr facemenu-self-insert-data)))
    (put-text-property (1- (point)) (point)
                       'face (car facemenu-self-insert-data))
    (setq facemenu-self-insert-data nil))
  (remove-hook 'post-self-insert-hook 'facemenu-post-self-insert-function))

হ্যাঁ, এটি সেভাবে কাজ করতে পারে এবং আমি মনে করি এটি একটি কম সমস্যাযুক্ত এবং ত্রুটি-প্রবণ সমাধান হবে solution ধন্যবাদ।
জো ডি কাস্ত্রো

3
+1 টি। কোনও ফাংশনের 3-লাইনের উদাহরণ থাকাতে আঘাত লাগবে না যা নিজেকে হুক থেকে সরিয়ে দেয়।
মালবারবা

শেষ পর্যন্ত আমার কাছে আপনার উত্তরের ভিত্তিতে মোট কার্যনির্বাহী সমাধান রয়েছে (শেষে আমি বুঝতে পেরেছি যে আমি হুক থেকে ফাংশনটি সরিয়ে না দিয়ে এটিকে বিন্দুতে পারি)। আপনাকে অনেক ধন্যবাদ!
জো ডি কাস্ত্রো

3

এখানে একটি ম্যাক্রো দেওয়া হয়েছে যা আপনি এর পরিবর্তে ব্যবহার করতে পারেন add-hook(ব্যাপকভাবে পরীক্ষিত নয়):

(defmacro add-hook-run-once (hook function &optional append local)
  "Like add-hook, but remove the hook after it is called"
  (let ((sym (make-symbol "#once")))
    `(progn
       (defun ,sym ()
         (remove-hook ,hook ',sym ,local)
         (funcall ,function))
       (add-hook ,hook ',sym ,append ,local))))

দ্রষ্টব্য: make-symbolপ্রদত্ত নামের সাথে একটি নিরবচ্ছিন্ন প্রতীক তৈরি করে। #হুক ভেরিয়েবলের দিকে তাকানোর সময় আপনি যদি এটির সামনে এসে পৌঁছান তবে আমি কিছুটা অস্বাভাবিক হিসাবে প্রতীকটিকে পতাকাঙ্কিত করার জন্য একটি নাম অন্তর্ভুক্ত করেছি ।


এটি আমার পক্ষে কাজ করে না, এটি এই ত্রুটিটি ছুড়ে ফেলে:(void-function gensym)
জো ডি কাস্ত্রো

@ জোয়েডিকাস্ট্রো আহ, হ্যাঁ, এটি clপ্যাকেজ থেকে এসেছে । এর জন্য দুঃখিত - আমি ভুলে গেছি যে প্রত্যেকে এটি ব্যবহার করে না। (make-symbol "#once")পরিবর্তে আপনি ব্যবহার করতে পারেন । আমি উত্তর আপডেট করব।
হ্যারাল্ড হানচে-ওলসেন 9'14

1
আমি আবার চেষ্টা করেছি, এবং আমার পক্ষে কাজ করিনি, এবং সত্যই যেহেতু ড্রয়ের কাছ থেকে আমার একটি আংশিক কার্যনির্বাহী সমাধান ছিল, আমি পরিবর্তে আরও আশাব্যঞ্জক পথটি খুঁজছি। আপনার উত্তর দেওয়ার জন্য যাইহোক ধন্যবাদ!
জো ডি কাস্ত্রো

@ জোয়েডিকাস্ট্রো: অবশ্যই এটি আপনার সিদ্ধান্ত, এবং অবশ্যই ড্রয়ের সমাধান কাজ করবে। এবং এটি করার প্রচলিত উপায়। প্রধান অসুবিধা হুক ফাংশনে হুকের নামটির হার্ড কোড করা দরকার, যদি প্রয়োজন হয় তবে এটি একাধিক হুকের মধ্যে ফাংশনটি পুনরায় ব্যবহার করা শক্ত করে তোলে। এছাড়াও, যদি আপনি নিজেকে অন্য কোনও প্রসঙ্গে ব্যবহারের সমাধানটি অনুলিপি করতে দেখেন তবে আপনাকে হুকের নামটিও সম্পাদনা করতে হবে। আমার সমাধান নির্ভরতা ভঙ্গ করে, টুকরোগুলি পুনরায় ব্যবহার করতে এবং ইচ্ছামত এগুলি এদিক ওদিক সরিয়ে দেয়। কেন এটি আপনার পক্ষে কার্যকর হয় না তা নিয়ে আমি আগ্রহী, তবে যদি…
হ্যারাল্ড হানচে-ওলসেন

… তবে আপনি যদি তার নীচে যেতে সময় নাও চান তবে আমি পুরোপুরি বুঝতে পারি। জীবন সংক্ষিপ্ত - আপনার জন্য যা কাজ করে তা নিয়ে যান।
হ্যারাল্ড হানচে-ওলসেন 10'14

0

আপনি কোনও ফাংশনে gen-onceএকটি সাধারণ ফাংশন স্থানান্তর করতে হাইপার ফাংশন তৈরি করতে পারেন যা কেবল একবার চালাতে পারে:

(setq lexical-binding t)

(defun gen-once (fn)
  (let ((done nil))
    (lambda () (if (not done)
                   (progn (setq done t)
                          (funcall fn))))))
(setq test (gen-once (lambda () (message "runs"))))

;;;;---following is test----;;;;
((lambda () (funcall test))) ;; first time, message "runs"
((lambda () (funcall test))) ;; nil
((lambda () (funcall test))) ;; nil

তারপরে, ব্যবহার করুন (add-hook 'xxx-mode-hook (gen-once your-function-need-to-run-once))

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.