Total results: 30

Customise the Atom fuzzy finder width using custom styles

I find for my projects that the fuzzy finder overlay dialog in the Atom editor is a little short for my liking. I often have long path names with the same file name so I and can't see the full path, therefore I am not sure which file I am choosing.

Atom fuzzy finder original size

The easiest way to do this is to use your custom stylesheet to alter the fuzzy finder interface. Open your Atom stylesheet via the menu options Atom -> Open Your Stylehseet.

Next paste in the following CSS code. Save the file and the Atom styles will automatically reload.

.modal.overlay {
  width: 800px;
  margin-left: -400px;
}

.fuzzy-finder {
  width: 784px;
}

Open the finder again and now it looks much better!

Atom fuzzy finder after width customisation

Of course you may want to customise the widths of the modal to fit your workspace better.

Getting started with the Atom Editor (and tips for switching from Vim)

Today I started working with the awesome Atom Editor instead of my usual tool MacVim.

Atom is open source and free, produced by the people at GitHub. To introduce Atom, what can I say that they can't say for themselves?

Atom is a desktop application based on web technologies. Like other desktop apps, it has its own icon in the dock, native menus and dialogs, and full access to the file system.

Open the dev tools, however, and Atom's web-based core shines through. Whether you're tweaking the look of Atom's interface with CSS or adding major features with HTML and JavaScript, it's never been easier to take control of your editor.

So basically Atom is a code editor built on top of a browser. Meaning, as a web developer you already have all the skills needed to extend the code base, or write a custom Atom package (plugin). Due to Atom being based on a browser engine (Blink) you even have the usual Chrome developer tools available to you!

Atom Editor preview showing Dev Tools

Why Change?

The main reasons I am trying out a new editor are:

  • Ease of use - Vim is powerful but can be painful too
  • Packages - Atom is easy to extend and has a large community, no Pathogen or Vundler required
  • Customisation - I'm a web developer, making packages easy to write
  • Teamwork - Many colleagues don't know Vim, or at least everyone has different key bindings
  • Look and feel - Atom is beautiful

Some Tips for Beginners

Key Combinations

Arguably the most attractive feature of Vim is the powerful key combinations + motions. For example, in Vim you can type 10dd to delete the next 10 lines. Atom does not have this built in, although there is of course a package for that, many of the more common combinations are available by default. A few useful ones that helped me switch are:

Sort string array items as integer with PHP

When sorting array items in PHP, normally you can use one of the PHP sort functions such as sort() or usort(). This will sort your array into ascending order for either integer, starting with zero or string, from A – Z.

However, consider the following example:

$scores = array(
    '32-Andy',
    '43-Steve',
    '28-Joe'
);

If you try to sort these by the prefixed ID (28, 32, 48) the sort function will not take just the numbers into account as the criteria. It will also then sort on the string, from A to Z.

There’s a simple way to fix this. We need to augment the usort() function by adding an extra argument. We’ll add the SORT_NUMERIC predefined constant as the second argument and this will instruct PHP to ignore sorting on the string segment of the array values and instead successfully sort the array by the ID only.

Using the following code will output the array in the order: 2, 0, 1 as expected.

usort($scores, SORT_NUMERIC);
print_r($scores);

//0 = 28-Joe
//1 = 32-Andy
//2 = 43-Steve

Cordova "rebuild precompiled header" error

In Cordova 3.5+ you may experience an error while trying to build the iOS platform stating a precompiled header has been modified and needs to be rebuilt.

This is usually caused by deleting an existing Cordova project and rebuilding it in the same directory.

Error:

fatal error: file '/Users/blake.simpson/cordova/del-app/platforms/ios/DEL Action/DEL Action-Prefix.pch' has been modified since the precompiled header '/var/folders/bq/1p80g4q56tl2zmcv96c3r3g9fw6s01/C/com.apple.DeveloperTools/6.0.1-6A317/Xcode/SharedPrecompiledHeaders/DEL Action-Prefix-edciowciqplpzxaziffeqsjfaaka/DEL Action-Prefix.pch.pch' was built note: please rebuild precompiled header

'/var/folders/bq/1p80g4q56tl2zmcv96c3r3g9fw6s01/C/com.apple.DeveloperTools/6.0.1-6A317/Xcode/SharedPrecompiledHeaders/DEL Action-Prefix-edciowciqplpzxaziffeqsjfaaka/DEL Action-Prefix.pch.pch'

1 error generated.

The simple option is to delete the existing .pch file. In the previous example that would be done in the terminal by using rm.

Terminal:

$  rm /var/folders/bq/1p80g4q56tl2zmcv96c3r3g9fw6s01/C/com.apple.DeveloperTools/6.0.1-6A317/Xcode/SharedPrecompiledHeaders/DEL\ Action-Prefix-edciowciqplpzxaziffeqsjfaaka/DEL\ Action-Prefix.pch.pch

Once deleted rebuild the iOS project.

Terminal:

$ cordova build ios

Quickly open a web page in all browsers for testing

In order to test a certain web page in all of my development browsers, I wrote a simple shell script that will open a new instance of each of my browsers and automatically point it to a given URL.

This script is designed for OSX and will likely need some tweaks for a Linux distribution (or perhaps a complete rewrite) but the concept can be easily transferred.

browser-test.sh

# $1: URL

open -a "/Applications/Google Chrome.app" $1 -g -n
open -a "/Applications/Google Chrome Canary.app" $1 -g -n
open -a "/Applications/Safari.app" $1 -g -n
open -a "/Applications/Webkit.app" $1 -g -n
open -a "/Applications/Firefox.app" -g $1 -g -n
open -a "/Applications/FirefoxAurora.app" -g $1 -g -n
open -a "/Applications/Opera.app" $1 -g -n
open -a "/Applications/Opera Beta.app" $1 -g -n

I have configured the script to work for Chrome and Canary (Nightly), Safari and Webkit (Nightly), Firefox and Aurora (Nightly) and finally Opera and Opera Beta (Nightly).

On my setup I additionally load an extra app called "CoRD" which is used to connect to remote Windows machines for Internet Explorer testing.

browser-test.sh

open -a "/Applications/CoRD.app" -g -n

The -g option after each open command tells the given app to open in the background. Finally the -n switch will force a new instance of the browser, even if you already have one running, so that the browser is in a clean state to test with.

Finally I symlink this file to my /usr/local/bin directory so that the script is always available on my PATH.

Terminal

$ cd /usr/local/bin
$ ln -s browser-test ~/path/to/browser-test.sh
$ chmod a+x browser-test

Complete these steps in order and you will be able to call browser-test from any directory in the terminal.

Terminal

$ browser-test http://blog.blakesimpson.co.uk/

Apache Configure CORS Headers for Whitelist Domains

In the current implementation of Cross Origin Resource Sharing (CORS) the Access-Control-Allow-Origin header can only provide a single host domain or a wildcard as the accept value. This is not optimal when you have multiple clients connecting to the same virtual server and simply want to allow a list of known client host domains to the "allow" list.

Since only a single domain in a single access header can be delivered back to the client, Apache must read the incoming Origin header and match it to the list of "white" (accepted) domains. If an appropriate match is found, echo the domain host back to client as the value of Access-Control-Allow-Origin.

Use the following configuration snippet in the Apache virtual host ".conf" file or in the server ".htaccess" file. Ensure mod_headers and SetEnvIfNoCase are enabled.

<IfModule mod_headers.c>
   SetEnvIfNoCase Origin "https?://(www\.)?(domain\.com|staging\.domain\.com)(:\d+)?$" ACAO=$0
   Header set Access-Control-Allow-Origin %{ACAO}e env=ACAO
</IfModule>

The regular expression https?://(www\.)?(domain\.com|staging\.domain\.com)(:\d+)?$ matches the URL of Origin, a required HTTP header for all requests. The pattern matches both the http and https protocols. It will match an optional www. subdomain and finally matches the actual host name of your whitelist entries. Any characters after the domain name are ignored. This example will therefore enable:

* http://domain.com
* https://domain.com
* http://www.domain.com
* https://www.domain.com
* http://staging.domain.com
* https://staging.domain.com
* http://www.staging.domain.com
* https://www.staging.domain.com

If you send a request from http://staging.domain.com/app/, the response would include the header:

Access-Control-Allow-Origin: http://staging.domain.com

If you sent another request from https://www.domain.com/client/, the response would include the header:

Access-Control-Allow-Origin: https://www.domain.com

JavaScript Beacon API Explained

Beacons are a new API that is being experimentally introduced by browser vendors that will allow an XHR call to be made to a server when a webpage unloads without blocking the thread in order to create a better user experience. Quoting the W3C Beacon Specification.

"analytics and diagnostics code will typically make a synchronous XMLHttpRequest in an unload or beforeunload handler to submit the data. The synchronous XMLHttpRequest forces the User Agent to delay unloading the document, and makes the next navigation appear to be slower. There is nothing the next page can do to avoid this perception of poor page load performance."

This specification will prevent developers from having to use tricks and hacks to bend the rules of the browser, creating a better experience for everyone.

Fixing the "You tried to define an association named transaction" Ruby on Rails Error

I recently encountered an error in Rails where I was trying to connect a Category model to a Transaction model. I had a has_one associtation and encountered the following error:

class Category < ActiveRecord::Base
  has_one :transaction
end

"You tried to define an association named transaction on the model Category, but this will conflict with a method transaction already defined by Active Record. Please choose a different association name."

This is caused by ActiveRecord already using a method named "transactions". To handle this issue, choose an appropriate alternative name for the association and specify the model class and foreign key manually.

has_one :association_name, :foreign_key: "key_name", class_name: "ModelClass"

In my case this was implement as:

class Category < ActiveRecord::Base
  #has_one :transaction
  has_one :owner, foreign_key: "category_id", class_name: "Transaction"
end

© Blake Simpson, 2012 – 2017