viernes, 28 de marzo de 2014

git reset. again

This is shamelessly copied from the web archive.

Assume you start from a "everything is committed and golden" state. Let's pretend you came to this starting point via a git checkout: and then you edit a bunch of stuff, compile/test, and then git add and git commit:
$ git checkout mywork
...edit edit edit...
$ git add ...
$ git commit
If at this point you do a git reset, here's how the type of reset ("soft", "hard", or the default, which is "mixed") affects things:
$ git checkout mywork
            # --hard resets to this point
...edit edit edit...
            # --mixed (default) resets to this point
$ git add ...
            # --soft resets to this point
$ git commit
Also note, as gitster says, that git commit --amend makes the git reset --soft mostly redundant.

jueves, 27 de marzo de 2014

sed vs unix

 UNIX         |  SED
 -------------+----------------------------------------------------------------
 cat          |  sed ':'
 cat -s       |  sed '1s/^$//p;/./,/^$/!d'
 tac          |  sed '1!G;h;$!d'
 grep         |  sed '/patt/!d'
 grep -v      |  sed '/patt/d'
 head         |  sed '10q'
 head -1      |  sed 'q'
 tail         |  sed -e ':a' -e '$q;N;11,$D;ba'
 tail -1      |  sed '$!d'
 tail -f      |  sed -u '/./!d'
 cut -c 10    |  sed 's/\(.\)\{10\}.*/\1/'
 cut -d: -f4  |  sed 's/\(\([^:]*\):\)\{4\}.*/\2/'
 tr A-Z a-z   |  sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'
 tr a-z A-Z   |  sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'
 tr -s ' '    |  sed 's/ \+/ /g'
 tr -d '\012' |  sed 'H;$!d;g;s/\n//g'
 wc -l        |  sed -n '$='
 uniq         |  sed 'N;/^\(.*\)\n\1$/!P;D'
 rev          |  sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'
 basename     |  sed 's,.*/,,'
 dirname      |  sed 's,[^/]*$,,'
 xargs        |  sed -e ':a' -e '$!N;s/\n/ /;ta'
 paste -sd:   |  sed -e ':a' -e '$!N;s/\n/:/;ta'
 cat -n       |  sed '=' | sed '$!N;s/\n/ /'
 grep -n      |  sed -n '/patt/{=;p;}' | sed '$!N;s/\n/:/'
 cp orig new  |  sed 'w new' orig
 hostname -s  |  hostname | sed 's/\..*//'

shamelessly copypasted from here

sábado, 22 de marzo de 2014

More Lua iterators


After the permutations post, I thought that we needed something like a 'take' function, that would allow us to use infinite streams safely.

local function take(n, it , param, state)
  local count = 0
  return function()
    count = count+1
    if count <= n then
      return it()
    end
    return nil
  end
end


local function take_while(fun, it , param, state)
  return function()
    if fun() then
      return it()
    end
    return nil
  end
end
 
Simple but nice.

miércoles, 19 de marzo de 2014

Permutations in Lua. An iterator example

Here's some code I just wrote when messing with an algorithm to generate permutations. The code is just perfect to be used in the form of an iterator, and although I was reading the example in Perl (I read it in Higher Order Perl, an amazing book no matter what's your programming language of choice), I thought Lua would be a good candidate for that.

Along the way, I wrote a few utility functions you can see in there. Mostly tests on function composition and mapping over iterators.

Here's the code. If you need to generate permutations, I found this algorithm (which I don't know the name, but let's call it 'odometer counting') very easy to implement and understand. At least easier than Randal's way of doing it.



local inspect = require'inspect'

function map(f, t)
  local r = {}
  if type(t) == 'table' then
    for _, x in ipairs(t) do
      r[#r+1] = f(x)
    end
  else
    for x in t do
      r[#r+1] = f(x)
    end
  end
  return r
end

function count()
  local c = 0
  return function()
    c = c + 1
    return c
  end
end

-- for x in count() do
--   print(x)
--   if x > 10 then break end
-- end

function permutations(...)
  local function inc(t, pos)
    if t[pos][3] == t[pos][2] then
      if pos == 1 then return nil end
      t[pos][3] = 1
      return inc(t, pos-1)
    else
      t[pos][3] = t[pos][3] + 1
      return true
    end

  end

  local sets = {...}
  local state = map(function(x)
                      return {x, #x , 1}
                    end , sets)
  state[#state][3] = 0

  local curr = #state

  return function()
    while true do
      if inc(state, curr) then
        return map(function(s)
                     return s[1][s[3]] end,
                   state)
      else
        return nil
      end
    end
  end
end

function compose(f,g)
  return function (...)
    return f(g(unpack(arg)))
  end
end

pinspect = compose(print, inspect)

map(pinspect, permutations({1,2,3}, {5,6,7}))

local c = 0
for i in permutations({1,2,3,5,6} , {3,4,5,6,7,6}) do
  c = c+1
  if c == 10 then break end
  pinspect(i)
end

miércoles, 5 de marzo de 2014

smart-browser

Since I discovered conkeror, I'm not using w3m that much, because conkeror works great :)

The issue is that doing any kind of web dev in conkeror is suboptimal. Its support for firebug is quite basic. One option is opening different browsers depending on the url. That makes sense, and I used this technique when I was using w3m.

But I wanted to explore a different approach. My problem is the following. Usually I want to open a url in conkeror, but if chromium is already opened, it's probably that I'm using some of the devtools, and I want to keep using it during this 'session'.

What I don't want is to have 2 browsers opened.Unless I open them manually, then, follow the preferences. Although being complex to explain, it just feels right when I use it.

So I hacked some elisp to give priorities to browsers, and use a default one when there's nothing opened.

The idea is quite simple: Just look for the browsers in order of preferences, and open the first one that is already opened. The last one is a hack, to open conkeror by default.

It's an ugly hack, but hopefully you'll learn some elisp API you didn't know :)

Sounds for programmers

Between usual music and abstract music (which I can't get to listen for any long time), I lately discovered some webs that provide generated sounds for as long as you want. Just the fact that they don't have ads is already a big +1 ;)

Pick your favourite :)

jueves, 13 de febrero de 2014

Guix tutorial, using, creating, contributing

GNU Guix is what they call a 'functional package manager'. Think as if git and apt-get had a child. It allows you to do transactional rollbacks or have multiple versions of the same app coexisting. Probably if you're here you already know what's GNU Guix, so I won't bother explaining it again. Visit the official page if you need more info.

To contribute to Guix, you'll have to have a few dependencies installed, and after that, follow a few steps which I'll try to explain in here, as the documentation that's now on the guix site is quite scarce (for newbies at least).

There are a few more steps than in most applications, so I'll put them here. 

- Install guix. Download the git version from git clone git://git.savannah.gnu.org/guix.git. Then,  ./configure && make # make install is optional
- Create users. Follow these instructions to create some build users.
- Create the package store. mkdir /nix/store
- Create ~/.guix-profile. This should be created by guix-deamon itself.
- Put ~/.guix-profile in $PATH.

 

 Basic commands 

 

To run any guix command, you should have the guix server running. When you run guix commands, the client will connect to the daemon, and will run the command itself.

We'll try to install and run a test demo that guix users use as a minimal test. It's a helloworld app.

- Run server.  ./pre-inst-env guix-daemon --build-users-group=guix-builder
- Search package.  ./pre-inst-env scripts/guix package -s hello
- Install package. ./pre-inst-env scripts/guix package -i hello
- Run hello. The hello app should be in your $PATH.
- Remove package. ./pre-inst-env scripts/guix package -r hello

If you installed Guix system-wide (make install), ./pre-inst-env is not needed.

Guix Recipes


If you're trying to write a recipe for guix, here are the steps to follow, and good practices.

First, let's see what's in the 'hello' recipe, and try to understand it. then, we'll add a few things to make it build something more interesting. The file is in gnu/packages/base.scm, so when we open it we see something like this:

We can see a few interesting lines there. Even if you have no scheme knowledge, you can find out what's going on there.  The name and version of the package in some places, the url (mirror:// means "download from any gnu mirror", but could be just a normal URL), description of the package.

The hash code in the sexp (sha256 (base32   "19qy37gkasc4csb1d3bdiz9snn8mir2p3aj0jgzmfv0r2hi7mfzc")) is a checksum of the downloaded file. You can get that number using

./pre-inst-env scripts/guix download URL or
./pre-inst-env scripts/guix hash FILE.

 

 Example Recipe


As an example, we'll build a relatively simple package, luajit.

In guix, recipes are organized in files, but not necessarily one recipe per file.  When I wrote the luajit recipe, lua.scm already existed, so it made sense to put it in the same file.  If we add a new file, we should add the file in the file gnu-system.am .

Although having different presets for different build systems, many packages need some special tweaking.

here we added PREFIX variable in make phase, and we removed configure phase and test.

Guix installations happen in phases, usng alist-delete we can remove one of them.

We can try the build by using ./pre-inst-env scripts/guix build luajit.  If everything is ok, we can submit the patch.

 

 Sending the patch


If the recipe built correctly, and you can install the package, that's the time for sending the recipe.

Make a commit with the recipe. The commit message should start with 'gnu:', and follow the GNU commit guidelines.

$ git format-patch -1 HEAD #will make a patch for the latest commit.

Send the patch to the mail list.

 

Addendum: Comunity


The community is also important in Free software projects. And this one is really nice. It's small but very helpful. If you have questions, don't hesitate asking in #guix on freenode or in the guix mail list.  Here's an example of a recent conversation I had with Ludovic (the main author of the project)
Neat, no? :)