miércoles, 21 de agosto de 2019

Taming zoom with ratpoison

If you use a manual tiling window manager (ratpoison), chances are zoom is misbehaving when you want to minimize it.

The minimized window steals the focus and you can't do anything while the window is minimized.

If the window is maximized you have to manually corner it somewhere (at least wasting 25% of your screen).

But! I found a way to use zoom while letting you work while you don't see the screen.

It's a tiny shellscript that pinpoints the Zoom full window, and then relegates it to a 1 pixel window on the top of the screen.  Very simple, but it works wonders for me.

miércoles, 7 de agosto de 2019

the simplest bookmark manager ever

So this is not even a bookmark manager with proper tags or anything.

It's just a stupid combination of shell tricks that compose into a quick memo browser.

I guess I'll keep reinventing program launchers and fuzzy finders till I die (first ratfinder version being from 2006)

jueves, 4 de julio de 2019

postgres indexes

I'm progressively more convinced PostgreSQL is my next "emacs", as in "a tool I'm addicted to and I'm determined to find out everything about it".

I'm starting with some of the internals, and some deep descriptions about its various types of indexes.  Those pages provided me a bunch of hours of reading and knowledge on postgres internals.


Also, this week I read somewhere that postgres was first written in Lisp! I guess it shows when you run EXPLAIN on a query. I just confirmed it for a fact. :)

miércoles, 3 de julio de 2019

who's next?

Queues is a pretty fascinating topic.

- https://www.braze.com/perspectives/article/building-braze-job-queues-resiliency
- https://www.youtube.com/watch?v=1bNOO3xxMc0
- http://www.treewhimsy.com/TECPB/Articles/SevenInsights.pdf
- https://www.johndcook.com/blog/2008/10/21/what-happens-when-you-add-a-new-teller/
- https://clojuresync.com/zach-tellman/?__s=syke5mi2pqufm5d27m7f

lunes, 1 de julio de 2019

What's dat?

I still don't know exactly, but it looks very interesting, in a similar spirit as Scuttlebutt:

- https://www.kickscondor.com/on-dat/
- https://github.com/datprotocol/how-dat-works
- https://dat.foundation/
- https://datprotocol.github.io/how-dat-works/

martes, 4 de junio de 2019

TIU: git merge -Xpatience -Xignore-all-space

For better or worse, I'm becoming an expert on git merges.

Today I got to use (TodayIUsed) the special flags: "git merge -Xpatience -Xignore-all-space  mybranch".  And it makes a difference!

Trying imerge again was a bit of a failure due to one of the two branches behaving very bad (lots of churn in the same lines over and over, so it felt like a rebase).

jueves, 30 de mayo de 2019

jq accessing fields with dashes

Let's say you have a json like {"foo": {"bar-baz": true}}.  Dashes in the keys make it impossible to look for jq '.foo.bar-baz'. you  look around and you read that you should use ["bar-baz"].   the thing is that you have to use that syntax everywhere in your query

solving lnav truncate files

lnav is an awesome tool for browsing logs.  I'm not sure what are most of the people doing with logs.... tail -f? grep?  anyway...

Sometimes log files get suddently truncated, and when you're doing development, you don't want lnav to be always refreshing itself with the current contents of the files.

just using a bit of unix magic, we can log our files with "lnav <(tail -F logs/access.log)". 

domingo, 12 de mayo de 2019

ncdu vs dired-du-mode

ncdu a very nice utility that does what you probably want to do when you do 'du -sh *'  repeatedly in different directories.

ncdu allows for navigating through the directory structure seeing sizes and disk usage percentages of files and subdirectories. Also, has vi-friendly keybindings.

Of course, there's a way to do a very similar thing in emacs, which is using `dired-du-mode`. Take a look at the "c-x c-h" keybind to toggle human friendly numbers, and m-x dired-du-count-size to aggregate the sizes of all marked files.

jueves, 9 de mayo de 2019

preview files/links without changing the focus

I realized today that there's a consistent way (although not very intuitive to me) to peek (preview) a destination of a clickable thing without opening it. 

It's "C-o".  Of course, it is very useful for browsing and exploring purposes.  Just try it in dired, occur, ibuffer, rg, and probably many more.

In most of those modes "o" "opens" a buffer on the destination and gives the focus to it, so I guess "C-o" makes sense, it's just I'm so used to hit RET that I never think of "C-o".

Anyway, I hope you find this one helpful

dashes-to-dashes goes "serverless"

jq is a known tool nowadays, with lots of uses everywhere in the industry. 

Today I just replaced dashes-to-dashes api that is hosted in heroku, (it is a single endpoint that did a json transformation) to a jq script that can live in a github, and travis can be the one that runs and self publishes itself, putting the json in the github page of the repo, so it's fast, statically served, and requires no heroku dinos to keep it running.

If something, I learnt about extracting keys from a hash in jq

viernes, 12 de abril de 2019

emacs 26.2 as a birthday present

Emacs 26.2 has been released in April 12th, matching my 36th birthday, 

Appart from this coincidence, it's the first emacs release that has any code of mine, which makes me extremely happy. I only contributed 2 tiny bugfixes, but nonetheless I'm very happy about it :D

jueves, 11 de abril de 2019

a gentle 1/8 screen popup

Found on https://victorzhou.com/ (which has very good content), and reminded me of those "FREE BEER" banners

miércoles, 10 de abril de 2019

bypass zsh commands in bash

Here's a small trick I came out with, when trying to run some scripts that were thought for zsh in bash.

I use 'noglob' in many places, and sometimes they leak into my bash scripts, or are called from bash somehow.  As bash doesn't know about noglob, usual result is an error.

But! you can use this

cat <<-EOF >~/bin/noglob
#!/usr/bin/env bash

So a bypass file is called in case the command 'noglob' is not catched by the shell.

EDIT: Now I remember why the f I created this.

You know I'm a heavy user of zsh's global aliases. my aliases that contain pipes are always UPPERCASE, because it gives a hint that something strange is happening there, and I also see it entering the realm of pipes. 

The thing is that when pairing with others, if I write that when they are looking, people have no clue what's happening when I type that, and it's pretty unintuitive.  Also, as my zsh and bash share part of the history, if I reach some command that contains one of the magic aliases, I've to manually fix them by expanding by hand.

1st fix: magic expansions

globalias() {
   if [[ $LBUFFER =~ ' [A-Z0-9]+$' ]]; then
     zle _expand_alias
     zle expand-word
   zle self-insert

zle -N globalias

bindkey " " globalias

This expands the previous word if it's an alias, but I only want to expand the ones that are ALL CAPSLOCK. Because I have very nasty aliases I don't want to expand as I go. (This has extra an benefit of allowing expansions of "dynamic aliases", which I'll show in some other post)

With this, I end up with noglobs scattered around my history, and if for some reason I execute those in bash, it'll try to run `noglob http ....`.  Here is where  ~/bin/noglob works fine by just bypassing everything.

jueves, 14 de marzo de 2019

dark mode for slack on mobile

So apparently slack app provides a way for a dark mode.


miércoles, 6 de marzo de 2019

emms ftw

I never got into the Emacs MultiMedia System, but just read that it has support for streaming radios so I gave it a try. And you know what?  It's awesome.  I'm adding all the radios I have in my radios repo.

But you already knew that.

Only a few concepts/commands:
- m-x emms-streams RET
- m-x emms RET
- c-+ + + +
- m-x emms-add-dired RET

Enough to get by and start using it.

martes, 19 de febrero de 2019

FP vs OO talk

Here's a quite balanced talk about FP and OO that fits my view of the two paradigms. Give it a shot if you have 40mins on your commute or something.

jueves, 7 de febrero de 2019

TIL: paste -sd+

Following https://hacker-tools.github.io/ lectures, I found a neat trick I didn't know in the data wrangling chapter:

seq 100 | paste -sd+ | bc -l     # 5050

That's pretty nice.  I already had this usecase solved by an "addup" perl script that I stole years ago from Mark Jason Dominus' utils repo.

As a bonus, it reminds me the very similar trick to generate a regex that matches either of many words. That's part of my git pre-commit hook

Not exactly the same, but it also belongs to "Higher Order Shell"

miércoles, 30 de enero de 2019

inifinite history

This is a very nice hack combo that makes shell history really useful.

Add precmd to log the last command into a given ~/zsh_history.log file that will log EVERY command you ever type in the console. With some context like date, and $cwd.

rghist finds commands from any of you history files, allowing you to find many words in the same line but not necessarily one after the other. But necessarily in the same order.

rghist is 100% mine, and comes without guarantees. The precmd command has been sitting in my .zshrc for years. Not sure where I got it from, but the idea is very nice.

Given that rghist can plow through gzipped files, gzipping the log (with password), could be a nice improvement.

function rghist(){
  local str="$(echo ${(j:.*:)*})"
  rg --no-filename -v rghist ~/.zsh_history.log ~/.zhistory | rg "$str"      

function precmd {
  if [ "$(id -u)" -ne 0 ]; then
    echo "`/bin/date +%Y%m%d.%H%M.%S` `pwd` `history -1`" >> ${FULL_CMD_LOG};

so, rghist will join $*  with '.*', making it seamless to find for many words in the same line. For example, sometimes I wonder: "How was the command to run a bash inside a running docker, was it run? was it exec?", then I just "rghist docker bash" and get a list of examples of commands I've run in the past like that. It's dead easy, it's something like a grep with infinite memory, but having this ever growing scratchpad has immense value to me.

EDIT: rghist above tried to be an improved version from my original one(better color managemen). But it's failing to produce output in some cases (I suspect binary strings in file). Here's the older and more robust way.

function rghist() { 
  local str="$(echo ${(j:.*:)*})"
  rg --no-filename --color always "$str" ~/.zsh_history.log ~/.zhistory |
  rg -v rghist

martes, 22 de enero de 2019

Formatting JSON

Here's something you probably had to do at some point. You have some big json blob and you want to format it nicely.

I had done this in vim and honestly, it comes very very easy.  In vim, if you have a buffer (/tmp/foo.json) you want to reformat, and you have jq, the nicest way I've found is something like:

:r !jq %

This is really hard to beat, and I'm not sure you can be much faster in any other thing.

But I live inside emacs, and I when I have this need, until now, I was selecting the region, then `M-| jq .`  The problem is I always forget about m-|, and it's really annoying to type it anyway.

So I was about to create my elisp function that would reformat my json region, and before coding it, I timidly tried M-x json-form..  and yes, of course, json-reformat-region is already there (you can download it from melpa).  Job done.

Btw, if you use evil, you can also use ':r !jq /tmp/foo.json'.  For some reason, % doesn't work as a substitute for the current buffer-file-name, but at that point, I don't care much. :)

miércoles, 16 de enero de 2019

rubber docker

 Thousand different blogs and people rambling about docker, and whatnot, and years later of its boom, I slowly get the knowledge of wtf is docker and why it might be useful. 

I still think it's super complex and flexible, and that most people do not fully understand the nuances between the different situations you can get at with it.

Here I leave some links that in one way or another have made me "tick" something about docker.
  • https://courses.cognitiveclass.ai/courses/course-v1:IBMDeveloperSkillsNetwork+CO0101EN+v1
  • https://towardsdatascience.com/learn-enough-docker-to-be-useful-b7ba70caeb4b
  • https://dockerbook.com/TheDockerBook_sample.pdf
  • https://blog.sixeyed.com/windows-dockerfile-26/
  • https://medium.com/@nagarwal/lifecycle-of-docker-container-d2da9f85959
  • https://medium.com/the-code-review/docker-run-vs-exec-deep-dive-into-their-differences-19a1041735a3

One of the differences that were somehow harder to grasp was what exactly makes a container different than an image.

As of what I know today, a docker image has its read-only layers. A container that you spawn off this image will have a rw layer on top of that, and will point to the top layer of the image, that's why you can have 2 containers off the same image.

If you want to create an image out of a container (that means, start some image, fuck around manually as much as you want, and then store it to a runnable image), you can use docker commit.

Another option to create an image out of another image is to create a dockerfile and make that dockerfile start FROM the initial image. Then, in the dockerfile you fuck around, and after that you'll have an image where you can spawn off many containers.

The image doesn't have any state. You build it and that's it.  A container, apart from the filesystem itself is a bunch of processes that are running, and a network setting, and mounted volumes.

You can start a container from an image with different network settings, or exposed ports. That belongs to the container dimension.  And containers can be in multitude of states. halt,run,stop,pause,....

Another weird thing is what does it mean to run a command in a container.  If you have a container running, you can use 'docker exec' and you'll run a command inside that container. no new container will be created, and if this command changes some internal state, or creates a file, it will create a file in that already existing container.  If instead, you 'docker run', you should pass an image name, not a container name, and if the command you run is stateless, and just does something to the outer world (run migrations), you can run it either with run or with exec inside an already running container (if you have one)

docker dilema

martes, 15 de enero de 2019

tmux session navigation

https://tmuxcheatsheet.com/ tells us that c-b ) and c-b ( lets us cycle through different "sessions". And I'm afraid that's pretty cool, and in fact I can import that to ratpoison and move through the different workspaces with c-t ) and c-t (.

I guess that's pretty basic tmux, but I found it very nice and I'm already using it to swing between my work session and the "slacks" session (using slack-term)

lunes, 14 de enero de 2019

Postgres compression of jsonb

Postgres supports JSON data since loong time ago, but until jsonb (9.4) all solutions were somewhat limited in features.  Jsonb gives you most of what a document storage engine would give you, but...  what about performance? and space efficiency? Unfortunately I don't have real answers to those questions, but I've started doing some research, and for now, here's a nice takeaway:

First of all you should be aware of "\dt+", which gives us the size of a table and "\d+" which describes a table. The "+" suffix adds more info to the descriptions.

CREATE TABLE foo AS SELECT '{"f":true}'::jsonb FROM generate_series(1,1e6);
CREATE TABLE bar AS SELECT '{"f":true}'::text FROM generate_series(1,1e6);
\dt+ foo;
\dt+ bar;  

We see that the text field takes about half of the size of the jsonb. So if you don't need json features in a field (you're only archiving data that happens to be json), think twice when giving it the jsonb type.

Jsonb is TOAST-able, but will probably be toasted  (and compressed) when it's bigger than a page, so don't count on that if you're jsons are <4kb .="" p="">

  • https://dba.stackexchange.com/questions/161864/do-long-names-for-jsonb-keys-use-more-storage
  • https://stackoverflow.com/questions/23120072/how-to-check-if-toast-is-working-on-a-particular-table-in-postgres
  • https://postgrespro.com/list/thread-id/1849114

So, don't think spacewise it comes for free. If you're concerned about space, there's a big impact on the size of the table.

domingo, 13 de enero de 2019

docker run top & docker exec

Here's how I test docker things:

docker container run -t ubuntu top

Then you have this top window  that shows only a single process.

In a different terminal you can then do things like "docker container exec 123456789abcdef sleep 10", and see it in the top window. It's a stupid thing, but I need instant feedback to solidify my knowledge of what's happening where.

jueves, 10 de enero de 2019

Remapping Keys "Up to Eleven"

Remapping keys on your linux is a "normal" thing to do amongst hardcore vim or emacs users.

The most standard hack is to remap CapsLock to Escape or to Ctrl.

And with emacs' key-chord and key-seq plugins, you can have really fancy combos to do the most obvious save-buffer, m-x, switch-to-buffer...

But I just discovered (via this reddit thread) that there's this "xcape" thing that allows you to bind keys to different keycodes depending on whether a key is pressed and released on its own or it's pressed as a modifier key along with other keys.

Here's how to "Remap left and right shift, when pressed alone, to left and right parens on keyup": xcape -t 250 -e "Shift\_L=parenleft;Shift\_R=parenright" &

That's super cool. And the readme of the project has some hardcore hacks for even more crazy conditional remappings.

As a side note, but kinda related, here's a great recent article about all kinds of glue (and duct tape) for X windows. And here's another awesome post about wizardy linux usages. The guy uses dmenu as an interface to a barebones plumber and gave me an idea to improve on my home made plumber (be smart and let you trim down witn dmenu when there are multiple options)

miércoles, 9 de enero de 2019

docker-compose, multiple yml files and environment variables

Did you know that docker-compose can merge multiple yml files into one? it seems like a very cool way to override configs and have something like a linear composability.

Just for fun, try

And do a few tests using

  • docker-compose -f docker-compose.yml config
  • docker-compose -f docker-compose.yml -f docker-compose-over.yml config
  • FOO=1 docker-compose -f docker-compose.yml config
  • FOO=1 docker-compose -f docker-compose.yml -f docker-compose-over.yml config
  • docker-compose -f docker-compose.yml up
  • docker-compose -f docker-compose.yml -f docker-compose-over.yml up
  • FOO=1 docker-compose -f docker-compose.yml up
  • FOO=1 docker-compose -f docker-compose.yml -f docker-compose-over.yml up

In addition to this, you can use the .env file to add defaults to the variables, and you can take a look at a special .override.yml suffix in https://docs.docker.com/compose/extends/. Plenty of ways to configure, reconfigure, and override variables. The difficult part is to make it understandable at all for the next guy touching your setups.

Also, in your app, you can have defaults for the env variables (docker will set them to empty strings if you don't set a value for them).

Also, remember that "docker-compose run" and "docker-compose exec" accept -e to set environment variables. I still haven't tried all the possibilities with those to see exactly what do they overwrite and what is fixed.