【问题标题】:How to interact with an external text editor in C如何在 C 中与外部文本编辑器交互
【发布时间】:2019-05-23 11:34:22
【问题描述】:

我正在用 C(linux 环境)开发一个命令行应用程序来编辑特定的文件格式。此文件格式是一个纯 XML 文件,经过压缩、加密和加密签名。

我想为用户提供一个选项,让他们以一种简单的方式编辑此类文件,而无需手动提取文件、编辑文件、然后压缩、加密和签名。

理想情况下,当调用时,我的应用程序应该执行以下操作:

  1. 打开加密/压缩文件并将其解压缩到一个临时位置(如/tmp
  2. 调用外部文本编辑器,如nanosublime-textgedit,具体取决于安装的内容以及用户偏好。等到用户编辑完文件并关闭文本编辑器。
  3. 读取修改后的临时文件并加密/压缩,替换旧的加密/压缩文件

我怎样才能达到第 1 点。 2?

我想过用system() 调用nano 并等待它返回,或者在临时文件上放置inotify() 以了解图形文本编辑器何时对其进行了修改。

哪种解决方案更好? 如何调用用户的默认文本编辑器? 有什么可以做得更好的方法吗?

【问题讨论】:

  • 你的意思是像gpg -d file -o- | xmlstarlet edit --update 'something' -value 'something' | gpg -ooutput_file?使用$EDITOR 环境变量来查找编辑器。看看systemctl edit ... 是如何工作的。

标签: c linux command-line text-editor


【解决方案1】:

首先,考虑不要自己编写一个实际的应用程序或包装器,它会调用另一个编辑器,而是为一些现有的编辑器编写某种插件,该插件足够灵活以支持其他格式并通过解压缩传递其输入。

当然,这不是唯一的解决方案,但对您来说可能更容易。

通过您的特定方法,您可以:

  • 使用EDITOR and/or VISUAL command-line variables(@KamilCuk 也指出)来确定要使用的编辑器。
  • 将编辑器作为子进程运行,以便您知道它何时结束执行,而不必与它通信。收到文件更改的通知,甚至是打开或关闭文件的通知还不够好,因为编辑器可能会更改多个文件,有些编辑器甚至不会在您处理文件时保持文件打开。
  • 记得处理编辑不上来的情况;或悬挂;或者您收到一些通知以停止等待编辑;等

【讨论】:

    【解决方案2】:

    调用外部文本编辑器,如 nano 或 sublime-text 或 gedit,具体取决于安装的内容以及用户偏好。等到用户编辑完文件并关闭文本编辑器。

    有趣的问题。使用用户的默认编辑器打开 xml 文件的一种方法是使用xdg-open,但它没有提供应用程序的pid,用户将在其中编辑文件。

    你可以使用xdg-mime query default application/xml找到默认编辑器的.desktop文件,但是你必须解析这个文件来找出程序的可执行路径——这正是how xdg-open actually works,在@ 987654323@ function 以Exec= 开头的行只是从*.desktop 中提取出来的,以调用编辑器可执行文件并将目标文件作为参数传递......我想说的是,在你找到编辑器可执行文件之后,你可以启动它,等到它关闭,然后检查文件内容是否已更改。好吧,这看起来像很多不必要的工作......

    改为,您可以尝试使用固定的知名编辑器,例如gedit,以实现所需的工作流程。您还可以为用户提供一种方法(即提示或配置文件)来设置默认的 xml 编辑器,即/usr/bin/sublime_text,然后可以在下次运行时在您的程序中使用。

    然而,关键是在这里打开一个阻止调用进程的编辑器,直到用户关闭编辑器。关闭编辑器后,您可以简单地检查文件是否已更改,如果已更改,则执行进一步的操作。

    如果文件内容被修改过,可以在打开文件之前,通过stat系统调用获取文件的inode change time,然后将时间戳值与当前值进行比较一旦关闭。

    即:

    stat -c %Z filename
    

    输出:1558650334

    总结:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    void execute_command(char* cmd, char* result) {
      FILE *fp;
      fp = popen(cmd, "r");
      fscanf (fp, "%s" , result);
    }
    
    int get_changetime(char* filename) {
      char cmd[4096];
      char output[10];
      sprintf(cmd, "stat -c %%Z %s", filename);
      execute_command(cmd, output);
      return atoi(output);
    }
    
    int main() {
      char cmd[4096];
      char* filename = "path/to/xml-file.xml";
    
      uint ctime = get_changetime(filename);
    
      sprintf(cmd, "gedit %s", filename);
      execute_command(cmd, NULL);
    
      if (ctime != get_changetime(filename)) {
          printf("file modified!");
          // do your work here...
      }
    
      return 0;
    }
    
    

    【讨论】:

      猜你喜欢
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      相关资源
      最近更新 更多