Monday, January 5, 2015

Arch linux on Dell XPS13

What?

Installing archlinux on a Dell XPS13 using archboot (instead of the standard archiso installer) via usb stick.

This turned out to be a pretty straightforward process. I also set up dm-crypt / luks and gave btrfs a go.

When: I ordered mine late 2014, got it before xmas.

Specs...

  • XPS 13BASE NBK XPS BTX 9333 WW (if that means anything)
  • i7-4510U processor
  • 8G ram
  • 256G ssd
  • basically this is the high end model

Disclaimer

I only infrequently do installs or set up operating systems. I don't really want to know more about UEFI than I absolutely have to, and I'm not bothered about Secure Boot either, nor am I all that knowledgeable on disk encryption. The commands and steps here should be taken as a guide only. Any security settings such as encryption settings and configurations should be researched by you.

Impressions of the XPS 13

Dell XPS13 just after switching over to Archlinux.

I asked about the developer edition of the XPS 13, aka project sputnik but was told this wasn't available in Australia. I bit my tongue, and went ahead anyway and paid the microsoft tax.

This is a sleek piece of kit. However I was alarmed on first switching this on to have the fans roaring into sudden and furious action. There I was, staring at this thing and trying to reconcile the desire to play with something so obviously new and shiny, with the increasing horror that maybe I had a turkey on my hands. Visions flashed through my head of me on the train or at work having to explain to people around me why the fan was so loud: "All the cool new ultrabooks do it", I'd protest weakly.

Fortunately, a reboot into the firmware (hit f12 at startup and look for Diagnostics) and then running some diagnostics including fan control seemed to quiet the system down and I haven't had a repeat episode since.

When doing nothing, this system is whisper quiet, no whirring and moving parts etc. There is a slight high-pitched and directional "eeeee" sound which goes from a lower pitch when the keyboard lights are off to a higher pitch when the keyboard lights go on - this apparently was a real big issue with earlier models. It feels like the "whine" is louder (at least lower so I can hear) when the lights are off. UPDATE: I feel the noise the keyboard makes when the lights go off (which happens after some inactivity) has gotten louder after a day or two and is potentially an issue.

My main concern at this point is that the XPS 13 may run hot. I'm packing an i7 in there and the base is really not that much thicker then a usb slot - and that's the end that doesn't taper. Time will tell. Browsing (using chromium) seems to provoke the fan almost straight away especially if scrolling. That being said, my experience during the install of arch on this system just got better and better. Working on a bare console (before building a gui) was almost a pleasant experience, probably because the gorgeous screen and keyboard were such a pleasure to use.

First things

  • f2 brings up the UEFI firmware setup utility
  • f12 brings up the UEFI loader
    • which you can also activate the setup utility or do other things
  • fn + arrow keys gives you Home, End, Pg up, Pg down which might be worth knowing if you've got to hit the man pages
  • there is no optical drive; this is a usb job; nothing spins on this thing, which is awesome

Installing Arch...

There are 2 choices up front.

  • which installer to use:
    • archiso
      • when I booted with this in early 2014 on a different system using an optical disk, I was dropped into a shell, and I did some re-partitioning and some fancy mounting and chrooting on the host file system to build the new arch system directly; this was a good experience, but I tried archboot this time...
    • or archboot
      • this is a larger image and seems dedicated to installing arch
      • the key differences are apparently listed here
        • archboot will boot up in ram and will provide a terminal UI (basic installer) to walk you through the setup
        • it won't mount your host system by defaut
        • a welcome script sits on tty1 through tty6 (well, I tested up to 2)
        • you hit enter on any of these and it will launch you into basic install mode which is a UI that walks you through an install (which is what I did below)
        • but if you switch over to another one (eg alt + f2), hit enter, you'll just get dropped into zsh where you'll have a lot more options about what you decide to do; personally I think it would be less confusing if the system just dropped you into zsh and printed a helpful message
        • so archboot can be used as a rescue utility: I was able to rescue my system this way after I b0rked my xorg input settings and lost my keyboard, so archboot can function as a rescue utility
  • and secondly either:
    • writing the image to the usb stick
      • this will limit your usb stick to the size of the image
    • or installing to a partition on the usb stick; involves copying files to the partition, more complicated, but you can still use the left over free space on your usb stick

I went with archboot and wrote the image directly onto the usb stick because this seemed like the most expedient option:

dd bs=4M if=archlinux-2014.11-1-archboot.iso of=/dev/sdX && sync

... which turned my 4G stick into a 1G stick.

This can be reset afterwards.

dd count=1 bs=512 if=/dev/zero of=/dev/sdx && sync

...and re-partition.

Booting the usb

At the beginning of this process my Phoenix SecureCore uefi was set to

  • boot mode: UEFI
  • Secure boot: ON
  • Legacy mode: disabled

These settings were the default.

I could cut a long story short here and just say disable secure boot . But I did initally try to go with these settings.

I gave up trying to set boot order in the UEFI firmware setup utility (f2); I was able to add a usb entry to the top of the list (only after plugging the usb in) but windows would always boot; maybe it was falling through to windows, but it wasn't terribly obvious.

Instead, I used f12 to load the uefi loader which showed the usb I had inserted into the laptop.

Selecting the usb entry from this menu gave an error dialog:

### Secure Boot ###
Image failed to verify with *ACCESS DENIED*.
Press any key to continue.

This led to another screen:

Failed to start loader
It should be called loader.efi (in the current directory)
Please enrol its hash and try again
I will now execute HashTool for you to do this
OK

This led to another screen

### Select Binary ###
The Selected Binary will have its hash Enrolled.
This means it will subsequently boot with no prompting
Remember to make sure it is a genuine binary before Enrolling its hash.
[a selection box with files in it including loader.efi]

(At this point I think I should have just turned Secure Boot off since I don't need it, but I persisted for a bit longer...)

I selected loader.efi from the selection box.

Which led to

Enroll this hash in MOK database?
Hash: big scary hash

Restarting with f12 and selecting the usb brought up the ACCESS DENIED error again. BUT this time, hitting ok brought up the archboot loader with the following selection

* Arch Linux x86_64 Archboot EFISTUB
* GRUB X64 - if EFISTUB boot fails
* UEFI Shell X64 v1
* UEFI Shell X64 v2
* EFI Default Loader
* Reboot into firmware interface

I tried the EFISTUB option 1. This ultimately failed for me. I got ACCESS DENIED again and a message about "enroll /boot/vmlinuz..." (I can't remember the last bit). I tried to enrol this using the Select Binary screen.

I did this, but then hit another crop of errors:

Failed to open file: boot\intel-uecode.img
Trying to load files to higher address
Failed to open file: boot\intel-uecode.img

I tried option 2. This time I had to enrol a grub file. I can't remember which one, I think it was /boot/EFI/grub/grubx64.efi . Rebooting, hitting f12 and hitting the 2nd option as before, getting ACCESS DENIED but clicking passed this, I eventually got the usb to boot.

As I mentioned, I should have turned secure boot off to avoid this rigmarole.

Archboot installer

You should see a message like this on booting the usb:

Welcome to Arch Linux (archboot environment)

Hitting enter put me straight into the basic install utility which is a series of sections you can enter and configure things.

  • Keyboard and console font
    • Pretty much skipped over this
  • Networking
    • I was able to get wireless working straight away. archboot will up a wireless profile in /etc/netctl and it also asked me if I preferred to use dhclient over dhcpcd, which from previous experience I did. So I had wireless working straight away which was super encouraging.
  • Prepare Storage Drive
    • I went with a GUID partition table (GPT)
    • I made a 2G swap partition; overkill? probably
    • archboot seems to make you setup separate / and /home partitoins; I didn't like this initially, but after some consideration I went with it; I selected ext4 for both and gave / root 20G. Not sure if that is enough, hopefully it will be.
    • selected /boot as the UEFISYS mountpoint
    • select the device name scheme
      • PARTUUID and PARTLABEL are specific to GPT disks, PARTUUID is recommended for GPT
      • I went with PARTUUID
  • Select a source
    • we are given 2 options: peripheral device cd/usb or network
    • I went with usb
  • Install packages
    • I selected BASE and SUPPORT
  • there were some steps around configuring the system
    • I set /etc/hostname
    • mirror list (enabled australian sites)
    • set root password
  • Install bootloader
    • Setup has detected that you are using "X64 UEFI", do you want to install a X64 UEFI bootloader?
      • yes
    • now it gets tricky, we have 3 choices
      • EFISTUB
      • GRUB_UEFI
      • SYSLINUX_UEFI
    • I went with GRUB_UEFI
      • Got this cryptic message

        You have entered /boot as the mountpoitn of your EFISYS partition. Any other partioin using /boot as mountpoint will be ignored. You may have to re-install kernel and bootloader files (currently existing in /boot) to the EFISYS partition once it is setup at /boot.

      • asked to edit grub.conf file; I did, but didn't change anything
      • then: do you want to copy /boot/EFI/grub/grubx64.efi to /boot/EFI/BOOT/bootx64.efi? This might be needed in some systems where efibootmgr may not work due to firmware issues.
        • yes

Booting Arch

After going through the options, I then exited the installer and rebooted the system and removed the usb.

Rebooting gave me the ACCESS DENIED dialog again. It appeared to try twice, then gave up with this message:

No bootable devices - strike F1 to retry boot, F2 for setup utility.
Press F5 to run onboard diagnostics.

Time to give secure boot the boot. I hit f2 to get back into setup, and when to Boot tab, and set 'Secure Boot' to Disabled.

And voila, it boots.

Might be a good time to do

pacman -Syu

While you're at it, get rid of the console beep:

echo "blacklist pcspkr" > /etc/modprobe.d/nobeep.conf

or

rmmod pcspkr  # for immediate non-permanent relief

Modifications

At this point I had a system with /, /home using ext4, and swap.

I decided I wanted to:

  • encrypt swap and /home
  • and also try btrfs on /home for snapshots, bitrot and compression and also for eventually super fast syncing.
  • I also wanted to tune the system a little for the solid state drive.

There is still debate about the stability of btrfs, but things look like they are getting to a point where it's becoming ok to use. One of the big motivations was this article (a year ago now). Since that time at least one major distro has made it the default.

And then there is https://btrfs.wiki.kernel.org/index.php/FAQ#Is_btrfs_stable.3F from 2 years ago:

Pragmatic answer: (2012-12-19) Many of the developers and testers run btrfs as their primary filesystem for day-to-day usage, or with various forms of "real" data. With reliable hardware and up-to-date kernels, we see very few unrecoverable problems showing up. As always, keep backups, test them, and be prepared to use them.

I've used zfs on my backup media for some time now via the arch AUR zfs-git package which requires kernel modules so I'm hoping to replace this eventually with just btrfs.

Crypting Swap

This turned out to be super easy. I'm not bothered about hibernating aka suspend-to-disk, so this simplified the task.

See:

I need gdisk for my partiion:

pacman -S gptfdisk # gdisk

This identified my swap partition:

gdisk -l /dev/sda  # for me /dev/sda3 was swap type=82

This shows what swap you're using if any:

swapon -s

You can turn swap off like this:

swapoff /dev/sdaX

Use

blkid

to give you UUID and PARTUUID etc.

So, all I had to do to get this working was adding a line like this to /etc/crypttab:

swap           PARTUUID=d4ae0d26-8df6-4005-aaf7-f419418134c2 /dev/urandom           swap,cipher=aes-cbc-essiv:sha256,size=256,discard

and adding this to /etc/fstab:

/dev/mapper/swap    none    swap    sw  0 0

Later I experimented with an alternative setting in /etc/crypttab:

swap           PARTUUID=d4ae0d26-8df6-4005-aaf7-f419418134c2 /dev/urandom           swap,cipher=aes-xts-plain64:sha256,size=512,discard

Originally, I tried to use UUID but this failed on a second reboot. Turned out the UUID for /dev/sda3 (my swap partition) was no longer present. So I switched to PARTUUID.

That's pretty much it. Reboot and see if it works. If it doesn't, the system may hang for a while at bootup and then give up and boot the system without any swap devices.

You might be able to get some information this way:

systemctl list-units | grep swap
journal -xe -u swap.target

you'll see not-so-helpful messages like:

Dependency failed for Swap.
Job swap.target/start failed with result 'dependency'.

If you forget the /etc/fstab entry, the system may also hang for a while at startup and ask for a password. You'll just have to sit it out.

fstab

I should note that my fstab had no uncommented entries in it.

genfstab might help in this regard:

genfstab -U -p  # prints entries you could put in fstab

Get it using: pacman -S arch-install-scripts .

Crypting Home

ae2-cbc-essiv looks to no longer be the standard for encryption (see https://wiki.archlinux.org/index.php/Dm-crypt/Device_encryption ):

Please note that with release 1.6.0, the defaults have changed to an AES cipher in XTS mode. It is advised against using the previous default --cipher aes-cbc-essiv, because of its known issues and practical attacks against them.

Also see for cbc vs xts etc:

You should have an empty /home directory courtesy of archboot.

Unmount it and prepare it for block encryption:

umount /dev/sdaX  # /home partition (for me /dev/sda5)
cryptsetup -s 512 luksFormat /dev/sdaX

Check:

cryptsetup luksDump /dev/sdaX

should show aes plain xts.

Now we can open this device and put a filesystem on it:

cryptsetup luksOpen /dev/sdaX home
mkfs.btrfs /dev/mapper/home

I have this entry in my /etc/crypttab - the system can boot without an entry in here, but i want to use the discard option:

home           PARTUUID=df5ba5f5-9492-4ae2-b1aa-2ac548841394 none                   home,luks,size=512,discard

Using discard may have security implications if you're using block encryption. Also confession: I don't know if this is actually enabling TRIM support, it is listed in man 5 crypttab.

And in /etc/fstab:

UUID=3f05ccbe-137b-4fb0-9236-be2520fda140   /           ext4        rw,noatime,discard,data=ordered 0 1
/dev/mapper/home    /home   btrfs   rw,compress=zlib,discard,ssd,relatime   0 0

I've included / above which I added with some additional flags: noatime / relatime, discard and ssd are used.

If this is all working, your system will ask for a password to open the /home partition as part of the boot up process. This is separate to your user account password(s) that you may have.

GUI

I won't cover xorg set up. I do use infinality to improve fonts especially in the browser.

Sound

I had some system sounds, but nothing when playing video.

Alsamixer and pavucontrol both showed 2 devices, the second one was the one I wanted: HDA Intel PCH. Following the advice of

I found this setting worked:

cat /etc/modprobe.d/modprobe.conf 
options snd_hda_intel enable=0,1

After this, earphones and pc speakers worked as expected.

Touchpad and touchscreen

The system is almost impossible to type on with the touchpad default settings. A slight glance will either click or scroll.

I have /etc/X11/xorg.conf.d/50-synaptics.conf with:

Section "InputClass"
    Identifier "touchpad"
    Driver "synaptics"
    MatchIsTouchpad "on"
        Option "TapButton1" "-1"
        Option "TapButton2" "-1"
        Option "TapButton3" "3"
        Option "VertEdgeScroll" "-1"
        Option "VertTwoFingerScroll" "on"
        Option "HorizEdgeScroll" "-1"
        Option "HorizTwoFingerScroll" "on"
        Option "CircularScrolling" "on"
        Option "CircScrollTrigger" "2"
        Option "EmulateTwoFingerMinZ" "40"
        Option "EmulateTwoFingerMinW" "8"
        Option "CoastingSpeed" "0"
        Option "FingerLow" "35"
        Option "FingerHigh" "40"
EndSection

This disables tap clicking (you can still depress the end of the touchpad for a normal click), and it enables 2-finger scrolling. I can still trigger 2-finger scrolling when both hands glance the trackpad so nothing's perfect.

The touchscreen is a bit of a mystery. It is recognised and looks to be treated like a mouse / pointer device (xinput --list). I can touch links in chromium but they are not clicked. What I really want is the ability to scroll but I haven't figured this out.

cat /proc/bus/input/devices  | egrep 'Bus|Name'
...
I: Bus=0018 Vendor=06cb Product=2734 Version=0100
N: Name="DLL060A:00 06CB:2734"
I: Bus=0003 Vendor=06cb Product=0af8 Version=0111
N: Name="SYNAPTICS Synaptics Large Touch Screen"
...

So I'm assuming DLL060A is the touchpad and the second set of entries is my screen.

I'm wondering if I can set up another Section in xorg.conf.d with

MatchIsTouchscreen "on"

But haven't got anywhere yet.

Links

Sunday, December 28, 2014

Emacs, flycheck and jshint and other jslinters

One of the benefits to emacs 24 is the new flycheck package.

Once you've installed flycheck be sure to head over to M-x flycheck-info, which should throw up the info manual for flycheck where you can learn that flycheck is the new flymake and how you can extend it. The author(s) of this document aren't shy in expressing their opinion:

"...we consider Flycheck superior to Flymake in all aspects"

I'm no judge of this. I only know that it works well for the things I need it on: js and jshint and also other languages such as php. I won't go into php here, but flycheck will happily use both phpcs - the code sniffer - and phpmd, the mess detector.

I'm probably nowhere near close to using the full capabilities of flycheck. Below I look at chaining an additional linter after jshint to provide indentation warnings.

But before I go any further...

Installing / Setup

I installed flycheck using the emacs package manager (ELPA) and specifically with a the melpa.milkbox.net repository.

Note I have the following in one of my emacs initialisation files (rightly or wrongly) which gives me several package repositories to choose from:

(require 'package)
(add-to-list 'package-archives
             '("marmalade" . "http://marmalade-repo.org/packages/") t)
(add-to-list 'package-archives
             '("melpa-stable" . "http://melpa-stable.milkbox.net/packages/") t)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)

I'm using:

  • flycheck 20141102.652 (use M-x package-list-packages to list and install packages)
    • WARNING: version 20141224.16 is more recent but blows up with my version of gjslint
    • delete it from *Packages* buffer (D) to reinstate the previous version

In my emacs configuration I have this to have flycheck always on:

(global-flycheck-mode 1)

Also, I use helm which means I can run interactive functions using M-x almost and sometimes faster than hitting keyboard shortcuts. It's gotten to the point that I often don't bother trying to add a keyboard shortcut for a new piece of functionality I'm using, preferring instead to hit M-x (helm-M-x under the covers) and typing a few short key strokes to precisely identify the command I want to use.

helm is a revelation, if you haven't tried it, you should.

The vexing issue of javascript major modes in emacs

Yes... it seems we have at least 3:

  • js-mode / javascript-mode
    • this is the in-built js package in emacs
  • js2-mode
    • version 20141224.347 melpa.milkbox.net
  • js3-mode
    • version 20140805.1529 melpa.milkbox.net
  • (There's also a json-mode which is worth installing as well to assist with things like ensuring double quotes.)

I sometimes switch between these.

  • One thing to note is that js2-mode insists on semi-colons, at least by default, and will apply an angry red underline to any offending line that doesn't.
    • This can be turned off with M-x customize-option RET js2-strict-missing-semi-waring and then toggling it off.
  • js3-mode appears to have been modelled on js2-mode and js-mode but tries to support npm-style js conventions which means out of the box it won't worry about semicolons.

Both js2-mode and js3-mode offer some error / linting / parsing and make this available via emacs' next-error facility.

  • In a js file, hitting M-g M-n will invoke next-error which will move you to the next error / warning or issue in your file.
  • M-g M-p will take you to the previous one
  • (Seasoned emacs users may be familiar with these keys since they are used by facilities such as M-x occur (file grepping) and M-x find-grep allowing you to traverse through a list of search hits.)
  • js2-mode will flag standard nodejs globals like require and process as undeclared, whereas js3-mode doesn't.
  • Also, js2-mode doesn't seem to detect some obvious syntax errors such as a double dot "..".

All of this however is unnecessary if you're using flycheck as flycheck will override the next-error system for its own purposes.

I tend to go with js2-mode as it seems more solid with things like switch-statement indentation.

Linters and hinters and code styler sniffers ...

M-x customize-group RET flycheck-executables will give you a good idea of what tools flycheck can handle. For js, there is jshint, gjslint, eslint and also jsonlint (for json).

A bunch of these come from the node eco-system:

sudo npm install -g jshint   # /usr/bin/jshint
sudo npm install -g jsonlint # /usr/bin/jsonlint
sudo npm install -g eslint   # /usr/bin/eslint

For google closure js linter (this is on an archlinux system) I had to do:

sudo easy_install-2.7 http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz
# /usr/bin/gjslint

Looking up eslint led to some interesting links: jshint and jslint apparently have their own parsers as opposed to using esprima or some other toolkit. eslint has now gone the same way and has its own parser called espree.

My version of flycheck didn't have out-of-the-box support for jscs -- the javascript code style(r) / ?sniffer. But it's not too hard to get it working with flycheck and it also solves the indent problem :) (see further down).

sudo npm install -g jscs     # /usr/bin/jscs

Flycheck and linter configurations

M-x customize-group RET flycheck-config-files allows you to set configuration files for your linters.

You can explicitly set config files for you linters eg you can set:

  • Flycheck Jshintrc: ".jshintrc"
  • Flycheck Gjslintrc: ".gjslintrc"
  • Flycheck Ejslintrc: ".eslintrc"

Flycheck will probably default to looking for dot files of the above form for jshint and gjslint. And it will probably intelligently determine where to look for these dot files in your project.

Using flycheck

Flycheck appears to use jshint by default (assuming you installed it), probably because it is listed before any of the other eligible checkers in flycheck-checkers variable.

In a js file, you should be able to do M-g M-n and M-g M-p to move forwards and backwards over warnings and errors that have been detected (using the next-error interface provided by emacs).

C-c ! l (M-x flycheck-list-errors) will list the errors in a buffer called *Flycheck errors* next to your js file giving you a point and click index into all your linting issues.

I use M-x flycheck-mode to toggle flycheck on and off.

Invoking multiple js linters in flycheck

Use M-x flycheck-select-checker to select a different checker (hint: you should be using helm or something like it which greatly accelerates selections and use of M-x).

  • M-x flycheck-select-checker RET javascript-jshint
  • M-x flycheck-select-checker RET javascript-gjslint
  • M-x flycheck-select-checker RET javascript-eslint

Flycheck has a mechanism for running multiple checkers at the same time which it refers to as chaining. For instance, by default flycheck's php facility will chain mess detector and code sniffer checkers so you will see output from both in the *Flycheck errors* buffer. But for js, by default, flycheck only uses one of supported linters at a time.

Checkers in flycheck are defined using flycheck-define-checker. Chaining checkers requires adding the :next-checkers property to this definition. All the standard in-built checkers are located in elpa/flycheck-20141102.652/flycheck.el .

Here's the jshint checker (it doesn't have :next-checkers property by default):

(flycheck-define-checker javascript-jshint
  "A JavaScript syntax and style checker using jshint.

See URL `http://www.jshint.com'."
  :command ("jshint" "--checkstyle-reporter"
            (config-file "--config" flycheck-jshintrc)
            source)
  :error-parser flycheck-parse-checkstyle
  :error-filter flycheck-dequalify-error-ids
  :modes (js-mode js2-mode js3-mode))

Chaining additional checkers is a topic of interest because, well, indentation...

The equally vexed issue of indenting in javascript

jshint no longer explicitly warns for indentation via the indent option. Boo, sad-face.

Indenting warnings with gjslint...

gjslint may come to the rescue here, it does show warnings for indentation, but it's not clear to me at this point how to control its indentation facility. It looks to be hard-coded to 2 spaces and it has particular ideas about breaking up lines of code that fall under the same rule (0006).

Here's an example of default gjslint preferences on indentation of function parameters :

// BAD: and anything less
promise.then (
  function promiseOk (result) {
  ...

// BAD: Up to this point...
promise.then (
             function promiseOk (result) {
             ...

// OK: if param comes after opening paren...
promise.then (
              function promiseOk (result) {
              ...

Personally I don't have a problem with the first form above, I think it makes the code more readable when a function has complex and extended arguments and reduces chance of exceeding line length.

You can put your gjslint flags passed to the linter on the cli into a flagfile eg create .gjslintrc in the root of your project with the following content:

--jslint_error=indentation

and then invoke like this:

gjslint --flagfile=path/to/.gjslintrc <file>

Flycheck presumably sets the flagfile option if it finds .gjslintrc (assuming you've configured the flycheck-config-files variable (above)). So you can have a .gjslintrc in the root of your project and flycheck will use this for all files.

gjslint lists a rule number or id for each rule that has been infringed. This provides another way to suppress some warnings provided by this linter (if you're using jshint). You can add to your flagfile like this:

--jslint_error=indentation
--disable=0001,0002,0220,0110

The above disabled rules are extra space (0001), missing space (0002), and "no docs found" (0220), line length (0110).

We can get gjslint to chain after jshint by using flycheck-add-next-checker.

In an emacs configuration file:

(with-eval-after-load 'flycheck
  ;; Chain javascript-jscs to run after javascript-jshint.
  (flycheck-add-next-checker 'javascript-jshint '(t . javascript-gjslint)))

This bit of elisp code waits for flycheck to get loaded and then executes its body. It calls flycheck-add-next-checker to add javascript-gjslint as the next checker after javascript-jshint. This means that both will be run on your js file and errors will be organised by line number in the *Flycheck errors* buffer.

Indentation warnings with eslint?

I ran out of gas here. It looks like eslint has taken the same stance as jshint. You can add it all the same using the above with-eval-after-load trick we just did above - but this is not something I'm doing atm.

(with-eval-after-load 'flycheck
  (flycheck-add-next-checker 'javascript-jshint '(t . javascript-eslint)))

Indentation warnings with jscs ... finally!

There doesn't look to be an in-built checker for jscs . This is something that should probably go into flycheck but there's nothing stopping us from using it with flycheck right now.

First, define a flycheck checker in your emacs configuration file(s) somewhere:

(flycheck-define-checker javascript-jscs
  "A JavaScript style checker using jscs.

See URL `https://www.npmjs.com/package/jscs'."
  :command ("jscs" "--reporter=checkstyle" 
            (config-file "--config" flycheck-jscsrc)
            source)
  :error-parser flycheck-parse-checkstyle
  :modes (js-mode js2-mode js3-mode))

For it to work, we'll need to add a file config for it as well:

(flycheck-def-config-file-var flycheck-jscsrc javascript-jscs ".jscsrc"
  :safe #'stringp)

Then add a .jscsrc file to the root of your project. eg

{
    "preset": "google",
    "requireCurlyBraces": null
}

At this point, you can do M-x flycheck-select-checker and see if you can select javascript-jscs. C-c ! l should give you a list of issues (assuming your file has issues).

With the above, I now can get indentation warnings eg if a line is not indented to 2 spaces (using the google preset here) - hooray!

So maybe what we want to do now, apart from tweaking configurations and presets, is combine this with jshint .

Easy enough, we extend what we did before with gjslint but replace it with jscs:


    (with-eval-after-load 'flycheck
    
      ;; Define a checker for jscs...
    
      (flycheck-define-checker javascript-jscs
        "A JavaScript style checker using jscs.
    
      See URL `https://www.npmjs.com/package/jscs'."
        :command ("jscs" "--reporter=checkstyle" 
                  (config-file "--config" flycheck-jscsrc)
                  source)
        :error-parser flycheck-parse-checkstyle
        :modes (js-mode js2-mode js3-mode))
    
      ;; Make flycheck-jscsrc configuration with default.
    
      (flycheck-def-config-file-var flycheck-jscsrc javascript-jscs ".jscsrc"
        :safe #'stringp)
    
      ;; Make javascript-jscs automatically selectable to flycheck
      ;;
      ;; Use t to append at the end so it's not used by default.
    
      (add-to-list 'flycheck-checkers 'javascript-jscs t)
    
      ;; Chain javascript-jscs to run after javascript-jshint.
    
      (flycheck-add-next-checker 'javascript-jshint '(t . javascript-jscs)))

Note we use add-to-list to add our new checker to flycheck-checkers to make it automatically selectable by flycheck, chaining may not work without this. And we take advantage of jscs's checkstyle output which flycheck can already handle.

Tweaking faces for flycheck

Probably because of my theme setup in emacs, the highlighted row in *Flycheck errors* buffer is all grey with the text hidden, so I do

M-x customize-group RET flycheck-faces

and customize Flycheck Error List Highlight and turn inherit off and set background to inverse video.

Similarly for mouse over text: M-x customize-option RET mouse-highlight which I disable.