Why People Distro Hop and How to Stop It.


I'm not a "Human Interaction Specialist" nor am I a "Psycho-analyst".  I did not use the Scientific Method to draw my conclusions, rather, I used my extensive experience on the subject.  I also don't claim that this is "fact" and that "everyone else is wrong", my conclusions are my opinions based on what I see as logic coupled together with experience.  Nothing more.

The Behavior:

We've all (in the Linux community) seen this before.  A relatively new user to Linux comes along, they've been using a(n) *buntu derivative for a month or three and at the urging of their slightly more savvy and infinitely more zealous compatriots, they make the switch to a "bare bones" distribution like Gentoo, Funtoo, Arch, Slackware, etc.  If this fictional user has been given even a modicum of direction, they have read the wiki articles for these distros, studied the "Beginner's Guide" and/or have the beginner's guide open and are going step by step through the installation process.

A few weeks go by, this bare bones distro has already been installed, our new user has some of their favorite programs setup and in-use, they're feeling mighty productive and happy.  Then, the worst thing on the planet happens, their GUI craps out on them for some "completely unexpected reason" and they are thrown into this mysterious "black hole" that has a weird heading with "TTY1", the date, , , Login:, and a blinking cursor.  Something ain't right here Jim!  However, our fictional user composes themselves and enters their login information.  That's when the reality sets in; they are met with a command prompt and nothing else.  Life has just thrown them a lemon and they have no idea how to make lemonade in this space.  Tears fall, sobs rise to the technological heavens, the great software engineers of yore look down in shame, and our user is left in the fetal position in the corner of a round room; their sanity seeping away.  Death looms closely in the air.

But wait! A ray of hope! Our user calls up one of their "guru" (I hate the improper use of that word!) friends who's got more zealotry than savvy and asks for help.  Surely my friend is zealous because he knows how to fix problems like these! Enter the zealous friend without a clue: "You what? Yeah, that's a CLI, you b0rk3d your OS n00b LOL!"  Our fictional user has lost hope, but not enough to go back to Windows or OS X.  They remember that they used to use a *buntu derivative so they hop on another computer to go online and look up "Ubuntu-like distros".  They come up with Mint, Peppermint, Zorin OS, etc.  All good distros, all try to make life easier for the user, and all are Linux! (We'll return to this last item in a few minutes.)

Our fictional user downloads an ISO, say Peppermint (excellent distro by the way), installs it to their system, is happy with the simple installer, loves the GUI package management, and is happy.  Until a few weeks later when something breaks and back to the TTY they go.  At this point, just start from the top and read down to here again, it pretty much goes like that for quite some time.

The Problem:

Ignorance.  Don't get all offended on me.  Hear me out, if we look at the definition of the word Ignorance, we find something:

(Taken from Merriam-Webster.com)

ig·no·rance noun \ˈig-n(ə-)rən(t)s\

Definition of IGNORANCE

: the state or fact of being ignorant : lack of knowledge, education, or awareness

Pay special attention to the last part: "lack of knowledge, education, or awareness".  Now, ask yourself these questions: "When was Stephen Hawking born?", "What is the exact algorithm that Google uses for its search?", "What type of language is LISP?".  If you said "I don't know" or you looked up these questions on Wikipedia, then you are ignorant of that particular item.  You do not have knowledge in that area, you are not educated in that area, or you lack awareness in that area.  It's not offensive, it's fact.

"But Brian! What is our fictional user ignorant of?"

I'm getting to that and then some.  The problem isn't so much the fictional user (though they have a part to play), the bigger problem is their "more zealous than savvy" friends.  The ones who call themselves "gurus" (improperly).  That's right, if you're die-hard Linux and are pushing your distro onto your buddies, I'm talking to you.  I know why you did it, you were afraid! Who wouldn't be?  Seriously though, I'm guilty of having done this as well.  You reach a point in your Linux use where you're pretty decent at the CLI, you've managed to sample various X environments (Desktop Environments and Window Managers), and possibly even creating a binary package for your particular distro.  You even know how to build a package from source! But, you're still very much lacking in the more "nitty gritty" things in the OS.  You're still copying and pasting scripts that you found on some obscure forum that you think is cool, you've graduated to using Tiling and/or Dynamic Window Managers like Awesome, you've even written a tutorial on how to best copy and paste someone else's config into your own config.  You're an "average" user but because you're surrounded by Windows users, you fancy yourself a god.  It happens, don't worry about it, just learn to recognize it and reign yourself in a bit.

It's okay to not know everything.  The trick is to know where to go to get your answers so that you aren't stuck in "I don't know" land.

The Solution:

There is a realization that comes to every new Linux user, usually after about ten distro hops (sometimes 1000 hops...); It's all Linux.

Think about that for a minute: It's all Linux.

That means that, underneath the GUI, underneath the userspace apps, and underneath the system utilities, there's a kernel.  That kernel is Linux (no, I will not get into the GNU/Linux vs Linux debate here! That's for another time :)  ).  Linux (the kernel) is in every (Linux) distro on the open source market right now.  Ubuntu uses the Linux Kernel, Fedora / Red Hat, Novelle, Gentoo, Arch, Debian, etc.  All of them have the Linux Kernel.  All of them have GNU Coreutils.  At the heart of every distro are these two pieces, Kernel and Coreutils.  Everything else that makes your distro a "distro" is (for the most part, I'm looking at you *buntus!) Userspace.  To oversimplify it, Userspace is the space in which the regular user (not root) operates.  GUI, Apps, your browser, games, office programs, etc.  All of these are executed with user permissions by a user who operates in a space meant specifically for that user.  That's userspace in a nutshell.

Note: To those who would quickly like to correct me, read what I said again, "To oversimplify it..."  The day that I want to spend a good ten pages going through more than a super-high-level-overview of "Userspace", we'll be in touch. Until then, the layman will appreciate this explanation.

Once you realize that all distros are basically the same, just configured differently, you begin to realize that you can take a "base distro" and turn it into any of the distributions that you see on the market today, often-times with a not-very-complex script!  What does this mean for you? It means that you don't have to say "Oh, I don't know how to use Gentoo because I've only ever used Fedora."  Sure you know how to use Gentoo! It's got a BASH shell (ZSH for those of us who like a few extra features), it has a package manager, etc.  All you'd need is about ten minutes alone with Portage and the Gentoo Help documentation on Portage in order to understand the basic system, what's already in stalled, with what flags, and what you would have to do to install your preferred packages.  It's not hard.  Hell, here's some anecdotal proof: Take an issue that you've been having on your *buntu derivative and don't go to the Ubuntu forums, instead, go to the Arch Linux Wiki.  Aside from the package manager specific stuff, you can apply those processes and concepts to your distro and any other distro.  Now, take your Arch based distro and go to the Ubuntu forums, notice anything? Yeah, those steps, aside from the package manager specific ones, will work in Arch! I wonder why that is? Oh! Right! They're all Linux! Victory is mine!

The Challenge:

Don't hop distros for at least one month.  In that one month, every time you have a problem with your current distro, I want you to go to at least three other distro's wiki sites/pages and/or forums.  Now, don't go posting on Ubuntu forums with an "Arch problem", that would be bad and would take away from the care being provided to Ubuntu users.  Instead, realize that your problem is not new and you aren't a special snowflake.  Linux has been around since the 90's, I can assure you that almost every problem that has ever been had on a Linux system has already been posted online somewhere and the solution available publicly.  Back to the challenge.  The three other forums/wikis for three different distros (for you *buntu people, that doesn't mean that if you're using Xubuntu that you go to Kubuntu wiki/forums, that means you pick something like Gentoo, Arch, Slackware, etc.  Debian would be cheating too!)  Read through the issue description and the solutions, you will find that the solutions are strikingly similar despite being on completely different distributions.

Once you realize all of this, you'll choose a distro based on it's merits, not FUD.  You'll also be much happier as you'll be able to tackle any problem using any distribution's documentation.  One month, no hopping.  Can you do it?


Microsoft makes me glad...

...that I don't work for them!

This "little" rant is in response to this particular article published on Vanity Fair's website and shared on Google+:

At the company that I work for, developers are treated like royalty.  We are "graded" by our peers.  This group of "peers" are fellow developers.  I'm not graded by a marketing manager, sales manager, or even my direct boss, the COO of the company.  I'm graded by the people that I work with on a daily basis.  Everyone gets to contribute ideas, no matter how "new" to the company they are and no matter which school they got their degree from (if applicable).  All ideas are put up on the board and put up to a peer review and used or discarded based on its own merit.

The culture of the development environment at my company is very much conducive to innovative thinking, learning, and practical application of ideas.  Everybody has their own individual goals that they set for themselves, and everybody has a set of goals that are recommended by the group.  We all try to make each other better at what we do so that all of our lives are made easier, more productive, more rewarding, and ultimately, more profitable for our company.

Stacked Ranking is BS, especially in the "wrong hands".  Ranking developers (or anyone for that matter) based on the input of people who have no idea what the hell you are doing (show me a sales agent that can write code, and I'll show you a closet geek; basically, the exception to the rule) is just plain stupid.

I colleague of mine said something like this when describing the reasons for the management style that the COO of our company takes with the development team: "She asked me how to quantify or grade what a software developer or engineer does with regard to work.  I told her that's very difficult because I would have to know what her definition of 'work' was.  Do you count the time that I'm sitting with my lunch quietly, not moving, but mulling over how best to implement a client feature request?  Do you count the amount of research that may go into finding the root cause for a bug rather than just 'getting rid of the error message' since the user doesn't know the difference? Should I also count the time I take to document any code that I write in case someone else has to go through it later for use in a new or updated feature? Do you also count work as being when I'm at home thinking about a problem at work and then using the VPN to commit code because an idea just 'clicked' in my head that solves that problem?  I'm sure that it could be done, but it's very difficult.  She basically trusts us to do what needs to be done, to help and provide feedback to each other, and give us enough rope to hang ourselves with.  So far, she hasn't had to step in to modify our processes or really do much other than ask if we need anything to make our lives easier at work."

I'm not saying that this is the only way to drive innovative thought in a development team, but in our team, it works very well.  We have a lot of autonomy and our "checks and balances" system is each other.  It also keeps things moving at a pretty fast pace.

I've said this before, much to the astonishment of my fellow Linux zealots, but it bears repeating, I don't want Microsoft to fail this way.  I don't want Linux and OS X to rise to higher percentages of desktop market-share this way.  I want Linux and OS X (but especially Linux) to rise in popularity and market-share based on their own merit.  I want Microsoft to fail, not because it was late to the party and fails at managing its various teams, but because the other products out on the market are just that good.  I'd rather they failed because they ran out of ideas and just couldn't recover than to focus on litigation so much that they forgot to have ideas in the first place.

"But Brian! That blasphemy in the Linux and Open Source world!"

Yeah, that's right.  I want competition in the markets.  I want ideas to stand on merit and I want companies fighting for every consumer dollar in an innovation race as opposed to a patent litigation race.  If wanting my preferred platform to rise to that occasion and be the best because it has the best features, functionality, and interfaces as opposed to defaulting to the top because the previous company just happened to run itself into the ground is "blasphemous", then just send me to that particular hell now.  I'd rather go down having high standards than to accept a prize based on a "default" in the competition.


Today's Ramblings (A programming adventure)

It's no secret, I'm not the best programmer in the world, if that's why you're following me, then I'm sorry to disappoint.  I'd like to think that I'm a decent programmer, that I think through problems in code to reach reasonable conclusions that are efficient and at times elegant, and I'd also like to think that I'm relatively creative in my solutions and designs for my own from-scratch code.  The fact of the matter is, nobody is perfect, we all make mistakes, and if you want to see this first-hand in the realm of programming, just look at your own code (some of you pros will have to go back pretty far, but you'll see something that could be better).

As many of you know, I have been at the company that I now work for, for a little over a month and a half.  I was hired to develop web applications, our main project being a combination of PHP, MySQL, JavaScript, and two frameworks, CodeIgniter and Doctrine.  Needless to say, I was conditionally hired on the premise that I would (at least) learn PHP very quickly, enough to be a productive contributor so that the other two devs wouldn't have to babysit me, and any other concepts and languages along the way that would aid in my productivity (MySQL, JavaScript, Selenium and Unittests, etc).

I think I've done a pretty good job so far, even to the point of writing some damn pretty and functional code (I know, it's PHP, there's only so much you can do, but dammit I'm proud of what I do!).  The company that I work for is a meritocracy, if you do well, you are rewarded and even praised publicly, if you don't do so well, you are privately educated and guided to resources/people that can help you to do well (every experience is a learning experience!).  Worst case scenario: you're attitude and work are so horrible that you are more of a burden than a help and are let go.  Why am I glad that this is the case? Because it's a damn good concept and business practice.

On the business side of the house, the company can't afford to keep bad programmers (employees, but we're being specific here).  "Bad" is largely subjective, but suffice it to say that if you have a terrible attitude and are putting out equally terrible code that is bug ridden and you're too hard-headed to recognize it, then you're probably bad and need some help.  On the more personal side of things, it does no good for you to be a douche when you make a mistake.  When someone makes a mistake and can't just own up to it, get the help/education that they need in order to fix the mistake (and hopefully not repeat it later), and move on, it wastes productivity time.  Other developers have to sit there and listen to you complain and go on about how great you are and how your code works and how they are stupid and if they try to prove you wrong it can turn ugly, for hours.  It's not good for you (you get pissed) it's not good for them (they get pissed) and when developers are pissed off they produce garbage code which gets us back to the business side of things not getting much of a return on their investment.  It's bad all around.

I said all of that so that you'd have an idea of where I'm coming from when I tell you a short story about what happened at work today; I made a mistake.

Yep, remember that part about "Nobody is perfect..."? Yeah, that includes me.  One of the components of our app is a document converter.  I've spent the better part of a week (maybe two, my brain is a bit fuzzy right now) doing the best that I could to fix someone else's code who is no longer with the company (for good reasons, they got a better offer elsewhere and I wish them well).  Lots of things were broken and with the help of my two partners-in-crime (and a lot of research), I've been hacking away at the bugs and broken cruft in order to produce something that I'm (still) pretty proud of.  We've all taken a few chunks out of the bigger pie in order to more easily manage implementing these fixes and today we were damn near finished, then 16:00 rolled around....

Bombs away! Someone else on the dev team had to go through some code that I had written a few days ago because of the particular task that they were working on.  First problem, (a personal peeve that I blame myself for) they had to ask me what was going on in my code.  That set off a red flag in the back of my head because I try to write as readable code as possible, so I failed at something.  The second flag that went off was, if they couldn't see how my code was working, I didn't write it simply enough, which means that I didn't understand the problem well enough to come up with a simple explanation (programmatic solution).  Two flags raised in the time it took for my cohort to utter one sentence, "Hey Brian, this code that you wrote, I'm having a hard time understanding what's going on with it and could use your eyes."  Taking every opportunity to learn something as well as to possibly help my colleague, I jumped right up from what I was working on and walked on over.  Come to find out, I was doing things the hard way.  Part of this is because of my lack of experience with PHP (I was writing loops where in_array() would have sufficed), the other part is that my mode of thought immediately went to loops because when I hear "arrays" that's what I think, "loops".  

Next up, we step through the code in the debugger and I explain what I intended for the code to do.  Now, keep in mind, I did test my code, but not well enough in this case.  I hadn't accounted for two possible user actions and so my code produced some odd results.  No problem, my colleague figured out really quickly what was wrong and we both went to work bouncing ideas for solutions back and forth once we were both sure that I understood where my mistakes were (this is a very important part of the process!).  By the time we had everything mapped out for what we needed to tackle and started writing the code to fix the problems (we found issues, unrelated to the code that I had written, that are definite "no nos") it was just after 17:00 and thus, time to leave for the day.

I have something to admit, I'm glad that my colleague found something wrong in my code even though I don't like being wrong.  Why? Because if that code would have been left there and the mistakes not caught, things would have been hairy and life would have gotten a bit more hectic.  I didn't catch it when I wrote it, our QA didn't catch it when they were testing, and my colleagues didn't catch it when they reviewed my code prior to the commit (whenever we are ready to push a commit, we always grab at least one other dev to take a look at the code and get their input, a second set of eyes helps!), and had my cohort not been digging around because of a problem that he was tracking down, our customers would have noticed it and badgered our tech support department.  That gets back to the "bad for the company" part I talked about earlier.

Here's the other reason why I'm glad that my mistakes were caught, I can learn from them.  Like I said, I'm not the best programmer in the world, I'm bound to make a mistake (or five) at some point(s) in time.  If my mistakes are brought to my attention, I can look at them, point out the problem(s), find a better way, and add to my notes so that I will (hopefully) not make those mistakes again.  
Note: I actually have a file for each language that I know (or am learning)with code examples and descriptions of what the mistakes are and how not to fall into those traps again.  I read them every morning, all of them, in their entirety, in hopes that I'll remember what not to do as well as the examples of what to do.  I highly recommend this practice!

Now, what does this have to do with my introduction to this monologue? If I were hard-headed and/or "bad" I wouldn't have learned anything today (regarding my mistakes).  I would have just plugged along making the same mistakes again, and again, and again, and I would not be progressing in my craft (programming is art!).  I would, most likely, not have ended up with a favorable review, and ultimately, I would have cost the company money rather than being a good investment, and eventually would have been fired.  A good attitude can take you pretty damn far in life, and the willingness to own up to your mistakes can be the difference between a valuable lesson that you keep, and a kick out the door.  Jobless.


Crowdsourcing Parenting Advice: A Shift from the Norm?


As many of you know, I'm an avid Google+ user and frequently post on various topics from my personal life to Linux.  Lately, I've been testing out an idea.  They say that "it takes a village" with regards to raising children.  I thought that I would test that theory "the internet way" by posting parenting related questions to my stream on Google+.  Basically, if I'm hitting a snag with my two kids in some way, or if there is a situation that I think poses a deeper dilemma, I post about it and see what kind of feedback I get.  I've done this a few times, the most recent of which was today and can be found at this link.

Before we go further...

Let's first define "Crowdsourcing".  The following is taken from this Wikipedia Article:

        "Crowdsourcing is a distributed problem-solving and production model. In the classic use of the term, problems are broadcast to an unknown group of solvers in the form of an open call for solutions. Users—also known as the crowd—typically form into online communities, and the crowd submits solutions. The crowd also sorts through the solutions, finding the best ones. These best solutions are then owned by the entity that broadcast the problem in the first place—the crowdsourcer—and the winning individuals in the crowd are sometimes rewarded. In some cases, this labor is well compensated, either monetarily, with prizes, or with recognition. In other cases, the only rewards may be kudos or intellectual satisfaction. Crowdsourcing may produce solutions from amateurs or volunteers working in their spare time, or from experts or small businesses which were unknown to the initiating organization."

There's obviously more to it than just that paragraph, but for the purposes of this article, I think we're good.

Shifting Paradigms:

Traditionally in the USA, a mother and a father are supposed to follow a particular model with regards to parenting.  Dad is the enforcer, sitting on the couch, reading his newspaper and only getting up when it's time for dishing out punishment; the mother is there to nurture, to feed, and to get exacerbated by trying to keep the kids under control.  Does this remind you of any 1950's pictures of what the traditional family is supposed to be like?  Good, now, scrap that image.  We're living in the 21st century now.  We have computers on our desks, in our pockets, on our laps, in our classrooms, and even in our towing and garbage collecting trucks.  Everything is connected via the internet in some way or another.  We are in the most inter-connected time that history has ever seen.

So why are we not leveraging these connections for more than journalistic buzz-words centering around Silicon Valley?  We are in the midst of the global consciousness every time we open a browser or communications app, why not leverage that collective knowledge for more?  Do we really need a scientific study to state that "There are people from all over the world connected to the internet, and at least some of them are smarter than you or have come across the same situation that you are dealing with now"?  Of course not!

So, what is needed? A "proof of concept".  People are usually pretty leery of doing anything "new" unless they can see that someone else did it first, it's just the way we're "wired" so to speak.  Ideas take a while to catch on at a "viral" level, that's okay.  We just need to have the open minds needed to receive these ideas and do something with them.

 Technological Effects:

Don't think of "Technological Effects" as meaning "A new device to do things for you".  That's not what I mean.  Technology makes subtle changes over a period of time just as well as it does bringing something along that is ten years before its time.  Sometimes, the only changes that happen are in how we use existing technologies to do new things.  I'm not saying that the concept of using the internet to ask a question and get several answers is by any means "new", I am saying that utilizing the global consciousness for more "mundane" things does have a benefit.  Why spend several hundred dollars an hour with a family therapist for an issue of "how do I get my daughter to accept that she's too big for a booster seat" when there are, literally, millions of other parents on the planet who have had the same problem at one time or another and have dealt with it with success?  I'm not saying that family therapists don't have their uses, and I'm not advocating replacing those therapists solely with crowdsourced information, not by any means.  But, as a supplement, crowdsourcing everyday problems, ideas, and questions is a great way to connect with other people, to gain wisdom and knowledge from the "collective", and ultimately to take the "it takes a village" scenario to the next level.


This isn't a "new" concept at all.  People have been writing to "Dear Abby" and other forums for quite some time.  What is new is that we are moving away from strict "sharing" and moving towards actual engagement.  Platforms like Google+ allow us to hold conversations in near-real-time and to reach large groups of individuals who all contribute, daily, to the collective knowledge and wisdom of the collective knowledge and wisdom.  It is expected that when you post something on a social platform that you are willing to talk about it, to dig deeper, and to come to a conclusion.  This shift is happening slowly, but, thanks to Google+, it's happening on a much larger scale.  All you have to do is ask.

By the way, I consider my small experiment to be a success.  Agree or disagree? Feel free to contact me on my Google+ Profile.


Updated Awesome Config (rc.lua)

A few words:

This rc.lua is the on that I use for my current desktop configuration.  Some options might not work for you (especially if you don't have Vicious installed).  Make sure that before you rely on this config in your setup that you first browse through it and make sure that your installed apps match.  The syntax is pretty simple, so if my IM app ("Pidgin") doesn't match yours, just change the name in quotes to the executable binary for your IM App.  My config assumes that you have moved the default themes into your ~/.config/awesome directory, if you have not done this, then edit accordingly.  Realistically, this should be used as more of a guide to doing some simple customizations to your existing configs and not as a "guaranteed to work replacement".

If you have any questions regarding my config or how to modify your own with some added widgets, menus, keybinding defaults, etc then hit me up on my Google+ Profile.

The Config:


-- Standard awesome library
-- Theme handling library
-- Notification library
-- Vicious Widgets

-- {{{ Variable definitions
-- Themes define colours, icons, and wallpapers

-- This is used later as the default terminal and editor to run.
terminal = "terminator"
editor = os.getenv("EDITOR") or "vim"
editor_cmd = terminal .. " -e " .. editor

-- Default modkey.
-- Usually, Mod4 is the key with a logo between Control and Alt.
-- If you do not like this or do not have such a key,
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
-- However, you can use another modifier like Mod1, but it may interact with others.
modkey = "Mod4"

-- Table of layouts to cover with awful.layout.inc, order matters.
layouts =
-- }}}

-- {{{ Tags
-- Define a tag table which hold all screen tags.
tags = {}
for s = 1, screen.count() do
    -- Each screen has its own tag table.
    tags[s] = awful.tag({ 'Terms', 'Net', 'Work', 'Dev', 'Coms', 'Down', 'Vids', 'Music', 'Misc' }, s, layouts[1])
-- }}}

-- {{{ Menu
-- Create a laucher widget and a main menu
myawesomemenu = {
   { "manual", terminal .. " -e man awesome" },
   { "edit config", editor_cmd .. " " .. awful.util.getdir("config") .. "/rc.lua" },
   { "restart", awesome.restart },
   { "quit", awesome.quit }
mydevmenu = {
   { "Spyder", "spyder"},
   { "Gedit", "gedit" },
   { "Bluefish", "bluefish" },
   { "CodeBlocks", "codeblocks"},
   { "VIM", terminal .. " -e vim" } 
mycustommenu = {
   { "Irc", terminal .. " -e screen weechat-curses" },
   { "IM", "pidgin" },
   { "Email", terminal .. " -e screen alpine" },
   { "Chrome", "chromium" },
   { "uzbl Browser", "uzbl-browser" },
   { "Image Viewer", "viewnior" }, 
   { "Music", terminal .. " -e screen cmus" },
   { "PCmanFM", "pcmanfm" },
   { "MC", terminal .. " -e screen mc" },
   { "rtorrent", terminal .. " -e screen rtorrent" },
   { "Monitor", terminal .. " -e htop" },
   { "Pulse Volume", "pavucontrol" }
mymainmenu = awful.menu({ items = { { "Dev", mydevmenu, beautiful.awesome_icon },
                   { "common", mycustommenu, beautiful.awesome_icon },
                                    { "awesome", myawesomemenu, beautiful.awesome_icon },
                                    { "open terminal", terminal }

mylauncher = awful.widget.launcher({ image = image(beautiful.awesome_icon),
                                     menu = mymainmenu })
-- }}}

-- {{{ Wibox
-- Start Vicious Widgets Config
-- Gmail Widget
-- Initilize widget
gmailwidget = widget({ type = "textbox" })
-- Register widget
vicious.register(gmailwidget, vicious.widgets.gmail, "Gmail: ${count}", 200)

-- Naughty Notifications on new email (WIP)
-- End Naughty Notifications on new email

-- CPU Graph
-- Initialize widget
cpuwidget = awful.widget.graph()
-- Graph properties
cpuwidget:set_gradient_colors({ "#FF5656", "#88A175", "#AECF96" })
-- Register widget
vicious.register(cpuwidget, vicious.widgets.cpu, "$1", 2)

-- CPU Text Widget
-- Initialize widget
cputextwidget = widget({ type = "textbox" })
-- Register widget
vicious.register(cputextwidget, vicious.widgets.cpu, "CPU: $1%", 4)

-- RAM Graph
-- Initialize widget
memwidget = awful.widget.graph()
-- Graph properties
memwidget:set_gradient_colors({ "#FF5656", "#88A175", "#AECF96" })
-- Register widget
vicious.register(memwidget, vicious.widgets.mem, "$1", 3)

-- Mem Text Widget
memtextwidget = widget({ type = "textbox" })
-- Register widget
vicious.register(memtextwidget, vicious.widgets.mem, "RAM: $1%", 5)
-- End Vicious Widgets Config

-- Separators (thanks anrxc)
sepline = widget({ type = "textbox" })
sepline.text = "|"
sepspace = widget({ type= "textbox" })
sepspace.text = " "

-- Create a textclock widget
mytextclock = awful.widget.textclock({ align = "right" })

-- Create a systray
mysystray = widget({ type = "systray" })

-- Create a wibox for each screen and add it
mywibox = {}
mypromptbox = {}
mylayoutbox = {}
mytaglist = {}
mytaglist.buttons = awful.util.table.join(
                    awful.button({ }, 1, awful.tag.viewonly),
                    awful.button({ modkey }, 1, awful.client.movetotag),
                    awful.button({ }, 3, awful.tag.viewtoggle),
                    awful.button({ modkey }, 3, awful.client.toggletag),
                    awful.button({ }, 4, awful.tag.viewnext),
                    awful.button({ }, 5, awful.tag.viewprev)
mytasklist = {}
mytasklist.buttons = awful.util.table.join(
                     awful.button({ }, 1, function (c)
                                              if c == client.focus then
                                                  c.minimized = true
                                                  if not c:isvisible() then
                                                  -- This will also un-minimize
                                                  -- the client, if needed
                                                  client.focus = c
                     awful.button({ }, 3, function ()
                                              if instance then
                                                  instance = nil
                                                  instance = awful.menu.clients({ width=250 })
                     awful.button({ }, 4, function ()
                                              if client.focus then client.focus:raise() end
                     awful.button({ }, 5, function ()
                                              if client.focus then client.focus:raise() end

for s = 1, screen.count() do
    -- Create a promptbox for each screen
    mypromptbox[s] = awful.widget.prompt({ layout = awful.widget.layout.horizontal.leftright })
    -- Create an imagebox widget which will contains an icon indicating which layout we're using.
    -- We need one layoutbox per screen.
    mylayoutbox[s] = awful.widget.layoutbox(s)
                           awful.button({ }, 1, function () awful.layout.inc(layouts, 1) end),
                           awful.button({ }, 3, function () awful.layout.inc(layouts, -1) end),
                           awful.button({ }, 4, function () awful.layout.inc(layouts, 1) end),
                           awful.button({ }, 5, function () awful.layout.inc(layouts, -1) end)))
    -- Create a taglist widget
    mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.label.all, mytaglist.buttons)

    -- Create a tasklist widget
    mytasklist[s] = awful.widget.tasklist(function(c)
                                              return awful.widget.tasklist.label.currenttags(c, s)
                                          end, mytasklist.buttons)

    -- Create the wibox
    mywibox[s] = awful.wibox({ position = "top", height = "18", screen = s })
    -- Add widgets to the wibox - order matters
    mywibox[s].widgets = {
            layout = awful.widget.layout.horizontal.leftright
        mylayoutbox[s], sepspace,
        mytextclock, sepspace, 
        s == 1 and mysystray or nil,
        sepline, sepspace, memwidget.widget, sepspace, memtextwidget,
        sepspace, sepline, sepspace, cpuwidget.widget, sepspace, cputextwidget,
        sepspace, sepline, sepspace, gmailwidget, sepspace,
        sepline, sepspace, 
        layout = awful.widget.layout.horizontal.rightleft
-- }}}

-- {{{ Mouse bindings
    awful.button({ }, 3, function () mymainmenu:toggle() end),
    awful.button({ }, 4, awful.tag.viewnext),
    awful.button({ }, 5, awful.tag.viewprev)
-- }}}

-- {{{ Key bindings
globalkeys = awful.util.table.join(
    awful.key({ modkey,           }, "Left",   awful.tag.viewprev       ),
    awful.key({ modkey,           }, "Right",  awful.tag.viewnext       ),
    awful.key({ modkey,           }, "Escape", awful.tag.history.restore),

    awful.key({ modkey,           }, "j",
        function ()
            awful.client.focus.byidx( 1)
            if client.focus then client.focus:raise() end
    awful.key({ modkey,           }, "k",
        function ()
            if client.focus then client.focus:raise() end
    awful.key({ modkey,           }, "w", function () mymainmenu:show({keygrabber=true}) end),

    -- Layout manipulation
    awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx(  1)    end),
    awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx( -1)    end),
    awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end),
    awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end),
    awful.key({ modkey,           }, "u", awful.client.urgent.jumpto),
    awful.key({ modkey,           }, "Tab",
        function ()
            if client.focus then

    -- Standard program
    awful.key({ modkey,           }, "Return", function () awful.util.spawn(terminal) end),
    awful.key({ modkey, "Control" }, "r", awesome.restart),
    awful.key({ modkey, "Shift"   }, "q", awesome.quit),

    awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)    end),
    awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)    end),
    awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1)      end),
    awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1)      end),
    awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1)         end),
    awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1)         end),
    awful.key({ modkey,           }, "space", function () awful.layout.inc(layouts,  1) end),
    awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(layouts, -1) end),

    awful.key({ modkey, "Control" }, "n", awful.client.restore),

    -- Prompt
    awful.key({ modkey },            "r",     function () mypromptbox[mouse.screen]:run() end),

    awful.key({ modkey }, "x",
              function ()
                  awful.prompt.run({ prompt = "Run Lua code: " },
                  awful.util.eval, nil,
                  awful.util.getdir("cache") .. "/history_eval")

clientkeys = awful.util.table.join(
    awful.key({ modkey,           }, "f",      function (c) c.fullscreen = not c.fullscreen  end),
    awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end),
    awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ),
    awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end),
    awful.key({ modkey,           }, "o",      awful.client.movetoscreen                        ),
    awful.key({ modkey, "Shift"   }, "r",      function (c) c:redraw()                       end),
    awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end),
    awful.key({ modkey,           }, "n",
        function (c)
            -- The client currently has the input focus, so it cannot be
            -- minimized, since minimized clients can't have the focus.
            c.minimized = true
    awful.key({ modkey,           }, "m",
        function (c)
            c.maximized_horizontal = not c.maximized_horizontal
            c.maximized_vertical   = not c.maximized_vertical

-- Compute the maximum number of digit we need, limited to 9
keynumber = 0
for s = 1, screen.count() do
   keynumber = math.min(9, math.max(#tags[s], keynumber));

-- Bind all key numbers to tags.
-- Be careful: we use keycodes to make it works on any keyboard layout.
-- This should map on the top row of your keyboard, usually 1 to 9.
for i = 1, keynumber do
    globalkeys = awful.util.table.join(globalkeys,
        awful.key({ modkey }, "#" .. i + 9,
                  function ()
                        local screen = mouse.screen
                        if tags[screen][i] then
        awful.key({ modkey, "Control" }, "#" .. i + 9,
                  function ()
                      local screen = mouse.screen
                      if tags[screen][i] then
        awful.key({ modkey, "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus and tags[client.focus.screen][i] then
        awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus and tags[client.focus.screen][i] then

clientbuttons = awful.util.table.join(
    awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
    awful.button({ modkey }, 1, awful.mouse.client.move),
    awful.button({ modkey }, 3, awful.mouse.client.resize))

-- Set keys
-- }}}

-- {{{ Rules
awful.rules.rules = {
    -- All clients will match this rule.
    { rule = { },
      properties = { border_width = beautiful.border_width,
                     border_color = beautiful.border_normal,
                     focus = true,
                     keys = clientkeys,
                     buttons = clientbuttons } },
    { rule = { class = "MPlayer" },
      properties = { floating = true } },
    { rule = { class = "pinentry" },
      properties = { floating = true } },
    { rule = { class = "gimp" },
      properties = { floating = true } },
    -- Set Firefox to always map on tags number 2 of screen 1.
    -- { rule = { class = "Firefox" },
    --   properties = { tag = tags[1][2] } },
-- }}}

-- {{{ Signals
-- Signal function to execute when a new client appears.
client.add_signal("manage", function (c, startup)
    -- Add a titlebar
    -- awful.titlebar.add(c, { modkey = modkey })

    -- Enable sloppy focus
    c:add_signal("mouse::enter", function(c)
        if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
            and awful.client.focus.filter(c) then
            client.focus = c

    if not startup then
        -- Set the windows at the slave,
        -- i.e. put it at the end of others instead of setting it master.

        -- Put windows in a smart way, only if they does not set an initial position.
        if not c.size_hints.user_position and not c.size_hints.program_position then

client.add_signal("focus", function(c) c.border_color = beautiful.border_focus end)
client.add_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)

-- { Autostart some things
os.execute("xscreensaver -nosplash &") --screensaver daemon
os.execute("volwheel &") -- volwheel system tray applet
os.execute("dropbox &") -- dropbox service
os.execute("nm-applet &") -- NetworkManager applet
-- }
-- }}}


Phew! That's a lot of text.  Hopefully this is helpful to you.  I'll get to work on re-writing my Awesome How To as soon as I find some time in my schedule.  Until then, this should get you started if you're clever :)