Emacs indent, use tab for shell and spaces for c - emacs

Is there a way to configure emacs so C-files are indented with four spaces and shell scripts with tab?

For instance:
(add-hook 'c-mode-common-hook (lambda ()
(setq indent-tabs-mode nil)
(set c-basic-offset 4)))
(add-hook 'sh-mode-hook (lambda () (setq indent-tabs-mode t)))

Related

Emacs ignoring setq for line numbers

I am trying to set up my .emacs to use relative line numbering, and so I have included:
(setq display-line-numbers 'relative)
to my .emacs, however this is being ignored on load. Line numbers appear, however they are simply absolute line numbers, as opposed to relative.
Interestingly, when I run M-x load-file .emacs, it actually evaluates this line (as well as the rest of the file) and the line numbers become relative, however this doesn't happen the first time.
Below is my entire .emacs, and the line in question is on line 95/96:
(package-initialize)
(load "~/.emacs.rc/rc.el")
(load "~/.emacs.rc/misc-rc.el")
(defun rc/get-default-font ()
(cond
((eq system-type 'windows-nt) "Consolas-13")
((eq system-type 'gnu/linux) "Iosevka-24")))
(add-to-list 'default-frame-alist `(font . ,(rc/get-default-font)))
(tool-bar-mode 0)
(menu-bar-mode 0)
(scroll-bar-mode 0)
(column-number-mode 1)
(show-paren-mode 1)
(rc/require-theme 'gruber-darker)
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(package-selected-packages
'(svelte-mode tramp-mode elixir-mode evil move-text nasm-mode company yasnippet multiple-cursors magit haskell-mode ido-completing-read+ smex gruber-darker-theme dash-functional dash)))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
(eval-after-load 'zenburn
(set-face-attribute 'line-number nil :inherit 'default))
(rc/require 'smex 'ido-completing-read+)
(require 'ido-completing-read+)
(ido-mode 1)
(ido-everywhere 1)
(ido-ubiquitous-mode 1)
(global-set-key (kbd "M-x") 'smex)
(global-set-key (kbd "C-c C-c M-x") 'execute-extended-command)
;;; C mode
(setq-default c-basic-offset 4
c-default-style '((java-mode . "java")
(awk-mode . "awk")
(other . "bsd")))
(add-hook 'c-mode-hook (lambda ()
(interactive)
(c-toggle-comment-style -1)))
;;; Elisp
(add-hook 'emacs-lisp-mode-hook
'(lambda ()
(local-set-key (kbd "C-c C-j")
(quote eval-print-last-sexp))))
(add-to-list 'auto-mode-alist '("Cask" . emacs-lisp-mode))
;;; Haskell mode
(rc/require 'haskell-mode)
(setq haskell-process-type 'cabal-new-repl)
(setq haskell-process-log t)
(add-hook 'haskell-mode-hook 'haskell-ident-mode)
(add-hook 'haskell-mode-hook 'interactive-haskell-mode)
(add-hook 'haskell-mode-hook 'haskell-doc-mode)
(add-hook 'haskell-mode-hook 'hindent-mode)
;;; Whitespace mode
(defun rc/set-up-whitespace-handling ()
(interactive)
(whitespace-mode 1)
(add-to-list 'write-file-fucntions 'delete-trailing-whitespace))
(add-hook 'c++-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'java-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'emacs-lisp-mode 'rc/set-up-whitespace-handling)
(add-hook 'rust-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'haskell-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'python-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'erlang-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'asm-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'nasm-mode-hook 'rc/set-up-whitespace-handling)
(global-display-line-numbers-mode)
(setq display-line-numbers 'relative)
;;; Magit
(rc/require 'cl-lib)
(rc/require 'magit)
(setq magit-auto-revert-mode nil)
(global-set-key (kbd "C-c m s") 'magit-status)
(global-set-key (kbd "C-c m l") 'magit-log)
;;; Multiple Cursors
(rc/require 'multiple-cursors)
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
(global-set-key (kbd "C-\"") 'mc/skip-to-next-like-this)
(global-set-key (kbd "C-:") 'mc/skip-to-previous-like-this)
;;; Dired
(require 'dired-x)
(setq dired-omit-files
(concat dired-omit-files "\\|^\\..+$"))
(setq-default dired-dwim-target t)
(setq dired-listing-switches "-alh")
;;; Yasnippet
(rc/require 'yasnippet)
(require 'yasnippet)
(setq yas/triggers-in-field nil)
(setq yas-snipped-dirs '("~/.emacs.snippets/"))
(yas-global-mode 1)
;;; Word-Wrap
(defun rc/enable-word-wrap ()
(interactive)
(toggle-word-wrap 1))
(add-hook 'markdown-mode-hook 'rc/enable-word-wrap)
;;; Company Mode
(rc/require 'company)
(require 'company)
(global-company-mode)
;;; NASM mode
(rc/require 'nasm-mode)
(add-to-list 'auto-mode-alist '("\\.asm\\'" . nasm-mode))
;;; TeX mode
(add-hook 'tex-mode-hook
(lambda ()
(interactive)
(add-to-list 'tex-verbatim-environments "code")))
;;; Move Text
(rc/require 'move-text)
(global-set-key (kbd "M-p") 'move-text-up)
(global-set-key (kbd "M-n") 'move-text-down)
(rc/require
'rust-mode
'markdown-mode
'elixir-mode
'svelte-mode
)
;;; Svelte Mode
(add-to-list 'auto-mode-alist '("\\.svelte\\'" . svelte-mode))
;;; Kill all buffers
(defun kill-all-buffers ()
(interactive)
(dolist (cur (buffer-list))
(kill-buffer cur)))
(defun close-current-buffer ()
(interactive)
(kill-buffer (buffer-name)))
(global-set-key (kbd "C-x K") 'kill-all-buffers)
(global-set-key (kbd "C-S-w") 'close-current-buffer)
(defun indent-whole-file ()
(interactive)
(indent-region (point-min) (point-max)))
(global-set-key (kbd "C-<tab>") 'indent-whole-file)
(global-set-key (kbd "C-=") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
Did you read this part of the doc for display-line-numbers:
This variable automatically becomes buffer-local when set outside Custom.
However, setting it through Custom sets the default value.
You're using setq with a user option - not a great idea in general. Use M-x customize-option instead, or use function customize-set-variable or custom-set-variables.
Unless you do some tricky finagling, you can't depend on your setq being evaluated in any particular buffer. And anyway, you apparently want to set the default value of the option. setq-default sets the default value of a variable. But anyway, use one of the custom* functions or (even better), M-x customize-option.
You need to use display-line-numbers-type instead as per the documentation
"The command M-x display-line-numbers-mode provides a convenient way to turn on display of line numbers. This mode has a globalized variant, global-display-line-numbers-mode. The user option display-line-numbers-type controls which sub-mode of line-number display, described above, these modes will activate."
So following works.
(global-display-line-numbers-mode 1)
(setq display-line-numbers-type 'relative)

Why is my newline taking 4 spaces by default?

I have set c-basic-offset & c-basic-indent to 4 expecting it to indent newlines after brackets only in C/C++ files. But the issue I'm facing is every newline in ".txt" document is taking 4 spaces by default which I don't want.
Here is my init.el file
(global-display-line-numbers-mode 1)
(set-frame-font "JetBrains Mono-11" nil t)
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq indent-line-function 'insert-tab)
(setq c-basic-offset 4)
(setq c-basic-indent 4)
;(setq-default c-basic-offset 4)
;(c-set-offset 'substatement-open 0)
; stop creating backup files
(setq make-backup-files nil)
(recentf-mode 1)
(setq recentf-max-menu-items 25)
(setq recentf-max-saved-items 25)
(global-set-key "\C-x\ \C-r" 'recentf-open-files)
;; start the initial frame maximized
(add-to-list 'initial-frame-alist '(fullscreen . maximized))
;; start every frame maximized
(add-to-list 'default-frame-alist '(fullscreen . maximized))
Please help me get rid of 4 space characters in a normal text file.
You can make your settings specific for mode. In your case if you want indentation settings to apply only for C/C++ files, you need to apply these settings for that mode hook. There are various ways of doing it, one of them is using defining those settings in a defun and add that defun to appropriate hook.
Example below shows to setup c-basic-offset and c-basic-indent to 4.
(defun my-c-mode-common-hook ()
;; my customizations for all of c-mode and related modes
(setq c-basic-offset 4)
(setq c-basic-indent 4)
)
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

Emacs: use add-hook inside function (defun)

If I do
(add-hook 'haskell-mode-hook
(lambda ()
(setq indent-tabs-mode t)
(setq tab-width 4)
(message "OK")))
in my ~/.emacs.d/init.el, then the (lambda ...) does get executed when I enter haskell-mode.
However, if I use a function like this:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
(lambda ()
(setq indent-tabs-mode tmode)
(setq tab-width twidth)
(message "OK"))))
and then call it later in ~/.emacs.d/init.el like so:
(my-add-hook 'haskell-mode-hook t 4)
Then nothing happens (even the "OK" message isn't displayed). Is add-hook a
special function that cannot be used from within a defun? I have per-project
settings defined in a separate initialization file that detects the buffer name
and adds (lambda ()...) calls to the pertinent major mode (in the example
above, haskell-mode); I want to reduce the code verbosity by using a thin
wrapper like my-add-hook above, but I cannot tell why add-hook is being so
difficult.
EDIT1: Added code for clarification.
EDIT2: I do get a "File mode specification error: (void-variable tmode)" message when I try to use my-add-hook.
Here's a simple fix without needing to know about lexical binding:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
`(lambda ()
(setq indent-tabs-mode ,tmode)
(setq tab-width ,twidth)
(message "OK"))))
You can use lexical-let to rebind the variables, then the lambda function will preserve their values:
(defun my-add-hook (hook tmode twidth)
(lexical-let ((tmode tmode)
(twidth twidth))
(add-hook hook
(lambda ()
(setq indent-tabs-mode tmode)
(setq tab-width twidth)
(message "OK")))))
I'm not sure whether this is the most idiomatic Emacs Lisp code, but it does follow the same pattern shown in the Emacs Wiki article DynamicBindingVsLexicalBinding, which defines compose as:
(defun compose (f g)
(lexical-let ((f f)
(g g))
(lambda (x)
(funcall f (funcall g x)))))

Indentation of groovy style method parameters in emacs

I am using emacs with groovy electric mode (installed as outlined here). The relevant parts (I think) of my .emacs file are given at the end of this question.
The current behaviour I am getting with indenting, as I type, is:
def someObject = new Something(
param1
Everything is how I would like it at this point, but as soon as I type the ':' character, it becomes:
def someObject = new Something(
param1:
I want the param/value pairs (and any that follow) to remain indented one level, as before, e.g.:
def someObject = new Something(
param1: val1,
param2: val2
)
.emacs excerpt:
(electric-indent-mode t)
(setq-default tab-width 4)
(setq-default indent-tabs-mode nil)
(setq indent-line-function 'insert-tab)
(setq tabify nil)
(setq-default c-basic-offset 4)
(delete-selection-mode 1)
(set-default-font "-apple-Bitstream_Vera_Sans_Mono-medium-normal-normal-*-*-*-*-*-m-0-iso10646-1")
(setq load-path (cons "~/.emacs.d/" load-path))
(add-to-list 'custom-theme-load-path "~/.emacs.d/themes/")
(setq whitespace-action '(auto-cleanup)) ;; automatically clean up bad whitespace
(setq whitespace-style '(trailing space-before-tab indentation empty space-after-tab)) ;; only show bad whitespace
;;; delete trailing whitespace
(add-hook 'before-save-hook 'delete-trailing-whitespace)
;;; turn on syntax highlighting
(global-font-lock-mode 1)
;;; use groovy-mode when file ends in .groovy or has #!/bin/groovy at start
(autoload 'groovy-mode "groovy-mode" "Major mode for editing Groovy code." t)
(add-to-list 'auto-mode-alist '("\\.groovy\\'" . groovy-mode))
(add-to-list 'interpreter-mode-alist '("groovy" . groovy-mode))
;;; make Groovy mode electric by default.
(add-hook 'groovy-mode-hook
(lambda ()
(require 'groovy-electric)
(groovy-electric-mode)))
Edit: regarding #ataylor 's suggestion below, I have tried both:
(add-hook 'groovy-mode-hook
'(lambda ()
(require 'groovy-electric)
(groovy-electric-mode)))
(add-hook 'groovy-mode-hook '(c-set-offset 'label 4))
and
(add-hook 'groovy-mode-hook
'(lambda ()
(require 'groovy-electric)
(groovy-electric-mode)
(c-set-offset 'label 4)))
neither of which work as I want. Is this the correct spot?
Groovy mode is treating these types of parameters as labels, like case statement labels and the rarely used feature inherited from Java that allows break statements to specify a target.
You can override the indentation by adding this to your hook:
(add-hook 'groovy-mode-hook
(lambda ()
(c-set-offset 'label 4)))

local keymap for emacs outline-minor-mode

I want to set the outline-minor-mode for init.el file and when TAB key is pressed on the lines starting with ; the function outline-toggle-children should be called in order to fold and expand the sub headings.
Below is the code for hook. But it does not work for the "TAB" key binding as expected.
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(if (equal (buffer-name) "init.el")
(progn
(outline-regexp "^;+")
(outline-minor-mode 1)
(local-set-key (kbd "TAB") ; this does not work
(lambda ()
(if (string-match outline-regexp (thing-at-point 'line))
(outline-toggle-children))))))))
I presume that the error you get is wrong-type-argument commandp. This happens because functions bound to keys must be "interactive" functions. You need to add an (interactive) declaration to the function, so that Emacs knows how to invoke the function in response to an event:
(lambda ()
(interactive)
(if (string-match outline-regexp (thing-at-point 'line))
(outline-toggle-children)))