繁体   English   中英

如何在 Linux 上将输入通过管道传输到 sublimetext?

[英]How to pipe input to sublimetext on linux?

如何从标准输入接收文本到 sublimetext 编辑器? 使用 vim 它的工作方式如下:

echo "potato potato potato" | vim -

同样的事情也适用于 gedit,创建一个包含内容的新文档。

Sublimetext 似乎刚刚开始在新选项卡中编辑一个名为“-”的文件,还有其他一些可以工作的 shell 技巧吗?

假设 Sublime 仍然不支持打开 STDIN,一个简单的解决方案是将输出转储到一个临时文件中,在 sublime 中打开该文件,然后删除该文件。 假设您在 bin 目录中创建了一个名为tosubl的脚本,如下所示:

#!/bin/bash

TMPDIR=${TMPDIR:-/tmp}  # default to /tmp if TMPDIR isn't set
F=$(mktemp $TMPDIR/tosubl-XXXXXXXX)
cat >| $F  # use >| instead of > if you set noclobber in bash
subl $F
sleep .3  # give subl a little time to open the file
rm -f $F  # file will be deleted as soon as subl closes it

然后你可以通过做这样的事情来使用它:

$ ps | tosubl

但是,如果您的 shell 支持(它可能支持),则更有效和可靠的解决方案是使用Process Substitution 这消除了临时文件。 这是 bash:

tosubl() {
    subl <(cat)
}

echo "foo" | tosubl

我很确定您可以在该函数中以某种方式删除cat的使用,因为它冗余地将位从 stdin 铲到 stdout,但是在这种情况下这样做的语法目前让我无法理解。

我不知道 Sublime Text,但您的问题应该是通用的,因为它适用于任何接受文件名作为参数但拒绝从 stdin 读取的程序。

幸运的是,Bash 允许您将标准输出从一个进程传送到某种临时文件,然后将该文件的名称传递给另一个进程。

man bash

在支持命名管道 (FIFO) 或命名打开文件的 /dev/fd 方法的系统上支持进程替换。 它采用 <(list) 或 >(list) 的形式。 进程列表运行时其输入或输出连接到 FIFO 或 /dev/fd 中的某个文件。 该文件的名称作为扩展的结果作为参数传递给当前命令。 如果使用 >(list) 形式,写入文件将为列表提供输入。 如果使用 <(list) 形式,则应读取作为参数传递的文件以获得 list 的输出。

假设SomeProcess生成您想在编辑器中捕获的输出:

sublimetext <(SomeProcess)

或者:

SomeProcess | sublimetext <(cat)

如果您认为您会经常手动输入它,那么您可能需要将sublimetext <(cat)放入 shell 脚本或别名中。

以防万一你的操作系统不支持进程替换,那么你当然可以自己指定一个临时文件:

SomeProcess > /tmp/myoutput
sublimetext /tmp/myoutput

您可能会发现moreutils 中的vipe很有用。 如果您已设置EDITOR='subl --wait' ,则可以简单地:

echo 'potato potato potato' | vipe

从版本 4 开始,SublimeText 支持从标准输入输入。

从变更日志

构建 4063

命令行: subl -现在可用于从所有平台上的 stdin 读取

更新!只! 在 MacOS 上:从 build 4109 开始

subl 现在可用于编辑标准输入,例如:echo test | 子|

https://stackoverflow.com/a/31035834/2429912 上捎带一点,因为对我来说它做了 90% 但不是全部:

使用临时文件是一种几乎可以与任何编辑器一起使用的方法。 如果编辑器支持等待文件关闭( sublime -w表示 Sublime Text )则更好,您实际上可以即时编辑它,这使其更加通用。 为此,您需要更改提供的脚本 @tylerl - PATH 中名为tosubl脚本:

#!/bin/bash

TMPDIR=${TMPDIR:-/tmp} # default to /tmp if TMPDIR isn't set
F=$(mktemp $TMPDIR/tosubl-XXXXXXXX)
cat >| $F # use >| instead of > if you set noclobber in bash
subl -w $F # waits until the file is closed
cat $F # prints out the contents of the file to stdout
rm -f $F # clean up the file

现在运行echo "hello" | tosubl > local.file echo "hello" | tosubl > local.file将在 Sublime 中打开第一个脚本的输出,一旦你关闭它,将它保存到local.file

如果要显示带有 ANSI 转义序列(例如终端缓冲区)的彩色文本,可以安装ANSIescape包并使用以下命令:

F=$(mktemp); cat > $F; subl $F; subl --command ansi; sleep .5; rm -f $F

好吧,现在是 2020 年,sublime 仍然无法(不会?)从 stdin 读取。 由于我将输入传递给 sublime 的程序,该线程中的所有答案都没有让我满意。

就我而言,我想利用kitty 终端仿真器的“粘贴当前选择进行编程”功能。 当您按下键盘快捷键时,该功能会获取终端中的当前选择并将其通过管道传输到程序中。 出于某种原因, kitty的开发人员决定将选择作为参数传递,而不是通过 stdin。

为了解决这个问题,我编写了一个可以处理这两种情况的小型 C 脚本。 为了运行脚本,您需要安装TCC 您可能想先检查您的回购。 我知道在 debian 上你可以用 apt 安装它: sudo apt install tcc 或者,您可以使用 GCC 编译以下代码,只需删除第一行。

#!/usr/bin/tcc -run

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    uint64_t randVal = 0;
    FILE *fp = fopen("/dev/urandom", "rb");
    fread((char *) &randVal, 8, 1, fp);
    fclose(fp);
    
    char tmpfile[512] = {0};
    sprintf(tmpfile, "/tmp/piped_input_%llu.txt", randVal);
    
    fp = fopen(tmpfile, "wb");
    
    if(!fp)
    {
        fprintf(stderr, "Could not open temporary file: '%s'\n", tmpfile);
        return -1;
    }
    
    if(argc == 2)
        fprintf(fp, "%s", argv[1]);
        
    if(argc == 1)
    {
        uint8_t tmpBuf[4096] = {0};
        memset(tmpBuf, 0, 4096); // Old habit... ¯\_(ツ)_/¯
        
        while(!feof(stdin))
        {
            int32_t numRead = fread((char *) tmpBuf, 1, 4096, stdin);
            
            if(numRead > 0)
                fwrite((char *) tmpBuf, numRead, 1, fp);
            else
                break;
        }
    }
    
    fflush(fp);
    fclose(fp);
    
    char cmdStr[512] = {0};
    sprintf(cmdStr, "subl %s", tmpfile);
    system(cmdStr);
    
    // Give sublime some time to open the file
    usleep(1000 * 250);
    unlink(tmpfile);
    
    return 0;
}

除非将参数传递给程序,否则上述脚本将从 stdin 读取。 在任何一种情况下,它都只是将输入( stdinargv[1] )读入一个临时文件,用 sublime 打开文件,等待 ~250ms 给 sublime 打开文件的时间,然后删除临时文件。

您可以将上述代码复制到路径中的某个位置(如 /usr/local/bin/subl_pipe)。 确保设置权限: chmod 755 /usr/local/bin/subl_pipe

无论如何,我希望这最终对其他人有用...^_^

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM