পূর্বাবস্থায় ফেরা ইতিহাস কীভাবে?


17

আমি একটি ইম্যাকস মোডে কাজ করছি যা আপনাকে স্পিচ স্বীকৃতি সহ ইম্যাক্স নিয়ন্ত্রণ করতে দেয়। আমি যে সমস্যার মুখোমুখি হয়েছি তার মধ্যে একটি হ'ল ইমা্যাকস যেভাবে পূর্বাবস্থায় ফিরে আসে তার সাথে মেলে না যে ভয়েস দ্বারা নিয়ন্ত্রণ করার সময় আপনি কীভাবে এটি কাজ করবেন বলে আশা করেন।

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

প্রতিটি উচ্চারনের শুরুতে এবং শেষে কলব্যাকগুলি পেতে আমার কাছে ইম্যাকস সেটআপ রয়েছে, তাই আমি পরিস্থিতিটি সনাক্ত করতে পারি, আমার কেবল ইমাসকে কী করতে হবে তা নির্ধারণ করতে হবে। আদর্শভাবে আমি এমন কিছু কল করতাম (undo-start-collapsing)এবং তারপরে (undo-stop-collapsing)এবং অভ্যন্তরে যে কোনও কিছুই করা হত যাদুতে এক রেকর্ডে পতিত।

আমি ডকুমেন্টেশনের মাধ্যমে কিছু ট্রলিং করেছি এবং খুঁজে পেয়েছি undo-boundary, তবে এটি যা আমি চাই তার বিপরীত - আমাকে একটি উচ্চারণের মধ্যে সমস্ত ক্রিয়াগুলি একটি পূর্বাবস্থায় রেকর্ডে পরিণত করতে হবে, সেগুলি বিভক্ত করা উচিত নয় not undo-boundaryসন্নিবেশগুলি পৃথক হিসাবে বিবেচনা করা হয় তা নিশ্চিত করার জন্য আমি বাক্যগুলির মধ্যে ব্যবহার করতে পারি (ডিফল্টরূপে ইমাসগুলি ক্রমাগত সন্নিবেশ ক্রিয়াকে কিছু সীমা পর্যন্ত এক ক্রিয়া হিসাবে বিবেচনা করে), তবে এটি।

অন্যান্য জটিলতা:

  • আমার স্পিচ রিকগনিশন ডিমন এক্স 11 কীপ্রেসগুলি অনুকরণ করে ইমাসকে কিছু কমান্ড প্রেরণ করে এবং এর মাধ্যমে কিছু প্রেরণ করে emacsclient -e, যদি সেখানে বলা (undo-collapse &rest ACTIONS)হয় যে কোনও लपेटার মতো কেন্দ্রীয় জায়গা নেই।
  • আমি ব্যবহার করি undo-tree, নিশ্চিত না যে এটি জিনিসগুলিকে আরও জটিল করে তোলে কিনা। আদর্শভাবে একটি সমাধান কাজ করবে undo-treeএবং ইমাকসের স্বাভাবিক পূর্বাবস্থায় আচরণ করবে।
  • যদি কোনও উচ্চারণের মধ্যে থাকা কোনও একটি আদেশ "পূর্বাবস্থায়" বা "আবার" হয়? আমি ভাবছি আমি কলব্যাকের যুক্তি পরিবর্তন করতে পারি যাতে এগুলিকে সর্বদা সহজ রাখার জন্য স্বতন্ত্র উক্তি হিসাবে এগুলিকে সর্বদা প্রেরণ করতে পারি, তবে যদি আমি কীবোর্ডটি ব্যবহার করতাম তবে এটি ঠিক যেমন পরিচালনা করা উচিত।
  • প্রসারিত লক্ষ্য: একটি উচ্চারণে একটি কমান্ড থাকতে পারে যা বর্তমানে সক্রিয় উইন্ডো বা বাফারটিকে স্যুইচ করে। এক্ষেত্রে প্রতিটি বাফারে আলাদা করে একবার "পূর্বাবস্থায়" বলা ভাল, আমার অভিনব হওয়ার দরকার নেই। তবে একটি একক বাফারের সমস্ত কমান্ড এখনও গোষ্ঠীভুক্ত করা উচিত, তাই যদি আমি "do-x do-y do-z সুইচ-বাফার do-a do-b-do-c" বলি তবে x, y, z একটিকে পূর্বাবস্থায় ফিরিয়ে আনতে হবে আসল বাফারে রেকর্ড এবং একটি, খ, সি সুইচড বাফারে একটি রেকর্ড হওয়া উচিত।

এটি করার কোনও সহজ উপায় আছে? আফ্রিকায় অন্তর্নির্মিত কিছুই নেই তবে ইমাকগুলি বিস্তৃত এবং গভীর ...

আপডেট: আমি নীচে কিছুটা অতিরিক্ত কোড দিয়ে jhc এর সমাধানটি ব্যবহার করে শেষ করেছি। বিশ্বব্যাপী before-change-hookআমি পরীক্ষা করে দেখছি যে বাফারটি পরিবর্তিত হচ্ছে বাফারগুলির একটি বিশ্বব্যাপী তালিকায় এই বাণীটি সংশোধিত হয়েছে, যদি তা তালিকায় না যায় এবং undo-collapse-beginডাকা হয়। তারপরে বক্তৃতা শেষে আমি তালিকার সমস্ত বাফারগুলিকে পুনরাবৃত্তি করি এবং কল করি undo-collapse-end। নীচের কোড (এমডি- নাম সারণের উদ্দেশ্যে ফাংশন নামের পূর্বে যুক্ত):

(defvar md-utterance-changed-buffers nil)
(defvar-local md-collapse-undo-marker nil)

(defun md-undo-collapse-begin (marker)
  "Mark the beginning of a collapsible undo block.
This must be followed with a call to undo-collapse-end with a marker
eq to this one.

Taken from jch's stackoverflow answer here:
http://emacs.stackexchange.com/a/7560/2301
"
  (push marker buffer-undo-list))

(defun md-undo-collapse-end (marker)
  "Collapse undo history until a matching marker.

Taken from jch's stackoverflow answer here:
http://emacs.stackexchange.com/a/7560/2301"
  (cond
    ((eq (car buffer-undo-list) marker)
     (setq buffer-undo-list (cdr buffer-undo-list)))
    (t
     (let ((l buffer-undo-list))
       (while (not (eq (cadr l) marker))
         (cond
           ((null (cdr l))
            (error "md-undo-collapse-end with no matching marker"))
           ((eq (cadr l) nil)
            (setf (cdr l) (cddr l)))
           (t (setq l (cdr l)))))
       ;; remove the marker
       (setf (cdr l) (cddr l))))))

(defmacro md-with-undo-collapse (&rest body)
  "Execute body, then collapse any resulting undo boundaries.

Taken from jch's stackoverflow answer here:
http://emacs.stackexchange.com/a/7560/2301"
  (declare (indent 0))
  (let ((marker (list 'apply 'identity nil)) ; build a fresh list
        (buffer-var (make-symbol "buffer")))
    `(let ((,buffer-var (current-buffer)))
       (unwind-protect
           (progn
             (md-undo-collapse-begin ',marker)
             ,@body)
         (with-current-buffer ,buffer-var
           (md-undo-collapse-end ',marker))))))

(defun md-check-undo-before-change (beg end)
  "When a modification is detected, we push the current buffer
onto a list of buffers modified this utterance."
  (unless (or
           ;; undo itself causes buffer modifications, we
           ;; don't want to trigger on those
           undo-in-progress
           ;; we only collapse utterances, not general actions
           (not md-in-utterance)
           ;; ignore undo disabled buffers
           (eq buffer-undo-list t)
           ;; ignore read only buffers
           buffer-read-only
           ;; ignore buffers we already marked
           (memq (current-buffer) md-utterance-changed-buffers)
           ;; ignore buffers that have been killed
           (not (buffer-name)))
    (push (current-buffer) md-utterance-changed-buffers)
    (setq md-collapse-undo-marker (list 'apply 'identity nil))
    (undo-boundary)
    (md-undo-collapse-begin md-collapse-undo-marker)))

(defun md-pre-utterance-undo-setup ()
  (setq md-utterance-changed-buffers nil)
  (setq md-collapse-undo-marker nil))

(defun md-post-utterance-collapse-undo ()
  (unwind-protect
      (dolist (i md-utterance-changed-buffers)
        ;; killed buffers have a name of nil, no point
        ;; in undoing those
        (when (buffer-name i)
          (with-current-buffer i
            (condition-case nil
                (md-undo-collapse-end md-collapse-undo-marker)
              (error (message "Couldn't undo in buffer %S" i))))))
    (setq md-utterance-changed-buffers nil)
    (setq md-collapse-undo-marker nil)))

(defun md-force-collapse-undo ()
  "Forces undo history to collapse, we invoke when the user is
trying to do an undo command so the undo itself is not collapsed."
  (when (memq (current-buffer) md-utterance-changed-buffers)
    (md-undo-collapse-end md-collapse-undo-marker)
    (setq md-utterance-changed-buffers (delq (current-buffer) md-utterance-changed-buffers))))

(defun md-resume-collapse-after-undo ()
  "After the 'undo' part of the utterance has passed, we still want to
collapse anything that comes after."
  (when md-in-utterance
    (md-check-undo-before-change nil nil)))

(defun md-enable-utterance-undo ()
  (setq md-utterance-changed-buffers nil)
  (when (featurep 'undo-tree)
    (advice-add #'md-force-collapse-undo :before #'undo-tree-undo)
    (advice-add #'md-resume-collapse-after-undo :after #'undo-tree-undo)
    (advice-add #'md-force-collapse-undo :before #'undo-tree-redo)
    (advice-add #'md-resume-collapse-after-undo :after #'undo-tree-redo))
  (advice-add #'md-force-collapse-undo :before #'undo)
  (advice-add #'md-resume-collapse-after-undo :after #'undo)
  (add-hook 'before-change-functions #'md-check-undo-before-change)
  (add-hook 'md-start-utterance-hooks #'md-pre-utterance-undo-setup)
  (add-hook 'md-end-utterance-hooks #'md-post-utterance-collapse-undo))

(defun md-disable-utterance-undo ()
  ;;(md-force-collapse-undo)
  (when (featurep 'undo-tree)
    (advice-remove #'md-force-collapse-undo :before #'undo-tree-undo)
    (advice-remove #'md-resume-collapse-after-undo :after #'undo-tree-undo)
    (advice-remove #'md-force-collapse-undo :before #'undo-tree-redo)
    (advice-remove #'md-resume-collapse-after-undo :after #'undo-tree-redo))
  (advice-remove #'md-force-collapse-undo :before #'undo)
  (advice-remove #'md-resume-collapse-after-undo :after #'undo)
  (remove-hook 'before-change-functions #'md-check-undo-before-change)
  (remove-hook 'md-start-utterance-hooks #'md-pre-utterance-undo-setup)
  (remove-hook 'md-end-utterance-hooks #'md-post-utterance-collapse-undo))

(md-enable-utterance-undo)
;; (md-disable-utterance-undo)

এটির জন্য অন্তর্নির্মিত প্রক্রিয়া সম্পর্কে সচেতন নয়। আপনি buffer-undo-listমার্কের হিসাবে নিজের নিজস্ব এন্ট্রিগুলি --োকাতে সক্ষম হতে পারবেন - ফর্মটির কোনও এন্ট্রি (apply FUN-NAME . ARGS)? তারপরে একটি উচ্চারণটি পূর্বাবস্থায় ফেরাতে আপনি undoপরবর্তী চিহ্নকারীর সন্ধান না করা পর্যন্ত বারবার কল করুন । তবে আমি সন্দেহ করি যে এখানে বিভিন্ন ধরণের জটিলতা রয়েছে। :)
গ্লুকাস

সীমানা অপসারণ করা আরও ভাল বাজি বলে মনে হয়।
jch

যদি আমি পূর্বাবস্থায় গাছ ব্যবহার করি তবে কি বাফার-পূর্বাবস্থায়-তালিকার কাজ করে? আমি এটি পূর্ববর্তী গাছ উত্সে রেফারেন্স দেখতে পাচ্ছি তাই আমি হ্যাঁ অনুমান করছি তবে পুরো মোডটি উপলব্ধি করা একটি বড় প্রচেষ্টা হবে।
জোসেফ গারভিন

@ জোসেফগারভিন আমি বক্তৃতা দিয়ে ইমাস নিয়ন্ত্রণ করতে আগ্রহী। আপনার কি কোনও উত্স উপলব্ধ আছে?
পাইথননট

@ পাইথননট: হ্যা :) গিথুব / জগারভিন / ম্যান্ডিমাস প্যাকেজিং অসম্পূর্ণ ... এবং কোডটি আমার জো-ইত্যাদি রেপোতেও আংশিক রয়েছে: p তবে আমি এটি সারাদিন ব্যবহার করি এবং এটি কার্যকর হয়।
জোসেফ গারভিন

উত্তর:


13

আকর্ষণীয়ভাবে যথেষ্ট, এটি করার জন্য কোনও বিল্ট-ইন ফাংশন রয়েছে বলে মনে হয়।

নীচের কোডটি buffer-undo-listএকটি সঙ্কুচিত ব্লকের শুরুতে একটি অনন্য মার্কার সন্নিবেশ করে nilএবং একটি ব্লকের শেষে সমস্ত সীমানা ( উপাদান) মুছে ফেলা এবং তারপরে চিহ্নিতকারীকে সরিয়ে কাজ করে। যদি কোনও কিছু ভুল হয়ে যায় তবে চিহ্নিতকারীটি পূর্বে (apply identity nil)তালিকায় না থাকলে এটি কিছু না করে তা নিশ্চিত করে ফর্মটি তৈরি করে।

আদর্শভাবে, আপনার with-undo-collapseম্যাক্রো ব্যবহার করা উচিত , অন্তর্নিহিত ফাংশনগুলি নয়। যেহেতু আপনি উল্লেখ করেছেন যে আপনি মোড়ানো করতে পারবেন না, তাই নিশ্চিত করুন যে আপনি নিম্ন-স্তরের ফাংশন চিহ্নিতকারীগুলিতে যাচ্ছেন eq, কেবল তা নয় equal

যদি অনুরোধ করা কোডটি বাফারগুলিকে স্যুইচ করে তবে আপনাকে অবশ্যই এটি অবশ্যই undo-collapse-endএকই বাফারে ডাকা হয়েছে তা নিশ্চিত করতে হবে undo-collapse-begin। সেক্ষেত্রে প্রাথমিক বাফারে কেবল পূর্বাবস্থায় ফিরে যাওয়া প্রবেশগুলিই ধসে যাবে।

(defun undo-collapse-begin (marker)
  "Mark the beginning of a collapsible undo block.
This must be followed with a call to undo-collapse-end with a marker
eq to this one."
  (push marker buffer-undo-list))

(defun undo-collapse-end (marker)
  "Collapse undo history until a matching marker."
  (cond
    ((eq (car buffer-undo-list) marker)
     (setq buffer-undo-list (cdr buffer-undo-list)))
    (t
     (let ((l buffer-undo-list))
       (while (not (eq (cadr l) marker))
         (cond
           ((null (cdr l))
            (error "undo-collapse-end with no matching marker"))
           ((null (cadr l))
            (setf (cdr l) (cddr l)))
           (t (setq l (cdr l)))))
       ;; remove the marker
       (setf (cdr l) (cddr l))))))

 (defmacro with-undo-collapse (&rest body)
  "Execute body, then collapse any resulting undo boundaries."
  (declare (indent 0))
  (let ((marker (list 'apply 'identity nil)) ; build a fresh list
        (buffer-var (make-symbol "buffer")))
    `(let ((,buffer-var (current-buffer)))
       (unwind-protect
            (progn
              (undo-collapse-begin ',marker)
              ,@body)
         (with-current-buffer ,buffer-var
           (undo-collapse-end ',marker))))))

ব্যবহারের উদাহরণ এখানে:

(defun test-no-collapse ()
  (interactive)
  (insert "toto")
  (undo-boundary)
  (insert "titi"))

(defun test-collapse ()
  (interactive)
  (with-undo-collapse
    (insert "toto")
    (undo-boundary)
    (insert "titi")))

আমি বুঝতে পারছি কেন আপনার চিহ্নিতকারীটি একটি তাজা তালিকা, তবে specific নির্দিষ্ট উপাদানগুলির কোনও কারণ আছে?
মালবারবা

@ মালবারবা এর কারণ এটি (apply identity nil)যদি আপনি প্রবেশের ডাক primitive-undoদেয় তবে কিছুই করতে পারবে না - কোনও কারণে যদি তালিকায় রেখে যায় তবে এটি কিছুই ভাঙবে না।
jch

আমি যুক্ত করা কোড অন্তর্ভুক্ত করতে আমার প্রশ্ন আপডেট করেছে। ধন্যবাদ!
জোসেফ গারভিন

এর (eq (cadr l) nil)পরিবর্তে কোন কারণ আছে (null (cadr l))?
ধারণাগুলি 42

@ ধারনাগুলি আপনার পরামর্শ অনুসারে পরিবর্তিত হয়েছে।
jch

3

"সাম্প্রতিক" পূর্বাবস্থায়িত ব্যবস্থার কিছু পরিবর্তন কিছুটা হ্যাক ভেঙেছিল viper-modeএই ধরণের পতন (কৌতূহলের জন্য, এটি নিম্নলিখিত ক্ষেত্রে ব্যবহৃত হয়) আপনি যখন ESCসন্নিবেশ / প্রতিস্থাপন / সংস্করণটি শেষ করার জন্য চাপেন তখন ভাইপার পুরোটি ভেঙে ফেলতে চায় একক পূর্ববর্তী পদক্ষেপে পরিবর্তন করুন) change

পরিষ্কারভাবে এটি ঠিক করার জন্য, আমরা একটি নতুন ফাংশন প্রবর্তন করেছি undo-amalgamate-change-group(যা আপনার সাথে কমবেশি মিলে যায় undo-stop-collapsing) এবং বিদ্যমানটিকে পুনরায় prepare-change-groupচিহ্নিত করে (অর্থাত আপনার সাথে আরও কম সংখ্যক undo-start-collapsing)।

রেফারেন্সের জন্য, এখানে সম্পর্কিত নতুন ভাইপার কোডটি:

(viper-deflocalvar viper--undo-change-group-handle nil)
(put 'viper--undo-change-group-handle 'permanent-local t)

(defun viper-adjust-undo ()
  (when viper--undo-change-group-handle
    (undo-amalgamate-change-group
     (prog1 viper--undo-change-group-handle
       (setq viper--undo-change-group-handle nil)))))

(defun viper-set-complex-command-for-undo ()
  (and (listp buffer-undo-list)
       (not viper--undo-change-group-handle)
       (setq viper--undo-change-group-handle
             (prepare-change-group))))

এই নতুন ফাংশনটি ইম্যাক্স -26 এ প্রদর্শিত হবে, সুতরাং আপনি যদি গড় সময়ে এটি ব্যবহার করতে চান তবে আপনি এর সংজ্ঞাটি অনুলিপি করতে পারেন (প্রয়োজনীয় cl-lib):

(defun undo-amalgamate-change-group (handle)
  "Amalgamate changes in change-group since HANDLE.
Remove all undo boundaries between the state of HANDLE and now.
HANDLE is as returned by `prepare-change-group'."
  (dolist (elt handle)
    (with-current-buffer (car elt)
      (setq elt (cdr elt))
      (when (consp buffer-undo-list)
        (let ((old-car (car-safe elt))
              (old-cdr (cdr-safe elt)))
          (unwind-protect
              (progn
                ;; Temporarily truncate the undo log at ELT.
                (when (consp elt)
                  (setcar elt t) (setcdr elt nil))
                (when
                    (or (null elt)        ;The undo-log was empty.
                        ;; `elt' is still in the log: normal case.
                        (eq elt (last buffer-undo-list))
                        ;; `elt' is not in the log any more, but that's because
                        ;; the log is "all new", so we should remove all
                        ;; boundaries from it.
                        (not (eq (last buffer-undo-list) (last old-cdr))))
                  (cl-callf (lambda (x) (delq nil x))
                      (if (car buffer-undo-list)
                          buffer-undo-list
                        ;; Preserve the undo-boundaries at either ends of the
                        ;; change-groups.
                        (cdr buffer-undo-list)))))
            ;; Reset the modified cons cell ELT to its original content.
            (when (consp elt)
              (setcar elt old-car)
              (setcdr elt old-cdr))))))))

আমি সন্ধান করলাম undo-amalgamate-change-groupএবং with-undo-collapseএই পৃষ্ঠায় সংজ্ঞায়িত ম্যাক্রোর মতো এটি ব্যবহার করার সুবিধাজনক উপায় বলে মনে হচ্ছে না , যেহেতু atomic-change-groupগ্রুপটি কল করার অনুমতি দেয় এমনভাবে কাজ করে না undo-amalgamate-change-group
ধারণাগুলি 42

অবশ্যই, আপনি এটি দিয়ে ব্যবহার করবেন না atomic-change-group: আপনি এটি দিয়ে ব্যবহার করুন prepare-change-group, যা আপনি undo-amalgamate-change-groupযখন শেষ হয়ে গেলে হ্যান্ডেলটি ফেরত দেবে returns
স্টেফান 21

এর সাথে লেনদেনকারী কোনও ম্যাক্রো কি কার্যকর হবে না? (with-undo-amalgamate ...)যা চেঞ্জ গ্রুপ স্টাফ পরিচালনা করে। অন্যথায় এটি কয়েকটি ক্রিয়াকলাপ ভেঙে যাওয়ার জন্য ঝামেলা।
ধারণাগুলি 42

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

1
এই ম্যাক্রো লিখিত এবং ইমাস অন্তর্ভুক্ত করা যেতে পারে? একজন অভিজ্ঞ বিকাশকারীর পক্ষে এটি তুচ্ছ, এমন কেউ যদি তাদের পূর্বাবস্থার ইতিহাসটি ভেঙে ফেলতে চান এবং কোথা থেকে শুরু করবেন জানেন না - এটি কিছু সময় অনলাইনে গন্ডগোল করছে এবং এই থ্রেডে হোঁচট খাচ্ছে ... তারপরে কোন উত্তরটি সবচেয়ে ভাল তা খুঁজে বের করতে হবে - যখন তারা বলার মতো পর্যাপ্ত অভিজ্ঞ না হয়। আমি এখানে একটি উত্তর যুক্ত করেছি: emacs.stackexchange.com/a/54412/2418
ধারণাগুলি 42

2

এখানে একটি with-undo-collapseম্যাক্রো যা ইমাস -26 পরিবর্তন-গ্রুপ বৈশিষ্ট্যটি ব্যবহার করে।

এটি যুক্ত atomic-change-groupকরে একটি লাইন পরিবর্তনের সাথে undo-amalgamate-change-group

এটির সুবিধাগুলি রয়েছে:

  • এটিকে সরাসরি পূর্বাবস্থায় ফেরা ডেটা কারবার করার দরকার নেই।
  • এটি নিশ্চিত করে যে পূর্বাবস্থায় ফেরানো তথ্য কাটা হয়নি isn't
(defmacro with-undo-collapse (&rest body)
  "Like `progn' but perform BODY with undo collapsed."
  (declare (indent 0) (debug t))
  (let ((handle (make-symbol "--change-group-handle--"))
        (success (make-symbol "--change-group-success--")))
    `(let ((,handle (prepare-change-group))
            ;; Don't truncate any undo data in the middle of this.
            (undo-outer-limit nil)
            (undo-limit most-positive-fixnum)
            (undo-strong-limit most-positive-fixnum)
            (,success nil))
       (unwind-protect
         (progn
           (activate-change-group ,handle)
           (prog1 ,(macroexp-progn body)
             (setq ,success t)))
         (if ,success
           (progn
             (accept-change-group ,handle)
             (undo-amalgamate-change-group ,handle))
           (cancel-change-group ,handle))))))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.