1

Тема: Emacs як IDE для C++

1. Встановлюєте Emacs. Якщо не вдається запустити його за допомогою пускача в меню програм, правою клавішею мишки зайдіть в налаштування пускача та встановіть позначку навпроти «запустити в терміналі» (це для OS Manjaro, всі подальші поради стосуються цієї ОС). Цей редактор створений для роботи в терміналі, без нього не запуститься.
2. У  вашій домашній теці знайдіть приховану директорію .emacs.d та створіть всередині неї файл init.el. Це ваш файл налаштувань, який ви змінюватимете за потреби.
3. Після запуску зайдіть в Emacs tutorial (перекладений українською) та ознайомтеся з основами керування. Там же є Emacs manual (поки що лише англійською) — це вже повноцінний підручник по Emacs. Раджу на їхньому сайті завантажити його та шпаргалку Emacs reference у форматі pdf.
4. Додайте до файлу налаштувань репозиторій MELPA. Emacs має власний менеджер пакунків через який онлайн можна встановити все, що вам треба. У цьому репозиторії кілька тисяч плагінів для Emacs.

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; Comment/uncomment this line to enable MELPA Stable if desired.  See `package-archive-priorities`
;; and `package-pinned-packages`. Most users will not need or want to do this.
;;(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)

5. За допомогою менеджера пакунків встановіть наступні програми:
auto-complete-clang — автодоповнення clang
catppuccin-theme — тема оформлення
clang-format — форматування коду С++
clang-format+  — автоматичне форматування коду при збереженні
company — основа для автодоповнення тексту (потребує певного рушія)
company-c-headers — автодоповнення для хедерів
company-ctags — підтримка ctags
dracula-theme — тема оформлення
flycheck — перевірка синтаксису, знаходження помилок «на льоту»
flycheck-clang-analyzer
flycheck-clang-tidy
flycheck-clangcheck
flycheck-flawfinder
flycheck-projectile
helm — дуже зручна програма автодоповнення будь-яких команд Emacs і не тільки
helm-company
helm-flycheck
helm-lsp
helm-projectile
helm-xref
lsp-mode — пакет для інтеграції мов програмування та взаємодії з іншими пакетами
projectile — керування проєктами
rainbow-delimiters — кольорове виділення дужок різного рівня
treemacs — менеджер файлів
treemacs-projectile
which-key — програма, що показує наявні комбінації клавіш та інформацію по ним
xclip — копіювання до clipboard та з нього
yasnippet — корисні сніппети автодоповнення, як от автоматичне додавання дужок до функцій
yasnippet-snippets

6. Тепер додайте решту файлу налаштування:

;;Налаштування поточної теми оформлення
(load-theme 'dracula t)
;;(load-theme 'catppuccin :no-confirm)

;;Підсвічування пар дужок відповідним кольором
(add-hook 'c++-mode-hook #'rainbow-delimiters-mode)

;;Автодоповнення дужок
(electric-pair-mode 1)
(setq electric-pair-preserve-balance nil)

;;Налаштування швидкого автодоповнення
(setq gc-cons-threshold (* 100 1024 1024)
      read-process-output-max (* 1024 1024)
      treemacs-space-between-root-nodes nil
      company-idle-delay 0.0
      company-minimum-prefix-length 1
      lsp-idle-delay 0.1)


;;Налаштування автопрокручування вікна компіляції до першої помилки
(setq compilation-scroll-output 'first-error)

;;Налаштування розміру табуляції
(setq-default tab-width 4)

;;Налаштування максимальної кількості символів у рядку
(setq-default fill-column 80)

;;Налаштування використання готових сніппетів (наприклад, автоматичне додавання дужок для функції С++)
(add-hook 'c++-mode-hook #'yas-minor-mode)

;;Налаштування автоматичного копіювання до clipboard
(xclip-mode 1)

;;Налаштування для менеджера файлів Treemacs
(use-package treemacs
  :ensure t
  :defer t
  :init
  (with-eval-after-load 'winum
    (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  :config
  (progn
    ;; The default width and height of the icons is 22 pixels. If you are
    ;; using a Hi-DPI display, uncomment this to double the icon size.
    (treemacs-resize-icons 44)

    (treemacs-follow-mode t)
    (treemacs-filewatch-mode t)
    (treemacs-fringe-indicator-mode 'always)
    (when treemacs-python-executable
      (treemacs-git-commit-diff-mode t))

    (pcase (cons (not (null (executable-find "git")))
                 (not (null treemacs-python-executable)))
      (`(t . t)
       (treemacs-git-mode 'deferred))
      (`(t . _)
       (treemacs-git-mode 'simple)))

    (treemacs-hide-gitignored-files-mode nil))
  :bind
  (:map global-map
        ("M-0"       . treemacs-select-window)
        ("C-x t 1"   . treemacs-delete-other-windows)
        ;;("C-x t t"   . treemacs)
        ("C-x t d"   . treemacs-select-directory)
        ("C-x t B"   . treemacs-bookmark)
        ("C-x t C-t" . treemacs-find-file)
        ("C-x t M-t" . treemacs-find-tag)))


;;Company — програма, що є основою для автодоповнення
(add-hook 'after-init-hook 'global-company-mode)

;;Показати нумерацію рядків
(add-hook 'prog-mode-hook 'display-line-numbers-mode)

;;Перевірка синтаксису flycheck
(add-hook 'after-init-hook #'global-flycheck-mode)
(add-hook 'c++-mode-hook
          (lambda () (setq flycheck-clang-language-standard "c++20")))
;;Показати помилки відразу в окремому вікні
(add-hook 'flycheck-after-syntax-check-hook
          (lambda  ()
            (if flycheck-current-errors
                (flycheck-list-errors)
              (when (get-buffer "*Flycheck errors*")
                (switch-to-buffer "*Flycheck errors*")
                (kill-buffer (current-buffer))
                (delete-window)))))


;;Налаштування керування проєктами Projectile
(projectile-mode +1)
;; Recommended keymap prefix on Windows/Linux
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)

;;Налаштування автодоповнення команд which-key
(which-key-mode)
(add-hook 'c-mode-hook 'lsp)
(add-hook 'c++-mode-hook 'lsp)

;;Налаштування clang-format при збереженні
(defun clang-format-save-hook-for-this-buffer ()
  "Create a buffer local save hook."
  (add-hook 'before-save-hook
            (lambda ()
              (when (locate-dominating-file "." ".clang-format")
                (clang-format-buffer))
              ;; Continue to save.
              nil)
            nil
            ;; Buffer local hook.
            t))

;; Run this for each mode you want to use the hook.
(add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer)))

;;Налаштування для відкривання останнього робочого файлу
(recentf-mode 1)
(setq recentf-max-menu-items 25)
(setq recentf-max-saved-items 25)


;;Налаштування програми автодоповнення команд Helm
(helm-mode)
(require 'helm-xref)
(define-key global-map [remap find-file] #'helm-find-files)
(define-key global-map [remap execute-extended-command] #'helm-M-x)
(define-key global-map [remap switch-to-buffer] #'helm-mini)

;;Налаштування прив'язки клавіш клавіатури
;;Прив'язка клавіші F2 до збереження файлу
(global-set-key [f2] 'save-buffer)

;;Прив'язка показу нещодавніх файлів до клавіші F3
(global-set-key [f3] 'recentf-open-files)

;;Прив'язка компіляції С++ до F5
(define-key global-map [f5] 'compile)
;;Автоматичне натискання Enter при компіляції
(setq compilation-read-command nil)

;;Налаштування команди компіляції
(require 'compile)
 (add-hook 'c++-mode-hook
           (lambda ()
         (unless (file-exists-p "Makefile")
           (set (make-local-variable 'compile-command)
            (let ((file (file-name-nondirectory buffer-file-name)))
                      (format "%s %s"
                              (or (getenv "CC") "cmake")
                              (or (getenv "CPPFLAGS") "-Bbuild/Debug -DCMAKE_BUILD_TYPE=Debug && cd build/Debug && make")
                  ))))))

;;Прив'язка виклику менеджера файлів treemacs до F7
(define-key global-map [f7] 'treemacs)

Зверніть увагу, що в мене компіляція та автодоповнення коду створені під CMake файл.

cmake_minimum_required(VERSION 3.5)

project(hello_world
    VERSION 1.0.0
    LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20 )
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

add_executable(${PROJECT_NAME} main.cpp)

# Цією командою можна зручно встановити бажаний стандарт [c++17, c++20, c++23]
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
# Цією командою можна легко додати дефайни, можна вписувати їх на місці
target_compile_definitions(${PROJECT_NAME} PUBLIC _GLIBCXX_DEBUG)
# Цією командою виставляємо прапорці компілятору
target_compile_options(${PROJECT_NAME}
    PUBLIC -Wall
           -Wextra
           -Wpedantic
           -fsanitize=address,undefined)
# Цією командою виставляємо прапорці лінкеру
target_link_options(${PROJECT_NAME}
    PUBLIC -fsanitize=address,undefined)


set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)



add_custom_command(
    TARGET ${PROJECT_NAME}
    POST_BUILD
    COMMAND ${PROJECT_NAME}
)



include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

Якщо ви не використовуєте CMake, вам доведеться встановити Bear для генерації відповідного файлу json (в CMake це відбувається ось тут
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)), а також переписати compile-comand в налаштуваннях.
Це лише прості базові налаштування для С++, але для початку вистачить.

2

Re: Emacs як IDE для C++

Ще раджу встановити cmake-mode та cmake-font-lock (після встановлення додайте (require 'cmake-mode) до файлу налаштувань).
Ці плагіни разом із іншими дадуть вам автодоповнення та кольорову підсвітку функцій при роботі з файлом CMakeLists.txt.

3

Re: Emacs як IDE для C++

Оновлений файл налаштувань:

;;Підсвічування пар дужок відповідним кольором
(add-hook 'c++-mode-hook #'rainbow-delimiters-mode)

;;Налаштування для відкривання останнього робочого файлу
(recentf-mode 1)
(setq recentf-max-menu-items 5
      recentf-max-saved-items 5
      recentf-exclude '("~/.emacs.d/.cache/treemacs-persist")
)

;;Автодоповнення дужок
(electric-pair-mode 1)
(setq electric-pair-preserve-balance nil)

;;Company — програма, що є основою для автодоповнення
(add-hook 'after-init-hook 'global-company-mode)

;;Показати нумерацію рядків
(add-hook 'prog-mode-hook 'display-line-numbers-mode)

;;Налаштування швидкого автодоповнення
(setq gc-cons-threshold (* 100 1024 1024)
      read-process-output-max (* 1024 1024)
      company-idle-delay 0.0
      company-minimum-prefix-length 1
      lsp-idle-delay 0.1
      )

;;Налаштування автопрокручування вікна компіляції до першої помилки
(setq compilation-scroll-output 'first-error)

;;Налаштування розміру табуляції
(setq-default tab-width 4)

;;Налаштування максимальної кількості символів у рядку
(setq-default fill-column 80)

;;Налаштування використання готових сніппетів
;;(наприклад, автоматичне додавання дужок для функції С++)
(add-hook 'c++-mode-hook #'yas-minor-mode)

;;Налаштування автоматичного копіювання до clipboard
(xclip-mode 1)

;;Налаштування lsp-mode
(use-package lsp-mode
  :init
  ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
  (setq lsp-keymap-prefix "C-c l"
        lsp-enable-symbol-highlighting nil
        lsp-ui-sideline-enable t
        lsp-ui-sideline-show-code-actions t
        lsp-ui-sideline-show-hover nil
        lsp-modeline-code-actions-enable nil
        lsp-diagnostics-provider :none
        lsp-ui-sideline-show-diagnostics t
        ;lsp-completion-provider :none
        lsp-completion-show-detail nil
        lsp-completion-show-kind nil
        lsp-completion-sort-initial-results t
        lsp-clients-clangd-args '("--header-insertion=never"
                                  "--fallback-style=WebKit"
                                  )
    )

  :hook (;; Прив'язка lsp-mode до певного режиму роботи
         (c++-mode . lsp)
         ;; Інтеграція з which-key
         (lsp-mode . lsp-enable-which-key-integration))
  :commands lsp)

;;Налаштування lsp-ui
(use-package lsp-ui
  :commands lsp-ui-mode)

;;Налаштування doom-themes
(use-package doom-themes
  :ensure t
  :config
  ;; Global settings (defaults)
  (setq doom-themes-enable-bold t    ; if nil, bold is universally disabled
        doom-themes-enable-italic t) ; if nil, italics is universally disabled
  (load-theme 'doom-one t)

  ;;Corrects (and improves) org-mode's native fontification.
  (doom-themes-org-config)
  )

;;Налаштування treemacs
(use-package treemacs
  :ensure t
  :defer t
  :config
  (progn
    (setq treemacs-show-hidden-files nil)

    (treemacs-follow-mode t)
    (treemacs-filewatch-mode t)
    (treemacs-fringe-indicator-mode 'always)

    (treemacs-hide-gitignored-files-mode nil))
  :bind
  (:map global-map
        ("M-0"       . treemacs-select-window)
        ("C-x t 1"   . treemacs-delete-other-windows)
        ("C-x t t"   . treemacs)
        ("C-x t d"   . treemacs-select-directory)
        ("C-x t B"   . treemacs-bookmark)
        ("C-x t C-t" . treemacs-find-file)
        ("C-x t M-t" . treemacs-find-tag)))

(use-package treemacs-projectile
  :after (treemacs projectile)
  :ensure t)

;;Налаштування lsp-treemacs
(lsp-treemacs-sync-mode 1)

;;Перевірка синтаксису flycheck
(use-package flycheck
  :ensure t
  :init
  (global-flycheck-mode)
  :config
    ;; Показувати індикатори помилок в крайньому лівому стовпчику
    (setq flycheck-indication-mode 'left-margin
          ;; Затримка показу помилок
          flycheck-display-errors-delay 0.1
          ;; Перевірка згідно певного стандарту мови С++
          flycheck-clang-language-standard "c++20"
    )
    ;; Налаштування ширини стовпчика з індикаторами помилок
    (defun my/set-flycheck-margins ()
      (setq left-fringe-width 8 right-fringe-width 8
        left-margin-width 1 right-margin-width 0)
      (flycheck-refresh-fringes-and-margins))
    ;; Поява індикаторів щоразу при відкритті нового буфера
    (add-hook 'flycheck-mode-hook #'my/set-flycheck-margins)
    ;; Додавання перевірки синтаксису clang в чергу після cppcheck
    (flycheck-add-next-checker 'c/c++-cppcheck 'c/c++-clang)
  )

(use-package flycheck-clang-tidy
  :after flycheck
  :hook
  (flycheck-mode . flycheck-clang-tidy-setup)
  )

(use-package flycheck-clang-analyzer
  :ensure t
  :after flycheck
  :config (flycheck-clang-analyzer-setup))

(with-eval-after-load 'flycheck
  (require 'flycheck-flawfinder)
  (flycheck-flawfinder-setup)
  ;; chain after cppcheck since this is the last checker in the upstream
  ;; configuration
  (flycheck-add-next-checker 'c/c++-cppcheck '(warning . flawfinder)))

;;Налаштування керування проєктами Projectile
(projectile-mode +1)
;; Recommended keymap prefix on Windows/Linux
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)

;;Налаштування автодоповнення команд which-key
(which-key-mode)
(add-hook 'c-mode-hook 'lsp)
(add-hook 'c++-mode-hook 'lsp)

;;Налаштування clang-format при збереженні
(defun clang-format-save-hook-for-this-buffer ()
  "Create a buffer local save hook."
  (add-hook 'before-save-hook
            (lambda ()
              (when (locate-dominating-file "." ".clang-format")
                (clang-format-buffer))
              ;; Continue to save.
              nil)
            nil
            ;; Buffer local hook.
            t))

;; Run this for each mode you want to use the hook.
(add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer)))

;;Налаштування програми автодоповнення команд Helm
(helm-mode)
(require 'helm-xref)
(define-key global-map [remap find-file] #'helm-find-files)
(define-key global-map [remap execute-extended-command] #'helm-M-x)
(define-key global-map [remap switch-to-buffer] #'helm-mini)

;;Налаштування cmake-mode
(require 'cmake-mode)

;;Налаштування прив'язки клавіш клавіатури
;;Прив'язка клавіші F2 до збереження файлу
(global-set-key [f2] 'save-buffer)

;;Прив'язка показу нещодавніх файлів до клавіші F3
(global-set-key [f3] 'recentf-open-files)

;;Прив'язка компіляції С++ до F5
(define-key global-map [f5] 'compile)
;;Автоматичне натискання Enter при компіляції
(setq compilation-read-command nil)

;;Налаштування команди компіляції
(require 'compile)
  (add-hook 'c++-mode-hook
    (lambda ()
      (unless (file-exists-p "Makefile")
        (set (make-local-variable 'compile-command)
        (let ((file (file-name-nondirectory buffer-file-name)))
          (format "%s %s"
            (or (getenv "CC") "cmake")
            (or (getenv "CPPFLAGS") "-Bbuild/Debug -DCMAKE_BUILD_TYPE=Debug && cd build/Debug && make")
            ))))))

;;Прив'язка виклику менеджера файлів treemacs до F7
(define-key global-map [f7] 'treemacs)

;;Прив'язка виклику переліку функції та класів у treemacs
(define-key global-map [f8] 'lsp-treemacs-symbols)

Якщо використовувати lsp-mode і flycheck,
краще вимкнути перевірку синтаксису в lsp-mode(lsp-diagnostics-provider :none),
бо налаштування lsp-mode для перевірки синтаксису будуть перебивати налаштування flycheck.
Хіба що вам більше подобаються налаштування саме lsp-mode.
Як все зараз виглядає можна побачити на знімку(це для текстового Emacs Manjaro OS).
https://replace.org.ua/misc.php?action=pun_attachment&item=2233

Post's attachments

Знімок Emacs.png 212.71 kb, 9 downloads since 2024-10-24