It’s standard in most modern editors that you can highlight a piece of code and indent or unindent a tab or however many spaces you’re using; how do you do this in emacs?
So, for example I just opened sublime text, highlighted the following piece of code:
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
then pressed tab and got
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
one shift-tab on that code returns it back to where it was, and if I continuing pressing shift-tab I eventually get the following:
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
Quote from another response:
emacs language modes don’t really have a notion of ‘indent this block
1 tab further’. Instead they’re very opinionated and have a notion of
‘this is the correct indentation’ and that’s what you get when you hit
tab in a language mode.
Except when I do that with the following code (haskell mode and ghc mod enabled):
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
I get the following:
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
when I wanted
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
Near enough to a solution from 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))))
It’d be nice if emacs had support for indent detection (i.e., just grab the value of some variable); the closest thing I found to this was a plugin called dtrt indent but it doesn’t work for Haskell.
indent-regionwill reindent a block of text according to the current mode.To force an indentation level to be added, you can use
string-rectangle, which will prompt you for a string. Here you can provide the string for an indentation level (e.g. a tab, 4 spaces, etc.). The string will be inserted on each line of the currently selected region, in the current column, effectively indenting it. Alternatively, you can get a similar effect fromopen-rectangle, which will insert whitespace into the rectangle with corners defined by the point and the mark.Another way to force indentation is to call
indent-rigidly(C-x TAB). This overrides the mode specific indentation rules and indents a fixed amount. The numeric argument specifies how much to indent, and a negative argument will unindent. If you want this to be the default behavior when a region is selected, you could do something like this: