Thursday, February 23, 2023

Emacs: Too many open files

Source: Gotcha: Emacs on Mac OS: Too Many Files Open
Got this error while trying to save a file in Emacs lately. Seems to be related to lsp-mode, which I'm using with Elixir.
Solution:
M-x file-notify-rm-all-watches

Before:
❯ ps auxww|grep Emacs
jerome            1697   0.0  1.0 37216772 162408   ??  S    16Feb23  21:04.84 /Applications/Emacs.app/Contents/MacOS/Emacs
❯ lsof -p 1697 | wc -l
    1640

After:
❯ lsof -p 1697 | wc -l
    664

Tuesday, May 17, 2022

macOS: follow mouse focus on all windows

Use this gem: yabai.
If you just want the follow focus behavior, you don't even need to disable System Integrity Protection. Just use:
> vi ~/.yabairc
yabai -m config focus_follows_mouse autofocus
And then
> chmod +x ~/.yabairc
> brew services start yabai

macOS: how to move or delete backward in iTerm2

Source: With iTerm2 on Mac, how to delete forward a word from cursor on command-line?

Friday, March 18, 2022

Elixir: Emacs lsp-mode: Unchecked dependencies for environment test

Source: https://github.com/elixir-lsp/vscode-elixir-ls/issues/132#issuecomment-743332723
Sometimes, the lsp-mode of Emacs remains stubbornly stuck on an error like:
MIX_ENV: test
MIX_TARGET: host
Unchecked dependencies for environment test:
* decimal (Hex package)
  the dependency does not match the requirement "~> 1.0", got "2.0.0"

18:56:16.378 [error] Process #PID<0.122.0> raised an exception
** (Mix.Error) Can't continue due to errors on dependencies
    (mix 1.13.1) lib/mix.ex:515: Mix.raise/2
    (mix 1.13.1) lib/mix/tasks/deps.loadpaths.ex:34: Mix.Tasks.Deps.Loadpaths.run/1
    (mix 1.13.1) lib/mix/task.ex:397: anonymous fn/3 in Mix.Task.run_task/3
    (mix 1.13.1) lib/mix/tasks/loadpaths.ex:40: Mix.Tasks.Loadpaths.run/1
    (mix 1.13.1) lib/mix/task.ex:397: anonymous fn/3 in Mix.Task.run_task/3
    (mix 1.13.1) lib/mix/tasks/compile.ex:123: Mix.Tasks.Compile.run/1
    (mix 1.13.1) lib/mix/task.ex:397: anonymous fn/3 in Mix.Task.run_task/3
    (language_server 0.8.2) lib/language_server/build.ex:200: ElixirLS.LanguageServer.Build.compile/0

In order to get out of this situation, do
> rm -rf .elixir_ls/build

Tuesday, March 8, 2022

Elixir: lsp-mode: No mixfile found in project. To use a subdirectory, set `elixirLS.projectDir` in your settings.

I'm using a mono-repo on GitHub, and this is the error message I get in Emacs/*lsp-log* buffer when adding a new sub-directory in the repo.
In order to fix that, you can update ~/.emacs.d/.lsp-session-v1 to manually add the sub-directory.
> vi ~/.emacs.d/.lsp-session-v1

#s(lsp-session ("/Users/jerome/src/repo" "/Users/jerome/src/boss/sub-directory...

And then bounce Emacs.
Source: https://github.com/elixir-lsp/elixir-ls/issues/364

Wednesday, December 22, 2021

Elixir: clean deps

Source: How to remove unused deps from mix.lock
This removes the unused files, as well as cleans mix.lock.
> mix deps.clean --unused --unlock

Tuesday, December 21, 2021

Elixir: rename_keys

Elixir equivalent of Clojure rename_keys()
  @doc """
  Returns the map with the keys in kmap renamed to the values in kmap.
  """
  def rename_keys(map, kmap) when is_map(map) and is_map(kmap) do
    for {key, value} <- map,
        into: %{},
        do: if(new_key = Map.get(kmap, key), do: {new_key, value}, else: {key, value})
  end

Elixir: if key exists: update, otherwise: assoc

Remember Clojure: if key exists: update, otherwise: assoc? Let's do that with Elixir.
  @doc """
  If `key` exists in `map`, updates its value (assumed to be a list) by concatenating `value`.
  If `key` does not exist in `map`, creates `{key => [value]}` in `map`.
  ## Examples

    iex(35)> Tap.Worker.update_conj!(%{a: [1]}, :a, 2)
    %{a: [1, 2]}

    iex(36)> Tap.Worker.update_conj!(%{a: [1]}, :b, 2)
    %{a: [1], b: [2]}

  """
  @spec update_conj!(map, any, any) :: map
  def update_conj!(map, key, value) when is_map(map) do
    Map.update(map, key, [value], fn
      existing_values when is_list(existing_values) ->
        existing_values ++ [value]

      existing_value ->
        raise(ArgumentError, "Value is not a list: #{inspect(existing_value)}")
    end)
  end

Elixir: map to struct

Courtesy of Jose Valim: (https://groups.google.com/forum/#!msg/elixir-lang-talk/6geXOLUeIpI/L9einu4EEAAJ).
  def to_struct(kind, attrs) do
    struct = struct(kind)

    Logger.debug("attrs = #{inspect(attrs)}")

    Enum.reduce(Map.to_list(struct), struct, fn {k, _}, acc ->
      case Map.fetch(attrs, k) do
        {:ok, v} -> %{acc | k => v}
        :error -> acc
      end
    end)
  end

Tuesday, November 16, 2021

macOS: Docker volumes and Minikube

This morning I decided to replace Docker Desktop on my mac with the Hyperkit + Minikube combo like explained in Run Docker without Docker Desktop on macOS.

Volumes

However, some file mounted through a volume in docker-compose invariably resulted in a directory being created in the container instead of a file.
docker-compose.yaml

version: "3.8"
services:
  postgres:
    container_name: oss-postgres
    image: postgres:14-alpine
    stdin_open: true
    tty: true
    restart: always
    ports:
      - 5432:5432
    volumes:
      - ./postgres/postgres.sh:/docker-entrypoint-initdb.d/postgres.sh
    environment:
      POSTGRES_PASSWORD: "xxx"
logs
oss-postgres  | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/postgres.sh
oss-postgres  | /usr/local/bin/docker-entrypoint.sh: line 169: /docker-entrypoint-initdb.d/postgres.sh: Is a directory
oss-postgres exited with code 126
It appears that the volumes need being created in the Minikube VM beforehand (source: Replace Docker Desktop with Minikube and Hyperkit on macOS), like in:
> minikube stop
> minikube start --mount --mount-string="/Users/jerome/src/boss/:/Users/jerome/src/boss/" --memory 4096 --cpus 4

Ports

Any service previously reachable through localhost by port forwarding is now available by using docker.dev, mapped to minikube ip in /etc/hosts. 

NOTE

Never use .local domain on macOS, or DNS resolving will become awfully slow: use for ex. docker.dev instead of docker.local for the hostname of the minikube ip, contrary to what the 1st article proposes.

Wednesday, September 15, 2021

Elixir: convert map to keywords list

iex(20)> Enum.reduce(%{"code" => 33, "kind" => 2, "servid" => 13}, [], fn {k, v}, acc -> acc ++ [{String.to_atom(k), v}] end)
[code: 33, kind: 2, servid: 13]
or
iex(23)> for {k, v} <- %{"code" => 33, "kind" => 2, "servid" => 13}, do: {String.to_atom(k), v}
[code: 33, kind: 2, servid: 13]

Tuesday, September 7, 2021

elixir-ls: /usr/local/bin/elixir: line 231: exec: erl: not found

Source: Elixir on Emacs: exec erl not found
If after installing elixir-ls in emacs, you get this error reported in *elixir-ls::stderr* buffer, then install exec-path-from-shell by using M-x package-list-packages.

Thursday, March 4, 2021

PostgreSQL: Get a column value corresponding to the min of another column

Purpose: Get a column value corresponding to the min of another column (i.e. both values must belong to the same row)
E.g. Let's say we have columns a,b,c,b. We want a,b matching min(c) while partitioning by d.
 

crmmbqt=# create table demo (a int, b int, c int, d int);

 

crmmbqt=# insert into demo (a, b, c, d) values (1,2,1,1), (2,1,3,1), (3,4,5,2), (4,3,4,2);

INSERT 0 4

Time: 6.106 ms

crmmbqt=# select * from demo;

┌───┬───┬───┬───┐

│ a │ b │ c │ d │

├───┼───┼───┼───┤

│ 1 │ 2 │ 1 │ 1 │

│ 2 │ 1 │ 3 │ 1 │

│ 3 │ 4 │ 5 │ 2 │

│ 4 │ 3 │ 4 │ 2 │

└───┴───┴───┴───┘

(4 rows)


crmmbqt=# select first_value(a) over (partition by d order by c) as a, first_value(b) over (partition by d order by c) as b, c, d from demo;

┌───┬───┬───┬───┐

│ a │ b │ c │ d │

├───┼───┼───┼───┤

│ 1 │ 2 │ 1 │ 1 │

│ 1 │ 2 │ 3 │ 1 │

│ 4 │ 3 │ 4 │ 2 │

│ 4 │ 3 │ 5 │ 2 │

└───┴───┴───┴───┘

(4 rows)


NB: The use of first_value() is really important here.
For example, if you want to get max(c) instead of min(c), do not use last_value(a) but instead:
first_value(a) over (partition by d order by c desc)

crmmbqt=# select min(a) as a, min(b) as b, min(c), d from (select first_value(a) over (partition by d order by c) as a, first_value(b) over (partition by d order by c) as b, c, d from demo) as foo group by d;

┌───┬───┬─────┬───┐

│ a │ b │ min │ d │

├───┼───┼─────┼───┤

│ 1 │ 2 │ 1   │ 1 │

│ 4 │ 3 │ 4   │ 2 │

└───┴───┴─────┴───┘

(2 rows)


Monday, January 18, 2021

Git: Moving files to a new repository while preserving history

> git --version
git version 2.18.0
This method did not work for me: Move files from one repository to another, preserving git history
But this one did the trick: Moving Files and Directories to a New Repository in Git

Here is the list of commands used in order to extract the contents of the perl/ directory from the connectmv repo. into the ss-sms-vas repo.:
> mkdir cloneA
> cd cloneA/
> git clone git@github.com:<MY_TEAM>/connectmv.git
> cd connectmv/
> git subtree split --prefix perl/ --branch my-subtree
> git checkout my-subtree
> git remote add repoA git@github.com::<MY_TEAM>/ss-sms-vas.git
> git pull repoA main --allow-unrelated-histories

> git push -u repoA my-subtree:main
> cd ../../
> rm -rf cloneA/

> cd ss-sms-vas/
> git pull
> git lol lib/MBQT/mod_perl/AbstractVas.pm 
* 72be224f (Thu Jan 7 18:32:47 2021 Jerome G) PLTBUGS-8700: exploded USSD CDR per process
* 680a9ff2 (Thu Jan 7 13:51:45 2021 Jerome G) PLTBUGS-8700: removed unlock
...

Friday, December 11, 2020

postgreSQL: see trigger dependencies of an extension

Source: How to select functions that belong in a given extension in PostgreSQL?
The StackExchange question shows this is the request to use:
SELECT e.extname, ne.nspname AS extschema, p.proname, np.nspname AS proschema
FROM pg_catalog.pg_extension AS e
    INNER JOIN pg_catalog.pg_depend AS d ON (d.refobjid = e.oid)
    INNER JOIN pg_catalog.pg_proc AS p ON (p.oid = d.objid)
    INNER JOIN pg_catalog.pg_namespace AS ne ON (ne.oid = e.extnamespace)
    INNER JOIN pg_catalog.pg_namespace AS np ON (np.oid = p.pronamespace)
WHERE d.deptype = 'e'
ORDER BY 1, 3
which led me to use
SELECT e.extname, t.tgname
FROM pg_catalog.pg_extension AS e
JOIN pg_catalog.pg_depend AS d ON (d.refobjid = e.oid)
JOIN pg_catalog.pg_trigger AS t ON (t.tgfoid = d.objid)
where e.extname = 'mbqt_shared_api'

┌─────────────────┬─────────────────────────────────────┐
│     extname     │               tgname                │
├─────────────────┼─────────────────────────────────────┤
│ mbqt_shared_api │ dt_dialdigit_after_ins_trg          │
│ mbqt_shared_api │ dt_imsi_range_before_ins_or_upd_trg │
│ mbqt_shared_api │ dt_rzgthlr_after_ins_trg            │
│ mbqt_shared_api │ dt_rzgthlr_before_del_trg           │
│ mbqt_shared_api │ dt_rzgthlr_after_upd_trg            │
│ mbqt_shared_api │ dt_dialdigit_after_upd_trg          │
│ mbqt_shared_api │ dt_tadig_after_ins_trg              │
│ mbqt_shared_api │ dt_mccmnc_after_ins_trg             │
└─────────────────┴─────────────────────────────────────┘

Monday, November 23, 2020

macOS: Brew emacs 27.1 keeps crashing on Big Sur 11.0.1

[Edit] Updated way to compile emacs on macOS 12: https://github.com/jimeh/build-emacs-for-macos

Version: macOS v11.0.1
Constant crashes of Emacs v27.1 installed from Brew for no reason.
As a workaround, let's compile the latest version locally (bleeding edge).
source: Transitioning to GUI'd Emacs on macOS
$ git clone https://git.savannah.gnu.org/git/emacs.git
$ cd emacs
Check out the native compilation branch.
$ git checkout feature/native-comp
Let's make it.
$ export LIBXML2_CFLAGS="-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libxml2"
$ ./autogen.sh
$ ./configure --without-makeinfo
$ make
$ make install
Then, replace the Brew version.
$ brew cask remove emacs
$ mv nextstep/Emacs.app/ /Applications/

Tuesday, November 10, 2020

jq: keep array values

 [jerome@jeroboam] > echo '["foo", "bar", "Baz"]' | jq '.[] | select(test("b"; "i"))'

"bar"

"Baz"


Wednesday, November 4, 2020

Clojure: destructuring map without naming key

Source: Destructuring map of map with unknown keys
user> (let [[[k {:keys [pim pam]}]] (seq {:basic {:pim 2 :pam 3}})] [k pim pam])
[:basic 2 3]
But no need of seq if we iterate with for.
user> (into {} (for [[k {:keys [pim pam]}] {:basic {:pim 2 :pam 3} :simple {:pim 20 :pam 30}}] [k {:pam pim :pim pam}]))
{:basic {:pam 2, :pim 3}, :simple {:pam 20, :pim 30}}

Friday, September 4, 2020

MacOS: unzip failure: need PK compat. v5.1 (can do v4.5)

 [jerome@jeroboam] > unzip CONNECTSA-565.zip 

Archive:  CONNECTSA-565.zip

   skipping: MBQT01186.OUT           need PK compat. v5.1 (can do v4.5)

   skipping: MBQT01191.OUT           need PK compat. v5.1 (can do v4.5)

   skipping: MBQT01197.OUT           need PK compat. v5.1 (can do v4.5)


[jerome@jeroboam] > brew install p7zip

[jerome@jeroboam] > 7za x CONNECTSA-565.zip