EverythingPostsNotes
mikker·about 11 years ago

El Capitan GM update notes

UPDATE 2015-10-11: Turns out, on a clean install /usr/local is still writable – even with SIP turned on.


I’ve been running the beta of OS X 10.11 El Capitan for some months and there’ve been very few hiccups. So full sail ahead on the update I say.

Upgrading to the GM broke my homebrew though. I think the days of using /usr/local might be over as El Capitan does some stuff to enforce even stricter permissions than a simple chown can get rid of.

So I’m moving out! Someone (forgot who or where – sorry!) mentioned in a Github issue thread how he’d been running his homebrew out of /Users/Shared/Developer for some months with no problems, so that’s what I did:

Installing Homebrew outside of /usr/local

$ git clone https://github.com/Homebrew/homebrew.git /Users/Shared/Developer

Now, that directory’s bin directory isn’t in your $PATH (like /usr/local/bin is automatically) so we need to add it. Open up ~/.bashrc or ~/.zshrc – whatever your preference – and add this:

export BREW_PATH=/Users/Shared/Developer
export PATH="$BREW_PATH/bin:$PATH"

Done. Run brew doctor to confirm.

Install taglib-ruby gem with Homebrew outside /usr/local

$ brew install taglib
$ gem install taglib-ruby -- --with-tag-dir=$BREW_PATH/Cellar/taglib/1.9.1/
mikker·about 11 years ago

Use webpack-dev-server and react-hot-loader with Phoenix

NB: Here’s an updated setup.

Phoenix has built-in livereload and it works right out of the box. But if you’ve ever had the joy of working with React and react-hot-loader you know you need to have that with you anywhere.

Phoenix uses Brunch to build it’s assets so we’ll have to pull that out and jam in a webpack-dev-server wherever it was. Luckily that’s quite easy.

The completed example is available on Github.

First, let’s create a new app:

$ mix phoenix.new my_app
$ cd my_app

We could’ve generated the app without Brunch but let’s keep it in, to see what we’re actually substituting.
Let’s start by pulling out Brunch and it’s dependencies and then add our new ones:

$ npm uninstall --save babel-brunch brunch clean-css-brunch css-brunch javascript-brunch sass-brunch uglify-js-brunch
$ npm install --save babel-loader react react-hot-loader webpack webpack-dev-server

Now, webpack needs to be told what to build and how, so let’s make a config file. Here’s webpack.config.js:

var path = require("path");
var webpack = require("webpack");

var env = process.env.MIX_ENV || "dev";
var prod = env === "prod";

var entry = "./web/static/js/bundle.js";
var plugins = [new webpack.NoErrorsPlugin()];
var loaders = ["babel"];
var publicPath = "http://localhost:4001/";

if (prod) {
  plugins.push(new webpack.optimize.UglifyJsPlugin());
} else {
  plugins.push(new webpack.HotModuleReplacementPlugin());
  loaders.unshift("react-hot");
}

module.exports = {
  devtool: prod ? null : "eval-sourcemaps",
  entry: prod
    ? entry
    : [
        "webpack-dev-server/client?" + publicPath,
        "webpack/hot/only-dev-server",
        entry,
      ],
  output: {
    path: path.join(__dirname, "./priv/static/js"),
    filename: "bundle.js",
    publicPath: publicPath,
  },
  plugins: plugins,
  module: {
    loaders: [{ test: /\.jsx?/, loaders: loaders, exclude: /node_modules/ }],
  },
};

I will not go into too much detail but notice the address http://localhost:4001. That’s where webpack-dev-server will be running from when we’re developing.

Next, let’s set up the dev server in webpack.devserver.js:

#!/usr/bin/env node
var webpack = require("webpack");
var WebpackDevServer = require("webpack-dev-server");
var config = require("./webpack.config");

new WebpackDevServer(webpack(config), {
  contentBase: "http://localhost:4001",
  publicPath: config.output.publicPath,
  hot: true,
}).listen(4001, "0.0.0.0", function (err, result) {
  if (err) console.error(err);
  console.log("webpack-dev-server running on port 4001");
});

// Exit on end of STDIN
process.stdin.resume();
process.stdin.on("end", function () {
  process.exit(0);
});

That last last bit is there to make the process shut down properly when Phoenix shuts down. (A big thank you to josevalim for guiding me in figuring that out, for being such a seemingly nice guy and of course for making Elixir!)

Don’t forget to make it executable:

$ chmod +x webpack.devserver.js

We need to tell Phoenix to run this instead of Brunch, so open up config/dev.exs and the change watchers: line to include our dev server instead:

config :my_app, MyApp.Endpoint,
  http: [port: 4000],
  debug_errors: true,
  code_reloader: true,
  cache_static_lookup: false,
  watchers: [{Path.expand("webpack.devserver.js"), []}]

And let’s just cut Phoenix some slack and tell it not to watch the assets:

config :my_app, MyApp.Endpoint,
  live_reload: [
    patterns: [
      # ~r{priv/static/.*(js|css|png|jpeg|jpg|gif)$},
      ~r{web/views/.*(ex)$},
      ~r{web/templates/.*(eex)$}
    ]
  ]

OK, let’s make our entry file, web/static/js/bundle.js:

import React from "react";
import App from "./App";

React.render(<App />, document.getElementById("root"));

This renders our App (that we haven’t made yet) to an element with the id root (that we also haven’t made yet). Splitting your React components into separate files let’s react-hot-loader reload them independently from each other.

Here’s a simple web/static/js/App.js:

import React, { Component } from "react";

export default class App extends Component {
  render() {
    return (
      <div>
        <h1>This app is hot!</h1>
      </div>
    );
  }
}

So far, so good. Now we just need some html document to render it in.

Edit web/templates/layout/app.html.eex:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>Hello Phoenix!</title>
  </head>
  <body>
    <%= @inner %>
    <%= if Mix.env == :dev do %>
      <script src='http://localhost:4001/bundle.js'></script>
    <% else %>
      <script src="<%= static_path(@conn, "/js/bundle.js") %>"></script>
    <% end %>
  </body>
</html>

Remember that our dev server is running on :4001. We want to use it’s bundle.js in dev and a built one in production.

The only thing left is the element with id root. Let’s put it in web/templates/pages/index.html.eex:

<div id="root"></div>

And we’re done! Now go open http://localhost:4000, edit App.js and behold the magic of our hot reloading gods!

Addendum: Production

Phoenix compiles all it’s assets with the task phoenix.digest which you’re supposed to run before deploying. We can just remember to run webpack beforehand — or we can make our own digest task.

Here’s lib/mix/tasks/digest.ex:

defmodule Mix.Tasks.MyApp.Digest do
  use Mix.Task

  def run(args) do
    Mix.Shell.IO.cmd "./node_modules/webpack/bin/webpack.js"
    :ok = Mix.Tasks.Phoenix.Digest.run(args)
  end
end

Let’s be fancy and override the original task so new developers or deployment scripts don’t need to know about our special setup. Open mix.exs and alias the original to our new task:

defmodule MyApp.Mixfile do
  # ...
  def project do
    [ # ...
      aliases: ["phoenix.digest": "my_app.digest"]]
  end
  # ...
end

Try mix phoenix.digest and see that webpack runs first.

mikker·over 11 years ago

Force-update text shortcuts in OS X Yosemite

My text shortcuts never synced when I recently set up my new Macbook and so I was left inserting all my emojis using ctrl+space and using my mouse like you would if you weren’t communicating primarily by thumbs-up emoji like me 👍🏼

So, to force a refresh:

  1. Turn off iCloud Drive
  2. rm -rf ~Library/Mobile Documents/com~apple~TextInput
  3. Turn iCloud Drive back on
mikker·over 11 years ago

Open every link in Safari's Reading List in tabs

Use Safari’s Reading List as an inbox.

When you come across some link or page that you would like to look into at some point just not right now, hit cmd+shift+d on your mac or use the share sheet available almost everywhere on your iOS device and add it to Reading List.

Then when the time is right explode that thing into separate tabs and purge through them.

#!/usr/bin/env ruby
# $ gem install CFPropertyList
require 'cfpropertylist'

path = File.expand_path '~/Library/Safari/Bookmarks.plist'
plist = CFPropertyList::List.new file: path

list = plist.value.value["Children"].value.select do |item|
  if title = item.value["Title"]
    title.value == 'com.apple.ReadingList'
  end
end.first.value["Children"].value

bookmarks = list.map do |item|
  item.value["URLString"].value
end.reverse

puts "Opening #{bookmarks.count} tabs "

bookmarks.each do |url|
  `osascript -e 'tell application "Safari" to tell window 1 to make new tab with properties {URL:"#{url}"}'`
  print '.'
end

puts ''

Clear all items in Reading List and just re-add any linkif you’re still undecided about it.

The script also works perfectly inside Run Shell Script in Automator if you want a .app.

mikker·over 11 years ago

foundation-grid

For years I’ve been using ZURB’s Foundation as a starting point for new sites. It’s really great — but also kind of huge. And the internals are very advanced so picking out parts isn’t as easy as it probably could be. But here’s the grid for your blocky pleasure:

screenshot

Get it: foundation-grid

mikker·over 11 years ago

blank

Oh, where do I even start.

Now and then I like to sport a completely stripped down Safari, hiding the toolbar and everything else:

Stripfari

Look at that! Just the content. Just me and my one million tabs. Only problem: when I make a new tab, the address bar isn’t focused as it is, when the toolbar is visible. So you need to press cmd + l yourself like an animal.

So we make a start-page for new tabs. But there’s no api for focusing the browser chrome. But there is AppleScript (there’s always AppleScript).

We’ll just make a tiny server that serves a page with one button that it clicks itself. And then make that button call some Applescript. That’s definately not an insane solution to a very serious problem.

Sounds good? You should try it out.

mikker·almost 12 years ago

Make Github responsive with 9 lines of CSS

My browser windows are seldomly as wide as Github’s layout. This works great for most of the websites that I visit - yay responsive - but Github’s layout is still too wiiiiiiide.

Taking matters into my own hands I opened up Web Inspector and found out that you can make it (naively) responsive with relatively few lines of css:

Please do fork it and improve it.

mikker·almost 12 years ago

Getting your locales in line before going on your dokku adventure

Update 2015-05-12: Seems the correct file to edit is /etc/default/locale:

export LANGUAGE="en_US.UTF-8"
echo 'LANGUAGE="en_US.UTF-8"' >> /etc/default/locale
echo 'LC_ALL="en_US.UTF-8"' >> /etc/default/locale

Then reboot.


I’m really digging dokku-alt. Dokku is a simple way of setting up a deployment setup as easy as Heroku’s. Dokku-alt is that plus some bundled plugins.

I had some troubles though with the Postgresql databases being created with ASCII encodings. So before you install and setup dokku get your locales in order - make your /etc/locales look like:

LANG=en_US.utf-8
LANGUAGE=en_US.utf-8
LC_CTYPE="en_US.utf-8"
LC_NUMERIC="en_US.utf-8"
LC_TIME="en_US.utf-8"
LC_COLLATE="en_US.utf-8"
LC_MONETARY="en_US.utf-8"
LC_MESSAGES="en_US.utf-8"
LC_PAPER="en_US.utf-8"
LC_NAME="en_US.utf-8"
LC_ADDRESS="en_US.utf-8"
LC_TELEPHONE="en_US.utf-8"
LC_MEASUREMENT="en_US.utf-8"
LC_IDENTIFICATION="en_US.utf-8"
LC_ALL=en_US.utf-8

Source it (or reboot) and then set up dokku.

mikker·about 12 years ago

Install Qt on OS X Yosemite (Beta 3)

To install Qt on Yosemite (Beta 3 right now) using homebrew, just act as if you’re on Mavericks and it will work fine:

Edit /usr/local/Library/Homebrew/os/mac/version.rb:

def to_sym
  return :mavericks # <-- stupid hack.
  SYMBOLS.invert.fetch(@version) { :dunno }
end

Then when you’re done; clean up after yourself!

mikker·over 12 years ago

Rename current TMUX session to current directory's basename

I like having a seperate TMUX session per project I’m currently working on. So a numbered list of sessions quickly becomes unhandy.

tmux rename-session `basename $(pwd)`

ctrl-b s and we get this:

(0) + angular-firmafon: 1 windows (attached)
(1) + blog: 3 windows (attached)
(2) + wallboard: 2 windows

Bonus tip: Put bind ^S switch-client -l in your .tmux.conf. Now ctrl-b ctrl-s toggles between the current and last session.

mikker·over 12 years ago

Open photo GPS location in Apple Maps using ruby

Dr. Drang posted a lengthy article and script to open a given photo’s EXIF GPS location in Apple Maps. He’s using python and a library called “PIL”. I liked the idea but couldn’t, no matter what I tried, get the damn thing to install and what is python anyway? I like ruby! I’m sure there’s an easier way?

Turns out there was.

The rubygem exifr reads EXIF data like a champ, so let’s get it:

$ sudo /usr/bin/gem install exifr

I’m using the absolute path to gem, because we want to end up using this as a system service, and system services use system ruby.

Now, here’s the script. Save it as something like ~/bin/map.rb:

#!/usr/bin/env ruby
begin
  require 'exifr'
rescue LoadError
  require 'rubygems'
  require 'exifr'
end

usage = <<-USAGE
usage: map.rb IMAGE_PATH
USAGE

path = ARGV.shift

if path.nil?
  puts usage
  exit(0)
end

exif = EXIFR::JPEG.new(path)
if coords = exif.gps
  system "open 'http://maps.apple.com/?q=#{coords.latitude},#{coords.longitude}'"
else
  puts "No GPS data for #{path}"
end

Remember to chmod +x it and call it like the Doctor does in a service like this, substituting the path to where you saved the script:

mikker·over 12 years ago

Update Safari from vim with AppleScript

When Livereload is too much and cmd-tab’ing too little, there’s always this AppleScript.

#!/bin/sh
osascript -e 'tell application "Safari"
  set _url to URL of current tab of front window
  set URL of current tab of front window to _url
end tell'

Put it in your PATH, chmod it +x, and map it to what you like in vim:

map ,r :call system("update_safari.sh")

You could even auto-run it when you save the current buffer:

autocmd BufWritePost <buffer> :call system("update_safari.sh")

Replace <buffer> with * to do it in every buffer.

mikker·almost 13 years ago

OS X's open with support for STDIN

OS X’s open command is great and I use it many times a day. But several times I’ve stumbled through some command that outputs something only to be reminded once again that open doesn’t support piping of input. Let’s fix that.

#!/bin/sh
# Put a dash at the end of open to use stdin as arguments
# usage: echo "TextEdit" | open -a -
for last; do true; done
if [ "$last" == '-' ]; then
  arg=`cat`
  cmd=`echo $@ | sed -e "s/-$/${arg}/"`
  /usr/bin/open $cmd
else
  /usr/bin/open $@
fi

This add a check to open: If the last argument is a dash (-), then use STDIN as the argument to the original open.

Put it somewhere that’s in your $PATH before /usr/bin is and you’re good!

mikker·almost 13 years ago

Get the true mime type of a file in Ruby

I was kind of disappointed to find out that the ruby mime-type gem just looks at the file extension instead of getting the true mime type. This can cause trouble. Say we’re having the user upload files to our webpage - but we only want .mp3s. Without checking the true mime-type the user will be let through if he just renames his file to .mp3.

If you’re lucky enough to be on Unix though, you can get the true mime type by using the shell command file.

true_mime_type = `file --mime -b mp4-renamed-to.mp3`.chomp
  # => video/mp4; charset=binary

There we are.

mikker·almost 13 years ago

MobilePay's undocumented URL schemes

I made a request on
Twitter
for url schemes
in the Danish app for easy mobile money transfers
MobilePay.
Turns out it already had
some.

mobilepay://send?amount=100&phone=88888888
mobilepay://request?amount=100&phone=88888888

Perfect! This makes for perfect Launch Center
Pro
actions.

Action

mikker·almost 13 years ago

Completely turn off Mac OS X Dashboard

Mavericks brings yet another version of Apple’s OS X and the continued existence of Dashboard confuses everyone. Here’s how to completely turn it off:

$ defaults write com.apple.dashboard mcx-disabled -boolean YES

Also for the hardcore — Completely turn off Desktop:

$ defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true

The folder will still exist it just wont be your desktop. You might have to re-log in for it to take effect. With these two power-settings you’re ready to concentrate and do your best procrastination on something better than files or widgets – fx Twitter.

mikker·almost 13 years ago

Editorial workflow: extend selection one word backwards

Editorial is my favourite iPad editor. Here’s a workflow that I made. It extends the current selection one word backwards.

Screenshot

Because of how Editorial workflows work I had to do a bit of hackery to make it work. The idea is to find the starting position of the word just before the current selection. My first version looped through every single word up till the selection but that was unusably slow on large documents. So this version only loops through every word in the 50 letters leading up to the selection. A hack, but it works really well.

mikker·almost 13 years ago

A favourite from my vimrc: Full-height and full-width splits

I use vim split windows all the time. Instead of tabbing between files I just open another split. Especially if the change is small.

Here’s to of my favourties from my vimrc: <c-w>S to open a full-width, horizontal split topmost and <c-w>V to open a full-height, vertical split rightmost.

" Open splits at top level
map <c-w>V :botright :vertical :split<cr>
map <c-w>S :topleft :split<cr>

This is what it could look like:

Vim

Pretty simple. Pretty neat.

mikker·almost 13 years ago

nb - a zsh function to change or create new git feature branches (with completion)

nb (new branch) is my very simplified method of creating new feature og fix branches in git.

When I’m working on fixes or features in an existing project, I check out a new branch. This also makes it way easier to create easily understood pull-requests when you need to get it reviewed.

# nb.zsh
nb () {
  if [[ $# > 0 ]]
  then
    if [[ $(git branch | tr -d '* ' | grep "$1") != "" ]]
    then
      git checkout $1
    else
      git checkout master && git checkout -b $1
    fi
  else
    git branch | tr -d '* '
  fi
}
# completion
_nb() { reply=($(git branch | tr -d '* ' | xargs echo)) }
compctl -K _nb nb

Without any arguments it just lists the current, existing, local branches. These are the ones it will tab-complete. If the argument is an existing branch then check it out, if it’s not then create it based on master.

I’m using zsh and I’m not sure what it would take to make it work in bash. Probably not too much.

mikker·almost 13 years ago

One-shot command to create a Github pull-request and open it in your browser

At Firmafon we almost always concentrate updates into Github’s pull reqeusts. This provides a nice overview of the changes and an obvious place to discuss them. Here’s two scripts that I use to make this process even easier.

The first one’s called last_commit_message:

#!/bin/sh
git --no-pager log -1 --pretty=%B | sed -e "s/^ *//g" -e "s/ *$//g" | tr -d "\n"

This outputs the last commit’s message, inline without anything else but the message.

The other is called prl:

#!/bin/sh -x
set -e

last_msg="`last_commit_message`"
git push -u
url=`hub pull-request "$last_msg"`
open "$url"

This get’s the last commit’s message for use as the pull request’s title. Then it pushes to a remote branch.

Then using Github’s hub command (brew install hub) it creates a pull request from the current HEAD, catches the returned url and open’s it.

Loading more posts...