How to make “man” open Dash

Update

Dash is a minor miracle. Absolutely indispensable.

The following script will make Dash.app open from your terminal when you use man. Ensure you have the “Man Pages” DocSet installed from within Dash.app.

# Put this in your .bash_profile or whatever.

# To override the DocSet shortcut Man Pages name, export DASH_MAN_DOCSET somewhere.
DASH_MAN_DOCSET=${DASH_MAN_DOCSET-manpages}

if [[ `uname` != Darwin ]]; then
    echo The Dash.app plugin is only available on Mac OS X.  Sorry!
    exit 
elif [[ ! -d /Applications/Dash.app ]]; then
    echo To use the Dash.app plugin, install Dash.app from http://kapeli.com/dash
    exit 
elif [[ ! -d "$HOME/Library/Application Support/Dash/DocSets/Man_Pages" ]]; then
    echo To use the Dash.app plugin, install the "Man Pages" DocSet from within Dash.app.
    exit
else
    # http://stackoverflow.com/questions/296536/urlencode-from-a-bash-script
    # this enables to search multiple strings; "man git fetch" will find the "git" page and search for "fetch" within
    function rawurlencode() {
      local string="${@}"
      local strlen=${#string}
      local encoded=""

      for (( pos=0 ; pos<strlen ; pos++ )); do
         c=${string:$pos:1}
         case "$c" in
            [-_.~a-zA-Z0-9] ) o="${c}" ;;
            * )               printf -v o '%%%02x' "'$c"
         esac
         encoded+="${o}"
      done
      echo "${encoded}"
    }

    function dash_man {        
        /usr/bin/open dash://${DASH_MAN_DOCSET}:`rawurlencode ${@}`
    }

    alias man=dash_man        
fi 

Here’s the GitHub Gist.

Grunt: TypeError at node.js:891

If you ever get this:


node.js:891
var fn = runInThisContext(source, this.filename, true);
^
TypeError: undefined is not a function
at createWritableStdioStream (node.js:555:18)
at process.stdout (node.js:613:16)
at write (something/node_modules/grunt/lib/grunt/log.js:78:12)
at writeln (something/node_modules/grunt/lib/grunt/log.js:85:3)
at Object.log.writeln something/node_modules/grunt/lib/grunt/log.js:96:3)
at writeln (something/node_modules/grunt/lib/grunt/fail.js:39:13)
at Object.fail.fatal (something/node_modules/grunt/lib/grunt/fail.js:55:3)
at process.uncaughtHandler (something/node_modules/grunt/lib/grunt.js:123:10)
at process.EventEmitter.emit (events.js:95:17)
at process._fatalException (node.js:272:26)

Know that you shouldn’t do this:


grunt.registerTask('concat', ['concat']);

That is all.

angular-history: A history (undo/redo) service for AngularJS

We (Decipher) just released version 0.3.0 of this bad boy and now it has support for batching, or transactions, or whatever you want to call it. You can make multiple changes to many models within a context and it will let you undo them all at once, without the headache of receiving 10s or 100s of individual events.

Check it out here: angular-history

AngularJS: Heavy-Handed Anchor Tag Disable Directive

As you may or may not know, the a tag has no disabled attribute, so you can’t use ngDisabled on it like you would on a button. This ends up creating a lot of ngShow/ngHide usages on a tags which just wastes a lot of time and markup.

Behold, a solution. Not necessarily the best one, but it works.

Usage:

[code lang=”html”]
<div ng-controller="MyCtrl">
<a ng-click="alert()" a-disabled="true">some link</a>
</div>
[/code]

And the directive:

[code lang=”js”]
var myApp = angular.module(‘myApp’, []);

function MyCtrl($scope) {
$scope.alert = function () {
alert(‘hi’);
};
}

myApp.directive(‘aDisabled’, function ($compile) {
return {
restrict: ‘A’,
priority: -99999,
link: function (scope, element, attrs) {
scope.$watch(attrs.aDisabled, function (val, oldval) {
if ( !! val) {
element.unbind(‘click’);
} else if (oldval) {
element.bind(‘click’, function () {
scope.$apply(attrs.ngClick);
});
}
});
}
};
});
[/code]

This hasn’t been tested much, but basically all this says is “unbind any bound click events if the value of this attribute is true.” This works because the priority is so low, the directive will generally link last.

Would be interested in other solutions as well, especially more elegant ones. :D

Update 1

I realize this thing, once you use it, will never let you re-enable the ngClick. I’ll spend some time on Monday seeing if I can’t find a workaround.

Update 2

Here it is Tuesday and I have a better solution. See above and Fiddle.

My Gruntfile.js: An example Gruntfile and My Workflow

I’m building a site on the MEAN stack; codename Zoltar. To build and run my tasks, I use the wonderful Grunt. I’d like to explore the Gruntfile.js and explain what does what and why I chose to do it that way. Hopefully this example will assist people trying to solve the same (common) problems.

Let’s look at the entire Gruntfile.js, then we can dig into each section.

Continue reading

AngularJS & jQuery: Coaxing a $.Deferred out of AngularJS

You probably won’t ever want to do this, but I actually had occasion to as sort of a AngularJS/jQuery bridge.

[code lang=”js”]
var myApp = angular.module(‘myApp’, []);

$(function () {
var body = $(‘body’),
injector = body.injector(),
giveMeJQueryPromise = function ($log, $timeout) {
var dfrd = $.Deferred();
$log.log(‘deferring’);
$timeout(angular.noop, 2000).then(function () {
dfrd.resolve(‘deferred’);
});
return dfrd.promise();
};
jqpromise = injector.invoke(giveMeJQueryPromise);
jqpromise.then(function (res) {
console.log(res);
});
});
[/code]
Bonus: working fiddle and example of doing entirely too much without any more markup than an ngApp directive (lives in the body tag).

AngularJS: Service Inheritance

You might want to have services inherit from each other. Here’s a way to do it:

[code lang=”js”]
var myApp = angular.module(‘myApp’, []);

var baseService = function () {
this._state = {};
};
baseService.prototype.getState = function () {
return this._state;
};
baseService.prototype.setState = function (state) {
this._state = state;
};

var chartService = function () {
this._seriesParam = {};
};
chartService.prototype = Object.create(baseService.prototype);
chartService.prototype.getSeriesParam = function () {
return this._seriesParam;
};
chartService.prototype.setSeriesParam = function (seriesParam) {
this._seriesParam = seriesParam;
};

myApp.service(‘baseService’, baseService);
myApp.service(‘chartService’, chartService);

function MyCtrl($scope, chartService) {

var state = {
foo: ‘bar’
},
seriesParam = {
baz: ‘spam’
};

chartService.setState(state);
$scope.state = chartService.getState();

chartService.setSeriesParam(seriesParam);
$scope.seriesParam = chartService.getSeriesParam();
}
[/code]
Make sure you really want to be doing this though. Dependency injection might serve you just fine.

AngularJS: QUnit Testing Examples

Awhile back I posted some examples of testing various AngularJS components in QUnit, but I thought it would be a good idea to repost it here:

[code lang=”js”]
var myApp = angular.module(‘myApp’, []);

myApp.controller(‘MyCtrl’, [‘$scope’, function($scope) {
$scope.addTwo = function(n) {
return n + 2;
};}]);

myApp.service(‘MyService’, function() {
this.addThree = function(n) {
return n + 3;
};
});

myApp.directive(‘myDirective’, function() {
return {
link: function(scope, elm, attrs) {
scope.$watch(attrs.myDirective, function(value) {
elm.text(value + 4);
});
}
}
});

myApp.filter(‘myfilter’, function() {
return function(s) {
return s + 5;
};
});

// tests
var injector = angular.injector([‘ng’, ‘myApp’]);

var init = {
setup: function() {
this.$scope = injector.get(‘$rootScope’).$new();
}
};

module(‘tests’, init);

test(‘MyCtrl’, function() {
var $controller = injector.get(‘$controller’);
$controller(‘MyCtrl’, {
$scope: this.$scope
});
equal(3, this.$scope.addTwo(1));
});

test(‘MyService’, function() {
var MyService = injector.get(‘MyService’);
equal(4, MyService.addThree(1));
});

test(‘MyDirective’, function() {
var $compile = injector.get(‘$compile’);
var element = $compile(‘<div my-directive="foo"></div>’)(this.$scope);
this.$scope.foo = 1;
this.$scope.$apply();
equal(5, element.text());
delete this.$scope.foo;
});

test(‘MyFilter’, function() {
var $filter = injector.get(‘$filter’);
equal(6, $filter(‘myfilter’)(1));
});
[/code]

Visit the fiddle to run the tests.