Download
(eval-when-compile (require 'cl))
(defgroup dummy-h-mode nil
"Dummy H mode"
:group 'convenience
:prefix "dummy-h-mode-")
(defcustom dummy-h-mode-hook nil
"Hook run when entering dummy H mode"
:type 'hook
:group 'dummy-h-mode)
(defcustom dummy-h-mode-default-major-mode 'c-mode
"Default major mode"
:type 'symbol
:group 'dummy-h-mode)
(defcustom dummy-h-mode-c-keywords
'(("_Bool[\* \t\n\r]" . 1)
("_Complex[\* \t\n\r]" . 1)
("_Imaginary[\* \t\n\r]" . 1))
"C keywords and their minimum counts of appearance"
:type '(repeat (cons regexp number))
:group 'dummy-h-mode)
(defcustom dummy-h-mode-cc-keywords
'(("[\n\r][ \t]*private:" . 1)
("[\n\r][ \t]*public:" . 1)
("[\n\r][ \t]*protected:" . 1)
("::" . 1)
("[\n\r][ \t]*using[ \t\n\r]+namespace[ \t\n\r]" . 1))
"C++ keywords and their minimum counts of appearance"
:type '(repeat (cons regexp number))
:group 'dummy-h-mode)
(defcustom dummy-h-mode-objc-keywords
'(("[\n\r][ \t]*@class[ \t\n\r]" . 1)
("[\n\r][ \t]*@end[ \t\n\r]" . 1)
("[\n\r][ \t]*@implementation[ \t\n\r]" . 1)
("[\n\r][ \t]*@interface[ \t\n\r]" . 1)
("[\n\r][ \t]*@protocol[ \t\n\r]" . 1))
"Objective-C keywords and their minimum counts of appearance"
:type '(repeat (cons regexp number))
:group 'dummy-h-mode)
(defcustom dummy-h-mode-search-limit 30000
"Search limit for large size files"
:type 'number
:group 'dummy-h-mode)
(defun dummy-h-mode-get-major-mode-by-source-file ()
"Get major mode by checking corresponding source file"
(if (buffer-file-name)
(let ((file-name-wo-h (file-name-sans-extension (buffer-file-name))))
(cond
((file-exists-p (concat file-name-wo-h ".c"))
'c-mode)
((or (file-exists-p (concat file-name-wo-h ".cc"))
(file-exists-p (concat file-name-wo-h ".cxx"))
(file-exists-p (concat file-name-wo-h ".cpp"))
(file-exists-p (concat file-name-wo-h ".cp")))
'c++-mode)
((or (file-exists-p (concat file-name-wo-h ".m"))
(file-exists-p (concat file-name-wo-h ".mm")))
'objc-mode)))
nil))
(defun dummy-h-mode-if-containing-keywords (keywords)
"Get if containing keywords"
(if keywords
(or (save-excursion
(goto-char (point-min))
(re-search-forward
(caar keywords) dummy-h-mode-search-limit t (cdar keywords)))
(dummy-h-mode-if-containing-keywords (cdr keywords)))
nil))
(defun dummy-h-mode-get-major-mode-by-keywords ()
"Get major mode by searching keywords"
(cond
((dummy-h-mode-if-containing-keywords dummy-h-mode-objc-keywords)
'objc-mode)
((dummy-h-mode-if-containing-keywords dummy-h-mode-cc-keywords)
'c++-mode)
((dummy-h-mode-if-containing-keywords dummy-h-mode-c-keywords)
'c-mode)))
(defun dummy-h-mode-count-file-extension (files extension)
"Counts file if its extension is matching"
(if files
(+ (if (string= (file-name-extension (car files)) extension) 1 0)
(dummy-h-mode-count-file-extension (cdr files) extension))
0))
(defun dummy-h-mode-get-major-mode-by-files-directory ()
"Get major mode by checking all files in directory"
(if (buffer-file-name)
(let* ((dir-files
(directory-files (file-name-directory (buffer-file-name))))
(count-c-files
(dummy-h-mode-count-file-extension dir-files "c"))
(count-cc-files
(+ (dummy-h-mode-count-file-extension dir-files "cc")
(dummy-h-mode-count-file-extension dir-files "cxx")
(dummy-h-mode-count-file-extension dir-files "cpp")
(dummy-h-mode-count-file-extension dir-files "cp")))
(count-objc-files
(+ (dummy-h-mode-count-file-extension dir-files "m")
(dummy-h-mode-count-file-extension dir-files "mm"))))
(cond
((and (> count-c-files count-cc-files)
(> count-c-files count-objc-files))
'c-mode)
((> count-cc-files count-objc-files)
'c++-mode)
((> count-objc-files 0)
'objc-mode)))
nil))
(defun dummy-h-mode-switch ()
"Switch major mode"
(funcall (or (dummy-h-mode-get-major-mode-by-source-file)
(dummy-h-mode-get-major-mode-by-keywords)
(dummy-h-mode-get-major-mode-by-files-directory)
dummy-h-mode-default-major-mode)))
(defun dummy-h-mode ()
"Dummy H mode"
(interactive)
(kill-all-local-variables)
(setq major-mode 'dummy-h-mode)
(setq mode-name "DummyH")
(run-hooks 'dummy-h-mode-hook)
(dummy-h-mode-switch))
(provide 'dummy-h-mode)