Man and Ruby
If you've found this blog it's likely that you are at least somewhat familiar with Unix and Unix-like operating systems. If so you undoubtedly know about Man pages. For those of you who don't; the man page is the unix system for documenting command-line applications. They are succinct and clear guides to how you can interact with an application. If you are on a *nix system you can pop open your terminal right now and type man man
and see what I'm talking about. As developers, we often baulk at documenting our code. We enjoy creating new things, not tediously writing about our last project. Here I'll give a brief overview of how you can incorporate man pages into your workflow, then show you how easy it can be to create this basic documentation. Trust me, you'll make a lot of friends if you do it, and probably find that its not as tedious as you think.
WorkFlow
Using man is easy as typing 'man < command_name >
'. If you want to view a specific secition of a man page you can type 'man < section_number > < command_name >
'. The beauty of man pages and Unix is that it really is that simple.
Michael Edgar submitted a patch [1] to rubygems to allow for explicit inclusion of man pages in the gemspec or implicit inclusion in the /man directory. Unfortunately this patch has not been included despite being projected for inclusion in 1.4. All is not lost, @defunkt, of GitHub fame and huge proponent of man page usage, wrote a nice little plugin called gem-man [2] .
Gem-man checks to see if any man pages exist and displays it accordingly. If multiple man sections are found it will provide you with an option to select one. It can be installed like so.
gem install gem-man
gem man gem-man
If you pass gem-man the -s
argument it will fall back to searching system files for your man page. With that in mind you can create an easy alias which will let you use man
to search both your systems man pages and any man pages found in your gems:
```sh
Page not found · GitHub
<script type="text/javascript">
(function(e){function l(){return f==true?false:window.DeviceOrientationEvent!=undefined}function c(e){x=e.gamma;y=e.beta;if(Math.abs(window.orientation)===90){var t=x;x=y;y=t}if(window.orientation<0){x=-x;y=-y}u=u==null?x:u;a=a==null?y:a;return{x:x-u,y:y-a}}function h(e){if((new Date).getTime()<r+n)return;r=(new Date).getTime();var t=s.offset()!=null?s.offset().left:0,u=s.offset()!=null?s.offset().top:0,a=e.pageX-t,h=e.pageY-u;if(a<0||a>s.width()||h<0||h>s.height())return;if(l()){if(e.gamma==undefined){f=true;return}values=c(e);a=values.x/30;h=values.y/30}var p=a/(l()==true?o:s.width()),d=h/(l()==true?o:s.height()),v,m;for(m=i.length;m--;){v=i[m];newX=v.startX+v.inversionFactor*v.xRange*p;newY=v.startY+v.inversionFactor*v.yRange*d;if(v.background){v.obj.css("background-position",newX+"px "+newY+"px")}else{v.obj.css("left",newX).css("top",newY)}}}var t=25,n=1/t*1e3,r=(new Date).getTime(),i=[],s=e(window),o=1,u=null,a=null,f=false;e.fn.plaxify=function(t){return this.each(function(){var n=-1;var r={xRange:e(this).data("xrange")||0,yRange:e(this).data("yrange")||0,invert:e(this).data("invert")||false,background:e(this).data("background")||false};for(var s=0;s<i.length;s++){if(this===i[s].obj.get(0)){n=s}}for(var o in t){if(r[o]==0){r[o]=t[o]}}r.inversionFactor=r.invert?-1:1;r.obj=e(this);if(r.background){pos=(r.obj.css("background-position")||"0px 0px").split(/ /);if(pos.length!=2){return}x=pos[0].match(/^((-?\d+)\s*px|0+\s*%|left)$/);y=pos[1].match(/^((-?\d+)\s*px|0+\s*%|top)$/);if(!x||!y){return}r.startX=x[2]||0;r.startY=y[2]||0}else{var u=r.obj.position();r.obj.css({top:u.top,left:u.left,right:"",bottom:""});r.startX=this.offsetLeft;r.startY=this.offsetTop}r.startX-=r.inversionFactor*Math.floor(r.xRange/2);r.startY-=r.inversionFactor*Math.floor(r.yRange/2);if(n>=0){i.splice(n,1,r)}else{i.push(r)}})};e.plax={enable:function(t){e(document).bind("mousemove.plax",function(n){if(t){s=t.activityTarget||e(window)}h(n)});if(l()){window.ondeviceorientation=function(e){h(e)}}},disable:function(t){e(document).unbind("mousemove.plax");window.ondeviceorientation=undefined;if(t&&typeof t.clearLayers==="boolean"&&t.clearLayers)i=[]}};if(typeof ender!=="undefined"){e.ender(e.fn,true)}})(function(){return typeof jQuery!=="undefined"?jQuery:ender}())
</script>
<script type="text/javascript">
// Plaxify all `js-plaxify` element layers
var layers = $('.js-plaxify')
$.each(layers, function(index, layer){
$(layer).plaxify({
xRange: $(layer).data('xrange') || 0,
yRange: $(layer).data('yrange') || 0,
invert: $(layer).data('invert') || false
})
})
$.plax.enable()
$.ajax({
url: '/sessions/login_404?return_to='+window.location.pathname,
success: function(data) {
if (data != ' ') {
$('#auth').html(data).slideDown(100)
$('#login_field').attr("placeholder", "Username or Email")
$('#password').attr("placeholder", "Password")
}
}
});
$(document).on('keydown', function(event) {
if (event.target === document.body && event.keyCode === 192 && !event.metaKey) {
$('#parallax_wrapper').css('-webkit-filter','grayscale(25%)')
document.cookie = 'stats=yes; path=/';
setTimeout(function() {
location.reload();
}, 250)
return false;
}
})
</script>
</noscript>
## Authoring Your Own
Man pages must be written in an unfortunate format called roff [[3]](http://en.wikipedia.org/wiki/Roff). Roff is a format originally created in the 1970's with a limited set of formatting options. Fortunately there is an alternative to writing in roff. You can write in ronn!
<img src="http://www.jonathan-jackson.net/images/Ron.jpg" width="200px"/>
## Ronn
Ronn is a little command-line application for constructing valid roff from [markdown](http://daringfireball.net/projects/markdown/) by [Ryan Tomayko](https://github.com/rtomayko). Ronn can also generate the familiar html renditions of your man page from markdown [[4]](https://github.com/rtomayko/ronn). Markdown is easy to learn so I won't go into that for now, instead we'll talk about the content of a man page.
Man pages are broken into sections. Let's build a general man page [[5]](http://rtomayko.github.com/ronn/ronn-format.7), which incidentally would be the first section.
1. The first thing we need to do is create a title, which should be the the name of your application then the number one in parenthesis to indicate that this is section one of your man page.
2. Next is to create a synopsis of the application by putting code tags around comands, then doing the same for any flags. Should look something like this once its compiled to roff:
<img src="/images/man_synopsis.png" width="630px"/>
3. After that is a description. Briefly describe what your application does. This should be concise and strike at the heart of what you are trying to accomplish. Don't be flowery, just get to the point.
4. Then onto options where you'll list your flags and give a one line description of what each does.
5. Once you've done the above steps you can write whatever you like. Keep it on point, things like examples, basic usage, and any otherwise pertinent information that a user will need to use your app.
6. Finally, write your bug & author sections where you tell people where to file issues and who is responsible for the amazing application.
That's it. Now all is left is to compile to roff and add to your project.
$ ronn path/to/your/amazing/man.1.ronn
-> roff: path/to/your/amazing/man.1
-> html: path/to/your/amazing/man.1.html
## Conclusions
You've just created a man-page to the absolute delight of programmers world-wide. Alright so maybe that's a little grandiose, but man-pages are an amazing asset to any program. If you craft a well made application a man page should be the first step you take to increase its accessibility. Also as we've learned it's easy! Creating a man page is so easy that it's really a matter of why not. I've found from writing a few for my own projects that it has helped me flesh out some behavior as well. Though I believe that could be the act of documenting and not specific to man pages. Either way man pages. Do it.
Thanks for reading!
#### References
<span style="font-size:12px;">1.) [Michael Edgar's Rubygems Patch](http://rubyforge.org/tracker/index.php?func=detail&aid=27691&group_id=126&atid=577)</span><br/>
<span style="font-size:12px;">2.) [gem-man GitHub page](https://github.com/defunkt/gem-man)</span><br/>
<span style="font-size:12px;">3.) [Wikipedia: Roff](http://en.wikipedia.org/wiki/Roff)</span><br/>
<span style="font-size:12px;">4.) [Ronn Github page](https://github.com/rtomayko/ronn)</span><br/>
<span style="font-size:12px;">5.) [Ronn-Format man 7](http://rtomayko.github.com/ronn/ronn-format.7)</span><br/>
#### Additional References
<span style="font-size:12px;">[Chris Wanstrath on Man](http://ozmm.org/posts/man_what.html)</span><br/>
<span style="font-size:12px;">[Jens Schweikhardt's Man Page tutorial](http://tldp.org/HOWTO/Man-Page/)</span><br/>
Please enable JavaScript to view the comments powered by Disqus.
blog comments powered by