DEV Community

Cover image for Customizing IEx: Personalizing Your Elixir Shell Environment
João Paulo Abreu
João Paulo Abreu

Posted on

Customizing IEx: Personalizing Your Elixir Shell Environment

In this article, we'll explore how to customize the Interactive Elixir (IEx) shell to enhance your development workflow. We'll cover everything from basic configuration to advanced customization techniques that can make your IEx sessions more productive and enjoyable.

Note: The examples in this article use Elixir 1.17.3. While most features should work across different versions, some functionality might vary.

Table of Contents

Understanding IEx Configuration

IEx configuration can be set up in multiple ways:

  • Through the .iex.exs file in your home directory (~/.iex.exs)
  • Through a project-specific .iex.exs file
  • Via runtime configuration in your IEx session

The configuration files are loaded in the following order:

  1. User's home directory configuration (~/.iex.exs)
  2. Current directory configuration (./.iex.exs)
  3. Project-specific configuration (if present)

Basic Shell Customization

Let's start with basic shell configurations. Create a .iex.exs file in your home directory:

# Configure IEx basic settings
IEx.configure(
  history_size: 100,
  inspect: [
    limit: 5_000,
    pretty: true,
    width: 80
  ],
  colors: [enabled: true]
)

# Common imports that you use frequently
import Enum, only: [map: 2, reduce: 3]
import String, only: [upcase: 1, downcase: 1]

# Default aliases
alias MyApp.Repo
alias MyApp.User
Enter fullscreen mode Exit fullscreen mode

You can verify if these configurations are working correctly by running the following tests in your IEx session:

# Test history_size configuration
iex(1)> IEx.configuration()[:history_size]
100  # Should return 100

# Test inspect configurations
iex(2)> list = Enum.to_list(1..10_000)
iex(3)> IO.inspect(list, width: 30)  # Compare with your width: 80 setting

# Test Enum imports
iex(4)> map([1, 2, 3], fn x -> x * 2 end)  # Should work without Enum.
[2, 4, 6]
iex(5)> reduce([1, 2, 3], 0, fn x, acc -> x + acc end)
6

# Test String imports
iex(6)> upcase("hello")  # Should work without String.
"HELLO"
iex(7)> downcase("WORLD")
"world"

# Test if colors are enabled
iex(8)> IO.ANSI.enabled?()
true

# Test aliases (will show error if modules don't exist, confirming alias setup)
iex(9)> Repo  # Should show MyApp.Repo module or error if not exists
iex(10)> User # Should show MyApp.User module or error if not exists

# Show complete current configuration
iex(11)> IEx.configuration()
# Displays all current IEx configurations
Enter fullscreen mode Exit fullscreen mode

Configuring the IEx Prompt

Customize your prompt to make it more informative and visually appealing:

# Custom prompt configuration
IEx.configure(
  default_prompt:
    "#{IO.ANSI.green}%prefix#{IO.ANSI.reset}" <>
    "(#{IO.ANSI.cyan}%counter#{IO.ANSI.reset}) >",
  alive_prompt:
    "#{IO.ANSI.green}%prefix#{IO.ANSI.reset}" <>
    "(#{IO.ANSI.cyan}%node#{IO.ANSI.reset}) " <>
    "(#{IO.ANSI.cyan}%counter#{IO.ANSI.reset}) >"
)

# Available prompt variables:
# %counter - command counter
# %prefix  - iex
# %node    - node name (when running distributed)
Enter fullscreen mode Exit fullscreen mode

Creating Custom Helpers

Custom helpers can significantly improve your workflow. Here are some useful examples:

# ~/.iex.exs

defmodule IExHelpers do
  def reload! do
    Mix.Task.reenable("compile.elixir")
    Application.stop(Mix.Project.config()[:app])
    Mix.Task.run("compile.elixir")
    Application.start(Mix.Project.config()[:app])
  end

  def list_app_modules(app) do
    case :application.get_key(app, :modules) do
      {:ok, modules} -> 
        modules 
        |> Enum.sort() 
        |> IO.inspect(pretty: true)
      :undefined -> 
        IO.puts "Application #{app} not found or has no modules"
    end
  end
end

import IExHelpers
Enter fullscreen mode Exit fullscreen mode

You can use these functions in IEx like this:

iex> reload!  # Recompiles and restarts your application for code changes
iex> list_app_modules(:phoenix)  # Lists all available modules in the Phoenix application
Enter fullscreen mode Exit fullscreen mode

Setting Up .iex.exs

Here's a complete example of a .iex.exs configuration file:

# ~/.iex.exs
# Configure IEx basic settings

# Common imports that you use frequently
import Enum, only: [map: 2, reduce: 3]
import String, only: [upcase: 1, downcase: 1]

# Set up aliases
alias MyApp.Repo
alias MyApp.User

# Configure shell appearance
Application.put_env(:elixir, :ansi_enabled, true)

IEx.configure(
  history_size: 100,
  inspect: [
    limit: 5_000,
    pretty: true,
    width: 80
  ],
  colors: [
    syntax_colors: [
      number: :yellow,
      atom: :cyan,
      string: :green,
      boolean: :red,
      nil: :red
    ],
    eval_result: [:green, :bright],
    eval_error: [:red, :bright],
    eval_info: [:blue, :bright]
  ],
  default_prompt:
    "#{IO.ANSI.green()}%prefix#{IO.ANSI.reset()}" <>
      "(#{IO.ANSI.cyan()}%counter#{IO.ANSI.reset()}) >"
)

defmodule IExHelpers do
  def reload! do
    Mix.Task.reenable("compile.elixir")
    Application.stop(Mix.Project.config()[:app])
    Mix.Task.run("compile.elixir")
    Application.start(Mix.Project.config()[:app])
  end

  def list_app_modules(app) do
     case :application.get_key(app, :modules) do
       {:ok, modules} -> 
         modules 
         |> Enum.sort() 
         |> IO.inspect(pretty: true)
       :undefined -> 
         IO.puts("Application #{app} not found or has no modules")
     end
  end
end

# Import helper functions into IEx session scope
import IExHelpers
Enter fullscreen mode Exit fullscreen mode

Color Schemes and Styling

IEx supports ANSI colors for various elements. Here's how to configure them:

# Color configuration
IEx.configure(
  colors: [
    enabled: true,
    syntax_colors: [
      number: :yellow,
      atom: :cyan,
      string: :green,
      boolean: :red,
      nil: :red,
    ],
    ls_directory: :cyan,
    ls_device: :yellow,
    doc_code: :green,
    doc_inline_code: :magenta,
    doc_headings: [:cyan, :underline],
    doc_title: [:cyan, :bright, :underline],
  ]
)
Enter fullscreen mode Exit fullscreen mode

Best Practices

  1. Organization

    • Keep your .iex.exs file organized and well-commented
    • Group related configurations together
    • Document custom helpers
  2. Project-Specific Configuration

    • Use project-level .iex.exs for project-specific settings
    • Keep general configurations in your home directory's .iex.exs
  3. Performance

    • Avoid loading unnecessary modules or making expensive computations
    • Use lazy loading when possible
    • Keep helper functions simple and focused
  4. Maintenance

    • Regularly review and update your configurations
    • Remove unused helpers and aliases
    • Keep configurations in version control

Conclusion

Customizing IEx can significantly improve your Elixir development experience. By properly configuring your shell environment, you can work more efficiently and effectively. Remember that the best configuration is one that suits your specific needs and workflow.

Next Steps

In the upcoming articles, we'll explore:

  • Numbers in Elixir
  • Integer, floats, and mathematical operations

Top comments (4)

Collapse
 
katafrakt profile image
Paweł Świątkowski

Thanks! This was a great inspiration to tune my iex.exs further.

Collapse
 
avdept profile image
Alex Sinelnikov

Will my global ~/.iex.exs gets merged with project specific iex.exs?

Collapse
 
abreujp profile image
João Paulo Abreu

Yes, they get merged in sequence: global config loads first, then project-specific one on top of it.

Collapse
 
lcezermf profile image
Luiz Cezer

Thanks for sharing, very helpful!