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+C
)q
,按回车
- 通过击打
Ctrl+C
,Ctrl+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-iex
IEx 提供选项来加载另一个文件。参阅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)
设置断点module
,function
和arity
与给定的数目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/1
与IEx.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
并传递--trace
到mix 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
并传递--trace
到mix test
以避免运行到超时:
iex -S mix test --trace
iex -S mix test path/to/file:line --trace
started?()
IEx开始时返回true
。
width()
获取打印的IEx宽度。
由助手使用,它的默认最大上限为80个字符。