इंडेंटेशन द्वारा नेविगेट करें


15

मैं इंडेंटेशन के आधार पर किसी फ़ाइल की पंक्तियों के बीच नेविगेट करना चाहता हूं। फ़ाइल को इंडेंटेशन द्वारा संरचित किया जाता है: एक लाइन जो पिछली लाइन की तुलना में अधिक इंडेंट होती है वह पिछली लाइन का एक बच्चा है, एक ऐसी लाइन जिसमें पिछली लाइन के समान इंडेंटेशन होता है। मैं ज्यादातर तीन कमांड ढूंढ रहा हूं:

  • अगली सिबिलिंग पर जाएं, यानी अगली लाइन उसी इंडेंटेशन के साथ, लंघन रेखाएं जो अधिक इंडेंटेड हैं, लेकिन ऐसी रेखा से अतीत नहीं लंघन करना जो कम इंडेंटेड हो।
  • पिछली सिबलिंग पर जाएं, यानी दूसरी दिशा में भी यही बात।
  • कम इंडेंटेशन के साथ माता-पिता की पिछली लाइन पर जाएं।

बिंदु की कॉलम स्थिति नहीं बदलनी चाहिए।

ये खरोज संरचित डेटा के लिए एनालॉग हैं forward-sexp, backward-sexpऔर backward-up-listsexp संरचित डेटा के लिए। इंडेक्सेशन हस्केल और पायथन जैसी भाषाओं में प्रोग्राम संरचना से मेल खाती है; ये कार्य इस संदर्भ में विशेष रूप से उपयोगी हो सकते हैं, लेकिन मैं कुछ भी मोड-विशिष्ट (मेरा प्राथमिक उपयोग मामला किसी अन्य फ़ाइल प्रारूप के अंदर डेटा को संरचित-संरचित) के लिए नहीं देख रहा हूं।

रंग इंडेंटेशन स्तर मैन्युअल रूप से Up/ Downलेकिन मुझे कुछ स्वचालित चाहिए के साथ नेविगेट करने में मदद कर सकते हैं ।

यह सुपर उपयोगकर्ता प्रश्न समान है, लेकिन कमजोर आवश्यकताओं के साथ है और वर्तमान में मेरे आवश्यकताओं को पूरा करने वाले उत्तर नहीं हैं।


क्या set-selective-displayआपको वह मिलता है जिसकी आपको आवश्यकता है?
कौशल मोदी

1
@KaushalModi यह उपयोगी है, और मुझे इस बारे में पता नहीं था, इसलिए धन्यवाद, लेकिन यह हमेशा वह नहीं है जिसकी मुझे आवश्यकता है। बस अब, मैं उन रेखाओं के बारे में जानना चाहता था जिन्हें मैं आगे बढ़ रहा था।
गिल्स एसओ- बुराई को रोकना '

यह प्रश्न पूछने के लिए धन्यवाद; मैं मूल रूप से एक ही सवाल पूछने के बारे में था केवल कम अच्छी तरह से। केवल एक और चीज जो मैं चाहूंगा वह है "अंतिम सिबलिंग की ओर बढ़ना" अर्थात अंतिम पंक्ति जिसमें समान इंडेंटेशन है, न कि लंघन की गई रेखाएं जो कम इंडेंटेड हैं। (दोहराए जाने के बराबर "अगले भाई-बहन के लिए कदम" जब तक कि कोई भी न हो।)
श्रीवत्सआर

मैंने केवल indent-toolsमेल्पा ( इंडेंट-टूल्स ) में पैकेज पर ध्यान दिया , जो शायद इस उद्देश्य के लिए काम करता है। यह सवाल पूछे जाने के लगभग 3 महीने बाद 2016-मई -16 को पहली कमेटी बनी थी।
श्रीवत्सआर

जवाबों:


4

वर्तमान में उपलब्ध चार उत्तरों की जाँच ( दो सुपर यूजर पर और दो इस सवाल पर), मैं निम्नलिखित मुद्दों को देखता हूं:

  • स्टीफन और पेंग बाई द्वारा लोगों SuperUser पर (पंक्ति-दर-पंक्ति चलती वर्तमान खरोज को देखते हुए), वर्तमान स्तंभ स्थिति को बनाए रखना और माता पिता के लिए ऊपर जा रहा है को लागू नहीं करते
  • दान से जवाब (फिर से खोज से आगे का उपयोग कर एक ही खरोज के साथ अगली पंक्ति को खोजने के लिए) कम खरोज के साथ लाइनों पर छोड़ देता है: जब कोई अगले भाई है यह पता नहीं है, और इसलिए कुछ करने के लिए स्थानांतरित कर सकते हैं कि एक भाई नहीं है लेकिन एक और माता-पिता का बच्चा ... शायद एक "चचेरा भाई"।
  • गिल्स का जवाब (आउटलाइन-मोड का उपयोग करके) स्तंभ की स्थिति को बनाए नहीं रखता है और यह शून्य इंडेंटेशन ("शीर्ष-स्तरीय" लाइनों) के साथ काम नहीं करता है। इसके अलावा, इसके कोड को देखते हुए outline.el, यह मूल रूप outline-next-visible-headingसे हमारे मामले में वैसे भी (उपयोग करके ) लाइन-बाय-लाइन जा रहा है , जैसा कि (लगभग) सभी लाइनें रूपरेखा regexp से मेल खाती हैं और "हेडिंग" के रूप में गिना जाता है।

इसलिए, प्रत्येक के कुछ विचारों को एक साथ रखते हुए, मेरे पास निम्नलिखित हैं: खाली और अधिक-इंडेंटेड लाइनों को छोड़ते हुए, लाइन-बाय-लाइन को आगे बढ़ाएं। यदि आप समान इंडेंटेशन पर हैं तो यह अगले भाई-बहन है। मूल विचार इस प्रकार है:

(defun indentation-get-next-sibling-line ()
  "The line number of the next sibling, or nil if there isn't any."
  (let ((wanted-indentation (current-indentation)))
    (save-excursion
      (while (and (zerop (forward-line))  ; forward-line returns 0 on success
               (or (eolp)  ; Skip past blank lines and more-indented lines
                 (> (current-indentation) wanted-indentation))))
      ;; Now we can't go further. Which case is it?
      (if (and (not (eobp)) (= (current-indentation) wanted-indentation))
        (line-number-at-pos)
        nil))))

(defun indentation-forward-to-next-sibling ()
  (interactive)
  (let ((saved-column (current-column)))
    (forward-line (- (indentation-get-next-sibling-line) (line-number-at-pos)))
    (move-to-column saved-column)))

सामान्य रूप से सामान्यीकृत (आगे / पीछे / ऊपर / नीचे), जो मैं उपयोग कर रहा हूं वह वर्तमान में निम्न प्रकार दिखता है:

(defun indentation-get-next-good-line (direction skip good)
  "Moving in direction `direction', and skipping over blank lines and lines that
satisfy relation `skip' between their indentation and the original indentation,
finds the first line whose indentation satisfies predicate `good'."
  (let ((starting-indentation (current-indentation))
         (lines-moved direction))
    (save-excursion
      (while (and (zerop (forward-line direction))
               (or (eolp)  ; Skip past blank lines and other skip lines
                 (funcall skip (current-indentation) starting-indentation)))
        (setq lines-moved (+ lines-moved direction)))
      ;; Now we can't go further. Which case is it?
      (if (and
            (not (eobp))
            (not (bobp))
            (funcall good (current-indentation) starting-indentation))
        lines-moved
        nil))))

(defun indentation-get-next-sibling-line ()
  "The line number of the next sibling, if any."
  (indentation-get-next-good-line 1 '> '=))

(defun indentation-get-previous-sibling-line ()
  "The line number of the previous sibling, if any"
  (indentation-get-next-good-line -1 '> '=))

(defun indentation-get-parent-line ()
  "The line number of the parent, if any."
  (indentation-get-next-good-line -1 '>= '<))

(defun indentation-get-child-line ()
  "The line number of the first child, if any."
  (indentation-get-next-good-line +1 'ignore '>))


(defun indentation-move-to-line (func preserve-column name)
  "Move the number of lines given by func. If not possible, use `name' to say so."
  (let ((saved-column (current-column))
          (lines-to-move-by (funcall func)))
    (if lines-to-move-by
      (progn
        (forward-line lines-to-move-by)
        (move-to-column (if preserve-column
                          saved-column
                          (current-indentation))))
      (message "No %s to move to." name))))

(defun indentation-forward-to-next-sibling ()
  "Move to the next sibling if any, retaining column position."
  (interactive "@")
  (indentation-move-to-line 'indentation-get-next-sibling-line t "next sibling"))

(defun indentation-backward-to-previous-sibling ()
  "Move to the previous sibling if any, retaining column position."
  (interactive "@")
  (indentation-move-to-line 'indentation-get-previous-sibling-line t "previous sibling"))

(defun indentation-up-to-parent ()
  "Move to the parent line if any."
  (interactive "@")
  (indentation-move-to-line 'indentation-get-parent-line nil "parent"))

(defun indentation-down-to-child ()
  "Move to the first child line if any."
  (interactive "@")
  (indentation-move-to-line 'indentation-get-child-line nil "child"))

अभी भी कुछ और कार्यक्षमता वांछनीय है, और इसमें से कुछ को देखने outline.elऔर फिर से लागू करने में मदद मिल सकती है, लेकिन मैं अभी अपने उद्देश्यों के लिए इसके साथ खुश हूं।


@ गिल्स: संपादन के लिए धन्यवाद! ऐसा लगता (current-line)है misc-fns.elकि मैं किसी तरह से कुछ oneonone.elपुस्तकालय के हिस्से के रूप में अपने एक्वामाक्स इंस्टॉलेशन में था ।
श्रीवत्सआर

6

यह सुविधा Emacs में मौजूद है। आउटलाइन मोड एक दस्तावेज़ का वर्णन करता है जिसमें एक स्तर के साथ हेडिंग लाइनें होती हैं, और इसमें स्तरों के बीच ले जाने की सुविधा होती है। हम हर लाइन को एक हेडिंग लाइन के रूप में एक स्तर के साथ परिभाषित कर सकते हैं जो इसके इंडेंटेशन को दर्शाता है: इंडेंटेशन पर सेट outline-regexpहै। अधिक सटीक रूप से, इंडेंटेशन प्लस पहला गैर-व्हाट्सएप चरित्र (और फ़ाइल की शुरुआत ऊपरवाला स्तर है) \`\|\s-+\S-:।

M-x load-libray outline RET
M-: (make-local-variable 'outline-regexp) RET
M-: (setq outline-regexp "\\`\\|\\s-+\\S-") RET
M-x outline-minor-mode RET

Emacs 22.1–24.3 में आप इसे सरल कर सकते हैं:

M-x load-libray outline RET
M-1 M-x set-variable RET outline-regexp RET "\\`\\|\\s-+\\S-" RET
M-x outline-minor-mode RET

तब आप रूपरेखा गति आदेशों का उपयोग कर सकते हैं :

  • C-C @ C-f( outline-forward-same-level) अगले भाई को स्थानांतरित करने के लिए;
  • C-C @ C-b( outline-backward-same-level) पिछले भाई को स्थानांतरित करने के लिए;
  • C-C @ C-u( outline-up-heading) माता-पिता को स्थानांतरित करने के लिए।

एक टैब और एक स्थान पर समान मात्रा में इंडेंटेशन के लिए गणना होती है। यदि आपके पास टैब और रिक्त स्थान का मिश्रण है, तो उचित रूप से सेट tab-widthकरें और कॉल करेंuntabify

यदि वर्तमान प्रमुख मोड में रूपरेखाएँ हैं, तो वे संघर्ष कर सकते हैं। इस स्थिति में, आप एक से अधिक कई प्रमुख मोड समाधान का उपयोग कर सकते हैं, सबसे सरल एक अप्रत्यक्ष बफर बनाने के लिए और इसे आउटलाइन मेजर मोड पर सेट करने के लिए। आउटलाइन मेजर मोड में, डिफॉल्ट कीबोर्ड शॉर्टकट टाइप करने के लिए सरल हैं: C-c C-fआदि।


ऐसा लगता है कि यह काम करना चाहिए, लेकिन वास्तव में किसी कारण से मेरे लिए काम नहीं करता है। M-x make-local-variable RET outline-regexp RETउस चर को स्वीकार नहीं करता है, और केवल `[कोई मैच नहीं]` कहता है। इसे अभी और ध्यान से देखना है।
श्रीवत्सआर

@ श्रीवत्सआर Emacs 24.4 में यह एक असंगत परिवर्तन है: outline-regexpअब कोई डिफक्यूट नहीं है और इसे इतनी आसानी से अंतःक्रियात्मक रूप से सेट नहीं किया जा सकता है।
गिल्स 'SO- बुराई होना बंद करो'

बहुत बढिया आपको धन्यवाद। दो मामूली मुद्दे हैं: (1) यदि आप सबसे ऊपरी स्तर पर हैं (बिना किसी इंडेंटेशन वाली एक लाइन, जिसका मुझे अनुमान है कि आउटलाइन-रेगेक्सपी के लिए कोई मैच नहीं है) तो न तो आगे और न ही पिछड़े काम करता है, और किसी कारण से यह दो हो जाता है लाइनें (2) जब यह अगले या पिछले भाई के पास जाती है, तो यह लाइन की शुरुआत में जाती है (कॉलम 0) लेकिन कॉलम को बनाए रखना अच्छा होगा। (जैसा कि आप प्रश्न में निर्दिष्ट करते हैं।) मुझे लगता है कि ये दोनों ही रूपरेखा मोड की सीमाएं हो सकती हैं।
श्रीवत्सआर

5

निम्नलिखित तीन आज्ञाओं को, न्यूनतम परीक्षण किया गया, उन्हें इंडेंटेड लाइनों द्वारा बुनियादी नेविगेशन के लिए अनुमति देनी चाहिए। कोड पुनरावृत्ति के लिए माफी।

(defun ind-forward-sibling ()
  "Move forward to the next sibling line with the same indentation."
  (interactive)
  (save-match-data
    (let ((col (current-column))
          (pad (progn
                 (back-to-indentation)
                 (current-column))))
      (end-of-line 1)
      (re-search-forward (concat "^\\s-\\{"
                                 (number-to-string pad)
                                 "\\}[^ ]") nil t)
      (move-to-column col))))

(defun ind-backward-sibling ()
  "Move backward to the next sibling line with the same indentation."
  (interactive)
  (save-match-data
    (let ((col (current-column))
          (pad (progn
                 (back-to-indentation)
                 (current-column))))
      (beginning-of-line 1)
      (re-search-backward (concat "^\\s-\\{"
                                 (number-to-string pad)
                                 "\\}[^ ]") nil t)
      (move-to-column col))))

(defun ind-up-parent ()
  "Move up to parent line with less indentation."
  (interactive)
  (save-match-data
    (let ((col (current-column))
          (pad (progn
                 (back-to-indentation)
                 (current-column))))
      (when (> pad 0)
        (beginning-of-line 1)
        (re-search-backward (concat "^\\s-\\{0,"
                                    (number-to-string (1- pad))
                                    "\\}[^ ]") nil t))
      (move-to-column col))))

यह अच्छा है (तय होने के बाद - मुझे समझ में नहीं आ रहा है कि आप 1 को घटाकर क्या करना चाह रहे थे, (current-column)लेकिन यह कर्सर को स्थानांतरित नहीं करने का कारण बनता है), लेकिन यह वास्तव में मेरी कल्पना को पूरा नहीं करता है: एक इंडेंटेशन स्तर पर चलना अतीत से कम चलता है- इंडेंटेड लाइन्स।
गिल्स एसओ- बुराई को रोकना '

यह काम नहीं करता है। उदाहरण के लिए, ind-forward-siblingबस एक ही इंडेंटेशन के साथ अगली लाइन की तलाश करता है, इसलिए यह कम इंडेंटेशन के साथ लाइनों पर स्कीप करता है (यह तब भी आगे बढ़ता है जब आगे कोई भाई नहीं होता है)।
श्रीवत्सआर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.