2012-05-07 3 views
3

Стандартно в большинстве современных редакторов вы можете выделить фрагмент кода и отступы или отменить вкладку или сколько бы пространства вы ни использовали; как вы это делаете в emacs?Tab и Shift-Tab интеллектуальный отступ по выбранному тексту

Так, например, я только что открыл возвышенный текст, выделен следующий фрагмент кода:

variation1 person phoneMap carrierMap addressMap = 
    case M.lookup person phoneMap of 
     Nothing -> Nothing 
     Just number -> 
      case M.lookup number carrierMap of 
      Nothing -> Nothing 
      Just carrier -> M.lookup carrier addressMap 

прижимаются язычок и получил

variation1 person phoneMap carrierMap addressMap = 
     case M.lookup person phoneMap of 
     Nothing -> Nothing 
     Just number -> 
      case M.lookup number carrierMap of 
       Nothing -> Nothing 
       Just carrier -> M.lookup carrier addressMap 

один сдвиг вкладками на этот код возвращает его обратно где это было, и если я продолжаю нажимать shift-tab, я в конечном итоге получаю следующее:

variation1 person phoneMap carrierMap addressMap = 
case M.lookup person phoneMap of 
Nothing -> Nothing 
Just number -> 
case M.lookup number carrierMap of 
Nothing -> Nothing 
Just carrier -> M.lookup carrier addressMap 

Цитата из другого ответа:

режимы Emacs языка на самом деле не имеют понятия «отступа этот блок 1 вкладка дальше». Вместо этого они очень упрямы и имеют понятие «это правильный отступ», и это то, что вы получаете, когда вы нажимаете вкладку в языковом режиме.

исключением случаев, когда я делаю это с помощью следующего кода (режим Haskell и GHC мод включен):

import Monad 
import System 
import IO 
import Random 
import Control.Monad.State 

type RandomState a = State StdGen a 
data CountedRandom = CountedRandom { 
     crGen :: StdGen 
    , crCount :: Int 
    } 

type CRState = State CountedRandom 

getRandom :: Random a => RandomState a 
getRandom = 
    get >>= \gen -> 
    let (val, gen') = random gen in 
    put gen' >> 
    return val 

я получаю следующее:

import Monad 
    import System 
    import IO 
    import Random 
    import Control.Monad.State 

type RandomState a = State StdGen a 
data CountedRandom = CountedRandom { 
    crGen :: StdGen 
    , crCount :: Int 
    } 

type CRState = State CountedRandom 

       getRandom :: Random a => RandomState a 
       getRandom = 
    get >>= \gen -> 
    let (val, gen') = random gen in 
    put gen' >> 
    return val 

, когда я хотел

import Monad 
import System 
import IO 
import Random 
import Control.Monad.State 

type RandomState a = State StdGen a 
data CountedRandom = CountedRandom { 
     crGen :: StdGen 
    , crCount :: Int 
    } 

type CRState = State CountedRandom 

getRandom :: Random a => RandomState a 
getRandom = 
    get >>= \gen -> 
    let (val, gen') = random gen in 
    put gen' >> 
    return val 

Достаточно близко к раствору из ataylor:

(defcustom tab-shift-width 4 
    "Sets selected text shift width on tab" 
    :type 'integer) 
(make-variable-buffer-local 'tab-shift-width) 

(global-set-key 
(kbd "<tab>") 
(lambda (start end) 
    (interactive "r") 
    (if (use-region-p) 
     (save-excursion 
    (let ((deactivate-mark nil)) 
     (indent-rigidly start end tab-shift-width))) 
    (indent-for-tab-command)))) 

(global-set-key 
(kbd "S-<tab>") 
(lambda (start end) 
    (interactive "r") 
    (if (use-region-p) 
     (save-excursion 
    (let ((deactivate-mark nil)) 
     (indent-rigidly start end (- tab-shift-width)))) 
    (indent-for-tab-command)))) 

Было бы неплохо, если бы Emacs была поддержка отступа обнаружения (т.е. просто захватить значение некоторой переменной); самая близкая вещь, которую я обнаружил, это плагин под названием dtrt indent, но он не работает для Haskell.

+0

Dunno о emacs, но в vim есть режим выбора прямоугольника; вставка текста в режим прямоугольного выделения вставляет этот текст в одно и то же место на каждой строке. Такая вещь должна решить вашу проблему, если emacs имеет аналог (и, вероятно, это делает). –

ответ

1

indent-region будет повторно содержать блок текста в соответствии с текущим режимом.

Чтобы добавить уровень отступов, вы можете использовать string-rectangle, в котором вам будет предложено ввести строку. Здесь вы можете указать строку для уровня отступов (например, вкладку, 4 пробела и т. Д.). Строка будет вставлена ​​в каждую строку текущего выбранного региона, в текущем столбце, эффективно отступы. В качестве альтернативы вы можете получить аналогичный эффект от open-rectangle, который будет вставлять пробелы в прямоугольник с углами, определяемыми точкой и меткой.

Другой способ принудительного отступа - позвонить по телефону indent-rigidly (C-x TAB). Это переопределяет специальные правила отступов и отступы фиксированной суммы. Числовой аргумент указывает, сколько отступ, и отрицательный аргумент будет недействительным. Если вы хотите, чтобы это поведение по умолчанию при выборе области, вы могли бы сделать что-то вроде этого:

(global-set-key 
(kbd "<tab>") 
(lambda (start end) 
    (interactive "r") 
    (if (use-region-p) 
     (save-excursion 
    (let ((deactivate-mark nil)) 
     (indent-rigidly start end 4))) 
    (indent-for-tab-command)))) 
+0

Как мне привязать это к сдвигу-вкладке/вкладке так, чтобы она считывала, какой отступ я использую, и применяет желаемое поведение? Должен ли я изучать elisp, чтобы добавить стандартное поведение, данное в большинстве других редакторов? – joshj

+0

Обновлен мой ответ. 'indent-rigidly' делает примерно то, что вы хотите. Добавлен пример того, как вы могли привязать его к 'TAB', когда выбран регион. – ataylor

0

Я выделил область и набрал C-M-\. Это indent-region и больше удовольствия можно найти на странице multi-line indent.

+0

Когда я делаю это (C-M - \\) в своем примере кода, он просто выглядит как последний пример в моем вопросе (без учета всех вкладок). И когда я использую indent-code-rigidly, он просто перемещает его вперед на одно пространство. Действительно, я хочу найти привязку или возможно плагин emacs, который дает мне поведение tab/shift-tab любого другого редактора кода, который я когда-либо использовал. Например, в vim я бы сделал 'vmap > gv vmap joshj

+0

На каком языке кода? из того, что я вижу в вашем фрагменте кода, просто перемещается на 2 пробела, нет? Таким образом, область отступа будет иметь отступ, основанный на «где это должно быть», и берет линию над этим фрагментом, поскольку это базовая линия. Может быть, этот язык имеет свой собственный отступ-регион в этом режиме? – pjammer

+0

Это haskell, и я очистил свои .emac при попытке вашего предложения. Я просто попробовал это с кодом на C++, и он автоматически отбросил выбор до того, что, по его мнению, должно быть (это было неправильно). – joshj

0

Режимы языка emacs на самом деле не имеют понятия «отступ этого блока 1 вкладка дальше». Вместо этого они очень упрямы и имеют понятие «это правильный отступ», и это то, что вы получаете, когда вы нажимаете вкладку в языковом режиме.

Как только вы привыкнете к этому, все остальное кажется странным. В вашем коде Haskell эти операторы case действительно имеют один отступ, который действителен, и все остальное является синтаксической ошибкой, если вы не добавите фигурные скобки и точки с запятой. Если вы действительно хотите настроить то, что emacs считает «правильным» отступом, смотрите, как настроить свой режим. Многие языковые режимы повторно используют переменные c-mode, поэтому here, вероятно, является хорошим местом для начала (хотя я не уверен, что режим Haskell делает, я никогда не находил необходимости настраивать его).

Редактировать: Я вижу в ваших комментариях, что ваши проблемы из-за отсутствия режима Haskell, достались github page, чтобы получить его.

+0

Я ответил вам в оригинальном вопросе с помощью редактирования. – joshj

2

Haskell код невероятно трудно правильно отступы, потому что есть несколько «правильных» Углубления для куска код.

haskell-mode имеет очень специфический формат линии, который он ожидает от вас (как в случае, вам нужно сделать разрывы строк в правильных местах), и в нем есть несколько правил отступа для форматирования кода, соответствующего этому формату. Эти правила существуют, чтобы сделать результаты автоматического отступов более согласованными. Правила примерно таковы:

  • После каждого ключевого слова, которое вводит блок, вы должны сделать разрыв строки или убедиться, что весь блок вписывается в макет. В противном случае вы получаете множество подвесных блоков, например, в вашем getRandom
  • Все блоки имеют отступы ровно два пробела. Это включает в себя модули модулей; если вы делаете module Bla where, вся часть после этой строки будет отступом. Это означает, что вы должны сохранить формат файла по умолчанию Haskell для того, чтобы порядок отступов работал.
  • Отступ линии должен быть как можно более однозначным; если линия может означать разные вещи в зависимости от ее отступов, это приведет к тому, что она будет отступом до положения, которое, по мнению haskell-mode, имеет смысл в контексте. Фиксация этого может быть невозможна в некоторых случаях.

Поскольку невозможно структурировать код Haskell, чтобы он соответствовал требованиям haskell-mode, вы не можете отступать в то время как код кода Haskell. Вы должны использовать автоматический отступ только локально. Это может быть сделано несколькими способами:

  • Когда вы находитесь на линии, вы можете задать отступ текущей строки в наиболее вероятной «правильной» позиции по отношению к предыдущей строке, нажав клавишу TAB . Нажав на кнопку TAB, вы переведете линию на «следующий» уровень отступов и непрерывно выполняете все возможные шаги логического отступа.
  • Если вы выберете серию блоков, которые находятся локально (тело функции и т. Д.), И используйте M-x indent-region, результат, скорее всего, будет правильным.

То, что я обычно делаю в такой ситуации, как это начать на линии, которая имеет «неправильный» отступ, нажмите TAB один раз, и идти вниз линию за линией, нажав TAB один или несколько раз на каждой строке до тех пор, пока отступ в этой строке не будет правильным. Текущие «логические позиции отступов» для текущей строки вычисляются из предыдущего контекста кода, поэтому исправление отступа от вершины почти всегда дает правильный результат.

Смежные вопросы