What if the trees were the real angels?

What if the trees were the real angels?

This is what I sat to think looking at this war memorial angel statue in Lier.

Turns out there is a name for this – Pantheism.

But my interpretation is roughly that Nature and God are the same thing. It’s reasonable to me to say “Nature created humans”.

Headspace is better than coffee

More generically this would be meditation is better than coffee, but the only meditation I do is via Headspace.

My central point is that it’s better to give up on coffee and replace it with meditation. I’ve been drinking a lot of coffee for years. I guess 4-5 mugs of coffee per day plus at least one mug of tea. But during these years my ability to concentrate has been terrible. So I’ve been slowly ever increasing the amount of tea and coffee. I do IT and avoid any kind of management – so the only thing I rely on is concentration for long periods.

But I can’t concentrate, so I need to change something. The first article that got me thinking was the BBC health article on waking up earlier:

  • Wake up 2-3 hours earlier than usual and get plenty of outdoor light in the morning
  • Eat breakfast as soon as possible
  • Exercise only in the morning
  • Have lunch at the same time every day and eat nothing after 19:00
  • Banish caffeine after 15:00
  • Have no naps after 16:00
  • Go to bed 2-3 hours earlier than usual and limit light in the evenings
  • Maintain the same sleep and wake times every day

The one that was easiest to implement was “Banish caffeine after 15:00” – so that was easy enough to stop coffee after 3. The next trigger was a Quora post saying that when waking up we need water and not coffee to help our kidneys get going.

For kidneys is very important that you go sleep on time, before 10pm if possible, and that you do a lot of exercises in the morning or afternoon (but not in the evening, our body should rest at that time of the day). Avoid any stimulants like coffee and alcohol which directly influence on our kidneys, making them dry and slow. When you wake up the first thing you should do is drink loads of warm water, this will warm up your kidneys and put them in work.

Obviously this is from a random stranger on the internet, so trust it less, but it’s easy enough to try drinking water first thing in the morning. However I don’t do this consistently – drinking water is boring, coffee tastes nice. I was doing this and not much was changing. Drinking no coffee after 3, but drinking quite a lot in the morning. Stopping regularly with my work to go make some more coffee or re-heat the coffee pot.

In the past I got into Headspace for doing meditation. I kept it up for about 2 years, but I stopped about 18 months ago. I hadn’t noticed any productivity increase during that period so I didn’t see the benefit, but looking back I realised that I managed to spend a full 18 months learning Machine Learning and Deep Learning through Coursera and also learning about Category Theory – almost entirely in the evenings. So it does seem like meditation helps – but maybe I’m just making up the link, there’s lots of other factors involved. So I tried to restart doing Headspace 6 months ago, but I would do it maybe one or two times and then stop for weeks on end, nothing changed. In an attempt to get myself to get Headspace done in the morning I came up with this phrase:

“Headspace is better than coffee.”

My main idea behind it is that Headspace does something similar to coffee – it helps me concentrate but it also has long term benefits. Coffee does bugger all except make you run around like a headless chicken for 30 minutes until you get the next ‘fix’ of caffeine. This statement is all well and good but it still didn’t change my habits. I had similar ideas about apples, that it’s better to eat an apple than drink coffee – but not sure where I heard that from.

I have finally though come to the conclusion that coffee is completely ineffective. It doesn’t work, it doesn’t help, so the only thing left to do is stop taking it completely. I might as well be completely unproductive without coffee than completely unproductive with coffee. Instead, in the mornings, I have switched to drinking green tea with a slice of lemon squeezed into it (and sometimes with local honey added too). There’s lots of benefits to green tea, so at least it’s useful. Then on top of that I take some grapes or fresh pineapple up with me as I start work.

Further to this I have added that I spend 5 minutes doing yoga and then the 15 minutes it takes to get Headspace done. The irony is that by stopping making coffee, I actually save about 15 minutes a day from the time I spend faffing around brewing and re-heating the stuff, so I now have time for Headspace. I’ve been doing this for 3 weeks now and the turnaround has been fantastic. My mornings are now almost totally focussed and I get a full morning’s work done.

Aside from that I also make sure to leave my phone outside the room that I’m working in and I also stopped going for walks in the morning. Walks are nice but they added too much pressure from the hour I lost going for a walk. I hope to start walks again in the afternoons because I know they’re good, but for now they’ll have to wait.

Getting started with ReasonML

I write this as a stumbling fumbling guide for how to actually get started, when all you have is a Javascript and React backgroud with no knowledge of OCaml.

I’m using a combination of Fedora and Ubuntu.

Obviously start here: https://reasonml.github.io/

Installation

I even went off the rails at this point because you need globally installed bsb support and you run into the sudo/not-sudo argument. Lots of people want you to install yarn/npm as non-sudo, but I do it as sudo.

The guide suggests that you do it without sudo and makes no mention of using sudo. So for people like me the documentation goes wrong from the very first step. This makes me sad.

The issue being that because I install npm with the Fedora package manager it’s installed as sudo. So I need to run sudo npm install -g which is all fine and good, but some well meaning people rightly express that this should be avoided if possible, but in the case of Fedora this is unavoidable.

I wrote this all up in an issue #2168, with the most relevant comment I made:

In the npm troubleshooting guide and Grunt getting started guide they have the following advice for global installs:

(You may need to prefix these commands with sudo, especially on Linux, or OS X if you installed Node using its default installer.)

I also hit the same problem with my ubuntu install.

If I run without sudo then the yarn add completes fine, but I get the following error if I try to run bsb:

Command ‘bsb’ not found

So I have to run:

sudo yarn global add bs-platform

However now, you have to run bsb with sudo too. Otherwise you get the following error:

$ bsb -init hello -theme basic-reason
Making directory hello
npm WARN checkPermissions Missing write access to /usr/lib/node_modules
npm ERR! code EACCES
npm ERR! syscall access
npm ERR! path /usr/lib/node_modules
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, access '/usr/lib/node_modules'
npm ERR!  { [Error: EACCES: permission denied, access '/usr/lib/node_modules']
npm ERR!   stack:
npm ERR!    'Error: EACCES: permission denied, access \'/usr/lib/node_modules\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/lib/node_modules' }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/channi16/.npm/_logs/2020-05-02T11_56_03_062Z-debug.log
failed to run : npm link bs-platform

So you have to run:

sudo bsb -init hello -theme basic-reason

The problem with this is that it then creates the hello directory and all its contents as root. However you don’t always need to use sudo. It seems like it’s either the first time you use it, or perhaps when you use a new template. However after than you can run bsb -init my-dir -theme basic-reason without sudo. It’s not even when using a new theme, you can init with un-used themes. It appears to be just the first time that you run bsb -init that it requires sudo.

Editor plugins

The advice here is quite simple. Use VS Code unless you’re like me and you want your freedom. In that case, if you use Vim, then you’re in luck. I’ve wasted the 10 hours of time for you trying all the different combinations of plugins. See my previous blog post on Using ReasonML with Vim / Neovim.

Initial coding of the demo project

I started with the demo project, this builds a Demo.re file to a Demo.bs.js file that can be run in node.

React our way up the tree

I wanted to get display into the browser – but the basic demo is node only. I want raw JS.

The react example gives raw JS output – but it has to go through webpack.

Kinda annoying – but I guess the webpack converts the bucklescript node javascript into browser style javascript.

Installing the demo

I ran the following to install the create-react demo:

bsb -theme react -init neural-network-re

Running the demo

This installs a runnable demo. I of course hit an error when running the code:

[ian@localhost neural-network-re]$ npm run webpack

> neural-network-re@0.1.0 webpack /var/www/vhosts/reasonml/neural-network-re
> webpack -w

/var/www/vhosts/reasonml/neural-network-re/node_modules/webpack-cli/bin/config-yargs.js:89
describe: optionsSchema.definitions.output.properties.path.description,
                                           ^

TypeError: Cannot read property 'properties' of undefined
    at module.exports (/var/www/vhosts/reasonml/neural-network-re/node_modules/webpack-cli/bin/config-yargs.js:89:48)
    at /var/www/vhosts/reasonml/neural-network-re/node_modules/webpack-cli/bin/webpack.js:60:27
    at Object.<anonymous> (/var/www/vhosts/reasonml/neural-network-re/node_modules/webpack-cli/bin/webpack.js:515:3)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! neural-network-re@0.1.0 webpack: `webpack -w`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the neural-network-re@0.1.0 webpack script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/ian/.npm/_logs/2018-11-26T22_05_12_616Z-debug.log

It’s so frustrating when things don’t ‘just work’. Anyway it turns out to be a webpack error that they fixed in the project back in October, the fix is to upgrade the webpack-cli version in the package.json.

Also it looks like I’m running an old version of bsb as it appears to install an old version of the project. My version has the stupid idea of trying to get hot reloading running first, rather than a simple build.

It looks like in the new version they simplify it and just run the regular build. At least then it’s obvious that it’s a webpack error rather than some weird compilation error. It’s now just:

npm install
npm run build
npm run webpack

Then open src/index.html

That is pretty sweet! Got me a lovely simple index.html page up and running.

Hot reloading

Now we can attempt the hot reloading.

npm run start

Then in a separate terminal:

npm run webpack

This then hot reloads the code – but it doesn’t auto refresh the webpage – but at least I understand it.

Steps towards a Neural Network

My reasons for doing all this is to convert a simple Neural Network I wrote in JavaScript into ReasonML.

Now the first thing I want to try and do is get some SVG displaying, this isn’t so simple because you need to do it in JSX that gets output to god knows what that eventually produces an SVG.

However via a forum post there is a link for how to display a basic SVG. The slightly cryptic thing in there is that it doesn’t display anything to the screen, it just creates the SVG in a variable.

I made some modifications to the demo code to it to output a simple SVG circle and then got the SVG displaying to the screen too

let m =
  <svg
    width="200"
    height="200"
    viewBox="0 0 200 200"
    xmlns="http://www.w3.org/2000/svg">
    <circle
      cx="5"
      cy="5"
      r="5"
      style=(ReactDOMRe.Style.make(~fill="black", ()))
      xmlns="http://www.w3.org/2000/svg"
    />
  </svg>;

ReactDOMRe.renderToElementWithId(m, "target");

The online tool (https://reason.surge.sh) is quite interesting because you get a lot more tooltips than I’m used to (this is because it has the language server plugged in). Also the fun with displaying the style attribute which was actually relatively painless. The ReasonReact Docs for Style gave me the perfect example:

<div style=(
  ReactDOMRe.Style.make(~color="#444444", ~fontSize="68px", ())
)/>

So now I’ve got an SVG circle appearing in the web version and I can use this in my local version without problem.

Dom dom dom…

Ideally for my basic project I didn’t want to use React. I have a simple HTML page that injects a few <p> tags and some <svg> circles. I do this easily enough with pure JavaScript, so I shouldn’t need React.

However trying it was very painful. Every DOM Element in Reason is an Option. So you have to spend your life with this ‘could be null’ chap and handle this could be null at every stage.

Basically it seems like the DOM is a type nightmare and trying to apply correct types to it produces your own personal hell.

  let _ =
    Document.getElementById("root", document)
    ->Belt.Option.map(_, Element.setInnerText(_, "Hello"));
  ();

  let el =
    document
    |> Document.createElement("p")
    |> Element.asHtmlElement
    |> unwrapUnsafely;
  /* let root = Document.getElementById("root", document); */
  document
  |> Document.getElementById("root")
  |> map(Element.appendChild(el));

The above is the equivalent of:

var root = Document.getElementById("root");
root.innerText = "Hello";

var el = Document.createElement("p")
Document.getElementById("root").appendChild(el);

But trying to create and element, set it’s innerText and then append it was beyond me after 8 hours of coding.

This is along with using the experimental (but interesting) library bs-webapi, which is also referred to in a useful book on Web Development with ReasonML.

It’s at this point I figure that ReasonReact seems to handle the Dom interaction better. I was able to get a fairly complex svg element displaying which is the hardest part. So perhaps just better to stick to that.

Hidden pipes

Note that here they use the “reverse-application” operator |>. There’s an excellent description about this in this 2ality blog post on ReasonML functions:

The operator |> is called reverse-application operator or pipe operator. It lets you chain function calls: x |> f is the same as f(x). That may not look like much, but it is quite useful when combining function calls.

In the reason docs they refer to the -> operator instead in the Pipe First section:

-> is a convenient operator that allows you to “flip” your code inside-out. a(b) becomes b->a. It’s a piece of syntax that doesn’t have any runtime cost.

It seems that -> is a subtly different operator from |> as the only reference to |> appears later on that page:

We also cannot use the |> operator here, since the object comes first in the binding. But -> works!

Frustratingly though the reason documentation just includes this mention of |> without actually saying what it is. The operator comes direct from OCaml, see ‘Composition operators’ in the Stdlib documentation.

Note that there is the similarity to the Javascript pipeline operator.

Belt

Also note the use of Belt.Option.map above. The Belt module is a community driven helper module:

A stdlib shipped with BuckleScript This stdlib is still in beta but we encourage you to try it out and give us feedback. Motivation The motivation for creating such library is to provide BuckleScript users a better end-to-end user experience, since the original OCaml stdlib was not written with JS in mind.

Easier DOM

Trying the latest bsb -init my-react-app -theme react-hooks includes the following snippet in src/Index.re:

  [@bs.val] external document: Js.t({..}) = "document";
  
  let title = document##createElement("div");
  title##className #= "containerTitle";
  title##innerText #= text;

which generates:

  var title = document.createElement("div");
  title.className = "containerTitle";
  title.innerText = text;

Now this looks a lot simpler. But of course I’ve no idea what the ## or #= operators do.

That’s as far as I’ve got, but at least now we have code that looks like recognisable JavaScript.

Using ReasonML with Vim / Neovim

Here’s my attempts to get ReasonML working within Vim and the journey it took me on to understand what language servers are. If you’re using Vim this is essentially step 2 of the ‘quick start’ guide for reason: editor plugins.

Warning to all who enter here… this took me 10+ hours to fix. It’s because my setup doesn’t mesh exactly with their expected setup. If you want an easy life just use VS Code. Failing that if you want an easy life with Vim, just use the following setup:

This assumes that you can install the LanguageServer which you have to do for VS Code as well.

Vim support

By default for using linting I have the following setup:

  • Vim 8
  • Vundle
  • ALE (Asynchronous Lint Engine)

This has managed to work ‘OK’ for Javascript with a bit of linting. But I never got fully fledged Language Server Protocol (LSP) integration working, I don’t really know why.

My initial attempts with my default setup were a total failure. Mostly because I find the LSP concept hard to understand. ALE should be a LSP ‘thing’. So it should be able to act as a Language Client and talk to Language Servers.

The repeated issue I come across is that to get LSP working you need the vim-plug Vim plugin manager. I don’t particularly know why, I guess it works better for these more complex plugins.

Looking through my .vimrc file it looks like I tried to get ALE to work as a LSP.

I switched to Neovim as part of this to minimise the number of plugins that I’m installing.

Switching from Vundle to vim-plug

Until now I’ve always used Vundle, it’s a good basic plugin. But I keep hitting plugins that don’t have instructions for Vundle and just vim-plug. vim-plug seems as good as Vundle, so let’s try it and see how much work the conversion is.

It’s actually ridiculously easy, much respect for vim-plug, and probably Vundle for both having very similar and easy to replace syntax. I replaced the Vundle lines at the start:

-filetype off                  " required
-set rtp+=~/.vim/bundle/Vundle.vim
-call vundle#begin()
-
-Plugin 'VundleVim/Vundle.vim'
+call plug#begin('~/.vim/bundle')

Then I replace all Plugin with Plug and then at the end:

-call vundle#end()
-filetype plugin indent on    " required
+call plug#end()

Then I ran :source % and :PlugInstall and it magically installed all my 31 plugins in 10s and they all seem to be magically working. If you use the .vim/bundle installation directory then vim-plug doesn’t even need to install anything.

There’s some useful instructions in the vim-plug wiki on Migrating from Vundle.

Magically also my installation of deoplete worked correctly. So now deoplete pops up all the time as I’m typing – I’m assuming it’s possible to make it less in your face…

if has('nvim')
  Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' }
else
  Plug 'Shougo/deoplete.nvim'
  Plug 'roxma/nvim-yarp'
  Plug 'roxma/vim-hug-neovim-rpc'
endif

Because I’ve switched to neovim it simplifies that installation as well.

But I’ve now fallen into the neovim only trap. Because my installation for deoplete only works with neovim, then I get an error if I try to use vim now. Perhaps I can just comment the whole block for if deoplete installed out. This works, so now vim-plug just doesn’t use deoplete if I’m in Vim.

Note that Deoplete should start working immediately after you install it and you should start seeing a popup box as you type.

Installing the language server

This was just downloading the zip from the language server releases page and unzipping it to ~/rls-linux.

Figuring out how to get ALE to work with reason-language-server

I’m using ALE rather than the recommended autozimu/LanguageClient-neovim. ALE is also a Language Client and so should also work fine.

Install via:

Plug 'dense-analysis/ale'

ALE needs to know about the existance of the reason-language-server and thankfully that support has been added. You can go to :help ale-reasonml-ols and it tells you the correct config:

  let g:ale_reason_ls_executable = '~/rls-linux/reason-language-server'

After this I expected to restart Vim and it to magically work which it didn’t.

The path has to be absolute (as noted in the config information for the LanguageClient-neovim in the README):

  let g:ale_reason_ls_executable = '/home/ian/rls-linux/reason-language-server'

You can also use the magic of vimscripts expand to handle it for you too:

  let g:ale_reason_ls_executable = expand('~/rls-linux/reason-language-server')

This then showed promise. Completion would work nicely and you get useful information coming up as you type, this also integrated with ALE via:

call deoplete#custom#option('sources', {
\ '_': ['ale'],
\})

It took a while to see if all the functionality was there. It pickedup linting errors which are put into the location list (:lopen) and would give useful info with :ALEHover

I compared it to VS Code, which does manage to implement this better. The error messages get formatted properly, for some reason the line breaks in the Vim error messages don’t get applied. Also you get the ‘Hover’ (equivalent to ALEHover) info showing up as you type in context.

I then tried to format the code. ALE has a :ALEFix command that I know works from eslint. It helpfully suggests that you need to configure the correct ‘fixer’ in .vimrc. However once that has been configured running ALEFix does nothing. I installed VS Code to check that using that along with the reason-language-server does correctly format the code – which it does. So there appears to be some problem with ALE.

Time to try another plugin…

So I can either try the Rust made LanguageClient, or the Typescript COC.

I’ve heard about COC a couple of times and it’s designed to be a VS Code matching ‘LSPy thing’. So you should be able to configure Language Clients almost exactly as they do with VS Code but inside Vim.

But hey, I prefer Rust so let’s try that first…

Trying LanguageClient-neovim instead of ALE

Now that I’ve switched to vim-plug installation of LanguageClient-neovim is easy because it includes the manual install step in the .vimrc code.

Then also the configuration was easy because it’s included in the vim-reason-plus README:

let g:LanguageClient_serverCommands = {
    \ 'reason': ['/absolute/path/to/reason-language-server.exe'],
    \ }

Note again here, that it mentions ‘absolute path’, so you have to use /home/ian instead of ~, although I still just use expand('~/path')

Now once I had installed that and restarted NVim then it all worked pretty smoothly.

Firstly the errors show up in the quickfix list :copen as well as to the right of the code. It’s not quite formatted as nicely with the line breaks as VS Code but is at least a consistent block of text, not spaced out with extra padding where the line breaks should be. I suspect though that using the location list is better as it won’t overwrite any searches that I’ve done.

Interstingly the ‘quickfix list’ is actually supposed to show errors according to :help :copen. So perhaps my searches should be in the location list. This can be changed via:

    let g:LanguageClient_diagnosticsList = 'Location'

The commands for the LanguageClient are more confusing though.

:ALEHover vs call LanguageClient#textDocument_hover()<cr>
:ALEFix vs call LanguageClient#textDocument_formatting()<cr>

But you can fix that through the vimrc mappings, but now happily the formatting did work which is what I want. Shit works without too much hassle.

Try getting it to work using COC

One nice property of COC is that it doesn’t use any advanced features of vim-plug, so this will probably all still work with Vundle. Also it looks like it combines the Auto-completion and LSP in one plugin.

Install nodejs – you can follow the instructions in https://github.com/neoclide/coc.nvim/wiki/Install-coc.nvim.
Remove Deoplete and LanguageClient-neovim and any settings from your .vimrc file. Then add COC:

Plug 'neoclide/coc.nvim', {'branch': 'release'}

Then reload the vimrc with :source % and run :PlugInstall. Warning you’ll get errors if you haven’t cleared all the deoplete settings. You might still need to restart Vim.

Install the reason extension

COC works similarly to VS Code in that it requires you install extensions to get it to work with certain language servers.

Install the reason extension, which is assuming that you are using the reason-language-server rather than the OCaml or Merlin LSP:

:CocInstall coc-reason

I ran this and it froze my Neovim. Closing and re-opening the terminal got it working again, but not good.

Now you’ll need to configure it as you always need to specify the absolute path to the reason-language-server. Handily there is a configuration section for Reason

Run :CocConfig and if it’s empty (because this is the first time of using it), then you first need to insert an empty root object:

{
}

Then put the following config inside the root object:

  "languageserver": {
     "reason": {
      "command": "/absolute/path/to/reason-language-server",
      "filetypes": ["reason"]
     }
  }
Troubleshooting

Don’t forget to put the correct absolute path for the command. Here now you can’t use the vimscript expand, so just use /home/[username].

e.g.: "/home/ian/rls-linux/reason-language-server"

Otherwise you’ll get:

[coc.nvim] Server languageserver.reason failed to start: Command “reason-language-server” of languageserver.reason is not executable
: Error: not found: reason-language-server

As soon as you set the correct path you should immediately start getting auto-completion and LSP goodies in your reason files.

Another possible error you can get is:

[coc.nvim] Server languageserver.reason failed to start: Cannot read property ‘reader’

This is a connected error that means you have the command path wrong. In my case I’d just written "/home/rls-linux/reason-language-server"

Further I tested it on a basic reason file created in an empty directory which gives this error:

[coc.nvim] No root directory found

This appears to be a reason-language-server issue #334. You need to initialise the directory as per the installation page.

The auto-completion seems to work very nicely, but I noticed that the error messages are severely truncted, for example:

src/Index.re|7 col 34 error| [undefined] Error: This expression has type [E]
src/Index.re|7 col 59 error| [undefined] Error: The function applied to this argument has type [E]

Actually you can get the full error, using :call CocAction('diagnosticInfo'), or :call CocAction('diagnosticPreview').

This gives a better error than I got with ALE or LanguageClient-neovim:

[reason] [E] Error: This expression has type
(~message: string) =>
ReasonReact.componentSpec(ReasonReact.stateless,
ReasonReact.stateless,
ReasonReact.noRetainedProps,
ReasonReact.noRetainedProps,
ReasonReact.actionless)
but an expression was expected of type
ReasonReact.component(‘a, ‘b, ‘c) =
ReasonReact.componentSpec(‘a, ‘a, ‘b, ‘b, ‘c)

To get code formatting working you need to run: :call CocAction('format'). So its similar to the LanguageClient-neovim in that you’ll probably want to create a whole bunch of vimrc shortcuts. But at least it does format which is a step up from ALE.

Hover info is through :call CocAction('doHover').

One nice thing about this plugin is that it combines the Complete and LSP plugins and so the Plug config is:

Plug 'neoclide/coc.nvim', {'branch': 'release'}

Instead of:

Plug 'autozimu/LanguageClient-neovim', {
    \ 'branch': 'next',
    \ 'do': 'bash install.sh',
    \ }

" for neovim
if has('nvim')
  Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' }
" for vim 8 with python
else
  Plug 'Shougo/deoplete.nvim'
  Plug 'roxma/nvim-yarp'
  Plug 'roxma/vim-hug-neovim-rpc'
  " the path to python3 is obtained through executing `:echo exepath('python3')` in vim
  let g:python3_host_prog = "/absolute/path/to/python3"
endif

So your choices are…

Note these are recommendations, you probably can get Vim/Vundle to work with these, but I’ve simplified my life to match the instructions that maintainers give out.

  1. Neovim, vim-plug, ALE, deoplete: format doesn’t appear to work, error messages are very ugly, deoplete has some nice integrations with fzf
  2. Neovim, vim-plug, LanguageClient-neovim, deoplete: has the most nice touches and seems to work the best with little config, format works, but error messages are still pushed into one long line that can be too long for the location list
  3. Vim/Neovim, vim-plug, COC: simplest plugin setup, but took a while to understand how to configure, doesn’t work so nicely out of the box, format works, appears to give the best formatted error messages – when you look for them. It’s easier if they just appear in the location/quickfix list. However I guess that’s the problem, location/quickfix don’t allow for multiline error messages. Also in this seems the most light weight of the plugins as it doesn’t bundle all possible language server configurations, you install them as extensions.

Futher work with COC

I’ve since had further thoughts with COC. Things that are actually fairly magical.

  1. If you’re a Javascript developer then working with eslint is very common. The coc-eslint plugin magically works with eslint straight off. I had all sorts of problems with eslint and ALE, which required eslint_d and neomake for reasons that I can’t quite remember.
  2. By default the errors in COC don’t show until you switch from insert mode to normal mode. This is actually a better experience in my opinion as it reduces the amount of constant information that you’re getting. There’s no need to display an error just because you haven’t typed something yet.
  3. So it means that I can replace, ALE, Neomake, Deoplete, LanguageServer-neovim with COC. COC requires node to be installed but beyond that there’s no specific vimrc config, so should allow using Vundle – although it does require a specific branch which I don’t think Vundle can handle. Also without Deoplete there’s no difference between using Vim or Neovim which is great.

Installing Haskell ++ Emacs on Windows

Haskell

Firstly install the haskell-stack chocolatey package:

choco install -y haskell-stack

For me that perfectly installed haskell and meant that I could run stack commands and have stack ghci running in a DOS prompt.

Emacs

Chocolatey has an Emacs package:

choco install -y emacs

This puts the emacs binaries into the chocolatey bin directory. Then the .emacs file and the .emacs.d directory go into %APPDATA%.

This installs an Emacs windows program. I wondered if there was a DOS version similar to Vim. There is an Emacs For DOS – but this isn’t part of the Chocolatey package, which comes from the GNU Emacs FTP directory.

Intero

The haskell project have a new integration with Emacs. I have to say this installed remarkably easy. The only problem I had was that I’d put a bad config into %APPDATA%\stack\config.yaml and this created errors – that were well explained in Emacs.

It’s not 100% clear how you get things to work though. Bare in mind I’ve never used Emacs before today.

I have managed to get Haskell setup and working, which came with stack.

Following the Intero guide, the installation of the package was easy enough – just edit the %APPDATA%\emacs.d file. I restarted Emacs and the Intero package installed itself without errors.

Following the guide further I ran the stack new intro-demo command in a directory. This created the intero-demo directory and put everything in it. If you then ‘File > Open Directory’ in Emacs to open the intero-demo directory. Opening Setup.hs had the affect of getting Intero to install itself.

At this point things were actually working – but it wasn’t obvious the the error as you type checking was happening because it was erroring at the very first command of the Setup.hs

However if you open up a new Haskell file in the directory it should start doing error checking on the fly.

Hoping the Brexit vote was a protest vote, not a racist one

The only positive I hope from this is that the Brexit vote was a protest vote.

So I’m hoping the majority of ‘leavers’ aren’t siding with Farage, they don’t care about Boris – they just want to say Fuck You to all politicians and leaders.

This is probably the first and only time that the entire population have been given a protest vote. This is not a choice between one dodgy politician or another politician. This is not choosing between Trump or Clinton.

This is a chance to say fuck you to every single party. This is fuck you to the leaders of both the Conservative and Labour parties.

When this chance comes along – you don’t care about the consequences. You don’t care if the ‘leave’ campaign is spouting lies, you don’t care about the doom spouted by the ‘remain’ campaign. You just want a chance to say fuck you. You know the system is wrong and this is the only tool you’ve got to say so.

I certainly respect the people who protest for what they believe in. Perhaps I’m wrong for thinking all the pensioners don’t care about the consequences. Perhaps they know better than me that the pain of leaving is worth it.

There are some heart felt comments from leavers, not based on the crap spouted by the leave campaign, in this blog post Dear Brexiteer. What we need you to do now.:

“I voted leave , There its out there .. I trusted DC to come back from Brussels with a list of pledges that would let us have some tools to work with to make me feel that improvements could be made to the way we live..
Be it a better NHS ,Schools ,social care services,security. ..
He came back with nothing and nothing was offered .. in fact we were told that it would never change..
So people who have had enough like myself and 17 million others voted with our feet in the only way we know .. a very British revolt ..
Now we are being called racist and xenophobic but this is just so untrue for the masses.. we just need change .
The EU is a broken antique of a monster that isn’t up to listening to the working classes..
We have been called inward looking but again that is not true. . I concider myself Global I want to be able to talk with anyone across the world’s economy. .
Things will never be the same again and for that I feel that my cross mattered.
The first time I think the working class has ever mattered…”

So I hope when all the dust settles that we’re all still willing to tell Farage and Johnson to go fuck themselves (I’m pretty sure not many people care about what Gove says).

Jupyter on Windows with Chocolatey

Install Python

This is a quick post (and will probably be outdated quickly), but it took me a while to get it correct.

I wanted to install Jupyter on Windows. The recommeded route is via Anaconda but I like to use Chocolatey the Windows package manager as much as possible.

I used Chocolatey to install Python package (currently v3.5.1). Assuming you’ve installed Chocolatey already, run as administrator:

choco install -y python

This installs python to C:\Program Files\Python35. It also installs and pip.exe to C:\Program Files\Python35\Scripts.

Add C:\Program Files\Python35 and C:\Program Files\Python35\Scripts to your PATH then you should be able to run python and pip immediately.

Install PIP (hint: it’s already installed)

Note that pip gets automatically installed when you install python – nothing extra is required.

You can get led astray here by an official guide which suggests having to download and run ez_setup.py.

Don’t do this.

There is also confusingly a Chocolatey PIP package. Again don’t install this.

Otherwise you might end up here.

Running PIP packages

Because we’re using Chocolatey, the installation doesn’t follow the recommended installation for Jupyter.

The main thing is that you need to add the python Scripts directory to your PATH, as above.

Install Jupyter

Run as administrator:

pip install jupyter

This will install a jupyter.exe file into the Scripts directory. If that directory is in your PATH, then you should be able to directly run jupyter commands.

Create a Jupyter notebook

Jupyter runs inside the browser but installs files and all the save data in the directory that you run the jupyter command from.

mkdir jupyter
cd jupyter
jupyter notepad

If everything is working that will open up your browser at http://localhost:8888/.

Lock Stock Pomodoros

I give you http://pom.ianchanning.com. Pomodoros with a Lock Stock film quote at the end of each one.

I’m a little obsessive about timers (see bottom) and the other pomodoro timers I’ve tried failed on different counts.

I’ve tried to cram everything I find useful about a timer.

Firstly spacebar to start/stop. The timer should be something that sits in the background and requires minimal attention. So a quick ctrl+tab to get the the pomodoro tab and then hit space and then back to your work.

Secondly the timer appears in the title bar and it appears first. Then you can easily see that it’s running so that you can still see the timer when you have lots of tabs open.

Thirdly there’s a start and stop. Possibly this flies against what a Pomodoro timer should do. However any timer I have I want to be able to start/stop/reset. That’s just what a timer should do, it’s annoying if it doesn’t.

Fourthly the timer has to notify you properly when the pomodoro finishes. This is achieved through a buzzer and a browser notification. Notifications sometimes don’t work or you don’t see them so you need the buzzer backup. Sorry IE folks your browser is still terrible and can’t handle the Javascript Notifications and I can’t be bothered to fix it when it’s just for a personal project.

Fifthly a count of the pomodoros is useful to know how many you cranked out in the day.

Sixthly, a bit of browser responsiveness goes a long way.

And that’s it. No more please.

Well except I needed to put something in the notification so I jazzed things up with quotes from Lock Stock and Two Smoking Barrels. If you can’t take the ‘c’ word at least once then this timer is not for you.

For those who got this far. I started with the most basic timer I could think of that still had a simple start-stop mechanism. Then after staring at the jquery code I’d copied I realised I could make a generic jquery ticker function. So I can tick 25 minutes down and then tick the pomodoro count up 1 each time. The rest is a codged together front end on top of that.