非常教程

Elixir 1.5参考手册

IEx

IEx

Elixir的交互式shell。

根据您的终端,此处介绍的某些功能将不可用。特别是,如果您收到消息说智能终端无法运行,则此处所述的某些功能将无法使用。

助手

IEx提供了一大堆帮手。可以通过h()在shell中键入或作为IEx.Helpers模块的文档来访问它们。

自动完成

要发现模块的所有可用功能,请输入模块名称后面跟一个点,然后按Tab键以触发自动完成。例如:

Enum.

某些Windows shell可能无法使用此功能。您可能需要--werl在启动IEx时通过此标志,因为iex --werl它可以正常工作。--werl可以通过设置IEX_WITH_WERL环境变量来永久启用。

Shell历史

从Erlang / OTP 20中,可以通过传递一些在VM中启用它的标志来获取shell历史记录。这可以在启动IEx时根据需要完成:

iex --erl "-kernel shell_history enabled"

如果您希望在整个系统上启用它,则可以使用ERL_AFLAGS环境变量,并确保在您的终端/外壳配置中对其进行相应设置。

在Linux上:

export ERL_AFLAGS="-kernel shell_history enabled"

在Windows上:

set ERL_AFLAGS "-kernel shell_history enabled"

IEX中的表达式

作为一个交互式shell,IEX计算表达式。这有一些有趣的结果值得讨论。

第一个是代码是真正的评估和编译。这意味着在shell中完成的任何基准测试都会有偏差的结果。因此,不要在shell中运行任何分析或基准测试。

其次,IEx允许你将表达式分解成许多行,因为这在Elixir中很常见。例如:

iex(1)> "ab
...(1)> c"
"ab\nc"

在上面的例子中,shell会期待更多的输入,直到找到结束报价。有时,shell不知道shell期望的是哪个字符,并且用户可能发现自己陷入了不完整表达的状态,除了通过退出shell之外无法终止它。

对于这种情况,有一个特殊的break-trigger(#iex:break),当它自己在一行上遇到时,会强制shell从任何挂起的表达式中跳出并返回到正常状态:

iex(1)> ["ab
...(1)> c"
...(1)> "
...(1)> ]
...(1)> #iex:break
** (TokenMissingError) iex:1: incomplete expression

中断命令

在IEx内部,点击Ctrl+C将打开BREAK菜单。在这个菜单中,您可以退出shell,查看进程和ets表信息等等。

退出Shell

有几种方法可以退出IEX外壳:

  • 通过键入BREAK菜单(可通过Ctrl+Cq,按回车
  • 通过击打Ctrl+CCtrl+C
  • 打中Ctrl+\

如果您连接到远程shell,它在断开连接后仍保持活动状态。

窥探与断点

IEX还能够在Elixir代码上设置断点,并“撬”正在运行的进程。这允许开发人员在给定函数中运行IEX会话。

IEx.pry/0 可以在您能够直接修改源代码并重新编译时使用:

def my_fun(arg1, arg2) do
  require IEx; IEx.pry
  ... implementation ...
end

代码执行时,它会要求您获得内省的许可。

或者,您可以使用IEx.break!/4在给定模块,函数和arity上设置断点,这些断点是您无法控制的。虽然IEx.break!/4更灵活,但它需要OTP 20+,它不包含源代码中的导入和别名信息。

用户切换命令

除了break命令外,还可以输入Ctrl+G用户切换命令菜单。到达后,您可以输入h以获取更多信息。

在这个菜单中,开发人员可以启动新的shell并在它们之间切换。试一试吧:

User switch command
 --> s 'Elixir.IEx'
 --> c

上面的命令将启动一个新的shell并连接到它。创建一个名为hello并赋予它一些价值:

hello = :world

现在,让我们回到第一个shell:

User switch command
 --> c 1

现在,尝试访问hello变量:

hello
** (UndefinedFunctionError) undefined function hello/0

上面的命令失败了,因为我们切换了shell。由于shell是相互隔离的,所以不能从另一个shell访问在一个shell中定义的变量。

用户开关命令也可用于终止现有会话,例如,当计算程序被困在无限循环中时,或者当您被困在输入表达式时:

User switch command
 --> i
 --> c

用户切换命令菜单还允许开发人员使用r命令。我们接下来要讨论的话题。

远程shell

IEX允许您以两种方式连接到另一个节点。首先,我们只能在给当前shell和要连接的shell都指定名称的情况下才能连接到shell。

我们试试看。首先启动一个新外壳:

$ iex --sname foo
iex(foo@HOST)1>

提示符中括号之间的字符串是节点的名称。我们可以通过调用node/0职能:

iex(foo@HOST)1> node()
:"foo@HOST"
iex(foo@HOST)2> Node.alive?()
true

为了好玩,让我们也在这个shell中定义一个简单的模块:

iex(foo@HOST)3> defmodule Hello do
...(foo@HOST)3>   def world, do: "it works!"
...(foo@HOST)3> end

现在,让我们开始另一个shell,并给它起一个名称:

$ iex --sname bar
iex(bar@HOST)1>

如果我们想派人去Hello.world,它将不可用,因为它只在另一个shell中定义:

iex(bar@HOST)1> Hello.world
** (UndefinedFunctionError) undefined function Hello.world/0

但是,我们可以远程连接到其他shell。打开用户切换提示符(Ctrl + G)并输入:

User switch command
 --> r 'foo@HOST' 'Elixir.IEx'
 --> c

现在我们连接到远程节点,如提示所示,我们可以访问在那里定义的信息和模块:

rem(foo@macbook)1> Hello.world
"it works"

实际上,连接到远程shell非常常见,因此我们还通过命令行提供了一个快捷方式:

$ iex --sname baz --remsh foo@HOST

“remsh”的意思是“远程shell”。一般来说,Elixir支持:

  • 从Elixir节点到Elixir节点的resh
  • 从一个普通的Erlang节点到一个Elixir节点(通过^ G菜单)
  • 从一个Elixir节点remsh到一个简单的Erlang节点(并在erl那里获得一个shell)

支持将Elixir外壳连接到没有Elixir的远程节点。

.iex.exs文件

启动时,IEx会查找本地.iex.exs文件(位于当前工作目录中),然后查找全局文件(位于~/.iex.exs)并加载找到的第一个文件(如果有)。加载.iex.exs文件中的代码在shell的上下文中进行评估。因此,例如,加载的任何模块或.iex.exs文件中绑定的变量在引导后都将在shell中可用。

例如,采取以下.iex.exs文件:

# Load another ".iex.exs" file
import_file "~/.iex.exs"

# Import some module from lib that may not yet have been defined
import_if_available MyApp.Mod

# Print something before the shell starts
IO.puts "hello world"

# Bind a variable that'll be accessible in the shell
value = 13

在上述.iex.exs文件所在的目录中运行IEx 导致:

$ iex
Erlang 19 [...]

hello world
Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> value
13

可以通过向--dot-iexIEx 提供选项来加载另一个文件。参阅iex --help

配置shell

IEx提供了许多自定义选项。IEx.configure/1通过键入来查看该函数的文档h IEx.configure/1

这些选项可以在您的项目配置文件中进行配置,也可以通过IEx.configure/1从您的~/.iex.exs文件调用进行全局配置 例如:

# .iex.exs
IEx.configure(inspect: [limit: 3])

现在运行shell:

$ iex
Erlang 19 [...]

Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [1, 2, 3, 4, 5]
[1, 2, 3, ...]

功能

after_spawn()

已登记的申报表after_spawn回调

after_spawn(fun)

注册一个函数在IEx进程生成后被调用

break!(ast, stops \ 1)

基于宏的快捷方式 IEx.break!/4

break!(module, function, arity, stops \ 1)

用给定的停止次数在模块,功能和参数中设置一个断点

color(color, string)

返回string使用指定的转义color

configuration()

返回IEX配置

configure(options)

配置IEX

inspect_opts()

获取用于检查的选项。

pry()

进入过程环境

started?()

IEx开始时返回true

width()

获取用于打印的IEX宽度。

after_spawn()

返回已注册的after_spawn回调。

after_spawn(fun)

注册在IEX进程生成后要调用的函数。

break!(ast, stops \ 1) (macro)

基于宏的快捷方式IEx.break!/4...

break!(module, function, arity, stops \ 1)

设置断点modulefunctionarity与给定的数目stops...

该函数将对给定的模块进行测试,并在内存中加载一个新版本,在给定的功能和属性处设置断点。如果重新编译该模块,则所有断点都将丢失。

当达到断点时,IEx会询问你是否想要给pry定的功能和参数。换句话说,这与IEx.pry/0运行过程成为IEx命令的评估者相似,并且暂时更改为具有自定义组领导。但是,IEx.pry/0与源代码中的别名和导入不同,在shell中将不可用。

IEX助手包括许多与断点相关的便利设施。下面列出了完整的模块,如IEx.Helpers.breaks/0,但请记住,它可以直接调用为breaks()在IEX里面。它们是:

  • IEx.Helpers.break!/2-为给定的Mod.fun/arity
  • IEx.Helpers.break!/4-为给定的模块、功能、属性设置断点
  • IEx.Helpers.breaks/0-打印所有断点及其ID
  • IEx.Helpers.continue/0-持续到同一Shell中的下一个断点
  • IEx.Helpers.open/0-打开当前断点上的编辑器
  • IEx.Helpers.remove_breaks/0-删除所有模块中的所有断点
  • IEx.Helpers.remove_breaks/1-删除给定模块中的所有断点
  • IEx.Helpers.reset_break/1-将给定id上的停止数设置为零
  • IEx.Helpers.reset_break/3-将给定模块、函数、属性上的停止数设置为零
  • IEx.Helpers.respawn/0 - 启动一个新的shell(断点将再次请求许可)
  • IEx.Helpers.whereami/1-显示当前位置

默认情况下,断点中的停止数为1。除非设置了另一个断点,否则任何后续调用都不会停止代码的执行。

或者,通过传递stops参数来增加数量。IEx.Helpers.reset_break/1IEx.Helpers.reset_break/3可以用来重置数回零。请注意,即使在所有断点的所有停止都消耗完毕后,模块仍保持“检测状态”。您可以通过调用IEx.Helpers.remove_breaks/1和调用所有模块来移除给定模块中的检测IEx.Helpers.remove_breaks/0

要退出断点,开发人员可以调用continue(),它将阻塞shell,直到找到下一个断点或进程终止或调用为止。respawn(),它启动了一个新的IEXShell,释放了一个撬开的Shell。

此功能只适用于Elixir代码,需要OTP 20+。

实例

下面设置一个断点URI.decode_query/2*

IEx.break!(URI, :decode_query, 2)

此调用将设置一个断点,该断点只停止一次。若要设置将停止10次的断点,请执行以下操作:

IEx.break!(URI, :decode_query, 2, 10)

IEx.break!/2是一个方便的宏,它允许在Mod.fun/arity格式:

require IEx
IEx.break!(URI.decode_query/2)

或者设置一个将停止10次的断点:

IEx.break!(URI.decode_query/2, 10)

此函数返回断点ID,如果设置断点时出错,则会引发。

休息和混合测试

要使用IEx.break!/4在测试过程中,你需要运行里面混合iex并传递--tracemix test以避免运行到超时:

iex -S mix test --trace
iex -S mix test path/to/file:line --trace

color(color, string)

使用指定的转义color返回string

string没有以任何方式处理ANSI转义。

configuration()

返回IEX配置。

configure(options)

配置IEX。

所支持的备选方案如下:

  • :colors
  • :inspect
  • :width
  • :history_size
  • :default_prompt
  • :alive_prompt

下文各节将分别讨论这些问题。

颜色

封装shell使用的所有颜色设置的关键字列表。有关IO.ANSI模块,用于所支持的颜色和属性列表。

关键字列表中支持的键列表:

  • :enabled-布尔值,允许打开和关闭着色
  • :eval_result-表达式结果值的颜色
  • :eval_info-...各种信息信息
  • :eval_error-…错误信息
  • :stack_info---堆栈的颜色
  • :blame_diff - ...当没有匹配时指责来源
  • :ls_directory - ...用于目录条目(ls helper)
  • :ls_device - ...设备条目(ls helper)

在打印文档时,IEX也会将Markdown文档转换为ANSI。为此,可以通过以下方式配置颜色:

  • :doc_code - 代码块的属性(青色,明亮)
  • :doc_inline_code - 内联代码(青色)
  • :doc_headings - h1和h2(黄色,亮)
  • :doc_title - 输出的总体标题(反转,黄色,亮)
  • :doc_bold - (明亮)
  • :doc_underline - (下划线)

IEX还将使用:syntax_colors选择。可通过以下方式使其无效:

IEx.configure [colors: [syntax_colors: false]]

但是,您也可以按需要配置语法颜色:

IEx.configure [colors: [syntax_colors: [atom: :red]]]

配置对于大多数内置的数据类型的支持::atom:string:binary:list:number:boolean:nil,等默认为:

[number: :magenta, atom: :cyan, string: :green,
 boolean: :magenta, nil: :magenta]

检查

包含shell在打印表达式计算结果时使用的检查选项的关键字列表。默认格式设置,限制为50个条目。

若要显示所有条目,请将限制配置为:infinity*

IEx.configure [inspect: [limit: :infinity]]

Inspect.Opts选项的完整列表。

宽度

一个整数,指示要在输出中使用的最大列数。默认值为80列。实际输出宽度是此数的最小值,并且是:io.columns这样你就可以将IEX配置成你最大的屏幕大小,并且它应该总是占用你当前终端屏幕的全部宽度。

历史规模

在历史上要保留的表达式数量及其结果。该值是一个整数。当它是否定的,历史是无限的。

提示符

这是一个选项,用于确定等待输入时显示给用户的提示。

该值是一个关键字列表,有两个可能的键表示提示类型:

  • :default_prompt-使用时Node.alive?/0返回false
  • :alive_prompt-使用时Node.alive?/0返回true

提示符字符串中的下列值将被适当替换:

  • %counter-历史索引
  • %prefix - 给出的前缀 IEx.Server
  • %node-本地节点的名称

inspect_opts()

获取用于检查的选项。

pry()(宏)

Pries进入流程环境。

这对于在由特定进程执行时调试特定块代码很有用。该过程成为IEx命令的评估者,并暂时更改为拥有自定义组长。这些值通过调用来恢复IEx.Helpers.respawn/0,这会启动一个新的IEx外壳,释放被撬的Shell。

当进程被激活时,所有的代码都在IEx内部运行,并且可以访问原始代码中的所有导入和别名。但是,代码已经过评估,因此无法访问被撬取模块的私有函数。模块功能仍然需要通过访问Mod.fun(args)

或者,您可以使用IEx.break!/4在给定模块,函数和arity上设置断点,这些断点是您无法控制的。虽然IEx.break!/4更灵活,但它需要OTP 20+,它不包含源代码中的导入和别名信息。

例子

假设您想调查某些特定功能正在发生的情况。通过IEx.pry/1从函数调用,IEx将允许您访问其绑定(变量),验证其词汇信息并访问过程信息。我们来看一个例子:

import Enum, only: [map: 2]


defmodule Adder do
  def add(a, b) do
    c = a + b
    require IEx; IEx.pry
  end
end

调用Adder.add(1, 2)时,您会在shell中收到一条消息来撬动给定的环境。通过允许它,shell将被重置,并且您可以从上面访问所有变量和词法范围:

pry(1)> map([a,b,c],&IO.inspect(&1))
1
2
3

请记住,IEx.pry/1在调用程序进程中运行,在评估周期中阻止调用程序。调用者进程可以通过调用来释放respawn/0,这会启动一个新的IEx评估循环,让这个循环进行:

pry(2)> respawn()
true

Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)

在IEx中设置变量或导入模块不会影响调用者的环境。但是,发送和接收消息会改变进程状态。

撬和混合测试

要使用IEx.pry/0在测试过程中,你需要运行里面混合iex并传递--tracemix test以避免运行到超时:

iex -S mix test --trace
iex -S mix test path/to/file:line --trace

started?()

IEx开始时返回true

width()

获取打印的IEx宽度。

由助手使用,它的默认最大上限为80个字符。

IEx相关

Elixir 1.5

Elixir 基于 Erlang 虚拟机的函数式、面向并行,是一种较好的编程语言。它以 Erlang 为基础,支持分布式、高容错、实时应用程序的开发。

主页 https://elixir-lang.org/
源码 https://github.com/elixir-lang/elixir
版本 1.5
发布版本 1.5.2