Notice
Recent Posts
Recent Comments
Link
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Tags more
Archives
Today
Total
관리 메뉴

HASKELL

Emacs + Haskell-Mode 본문

Environment

Emacs + Haskell-Mode

__main__ 2020. 11. 23. 17:56

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 파일을 보면 `resolverlts-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 파일에 다음과 같은 내용 추가

- Getting Started - MELPA

(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)))))
Comments