获取光标在命令行中的位置(Elixir)
我想知道是否有一种方法可以捕捉光标的绝对位置 在Elixir的命令行中 我知道我必须使用以下ansi转义序列\033[6n, 执行后:获取光标在命令行中的位置(Elixir),elixir,Elixir,我想知道是否有一种方法可以捕捉光标的绝对位置 在Elixir的命令行中 我知道我必须使用以下ansi转义序列\033[6n, 执行后: echo -en "\033[6n" 打印出我想要的内容,但我不确定如何从Elixir获得命令响应 谢谢!如果您知道系统命令,请使用Elixir执行该命令。我最接近的方法是: ~C(bash -c "echo -en '\033[6n'") |> :os.cmd 但是,它返回的是'\e[6n'而不是光标位置。必须是:os.cmd/1函数中包含转义符号
echo -en "\033[6n"
打印出我想要的内容,但我不确定如何从Elixir获得命令响应
谢谢!如果您知道系统命令,请使用Elixir执行该命令。我最接近的方法是:
~C(bash -c "echo -en '\033[6n'") |> :os.cmd
但是,它返回的是'\e[6n'
而不是光标位置。必须是:os.cmd/1
函数中包含转义符号的内容,不确定
虽然这不是一个完整的答案,但希望它能有所帮助。我知道这是一个奇怪的宏东西,但它可以工作!;)我在研究IO.ANSI.Sequence.home()函数的实现时发现了它 特别感谢一位也是唯一一位 然后简单地打电话:
IO.puts Foo.bar
这一条几乎让我发疯,我不得不挖掘太多无法分辨的线程。我将添加所有与解决方案相关的线程,它们都值得一读
所以首先,我们不能使用System.cmd
,System.cmd是在没有tty的情况下运行的
iex(1)> System.cmd("tty", [])
{"not a tty\n", 1}
我们要做的是需要一个TTY,所以对于同一个TTY,很少有有趣的库
但这对TTY也不起作用
iex(1)> Porcelain.shell("tty")
%Porcelain.Result{err: nil, out: "not a tty\n", status: 1}
然后来到另一个图书馆
这一个似乎与TTY相同
iex(3)> ShellStream.shell("tty") |> Enum.to_list
["/dev/pts/6"]
此TTY与当前终端的TTY相同,这意味着TTY正在传播到子进程
接下来是检查我们是否能得到坐标
iex(8)> ShellStream.shell("echo -en '033[6n'") |> Enum.to_list
[]
所以经过大量的尝试,我想出了一个方法
defmodule CursorPos do
def get_pos do
settings = ShellStream.shell("stty -g") |> Enum.to_list
#ShellStream.shell("stty -echo -echoctl -imaxbel -isig -icanon min 1 time 0")
ShellStream.shell("stty raw -echo")
#settings |> IO.inspect
spawn(fn ->
IO.write "\e[6n"
#ShellStream.shell "echo -en \"\033[6n\" > `tty`"
:timer.sleep(50)
IO.write "\n"
end)
io = IO.stream(:stdio,1)
data = io |> Stream.take_while(&(&1 != "R"))
data|> Enum.join |> IO.inspect
ShellStream.shell("stty #{settings}")
end
def main(args) do
get_pos
end
end
这种类型的作品,但仍然需要你按回车键来阅读stdio
$ ./cursorpos
^[[24;1R
"\e[24;1"
它还改变屏幕坐标以获取它们,这不是我们想要的。但问题是坐标控制字符需要由您的shell而不是子shell处理。我尝试使用
ShellStream.shell("stty -echo -echoctl -imaxbel -isig -icanon min 1 time 0")
不起作用,因为stty
不会影响我们需要获取坐标的父shell
$ EXISTING=$(stty -g);stty -echo -echonl -imaxbel -isig -icanon min 1 time 0; ./cursorpos ; stty $EXISTING
"\e[24;1"
这是因为我们可以更改当前tty的属性。现在您可能需要更深入地挖掘并找到如何从代码内部实现这一点
我已经把我所有的代码都放到下面的Github项目中了
你们也应该看看下面的项目
如果获取光标位置并不重要,那么您可以自己将光标固定到某个位置
参考资料
中介绍了在erlang中获取命令响应的一种方法,但您必须将其转换为Elixir。这与
def bar,do:“\e[6n”
。问题是如何将终端在响应时打印的值转换为变量。def bar,do:“\e[6n”
似乎只有在我的模块:ok
原子和光标位置时才返回字符串(至少在iex中运行时是这样)我猜:var=IO.gets Foo.bar
有了这个def bar
,你也需要做IO.puts Foo.bar
。不幸的是,IO.get无法读取输出。(我刚刚试过,收到了“4;1R\n”
-所以我们就快到了,只需要重新格式化;)不幸的是,是的。今天晚些时候我会检查我们能做些什么。spawn
编写并使其休眠的过程!当然!很好。感谢您查看此过程。如果用户需要按enter键,这是否比只按IO.put(“\e[6n”);IO.get(”)更好
?@Dogbert,不是在我发布的最后一个案例中,$EXISTING=$(stty-g);stty-echo-echonl-imaxbel-isig-icanon最小1次0;/cursorpos;stty$EXISTING“\e[24;1”
。正如您所看到的,这个输出来自我们的检查
$ EXISTING=$(stty -g);stty -echo -echonl -imaxbel -isig -icanon min 1 time 0; ./cursorpos ; stty $EXISTING
"\e[24;1"