5

SQL mode has some cool stuff set up for indenting with aligned keywords and such. Normally, I'd think it was cool. The problem is that at my new job, the people who wrote our mountains of sql did not have this set up, and just indented sql 4 spaces.

I could bully them all into switching to emacs, but that's more of a long term project. In the short term, I want to make emacs indent sql in the stupid way lesser editors do it: 4 spaces, more or less ignorant of context. How would I do this?

EDIT:

A so-so solution is to create a mode hook with (setq indent-line-function 'tab-to-tab-stop). Unfortunately, this interacts badly with indent-tabs-mode nil and the lack of a customized backspace function. What i'd really like is something straightforward that would allow bounce-indent within a few levels.

EDIT2:

I no longer actually need this. I've just started indenting my own SQL correctly, and everyone else seems to appreciate it.

2 Answers 2

1

I'm not sure I understand exactly what you mean by "bounce-indent within a few levels". Would something like the following suit you?

It works more or less like in python: the first time you indent, you go 4 columns further than the previous line. If you keep pressing TAB, you decrease the indentation level until you hit the first column (at which point you cycle back to the most indented level)

(defun my-indent ()
  (let ((last-indent (if (> (line-number-at-pos) 1)
                         (save-excursion
                           (previous-line)
                           (back-to-indentation)
                           (current-column))
                       0)))
    (save-excursion
      (back-to-indentation)
      (if (and (eq last-command this-command)
               (> (point) (line-beginning-position)))
          (delete-region (max (line-beginning-position) (- (point) 4)) (point))
        (while (< (current-column) (+ 4 last-indent))
          (insert " "))))
    (if (< (point) (save-excursion (back-to-indentation) (point)))
        (back-to-indentation))))


(defun my-sql-mode-hook ()
  (setq indent-line-function 'my-indent))

(add-hook 'sql-mode-hook 'my-sql-mode-hook)
1
  • This looks cool. I'll try it, and maybe accept it. In any case, I no longer really need it, but I'll keep it in mind for when a similar problem comes up (it probably will). Sep 11, 2015 at 23:06
0

You might want to take a look at this SO response for reference, which details how to switch emacs to defaulting to spaces instead of tabs and how to get tab to insert spaces in multiples of 4. Specifically for SQL mode, you should include this code:

;; Use the regular major mode hook to add a buffer-local hack-local-variables-hook
(add-hook 'sql-mode-hook 'my-sql-mode-hook)
(defun my-sql-mode-hook ()
  (add-hook 'hack-local-variables-hook
            (lambda () (setq indent-tabs-mode nil) (setq tab-width 4) )))
            nil t))

The real meat of the code is inside the lambda function and relies on setting the local variables indent-tabs-mode and tab-width. Including this in you init.el will cause sql-mode to use tabs instead of spaces and make the tab width 4 spaces.

5
  • 1
    Wouldn't using setq-default affect the value for all modes?
    – npostavs
    Jul 12, 2015 at 17:20
  • @npostavs whoops, you're right. Code updated to use setq rather than setq-default.
    – GJStein
    Jul 12, 2015 at 17:38
  • Maybe you misunderstood. The point isn't about tabs or tab width. I already set both of those variables globally. It's about overriding the default indentation method. I think I figured it out though. Jul 12, 2015 at 19:42
  • Sure, ok. Glad you figured it out.
    – GJStein
    Jul 12, 2015 at 19:49
  • I actually didn't really. I have an ugly approach that's nowhere near satisfactory. I edited the OP. Jul 12, 2015 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.