Resuming nand2tetris with a touch of emacs

So I have been following the nand2tetris course in Coursera, but I find it could have a better integration with emacs. So here I am declaring that I'll do a major mode for nand2tetris. You can follow my progress here. And I'll keep updating you on improvements.


So First things I did was to copy python-mode because I kinda feel more comfortable with it, even though I don't understand much of it.

We first assume people are gonna get the nand2tetris source dir, so we can do

(defvar nand2tetris-source-dir nil
  "Source directory where nadn2tetris has been downloaded")

Now we define the major mode:

(define-derived-mode nand2tetris-mode prog-mode
  "nand2tetris"
  "Major mode for editing HDL files for the course Nand2Tetris.

\\{nand2tetris-mode-map}")

This will use nand2tetris-mode-syntax-table by default, so let's also define that:

(defconst nand2tetris-mode-syntax-table
  (let ((table (make-syntax-table)))
    (c-populate-syntax-table table)
    table))

We inherit the C syntax table because it will do the // and /* ... */ comments for free. and now our mode has syntax highlighting for comments and stuff. Now we only need font-locking.

So far I've seen these keywords CHIP, IN, OUT, PARTS, so let's see how it looks:

(defvar nand2tetris-font-lock-keywords
  ;;Keywords
  `(,(rx symbol-start
         (or "CHIP" "IN" "OUT" "PARTS")
         symbol-end)
    ;; CHIP <ChipName>
    (,(rx symbol-start "CHIP" (1+ space) (group (1+ (or word ?_))))
     (1 font-lock-type-face))
    ;; <ChipName> (in=in, out=out);
    (,(rx symbol-start (group (1+ (or word ?_)))
          (? space) (seq "(" (0+ not-newline) ")"))
     (1 font-lock-variable-name-face))))

Lets add it to the major-mode:

(define-derived-mode nand2tetris-mode prog-mode
  "nand2tetris"
  "Major mode for editing HDL files for the course Nand2Tetris.

\\{nand2tetris-mode-map}"

  (set (make-local-variable 'font-lock-defaults)
       '(nand2tetris-font-lock-keywords nil nil nil nil)))

Now, the hard part will be to bind the hdl files. As I know hdl is a very common extension (maybe? correct me if I'm wrong plz) I will just limit this major mode to bind to all .hdl files inside the nand2tetris-source-dir.

(add-to-list 'auto-mode-alist
             `(,(concat (expand-file-name nand2tetris-source-dir) "\.*\\.hdl")
               . nand2tetris-mode))

And that's been it for today. it all looks like this:

;;; nand2tetris.el --- Major Mode for HDL files in the Nand2Tetris Course
;;; https://www.coursera.org/course/nand2tetris1

;; Copyright (C) 2015 Diego Berrocal

;; Author: Diego Berrocal <cestdiego@gmail.com>
;; Created: 10 August 2015

;; Keywords: nand2tetris, hdl
;; Homepage: http://www.github.com/CestDiego/nand2tetris.el/
;; Version: 0.0.1

;; This file is not part of GNU Emacs.

;;; License: GPLv3

;;; Commentary:

;; Useful functions to make following the coursera course easier.

;;; Code:

(defvar nand2tetris-source-dir nil
  "Source directory where nadn2tetris has been downloaded")

(defconst nand2tetris-mode-syntax-table
  (let ((table (make-syntax-table)))
    (c-populate-syntax-table table)
    table))

(defvar nand2tetris-font-lock-keywords
  ;;Keywords
  `(,(rx symbol-start
         (or "CHIP" "IN" "OUT" "PARTS")
         symbol-end)
    ;; CHIP <ChipName>
    (,(rx symbol-start "CHIP" (1+ space) (group (1+ (or word ?_))))
     (1 font-lock-type-face))
    ;; <ChipName> (in=in, out=out);
    (,(rx symbol-start (group (1+ (or word ?_)))
          (? space) (seq "(" (0+ not-newline) ")"))
     (1 font-lock-variable-name-face))))

(define-derived-mode nand2tetris-mode prog-mode
  "nand2tetris"
  "Major mode for editing HDL files for the course Nand2Tetris.

\\{nand2tetris-mode-map}"

  (set (make-local-variable 'font-lock-defaults)
       '(nand2tetris-font-lock-keywords nil nil nil nil)))

(add-to-list 'auto-mode-alist
             `(,(concat (expand-file-name nand2tetris-source-dir) "\.*\\.hdl")
               . nand2tetris-mode))

(provide 'nand2tetris)

Next things is to actually use the scripts that nand2tetris gives us.