eMBee is currently certified at Journeyer level.

Name: Martin Bähr
Member since: 2000-05-18 04:08:12
Last Login: 2013-01-01 10:17:48

FOAF RDF Share This

Homepage: http://societyserver.org/mbaehr/


Articles Posted by eMBee

Recent blog entries by eMBee

Syndication: RSS 2.0
19 Sep 2013 (updated 19 Sep 2013 at 07:11 UTC) »

watch for the fish shell

The following command is used to watch the progress of files being updated in a directory.

watch 'du -h *| tail -20 | cut -c -$(($COLUMNS-5))'

cut is used so we don't get linewraps in the output. And we need to subtract 5 from the width because there is a tabstop in there which cut counts as 1 instead of the width of the tabstop (which is 8 minus the width of the size column)

This command works fine as long as files are updated in alphabetical order, but when this is not the case we need to sort files by time.

We need to do something like this instead:

watch 'du -h $(ls -tr)| tail -20 | cut -c -$(($COLUMNS-5))'

Unfortunately this only works if the filenames don't contain spaces.

fish handles spaces in filenames just fine:

du -h (ls -tr)| tail -20 | cut -c -(math $COLUMNS - 5)

So instead of trying to find a solution for dealing with spaces in bash, lets just use a better shell, shall we?

However, watch insists on executing the command with sh -c, so we need to devise our own watch loop for fish instead. That's not really hard:

while true
  du -h (ls -tr) | tail -20 | cut -c -(math $COLUMNS - 5)
  sleep 2

Unfortunately using clear causes an annoying flicker, especially if the du command takes a bit longer.

ANSI escape-sequences help:

while true
  echo \e\[H
  du -h (ls -tr) | tail -20 | cut -c -(math $COLUMNS - 5)
  sleep 2

This causes the cursor to be moved into the top-left corner without clearing the screen. Now we are almost there. Two problems still:
The tab character used to align the columns does not overwrite anything in its space. Likewise at the end of the line, if the newly written line is shorter then the remaining part of the old line is not cleared.

We can fix this with some sed trickery to clear the path:

while true
    echo \e\[H
    du -h (ls -tr) | tail -20 | sed -e 's/^/'\e'\[K/' | cut -c -(math $COLUMNS - 2)
    sleep 2

The ANSI escape sequence ESC[K clears the line just before it is rewritten. This has almost the same effect as clearing the screen, but without the flicker because we only start clearing after du has done its work.
And because the escape sequence adds 3 characters to the output we need to adjust the width accordingly.

At the end we can also add a command to clear the rest of the screen.

Leaves one last issue: $COLUMNS doesn't get updated if the terminal is resized. Granted, it's a nit-pick really, because how often does one resize the terminal. But to make this command generally usable, let's fix this too:

while true
    echo \e\[H
    du -h (ls -tr) | tail -20 | sed -e 's/^/'\e'\[K/' | cut -c -(math (tput cols) - 2)
    echo \e\[0J
    sleep 2

This is now pretty usable, so we'll leave it at that. There is still some room for improvement though. For example currently we are estimating that the size column is at least 2 characters wide so the tabstop adds at most 5 characters worth of space which cut does not count. Should it be less then we would get a linewrap again and if it is more then we get empty space at the end of the line. cut likely also has problems with multibyte unicode characters. This can probably be solved by switching the terminal in a no-wrap mode while the command is running, or finding a replacement for cut that handles these issues.

Syndicated 2013-09-19 05:44:43 (Updated 2013-09-19 07:11:05) from DevLog

basic http file server

I needed to quickly serve some files, and i didn't want to install a full webserver, knowing that this was only temporary. So instead here is a simple http file-server in Pike. I call it a file-server because it serves static files, and nothing else.

Based on this example for a simple web-server, it just takes a few additions to turn this into a file-server:


constant default_port = 8080;
constant my_version = "0.0";

Protocols.HTTP.Server.Port port;

string basedir = "/srv/www";

int main(int argc, array(string) argv)
  int my_port = default_port;
  if(argc>1) my_port=(int)argv[1];

  write("SocServe starting on port %d\n", my_port);

  port = Protocols.HTTP.Server.Port(handle_request, my_port);
  return -1;

void handle_request(Protocols.HTTP.Server.Request request)
  write(sprintf("got request: %O\n", request));

  mapping response = ([]);

  response->server="SocServe " + my_version;

  string target = Stdio.append_path(basedir, request->not_query);
  mixed tstat = file_stat(target);
  write("target: %O\n", tstat);

  if (tstat 
& tstat->isdir)
    response->type = "text/html";
    response->error = 200;
    response->data = dirlist(target);
  else if (tstat 
& tstat->isreg)
    response->type = MIME.ext_to_media_type((target/".")[-1]) || "octet/stream";
    response->error = 200;
    response->file = Stdio.File(target);
    response->type = "text/html";
    response->error = 200;
    response->request = sprintf("%O", mkmapping(indices(request), values(request)));
    response->data = "<h1>SocServe " + my_version + "</h1>n<pre>"
    + response->request + "</pre>n";


string dirlist(string path)
  array dir = get_dir(path);
  return sprintf("%{<a href=\"%s\">%s</a><br>\n%}", ({ dir[*], dir[*] })); 

These are the changes: first combine the request path with our basedir which will reduce any embedded /../ to not go beyond that base. Then we check if it's a directory or a file. For a directory we make a simple listing, and for a file we find the mime-type and then just open the file and pass it to the request. This will cause the file to be served with non-blocking I/O, allowing you to handle multiple requests in parallel without blocking the server while a file is being downloaded.

That's all there is to it. Start it up, and it's ready to serve files.

Syndicated 2013-07-07 17:51:04 from DevLog

6 Mar 2013 (updated 6 Mar 2013 at 06:12 UTC) »

vim tips: capitalize the first word of every sentence

To solve this problem i found this useful solution, but discovered that it didn't cover all cases i had.


To start with, \U does not mean every not-uppercase letter, but every character from the whole set that is not uppercase. So it includes spaces and everything else. This causes the expression to match " hello world!" if the sentence doesn't start at the beginning of the line, which is not quite what we want. To get every non-uppercase (that is lowercase) letter use \l. But even that does not really work, because it means that now it matches "Hello world." as "ello world.", and we get a transformation as "HEllo world!". Again, not what we are looking for. Unfortunately, until someone can suggest a method to skip already capitalized sentences we have to stick to \w.

Next, the expression only excludes periods, but not question-marks, exclamations or other sentence ending characters. We can extend this by simply including the respective characters: [^\.?!:;]. We also do not need to enforce the terminating character, we can simply drop that. What we really want to match is the beginning of the sentence, we don't care about the end.

Also, unless the text is in all uppercase, lower-casing the second group could be counter productive as it would affect upper-cased acronyms etc. that are already there.

Lastly, we want to capture sentences spanning multiple lines, lest every line gets matched as a separate sentence. This is achieved using \_

Putting it all together we get s/\v(\w)(\_[^\.?!:;]*)/\u\1\2/g

Syndicated 2013-03-06 06:09:00 (Updated 2013-03-06 06:12:07) from DevLog

5 Mar 2013 (updated 6 Mar 2013 at 07:12 UTC) »

(moved) vim tips: capitalize the first word of every sentence

this article moved

Syndicated 2013-03-05 09:52:53 (Updated 2013-03-06 07:12:02) from DevLog

javascript frameworks

Since i already found last week that creating views with jquery is not easy i decided to explore alternatives first. Already from early check-ins i received recommendations for angular.js, knockout.js and backbone.js.

Taking this frame work comparison as a guide i excluded backbone.js, and because a friend from the singapore hackerspace had also recommended angular.js i started with that.

Implementation was straight forward. What i really liked was that i didn't have to redo my datastructure that i had made up beforehand, but angular.js allowed me to access and traverse the data in the form that it was available. After some trials i even managed to build that 3 levels deep nested loop. (Iterate over columns, then projects and then task-types)

Then i briefly tried knockout.js but dropped it quickly because it would have caused me to put ko.observable() all over the place. angular.js handles this way better in my opinion. It simply observes the whole dataset and checks for updates.

Other contenders from the above comparison table were ember.js and batman.js. I had a brief look at ember.js and found that similar to knockout it would force me to write a new object-based datastructure, so i dropped the idea. batman.js is written in coffeescript, which is interesting but i want to stick to pure javascript for now, so i'll explore that later.

Syndicated 2012-08-22 15:06:23 from DevLog

8 older entries...


eMBee certified others as follows:

  • eMBee certified loki as Master
  • eMBee certified jtraub as Journeyer
  • eMBee certified miguel as Master
  • eMBee certified alan as Master
  • eMBee certified Telsa as Journeyer
  • eMBee certified riel as Master
  • eMBee certified kojima as Master
  • eMBee certified zab as Journeyer
  • eMBee certified scandal as Master
  • eMBee certified eMBee as Apprentice
  • eMBee certified mhanni as Journeyer
  • eMBee certified id as Journeyer
  • eMBee certified teknix as Journeyer
  • eMBee certified kris as Journeyer
  • eMBee certified octobrx as Journeyer
  • eMBee certified davem as Master
  • eMBee certified BrucePerens as Master
  • eMBee certified quinlan as Journeyer
  • eMBee certified jae as Journeyer
  • eMBee certified jwz as Master
  • eMBee certified xandi as Apprentice
  • eMBee certified Zell as Apprentice
  • eMBee certified wardv as Apprentice
  • eMBee certified mortis as Apprentice
  • eMBee certified kuro5hin as Journeyer
  • eMBee certified andreas as Journeyer
  • eMBee certified graydon as Journeyer
  • eMBee certified js as Journeyer
  • eMBee certified Dauphin as Journeyer
  • eMBee certified jmcastagnetto as Journeyer
  • eMBee certified lucas as Journeyer
  • eMBee certified cbbrowne as Journeyer
  • eMBee certified sparks as Master
  • eMBee certified dnelson as Journeyer

Others have certified eMBee as follows:

  • eMBee certified eMBee as Apprentice
  • jae certified eMBee as Journeyer
  • Zell certified eMBee as Journeyer
  • wardv certified eMBee as Apprentice
  • js certified eMBee as Journeyer
  • jmcastagnetto certified eMBee as Journeyer
  • lucas certified eMBee as Journeyer
  • cbbrowne certified eMBee as Journeyer
  • jLoki certified eMBee as Journeyer
  • dnelson certified eMBee as Journeyer
  • scandal certified eMBee as Journeyer
  • Ohayou certified eMBee as Journeyer
  • Andree certified eMBee as Journeyer
  • chakie certified eMBee as Journeyer
  • hiddenpower certified eMBee as Journeyer
  • rayking71 certified eMBee as Journeyer
  • martinez certified eMBee as Journeyer

[ Certification disabled because you're not logged in. ]

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!

Share this page