Emacs में लाइन / क्षेत्र को ऊपर और नीचे ले जाएं


85

चयनित क्षेत्र या रेखा (यदि कोई चयन नहीं है) को ईमैक में ऊपर या नीचे ले जाने का सबसे आसान तरीका क्या है? मैं उसी कार्यक्षमता की तलाश कर रहा हूं जो ग्रहण में है (एम-अप, एम-डाउन के लिए बाध्य है)।


1
मुझे पूरा यकीन है कि मुहावरा सिर्फ उस चीज को मारना है जिसे आप स्थानांतरित करना चाहते हैं, उस बिंदु को स्थानांतरित करने के लिए सामान्य नेविगेशन फ़ंक्शंस (isearch सहित, आदि) का उपयोग करें जहां आप चाहते हैं कि कोड हो, और फिर yank। वहाँ मारता है, याद है, तो आप भी तुरंत स्थान खोजने की जरूरत नहीं है; बाद में आप अन्य बिट्स को इकट्ठा कर सकते हैं। व्यक्तिगत रूप से, एक भारी Emacs उपयोगकर्ता के रूप में, मैं किसी भी स्थिति की कल्पना नहीं कर सकता, जहां मैं मैन्युअल रूप से एक पंक्ति को ऊपर या नीचे ले जाऊं। यह सिर्फ उपयोगी नहीं होगा।
jrockway

7
@ जोकवे: आपकी टिप्पणी के लिए धन्यवाद। मुझे लगता है कि हर किसी का काम करने का अपना तरीका होता है। मैं ग्रहण के साथ बहुत काम करता हूं और मैं लाइनों / क्षेत्रों को स्थानांतरित करने के लिए बहुत आदत रखता हूं। Emacs बहुत ही एक्स्टेंसिबल होने की एक बड़ी बात यह है कि इस कार्यक्षमता को आसानी से जोड़ा जा सकता है।
fikovnik

3
माना। मैं बार-बार लाइनों को ऊपर-नीचे करना चाहता हूं जैसा कि आप वर्णन करते हैं, चाहे मैं एक संपादक में हूं या नहीं जो इसका समर्थन करता है। या, उस मामले के लिए, मैं कोड पर काम कर रहा हूं या नहीं। वर्ड ऑल्ट (शिफ्ट + अप और डाउन) के साथ इसे (पैराग्राफ को) सपोर्ट करता है, और मैं अपने संपादकों को मैप करता हूं कि जब भी मैं कर सकता हूं।
हार्पो

6
@ ड्रू और जॉकवे: मुझे लगता है कि कम के लिए समझौता करना शायद ही एमएसीएस तरीका है। जब आप उन्हें मारना चाहते हैं तो उन्हें हिलाना आसान होता है। और ऑर्ग-मोड ऑफ़कोर्स ने इसे एक कारण के लिए भी लागू किया है: वास्तव में ऐसे कई मामले हैं जो आप एक लाइन को स्थानांतरित करना चाहते हैं, गलत तरीके से रखा गया स्टेटमेंट इन / आउट एक ब्लॉक स्कोप एक है, स्टेटमेंट ऑर्डर में बदलाव करें, डॉक्युमेंट ऑर्डर में बदलाव करें (ऑर्ग देखें-) मोड), .. बहुत से लोग इसे ग्रहण में उपयोग करते हैं। आप क्या उपयोग नहीं करते हैं, आप अक्सर याद नहीं करते हैं, लेकिन चलती लाइनों की उपयोगिता प्रोग्रामर्स की एक पूरी बहुत कुछ के लिए एक तथ्य है
पीटर

2
यह उपयोगी है जब git-rebase फ़ाइलों को संपादित करते हुए, उन कॉमेट्स की सूचियों को शामिल किया जाए जिन्हें आप फिर से लिखना चाहते हैं।
केन विलियम्स

जवाबों:


47

सीमा से बंधी ट्रांज़ोज़-लाइनों का उपयोग करके एक रेखा को स्थानांतरित किया जा सकता है C-x C-t। हालांकि क्षेत्रों के बारे में पता नहीं।

मुझे यह सटीक स्निपेट मिला जो आपको वह करना चाहता है, सिवाय इसके कि आपको बाइंडिंग बदलने की जरूरत है।

(defun move-text-internal (arg)
   (cond
    ((and mark-active transient-mark-mode)
     (if (> (point) (mark))
            (exchange-point-and-mark))
     (let ((column (current-column))
              (text (delete-and-extract-region (point) (mark))))
       (forward-line arg)
       (move-to-column column t)
       (set-mark (point))
       (insert text)
       (exchange-point-and-mark)
       (setq deactivate-mark nil)))
    (t
     (beginning-of-line)
     (when (or (> arg 0) (not (bobp)))
       (forward-line)
       (when (or (< arg 0) (not (eobp)))
            (transpose-lines arg))
       (forward-line -1)))))

(defun move-text-down (arg)
   "Move region (transient-mark-mode active) or current line
  arg lines down."
   (interactive "*p")
   (move-text-internal arg))

(defun move-text-up (arg)
   "Move region (transient-mark-mode active) or current line
  arg lines up."
   (interactive "*p")
   (move-text-internal (- arg)))

(global-set-key [\M-\S-up] 'move-text-up)
(global-set-key [\M-\S-down] 'move-text-down)

स्निपेट के लिए धन्यवाद। यही वह है जिसकी तलाश में मैं हूं!
fikovnik

इस समाधान के साथ थोड़ी समस्या है, और @sanityinc द्वारा पोस्ट किए गए लगभग समान: यदि मैं एक क्षेत्र को ऊपर और / या नीचे ले जाने के लिए परिभाषित शॉर्टकट का उपयोग करता हूं, तो तुरंत पूर्ववत करें (डिफ़ॉल्ट रूप से C-_) शॉर्टकट का उपयोग करें, क्षेत्र बस गायब हो जाता है, और संदेश "क्षेत्र में पूर्ववत करें!" प्रतिध्वनि क्षेत्र में प्रदर्शित किया जाता है। एक अन्य पूर्ववत आदेश "क्षेत्र के लिए कोई और पूर्ववत जानकारी नहीं" संदेश देता है। हालांकि, अगर मैं कर्सर को स्थानांतरित करता हूं, तो पूर्ववत करें, पूर्ववत फिर से काम करना शुरू कर देता है। एक अपेक्षाकृत मामूली जलन, लेकिन अन्य सभी Emacs कमांड एक चाल का सहारा लिए बिना तुरंत पूर्ववत किया जा सकता है।
तेमू लीस्टी

1
यह बिल्कुल ऐसा करने का सही तरीका है। Emacs में डिफ़ॉल्ट ट्रांज़ोज़ लाइन सही कार्यक्षमता नहीं है क्योंकि ट्रांसफ़र के बाद कर्सर अगली लाइन में चला जाता है, जिससे चरण दर चरण इसे दोहराना मुश्किल हो जाता है।
पौराणिक

51

अद्यतन: निम्नलिखित कोड प्राप्त करने के लिए move-textMarmalade या MELPA से पैकेज स्थापित करें ।

यहां मैं उपयोग करता हूं, जो दोनों क्षेत्रों और व्यक्तिगत लाइनों पर काम करता है:

(defun move-text-internal (arg)
  (cond
   ((and mark-active transient-mark-mode)
    (if (> (point) (mark))
        (exchange-point-and-mark))
    (let ((column (current-column))
          (text (delete-and-extract-region (point) (mark))))
      (forward-line arg)
      (move-to-column column t)
      (set-mark (point))
      (insert text)
      (exchange-point-and-mark)
      (setq deactivate-mark nil)))
   (t
    (let ((column (current-column)))
      (beginning-of-line)
      (when (or (> arg 0) (not (bobp)))
        (forward-line)
        (when (or (< arg 0) (not (eobp)))
          (transpose-lines arg)
          (when (and (eval-when-compile
                       '(and (>= emacs-major-version 24)
                             (>= emacs-minor-version 3)))
                     (< arg 0))
            (forward-line -1)))
        (forward-line -1))
      (move-to-column column t)))))

(defun move-text-down (arg)
  "Move region (transient-mark-mode active) or current line
  arg lines down."
  (interactive "*p")
  (move-text-internal arg))

(defun move-text-up (arg)
  "Move region (transient-mark-mode active) or current line
  arg lines up."
  (interactive "*p")
  (move-text-internal (- arg)))


(global-set-key [M-S-up] 'move-text-up)
(global-set-key [M-S-down] 'move-text-down)

1
Ive ने आपके लिए EmacsWiki में इसे शामिल किया, यह यहाँ है: emacswiki.org/emacs/MoveText
ocodo

धन्यवाद! मुझे लगता है कि कोड पहले से ही वहां था ( emacswiki.org/emacs/basic-edit-toolkit.el ) लेकिन इस नए पेज से लोगों को ढूंढना आसान हो जाएगा।
8

आह, कूल मैंने पहले नहीं देखा है, ऐसा लगता है कि बेसिक-एडिट-टूलकिट एक क्लीनअप का उपयोग कर सकता है।
ओसोडो

1
@ एमसीबी हां, किसी भी ईएलपीए पैकेज को एल-गेट के माध्यम से स्थापित किया जा सकता है। (ध्यान दें कि यहां तक ​​कि el-get लेखक इन दिनों package.el की ओर बढ़ रहा है।) पूर्ण लाइनों का चयन करने के लिए, मैं एक अलग फ़ंक्शन लिखने का सुझाव दूंगा जो जल्दी से वर्तमान लाइन का चयन करता है, या पूर्ण लाइनों को शामिल करने के लिए वर्तमान क्षेत्र का विस्तार करता है। फिर बस चाल-पाठ कार्यों से पहले उस फ़ंक्शन को लागू करें।
१३:१४

1
@sanityinc इसके लिए धन्यवाद। मैंने पहली बार मिनी एमएसीएस 'ओ' का इस्तेमाल किया था। अच्छी चीज़!
जेएस।

31

आपको कोशिश करनी चाहिए drag-stuff!

यह बिल्कुल ग्रहण की तरह काम करता Alt+ Up/ Downचयनित क्षेत्र लाइनों के लिए एकल लाइनों के लिए, साथ ही!

इसके अलावा, यह आपको शब्दों को Alt+ के साथ स्थानांतरित करने की अनुमति देता है Left/ Right
यह वही है जो आप देख रहे हैं! और यह ELPA रेपो से भी उपलब्ध है !

अन्य समाधानों ने कभी मेरे लिए काम नहीं किया। उनमें से कुछ छोटी थीं (अपने आदेश को बदलते हुए लाइनों को ट्रांसफ़ॉर्म करते हुए, wtf?) और उनमें से कुछ बिल्कुल चुने हुए क्षेत्र में जा रही थीं, जो लाइनों के अचयनित भागों को उनके पदों पर छोड़ रही थीं। लेकिन drag-stuffग्रहण की तरह ही काम करता है!

और भी अधिक! आप एक क्षेत्र का चयन करने और Alt+ Left/ का उपयोग करके कोशिश कर सकते हैं Right! यह चयनित क्षेत्र को एक वर्ण द्वारा बाईं या दाईं ओर स्थानांतरित करेगा। गजब का!

इसे विश्व स्तर पर सक्षम करने के लिए बस इसे चलाएं:

(drag-stuff-global-mode)

यह वास्तव में बाएँ और दाएँ आंदोलन को वैकल्पिक करने की आवश्यकता है, क्योंकि यह डिफ़ॉल्ट emacs कीमैप को ओवरराइड कर रहा है।
ओडोको

@Slomojo शायद! तुम क्यों नहीं सुझाव है कि emacswiki पर? :)
एलेक्सा-डैनियल जकिमेंको-ए।

1
मैं इसका उपयोग करता था, मैं अब स्मार्ट-शिफ्ट का उपयोग कर रहा हूं। मुझे यह पसंद है कि यह क्षैतिज आंदोलन के लिए DWIM है।
jpkotta

1
(drag-stuff-define-keys)कीबाइंडिंग काम शुरू करने से पहले इनिट फ़ाइल की आवश्यकता है। यह इस github में समझाया गया है: github.com/rejeep/drag-stuff.el
agent18

11

मैंने लाइनों को ऊपर / नीचे ले जाने के लिए कुछ इंटरैक्टिव कार्यों को लिखा है:

;; move line up
(defun move-line-up ()
  (interactive)
  (transpose-lines 1)
  (previous-line 2))

(global-set-key [(control shift up)] 'move-line-up)

;; move line down
(defun move-line-down ()
  (interactive)
  (next-line 1)
  (transpose-lines 1)
  (previous-line 1))

(global-set-key [(control shift down)] 'move-line-down)

कीबाइंडिंग IntelliJ IDEA स्टाइल हैं, लेकिन आप अपनी इच्छानुसार कुछ भी उपयोग कर सकते हैं। मुझे संभवतः कुछ कार्यों को लागू करना चाहिए जो क्षेत्रों पर भी काम करते हैं।


5

यहां वर्तमान रेखा या सक्रिय क्षेत्र द्वारा फैली लाइनों को स्थानांतरित करने के लिए मेरा स्निपेट है। यह कर्सर स्थिति और हाइलाइट किए गए क्षेत्र का सम्मान करता है। और जब क्षेत्र सीमा रेखा (नों) पर शुरू / समाप्त नहीं होता है तो यह रेखाएँ नहीं टूटेंगी। (यह ग्रहण से प्रेरित है; मैंने ग्रहण को 'ट्रांसपोज़-लाइन्स' की तुलना में अधिक सुविधाजनक पाया।)

;; move the line(s) spanned by the active region up/down (line transposing)
;; {{{
(defun move-lines (n)
  (let ((beg) (end) (keep))
    (if mark-active 
        (save-excursion
          (setq keep t)
          (setq beg (region-beginning)
                end (region-end))
          (goto-char beg)
          (setq beg (line-beginning-position))
          (goto-char end)
          (setq end (line-beginning-position 2)))
      (setq beg (line-beginning-position)
            end (line-beginning-position 2)))
    (let ((offset (if (and (mark t) 
                           (and (>= (mark t) beg)
                                (< (mark t) end)))
                      (- (point) (mark t))))
          (rewind (- end (point))))
      (goto-char (if (< n 0) beg end))
      (forward-line n)
      (insert (delete-and-extract-region beg end))
      (backward-char rewind)
      (if offset (set-mark (- (point) offset))))
    (if keep
        (setq mark-active t
              deactivate-mark nil))))

(defun move-lines-up (n)
  "move the line(s) spanned by the active region up by N lines."
  (interactive "*p")
  (move-lines (- (or n 1))))

(defun move-lines-down (n)
  "move the line(s) spanned by the active region down by N lines."
  (interactive "*p")
  (move-lines (or n 1)))

1
मेरे लिए मूव-टेक्स्ट पैकेज टूट गया था। आपका समाधान मेरे सिस्टम पर पूरी तरह से काम करता है। उसके लिए धन्यवाद!
रूण कागार्ड


1

कोई बिल्ट-इन नहीं है। आप ट्रांसपोज़-लाइन्स (Cx Ct) का उपयोग कर सकते हैं, लेकिन आप इसे बार-बार उपयोग नहीं कर सकते। Http://www.schuerig.de/michael/blog/index.php/2009/01/16/line-movement-for-emacs/ पर कार्यों को देखें

यह कि क्षेत्रों के लिए भी अनुकूलित करना आसान होना चाहिए।


1
Btw, यदि आप लिंक किए गए स्निपेट का उपयोग करने का निर्णय लेते हैं, तो आप लेट स्टेटमेंट को बदल सकते हैं (लेट ((करंट-कॉलम))) (लाइन-मूव-विज़ुअल नाइल)), अन्यथा आप लिपटे लाइनों के साथ मजाकिया व्यवहार करते हैं। ।
लियो अलेक्सेयेव

1

transpose-paragraphसमारोह आप मदद कर सकता है।

तुम भी Emacs मैनुअल में पारगमन अनुभाग को देखने के लिए चाहते हो सकता है । अनिवार्य रूप से:

C-t
Transpose two characters (transpose-chars).
M-t
Transpose two words (transpose-words).
C-M-t
Transpose two balanced expressions (transpose-sexps).
C-x C-t
Transpose two lines (transpose-lines).

0

मैं इसके लिए स्मार्ट-शिफ्ट पैकेज (मेलपा में) का उपयोग करता हूं। डिफ़ॉल्ट रूप से यह C-C <arrow>एक पंक्ति या क्षेत्र को स्थानांतरित करने के लिए विद्रोह करता है। यह एक प्रमुख-मोड-विशिष्ट राशि (जैसे सी-बेसिक-ऑफ़सेट या पायथन-इंडेंट-ऑफ़सेट) द्वारा क्षैतिज रूप से चलती है। क्षेत्रों पर भी काम करता है।

;; binds C-C <arrows>
(when (require 'smart-shift nil 'noerror)
  (global-smart-shift-mode 1))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.