init-sh.el 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. ;;; Sh
  2. (defvaralias 'sh-basic-offset 'tab-width)
  3. (defvaralias 'sh-indentation 'sh-basic-offset)
  4. (setq sh-indent-comment t)
  5. (setq-default sh-shell-file "/bin/sh")
  6. ;; (setq-default sh-shell 'sh)
  7. ;;; Faces
  8. (set-face-foreground 'sh-heredoc "#00bfff")
  9. (set-face-bold 'sh-heredoc nil)
  10. (defun ambrevar/sh-set-compiler ()
  11. "Set shell interpreter.
  12. Set `sh-shell', `sh-shell-file' and `compile-command' according to the following rules:
  13. - Look at shabang.
  14. - If file has no name, use default value of sh-shell-file.
  15. - Check extension or file name.
  16. - If none of the above yields a result, use default value of
  17. sh-shell-file.
  18. The advantages of this function over the vanilla code are:
  19. - You can change default value of sh-shell-file in sh-mode-hook
  20. and it will be used subsequently.
  21. - Zsh is supported
  22. - compile-command is set.
  23. - Once sh-shell is set, sh-shell-file is changed accordingly. In
  24. default Emacs, sh-shell-file is always the same."
  25. (interactive)
  26. (sh-set-shell
  27. (cond ((save-excursion
  28. (goto-char (point-min))
  29. (looking-at "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)"))
  30. (match-string 2))
  31. ((not buffer-file-name) sh-shell-file)
  32. ;; Checks that use `buffer-file-name' follow.
  33. ((string-match "\\.m?spec\\'" buffer-file-name) "rpm")
  34. ((string-match "[.]bash\\>" buffer-file-name) "bash")
  35. ((string-match "[.]csh\\>" buffer-file-name) "csh")
  36. ((string-match "[.]ksh\\>" buffer-file-name) "ksh")
  37. ((string-match "[.]sh\\>" buffer-file-name) "sh")
  38. ((string-match "[.]zsh\\>" buffer-file-name) "zsh")
  39. ((equal (file-name-nondirectory buffer-file-name) ".profile") "sh")
  40. (t sh-shell-file))
  41. nil nil)
  42. ;; Universal version:
  43. ;; (setq sh-shell-file (executable-find (symbol-name sh-shell)))
  44. ;; Convenient version:
  45. (setq sh-shell-file (concat "/bin/" (symbol-name sh-shell)))
  46. ;; Sometimes with `git merge` it seems that the `buffer-file-name' is not a
  47. ;; string. We safe-guard that case.
  48. (when (stringp buffer-file-name)
  49. (setq compile-command (concat sh-shell-file " " (shell-quote-argument buffer-file-name)))))
  50. (defun ambrevar/sh-set-indent-rules ()
  51. (setq sh-indent-for-case-label 0
  52. sh-indent-for-case-alt '+))
  53. (defun ambrevar/sh-set-prompt ()
  54. (set (make-local-variable 'defun-prompt-regexp)
  55. (concat "^\\(function[ \t]\\|[[:alnum:]_]+[ \t]+()[ \t]+\\)")))
  56. ;;; Hooks
  57. (dolist (fun '(ambrevar/sh-set-indent-rules ambrevar/sh-set-prompt ambrevar/sh-set-compiler))
  58. (add-hook 'sh-mode-hook fun))
  59. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  60. (define-skeleton ambrevar/sh-commands-or-die
  61. "Insert a loop that exits if any of the commands is not found in path."
  62. "Command names: "
  63. > "for i " @ str "; do" \n
  64. > "if ! command -v \"$i\" >/dev/null 2>&1; then" \n
  65. > "echo >&2 \"'$i' not found\"" \n
  66. > "exit 1" \n
  67. "fi" > \n
  68. "done" > \n \n)
  69. (define-skeleton ambrevar/sh-ifcommand
  70. "Insert a test to check if command is found in path."
  71. "Command name: "
  72. > "if command -v " @ str " >/dev/null 2>&1; then" \n
  73. > @ _ \n
  74. "fi" > \n)
  75. (define-skeleton ambrevar/sh-while-getopts
  76. "Insert a getops prototype."
  77. "optstring: "
  78. > "usage() {" \n
  79. > "cat<<EOF" \n
  80. "Usage: ${1##*/} [OPTIONS] FILES
  81. Options:
  82. -h: Show this help.
  83. EOF
  84. }" > \n
  85. \n
  86. > "while getopts :" str " OPT; do" \n
  87. > "case $OPT in" \n
  88. '(setq v1 (append (vconcat str) nil))
  89. ((prog1 (if v1 (char-to-string (car v1)))
  90. (if (eq (nth 1 v1) ?:)
  91. (setq v1 (nthcdr 2 v1)
  92. v2 "\"$OPTARG\"")
  93. (setq v1 (cdr v1)
  94. v2 nil)))
  95. > str ")" \n
  96. > _ v2 " ;;" \n)
  97. > "\\?)" \n
  98. > "usage \"$0\"" \n
  99. "exit 1 ;;" > \n
  100. "esac" > \n
  101. "done" > \n
  102. \n
  103. "shift $(($OPTIND - 1))" \n
  104. "if [ $# -eq 0 ]; then" \n
  105. > "usage \"$0\"" \n
  106. "exit 1" \n
  107. "fi" > \n)
  108. (define-skeleton ambrevar/sh-while-read
  109. "Insert a while read loop."
  110. nil
  111. > "while IFS= read -r i; do" \n
  112. > @ _ \n
  113. "done <<EOF" > \n
  114. "EOF" > \n)
  115. (provide 'init-sh)