Monday, November 12, 2018

iTerm2 sends commands to all panes

I use iTerm2 in Mac OSX as a replacement for built-in terminal, and it is pretty handy. I like that I can split a single window into multiple panes and run different cmds and observe outputs simultaneously, for example, starting different services and watching the logs. It saves me some time to otherwise align or locate multiple terminal windows constantly. There are of course many other benefits of iTerm2.

Today, I was switching between Chrome and iTerm2 feverishly to test something out, and all the sudden iTerm2 entered into a mode where my typings got sent to all panes instead of just the one I was interacting. This might be a useful feature, but not now. So what's going on and how can I get back?

It turns out this mode is activated via a "⌘Command + ⇧Shift + i" or "Shell -> Broadcast Input -> ... ". You know very well that the same keyboard shortcut in browser is used to bring out the "Developer Tools". So I probably hit this shortcut in the iTerm2 instead of browser by accident. To get back, just hit the same shortcut again, or use the menu.

Ok, back to work ...

Jun

Wednesday, November 7, 2018

Remove unwanted Confluence macro auto conversion

Confluence is widely used as a wiki platform for companies to document their internal knowledge. It also has a large collection of macros to help make the content more interactive, for example, embedding other documents, spreadsheets, videos, lists, tables, status, etc. Sometimes it can even detect your typing and automatically convert things into macros, although it may not be what you always want.

For example, I want to make a link to a Google Presentation in my page, so I pasted in the URL to that presentation, but then Confluence recognizes the URL and automatically convert it into a Google Slide macro and it is now a GIANT block showing the content of the slides, breaking the page layout, and there seems to be no way to stop that auto conversion. Frustrating ...

To workaround, instead of pasting the link directly into the editor, create a link macro by highlighting some text and clicking the "Insert Link" icon in the editor's toolbar, and then you can paste in the URL into the dialog that pops up, this way it will remain a link and not the block showing actual slides.

Enjoy!

Jun

Friday, November 2, 2018

Elixir strings in single quote vs double quote

Today I stumbled on the subtle difference in Elixir between strings in single quote and double quote. Although the documentation explains it clearly, but who reads the documentation these days anyway.

Here is the deal:

  • Single quoted string, is actually a charlist, aka a list of chars. If you want to concatenate them, you need to use list concatenation operator '++'. 
  • 'hello' ++ ' ' ++ 'world' 
  • Double quoted string, is a UTF-8 encoded 'binary', aka a series of bytes. Their concatenation is done via '<>'. 
  • "hello" <> " " <> "world"
  • You can't mix the two
  • "hello" ++ " " ++ "world" # this is wrong
    'hello' ++ " " ++ 'world' # also wrong
    "hello" <> " " ++ 'world' # you just don't get it
  • There are functions to convert
  • to_charlist("hello")
    to_string('hello')

    to_string('hello') <> " world"
    to_charlist("hello") ++ ' world'
  • You may tend to care less about the difference, and just stick to just one type, say always use the double quoted strings. However be aware that some erlang library you end up using unknowingly may use different type and give you cryptic error. For example
    iex> "<h1><a>title</a></h1>" |> SweetXml.xpath(~x"//h1/a/text()")

    'title' 

    Note the return is a charlist even the original input is a string/binary!

Thursday, October 25, 2018

Center Align an Image or other types block content

I need to center an image inside a div, tried
text-align: center; align-content: center; align-items: center; and many variations of such, with no luck.

It turns out I need to use margin-left: auto; margin-right: auto;
to center an image or other block.

Tuesday, September 25, 2018

Quote your ports in Docker compose file

I struggled for quite a while to fix a Docker compose problem. I have this simple config line:


services:
  git:
    ports:
      - 2222:22


But I kept getting an error message when trying to start the instance:


  Cannot create container for service git: invalid port specification: "133342"


What the heck, where did that weird number come from ?!
It turns out YAML 1.1 supports so called "base 60 float" useful for time calculation. So 2222:22 is interpreted as 2222*60+22 which is 133342. ta-dah! It is not a problem if the parts contain numbers bigger than 60, e.g. 3306:3306, or 8080:80, so this problem does not always occur, making it covert.
So quote your ports!


services:
  git:
    ports:
      - "2222:22"

Tuesday, June 12, 2018

GIT cheat sheet

GIT shortcuts $ git config --global alias.co checkout $ git config --global alias.br branch $ git config --global alias.ci commit $ git config --global alias.st status $ git config --global alias.unstage 'reset HEAD --' $ git config --global alias.last 'log -1 HEAD' push a local commit to server $ git push origin master:remote_branch_name check out a remote branch to local and start work on it, and have this local copy 'linked' to the remote branch $ git checkout --track origin/gradle diff a file between two commits $ git diff -w 9655d51..c48be72 -- src/uniflow/plate.java Revert a local uncommited change to its original content as in last commit $ git checkout -- file.java // same as svn revert Undo the last commit (change the files to the previous commit state, and make a new commit) $ git revert HEAD Unstage a file (keep the working file content unchanged, including these unstaged changes) $ git reset file Remove two local commits (last two commits will be removed, don't do this to published commits) $ git reset --hard HEAD~2 $ git reset --hard // obliterates all uncommitted changes. Modify previous commit (e.g. commit additional files) or commit message $ git commit --amend Reset local branch to match exactly the remote branch $ git checkout develop // select the target branch to reset $ git fetch origin $ git reset --hard origin/develop remove untracked files $ git clean -n // dry run, just list files to be removed $ git clean -f // force remove untracked files $ git clean -df // force remove both untracked files and directories Merge multiple local commits into one commit $ git rebase -i origin/master pick 16b5fcc Code in, tests not passing squash c964dea Getting closer squash 06cf8ee Something changed squash 396b4a3 Tests pass squash 9be7fdb Better comments squash 7dba9cb All done Note: change all 'pick' to 'squash' except for the first line in the pop up editor merge multiple commits locally $ git rebase -i merge last two commits $ git rebase -i HEAD~2 Create a new local branch $ git checkout -b experimental_tilde Abort rebase $ git rebase --abort Delete a local branch $ git branch -d experimental_tilde Delete a remote branch $ git branch -d -r origin/brach_name Daily synch from remote master to local feature branch # assume you are on local feature branch # stash the local uncommited changes $ git stash # pull in latest changes from master $ git co master $ git pull # switch to your feature branch $ git co myfeature # rebase the feature branch on top of master, alternatively one could merge (see https://stackoverflow.com/questions/13006135/copy-last-commits-from-master-to-branch) $ git rebase master # reapply your previously saved local changes. $ git stash pop Add feature branch changes to master thru rebase. Simple version, see next for more options $ git checkout feature $ git checkout -b temporary-branch # create temp branch for rebaseing $ git rebase -i master # [Clean up the history] $ git checkout master $ git merge temporary-branch # put the changes back to master. $ git push Rebase feature branch onto master (https://randyfay.com/content/rebase-workflow-git) Assume you have a master branch for shared work, and a personal branch called feature. $ git checkout feature # feature branch to do local work $ # do some local commits on this branch. $ git fetch origin # pull changes from remote $ git rebase -i master # plop our branch changes onto everyone else’s. There might be conflicts, need to resolve and resume the rebase using git rebase --continue # now our branch has the latest ideal code with all the local and remote changes. Need to publish it. We will switch to master and make it the same as our rebased branch. $ git checkout master # switch to master branch # there are a few ways to push changes back to remote 1. $ git rebase feature # now master is fast-forwarded to have feature commits on it 2. $ git merge feature # same effect as option 1 rebase 3. $ git merge --squash feature # squash will merge all branch commits into one onto the master develop branch 4. $ git merge --no-ff feature # explicitly document the merge by adding a merge commit $ git push origin master # push the master change back to the remote Find out number of file changes between two tags, exclude type-change items $ git diff v6.1.0001..v6.1.0003 --name-status --diff-filter=t | wc -l Find the commits between two tags $ git log v6.1.0001..v6.1.0003 --pretty=oneline Move the last commit to a new feature branch # so you have been working on master branch although on a feature, and committed some thing locally, however it really belongs to a feature branch, and needs more work. Here is a way to create that new branch with the commit but back out the commit from the master branch. # assume you are currently on the master branch $ git checkout -b new_branch # make a new branch containing the last commit $ git checkout master $ git reset —hard HEAD~1 # move the master head back one commit, now that commit only lives in the new branch created. $ git checkout new_branch # move to the new branch to continue working on it. Git password free $ cd $ git config credential.helper store $ git fetch

Wednesday, May 30, 2018

Elixir load module file

During debugging Elixir script, one sometimes wants to edit the script file and reload modules defined inside from an Elixir shell. Issue this command from your Elixir shell: iex> import_file("path/to/script_file.exs") Thanks to this blog post!