HASKELL
Emacs + Haskell-Mode 본문
I. Install Haskell by Stack
1. Stack 을 다운로드, 설치
- Home - The Haskell Tool Stack (haskellstack.org)
- WIndows 64-bit installer 다운로드, 설치(Haskell 설치를 원하는 폴더에)
- 'config.yaml' 파일 하나 만들고 다음을 추가
local-programs-path: D:\HaskellStack\programs
- 이렇게 하면 Haskell이 C 드라이브 AppData 등의 여러 곳에 산만하게 설치되지 않고, 원하는 폴더 내에 Haskell 파일 모두 한 곳에 모을 수 있다. C 드라이브 용량이 적고, 지저분해지면 PC가 느려질 수 있으니, D: 드라이브나 USB에 portable 하게 만드는 의미다.
2. Stack 으로 새로운 local-project 만들기
- 원하는 폴더에서 `stack new hello` 명령을 도스창에서 실행하면 hello 라는 폴더가 만들어지며, 그 폴더에 들어가보면 `stack.yaml`, `package.yaml` 파일 등이 자동으로 만들어진다.
3. Stack 으로 Haskell 다운로드 및 build 하기
- local-project 폴더 내의 stack.yaml 파일을 보면 `resolver: lts-14.20` 라는 부분이 있는데, 특정한 version의 Haskell을 다운로드 받으라고 정해주는 의미다. 이 부분을 원하는 버전으로 바꿀 수도 있고, 그냥 놔 둔 채로 다음과 같이 Haskell을 설치할 수도 있다.
- `stack setup` 명령을 실행하면 꽤 오랜 시간 Haskell을 설치한다. 설치 폴더는 위에서 설정한 `local-programs-path` 이다.
- `stack build` 명령을 실행하면, local-project 가 빌드되어 실행 파일이 만들어진다.
II. Emacs + haskell-mode
1. Emacs 를 설치
- MIRROR.YONGBOK.NET - /gnu/emacs/windows/
- Windows 10 64-bit system용 다운로드, 압출 풀고 bin/runemacs.exe 파일 실행
2. Emacs 설정 파일 위치 지정
- D:/util/emacs/share/emacs/site-lisp/site-start.el 파일 만들고 내용 추가
(defun set-home-dir (dir) "Set a new HOME directory. This is where Emacs will look for init files and where '~' will default to." (setenv "HOME" dir) (message (format "HOME location is %s" (getenv "HOME")))) (set-home-dir "D:/util/emacs")
3. MELPA 추가
- D:/util/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)
4. Haskell-mode 설치
- M-x package-install RET haskell-mode
5. 테스트
- Emacs 다시 띄우고 Haskell 파일 아무거나 만들어 코딩
- C-c C-l 해서 파일을 GHCi REPL 창으로 로딩하려고 할 때마다 다음과 같은 에러 등장
Error message: The Haskell process *** has died.
- D:/util/emacs/.emacs 파일 안에 다음과 같은 내용을 추가 (결국 파일 인코딩의 문제였다!)
(set-language-environment 'utf-8)
- 이제 C-c C-l 하면 작업 파일이 cabal repl에 로딩되어 제대로 작동
6. 설정 파일
- Emacs configuration file example (`init.el` or `.emacs` file)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; The default is 800 kilobytes. Measured in bytes. (setq gc-cons-threshold (* 50 1000 1000)) ;; Profile emacs startup (add-hook 'emacs-startup-hook (lambda () (message "*** Emacs loaded in %s with %d garbage collections." (format "%.2f seconds" (float-time (time-subtract after-init-time before-init-time))) gcs-done))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; package source (require 'package) (setq package-archives '(("melpa" . "https://melpa.org/packages/") ("melpa-stable" . "https://stable.melpa.org/packages/") ("org" . "https://orgmode.org/elpa/") ("elpa" . "https://elpa.gnu.org/packages/"))) (package-initialize) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; use-package - more convenient package manager (when (not (package-installed-p 'use-package)) (package-refresh-contents) (package-install 'use-package)) ;; install package automatically if not already present on your system (require 'use-package-ensure) (setq use-package-always-ensure t) ;; keep your packages updated automatically (use-package auto-package-update :config (setq auto-package-update-delete-old-versions t) (setq auto-package-update-hide-results t) (auto-package-update-maybe)) ;; org-mode config (use-package org :config (setq org-hide-emphasis-markers t) (global-set-key "\C-ca" 'org-agenda) (setq org-src-fontify-natively t) (setq org-babel-load-languages '((awk . t) (C . t) (calc . t) (css . t) (ditaa . t) (emacs-lisp . t) (gnuplot . t) (haskell . t) (js . t) (lisp . t) (org . t) (plantuml . t) (python . t) (scheme . t) (shell . t) (sql . t))) ;; Activate Babel languages (org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages)) ;; key setting (global-set-key [f12] 'shell) (global-set-key (kbd "<escape>") 'keyboard-escape-quit) ;; org-bullet (use-package org-bullets :ensure t :config (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))) ;; haskell-mode (use-package haskell-mode :ensure t :init (add-hook 'haskell-mode-hook 'structured-haskell-mode) (add-hook 'haskell-mode-hook 'interactive-haskell-mode) :mode (("\\.hs\\'" . haskell-mode) ("\\.cabal\\'" . haskell-cabal-mode) ("\\.hcr\\'" . haskell-core-mode)) :custom (haskell-process-type 'stack-ghci)) :config (setq tab-width 2) ;; company mode (use-package company :ensure t :init (add-hook 'after-init-hook 'global-company-mode) :config (setq company-idle-delay 0) (setq company-show-numbers "on")) ;; company-ghci mode (use-package company-ghci :ensure t :after (pos-tip) :config (defun show-hoogle-info-in-popup () (pos-tip-show (company-ghci/hoogle-info (symbol-at-point)) nil nil nil -1)) (defun company-ghci-setup () (push 'company-ghci company-backends) (define-key evil-normal-state-map (kbd "C-;") (lambda () (interactive) (show-hoogle-info-in-popup)))) (add-hook 'haskell-interactive-mode-hook 'company-mode) (add-hook 'haskell-mode-hook 'company-ghci-setup)) ;; autocomplete (use-package auto-complete :ensure t :diminish auto-complete-mode :config (require 'auto-complete-config) (ac-config-default)) ;; hl-line (use-package hl-line ;; visible current line :ensure t :diminish global-hl-line-mode :config (global-hl-line-mode)) ;; highlight-parentheses (use-package highlight-parentheses :ensure t :diminish highlight-parentheses-mode :commands highlight-parentheses-mode) ;; highlight multiple occurences (use-package highlight-symbol :ensure t :bind (("M-p" . highlight-symbol-prev) ("M-n" . highlight-symbol-next) ("M-'" . highlight-symbol-query-replace)) :init (defun highlight-symbol-first () "Jump to the first location of symbol at point." (interactive) (push-mark) (eval `(progn (goto-char (point-min)) (search-forward-regexp (rx symbol-start ,(thing-at-point 'symbol) symbol-end) nil t) (beginning-of-thing 'symbol)))) (defun highlight-symbol-last () "Jump to the last location of symbol at point." (interactive) (push-mark) (eval `(progn (goto-char (point-max)) (search-backward-regexp (rx symbol-start ,(thing-at-point 'symbol) symbol-end) nil t)))) (bind-keys ("M-P" . highlight-symbol-first) ("M-N" . highlight-symbol-last))) ;; iedit mode (use-package iedit :ensure t :diminish iedit-mode :bind ("C-'" . iedit-mode)) ;; spaceline configuration (use-package spaceline :ensure t :config (setq-default mode-line-format '("%e" (:eval (spaceline-ml-main)))) ) (use-package spaceline-config :ensure spaceline :config (spaceline-helm-mode 1) (spaceline-emacs-theme) ) ;; spaceline-all-the-icons (use-package spaceline-all-the-icons :ensure t :config (spaceline-all-the-icons--setup-anzu) ;; Enable anzu searching (spaceline-all-the-icons--setup-package-updates) ;; Enable package update indicator (spaceline-all-the-icons--setup-git-ahead) ;; Enable # of commits ahead of upstream in git (spaceline-all-the-icons--setup-paradox) ;; Enable Paradox mode line (spaceline-all-the-icons--setup-neotree) ;; Enable Neotree mode line ) ;; multiple cursors (use-package multiple-cursors :ensure t :defer t :bind (("C-S-c C-S-c" . mc/edit-lines) ("C->" . mc/mark-next-like-this) ("C-<" . mc/mark-previous-like-this) ;; ("C-c C-<" . mc/mark-all-like-this) ("C-c o" . mc/mark-all-like-this) ) ) ;; which-key - it shows which combos are setup while we are typing (use-package which-key :ensure t :diminish which-key-mode :config (which-key-mode 1) (which-key-setup-side-window-right) (setq which-key-idle-delay 0.1)) ;; iedit-mode (use-package iedit :ensure t :diminish iedit-mode :bind ("C-`" . iedit-mode)) ;; avy (use-package avy :ensure t :bind ("C-." . avy-goto-word-or-subword-1) ("C-," . avy-goto-char-2) :config (setq avy-background t)) ;; ido (use-package ido-vertical-mode :config (ido-mode t) (ido-everywhere t) (ido-vertical-mode 1) (setq ido-vertical-define-keys 'C-n-and-C-p-only)) ;; icomplete-vertical (use-package icomplete-vertical :ensure t :demand t :custom (completion-styles '(partial-completion substring)) (completion-category-overrides '((file (styles basic substring)))) (read-file-name-completion-ignore-case t) (read-buffer-completion-ignore-case t) (completion-ignore-case t) :config (icomplete-mode) (icomplete-vertical-mode) :bind (:map icomplete-minibuffer-map ("<down>" . icomplete-forward-completions) ("C-n" . icomplete-forward-completions) ("<up>" . icomplete-backward-completions) ("C-p" . icomplete-backward-completions) ("C-v" . icomplete-vertical-toggle))) ;; gruvbox theme (use-package gruvbox-theme :ensure t :config (load-theme 'gruvbox-dark-hard t)) ;; turn page breaks into lines (use-package page-break-lines :ensure t :init (global-page-break-lines-mode) :diminish page-break-lines-mode) ;; add stripes to a buffer (use-package stripe-buffer :disabled t :ensure t :init (add-hook 'dired-mode-hook #'stripe-buffer-mode)) ;; ibuffer (use-package ibuffer :bind ("C-x C-b" . ibuffer)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; my custom settings (menu-bar-mode -1) ;; hide menu bar (tool-bar-mode -1) ;; hide tool bar (scroll-bar-mode -1) ;; hide scroll bar (set-language-environment "Korean") ;; korean environment (prefer-coding-system 'utf-8) ;; encoding UTF-8 (set-language-environment 'utf-8) ;; encoding UTF-8 (setq make-backup-files nil) ;; no backup file (setq-default column-number-mode t) ;; column number (show-paren-mode t) ;; parenthesis (setq show-paren-delay 0) (electric-indent-mode 1) ;; indent (global-linum-mode 1) ;; line number (display-time) ;; display time (setq system-time-locale "C") ;; time format English (defalias 'yes-or-no-p 'y-or-n-p) (setq inhibit-startup-screen t) ;; skip welcome screen (windmove-default-keybindings) ;; Let me switch windows with shift-arrows instead of "C-x o" all the time (setq-default line-spacing 0.2) ;; line space (global-font-lock-mode 1) ;; syntax highlighting (ido-mode t) (ido-everywhere t) ;; (add-hook 'emacs-startup-hook 'toggle-frame-maximized) (when window-system (set-frame-position (selected-frame) 960 0)) (add-to-list 'default-frame-alist '(height . 43)) (add-to-list 'default-frame-alist '(width . 90)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; custom settings (automatically modified by Emacs) (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. '(column-number-mode t) '(org-agenda-files '("c:/Users/k/OneDrive/study/myhs/h99/src/org_practice.org")) '(package-selected-packages '(auto-package-update use-package)) '(show-paren-mode t)) (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. '(default ((t (:family "Ubuntu Mono" :foundry "outline" :slant normal :weight normal :height 158 :width normal)))))
'Environment' 카테고리의 다른 글
Haskell: Warning: Multiple files use the same module name: (0) | 2021.01.03 |
---|---|
Haskell: Windows 10 에서 Haskell 설치, 내용 업데이트 (0) | 2021.01.03 |
Docker for haskell (0) | 2019.03.19 |
Haskell project setting - cabal file (0) | 2019.01.27 |
How to Uninstall Old GHC (0) | 2019.01.11 |