├── README.md ├── img └── repl.gif └── inim.el /README.md: -------------------------------------------------------------------------------- 1 | # Installation: 2 | 3 | ``` 4 | nimble install inim 5 | ``` 6 | 7 | # Obligatory gif 8 | 9 | ![image info](/img/repl.gif) 10 | 11 | 12 | 13 | I highly recommend using the straight package manager 14 | 15 | ``` 16 | (straight-use-package 17 | '(inim 18 | :type git 19 | :host github 20 | :repo "serialdev/inim-mode" 21 | :config 22 | (add-hook inim-mode-hook #'evcxr-minor-mode) 23 | )) 24 | ``` 25 | 26 | Alternatively pull the repo and add to your init file 27 | ``` 28 | git clone https://github.com/SerialDev/inim-mode 29 | ``` 30 | 31 | ## Hard Requirements 32 | Inim is required 33 | s.el is required 34 | 35 | 36 | # Current functionality: 37 | 38 | ``` 39 | C-c C-p [Start repl] 40 | C-c C-b [Eval buffer] 41 | C-c C-l [Eval line] 42 | C-c C-r [eval region] 43 | ``` 44 | 45 | -------------------------------------------------------------------------------- /img/repl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SerialDev/inim-mode/feba1d9c55ca43456824faf0faa05e53ebb9f63a/img/repl.gif -------------------------------------------------------------------------------- /inim.el: -------------------------------------------------------------------------------- 1 | ;;; inim.el --- Inim minor mode for Nim Repl support 2 | 3 | ;; Copyright (C) 2018 Andres Mariscal 4 | 5 | ;; Author: Andres Mariscal 6 | ;; Created: 26 Sep 2018 7 | ;; Version: 0.0.1 8 | ;; Keywords: nim languages repl 9 | ;; URL: https://github.com/serialdev/inim-mode 10 | ;; Package-Requires: ((emacs "24.3", parsec )) 11 | ;;; Commentary: 12 | ;; Nim Repl support through inim repl 13 | 14 | ;; Usage 15 | 16 | 17 | (defun regex-match ( regex-string string-search match-num ) 18 | (string-match regex-string string-search) 19 | (match-string match-num string-search)) 20 | 21 | 22 | (defcustom inim-shell-buffer-name "*Inim*" 23 | "Name of buffer for inim." 24 | :group 'inim 25 | :type 'string) 26 | 27 | (defun inim-is-running? () 28 | "Return non-nil if inim is running." 29 | (comint-check-proc inim-shell-buffer-name)) 30 | 31 | (defalias 'inim-is-running-p #'inim-is-running?) 32 | 33 | ;;;###autoload 34 | (defun inim (&optional arg) 35 | "Run inim. 36 | Unless ARG is non-nil, switch to the buffer." 37 | (interactive "P") 38 | (let ((buffer (get-buffer-create inim-shell-buffer-name))) 39 | (unless arg 40 | (pop-to-buffer buffer)) 41 | (unless (inim-is-running?) 42 | (with-current-buffer buffer 43 | (inim-startup) 44 | (inferior-inim-mode) 45 | ) 46 | (pop-to-buffer buffer) 47 | (other-window -1) 48 | ) 49 | ;; (with-current-buffer buffer (inferior-inim-mode)) 50 | buffer)) 51 | 52 | 53 | 54 | ;;;###autoload 55 | (defalias 'run-nim #'inim) 56 | ;;;###autoload 57 | (defalias 'inferior-nim #'inim) 58 | 59 | 60 | (defmacro with-system (type &rest body) 61 | "Evaluate BODY if `system-type' equals TYPE." 62 | (declare (indent defun)) 63 | `(when (eq system-type ',type) 64 | ,@body)) 65 | 66 | (defun inim-startup () 67 | "Start inim." 68 | 69 | (with-system darwin 70 | (comint-exec inim-shell-buffer-name 71 | (s-prepend 72 | (s-prepend 73 | "cd " (shell-command-to-string "nimble path inim")) 74 | " && ./inim") inim-program nil inim-args) 75 | ) 76 | 77 | 78 | (with-system gnu/linux 79 | (comint-exec inim-shell-buffer-name "inim" inim-program nil inim-args) 80 | 81 | ) 82 | 83 | (with-system windows 84 | (comint-exec inim-shell-buffer-name "inim" inim-program nil inim-args) 85 | 86 | ) 87 | 88 | ) 89 | 90 | (defun maintain-indentation (current previous-indent) 91 | (when current 92 | (let ((current-indent (length (inim-match-indentation (car current))))) 93 | (if (< current-indent previous-indent) 94 | (progn 95 | (comint-send-string inim-shell-buffer-name "\n") 96 | (comint-send-string inim-shell-buffer-name (car current)) 97 | (comint-send-string inim-shell-buffer-name "\n")) 98 | (progn 99 | (comint-send-string inim-shell-buffer-name (car current)) 100 | (comint-send-string inim-shell-buffer-name "\n"))) 101 | (maintain-indentation (cdr current) current-indent) 102 | ))) 103 | 104 | (defun inim-split (separator s &optional omit-nulls) 105 | "Split S into substrings bounded by matches for regexp SEPARATOR. 106 | If OMIT-NULLS is non-nil, zero-length substrings are omitted. 107 | This is a simple wrapper around the built-in `split-string'." 108 | (declare (side-effect-free t)) 109 | (save-match-data 110 | (split-string s separator omit-nulls))) 111 | 112 | 113 | (defun inim-match-indentation(data) 114 | (regex-match "^[[:space:]]*" data 0)) 115 | 116 | 117 | (defun inim-eval-region (begin end) 118 | "Evaluate region between BEGIN and END." 119 | (interactive "r") 120 | (inim t) 121 | (progn 122 | (maintain-indentation (inim-split "\n" 123 | (buffer-substring-no-properties begin end)) 0) 124 | (comint-send-string inim-shell-buffer-name ";\n") 125 | )) 126 | 127 | 128 | ;; (defun inim-type-check () 129 | ;; (interactive) 130 | ;; (comint-send-string inim-shell-buffer-name (concat "let inimmodetype: () = " (thing-at-point 'symbol) ";")) 131 | ;; (comint-send-string inim-shell-buffer-name "\n") 132 | ;; ) 133 | 134 | ;; (defun inim-type-check-in-container () 135 | ;; (interactive) 136 | ;; (comint-send-string inim-shell-buffer-name (concat "let inimmodetype: () = " (thing-at-point 'symbol) "[0];")) 137 | ;; (comint-send-string inim-shell-buffer-name "\n") 138 | ;; ) 139 | 140 | 141 | (defun inim-parent-directory (dir) 142 | (unless (equal "/" dir) 143 | (file-name-directory (directory-file-name dir)))) 144 | 145 | (defun inim-find-file-in-hierarchy (current-dir fname) 146 | "Search for a file named FNAME upwards through the directory hierarchy, starting from CURRENT-DIR" 147 | (let ((file (concat current-dir fname)) 148 | (parent (inim-parent-directory (expand-file-name current-dir)))) 149 | (if (file-exists-p file) 150 | file 151 | (when parent 152 | (inim-find-file-in-hierarchy parent fname))))) 153 | 154 | 155 | (defun inim-get-string-from-file (filePath) 156 | "Return filePath's file content. 157 | ;; thanks to “Pascal J Bourguignon” and “TheFlyingDutchman 〔zzbba…@aol.com〕”. 2010-09-02 158 | " 159 | (with-temp-buffer 160 | (insert-file-contents filePath) 161 | (buffer-string))) 162 | 163 | 164 | (defun inim-eval-buffer () 165 | "Evaluate complete buffer." 166 | (interactive) 167 | (inim-eval-region (point-min) (point-max))) 168 | 169 | (defun inim-eval-line (&optional arg) 170 | "Evaluate current line. 171 | If ARG is a positive prefix then evaluate ARG number of lines starting with the 172 | current one." 173 | (interactive "P") 174 | (unless arg 175 | (setq arg 1)) 176 | (when (> arg 0) 177 | (inim-eval-region 178 | (line-beginning-position) 179 | (line-end-position arg)))) 180 | 181 | 182 | ;;; Shell integration 183 | 184 | (defcustom inim-shell-interpreter "inim" 185 | "default repl for shell" 186 | :type 'string 187 | :group 'inim) 188 | 189 | (defcustom inim-shell-internal-buffer-name "Inim Internal" 190 | "Default buffer name for the internal process" 191 | :type 'string 192 | :group 'nim 193 | :safe 'stringp) 194 | 195 | 196 | (defcustom inim-shell-prompt-regexp "nim> " 197 | "Regexp to match prompts for inim. 198 | Matchint top\-level input prompt" 199 | :group 'inim 200 | :type 'regexp 201 | :safe 'stringp) 202 | 203 | (defcustom inim-shell-prompt-block-regexp " " 204 | "Regular expression matching block input prompt" 205 | :type 'string 206 | :group 'inim 207 | :safe 'stringp) 208 | 209 | (defcustom inim-shell-prompt-output-regexp "" 210 | "Regular Expression matching output prompt of evxcr" 211 | :type 'string 212 | :group 'inim 213 | :safe 'stringp) 214 | 215 | (defcustom inim-shell-enable-font-lock t 216 | "Should syntax highlighting be enabled in the inim shell buffer?" 217 | :type 'boolean 218 | :group 'inim 219 | :safe 'booleanp) 220 | 221 | (defcustom inim-shell-compilation-regexp-alist '(("[[:space:]]\\^+?")) 222 | "Compilation regexp alist for inferior inim" 223 | :type '(alist string)) 224 | 225 | (defgroup inim nil 226 | "Nim interactive mode" 227 | :link '(url-link "https://github.com/serialdev/inim-mode") 228 | :prefix "inim" 229 | :group 'languages) 230 | 231 | (defcustom inim-program (executable-find "inim") 232 | "Program invoked by `inim'." 233 | :group 'inim 234 | :type 'file) 235 | 236 | 237 | (defcustom inim-args nil 238 | "Command line arguments for `inim-program'." 239 | :group 'inim 240 | :type '(repeat string)) 241 | 242 | 243 | 244 | (defcustom inim-prompt-read-only t 245 | "Make the prompt read only. 246 | See `comint-prompt-read-only' for details." 247 | :group 'inim 248 | :type 'boolean) 249 | 250 | (defun inim-comint-output-filter-function (output) 251 | "Hook run after content is put into comint buffer. 252 | OUTPUT is a string with the contents of the buffer" 253 | (ansi-color-filter-apply output)) 254 | 255 | 256 | 257 | (define-derived-mode inferior-inim-mode comint-mode "Inim" 258 | (setq comint-process-echoes t) 259 | ;; (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\)" 260 | ;; inim-shell-prompt-regexp 261 | ;; inim-shell-prompt-block-regexp)) 262 | (setq comint-prompt-regexp "nim> ") 263 | 264 | (setq mode-line-process '(":%s")) 265 | (make-local-variable 'comint-output-filter-functions) 266 | (add-hook 'comint-output-filter-functions 267 | 'inim-comint-output-filter-function) 268 | (set (make-local-variable 'compilation-error-regexp-alist) 269 | inim-shell-compilation-regexp-alist) 270 | (setq comint-use-prompt-regexp t) 271 | 272 | (setq comint-inhibit-carriage-motion nil) 273 | 274 | (setq-local comint-prompt-read-only inim-prompt-read-only) 275 | 276 | ;; (when inim-shell-enable-font-lock 277 | ;; (set-syntax-table nim-mode-syntax-table) 278 | ;; (set (make-local-variable 'font-lock-defaults) 279 | ;; ;; '(nim-mode-font-lock-keywords nil nil nil nil)) 280 | ;; ) 281 | ;; (set (make-local-variable 'syntax-propertize-function) 282 | ;; (eval 283 | ;; "Unfortunately eval is needed to make use of the dynamic value of comint-prompt-regexp" 284 | ;; '(syntax-propertize-rules 285 | ;; '(comint-prompt-regexp 286 | ;; (0 (ignore 287 | ;; (put-text-property 288 | ;; comint-last-input-start end 'syntax-table 289 | ;; python-shell-output-syntax-table) 290 | ;; (font-lock-unfontify--region comint-last-input-start end)))) 291 | ;; ))) 292 | ;; (compilation-shell-minor-mode 1))) 293 | 294 | ) 295 | 296 | (progn 297 | (define-key nim-mode-map (kbd "C-c C-b") #'inim-eval-buffer) 298 | (define-key nim-mode-map (kbd "C-c C-r") #'inim-eval-region) 299 | (define-key nim-mode-map (kbd "C-c C-l") #'inim-eval-line) 300 | (define-key nim-mode-map (kbd "C-c C-p") #'inim)) 301 | 302 | ;;;###autoload 303 | ;; (inim-nim-keymap) 304 | 305 | 306 | (provide 'inim) 307 | 308 | ;;; inim.el ends here 309 | --------------------------------------------------------------------------------