• 使用Mac的Applescript定制sublime执行C/C++程序弹出终端



    tags: MacOS Tips Sublime

    写在前面

    最近又开始折腾编辑器了, 当然还是一个历史遗留问题, 我最爱的Sublime还是不能通过终端执行C/C++程序, 或者就是执行完之后直接退出了, 绕了一圈, 从每一个程序中加上system(read);算是一个折中的方案, 但是终归有点麻烦, 采用AppleScript(命令行中使用osascript -e)的方法当然可以, 但是我找了半天也没一个能跑明白… 只能说自己功力不够

    针对Terminal

    下面倒是一个可以通过applescript跑起来的例子, 就是对iTerm不行, 只能对系统默认的终端(Terminal.app)来操作… 还是有点鸡肋的. 这个命令我参考了1, 并做了一些改动.

    # double `-e`
    osascript -e 'tell application "Terminal" to activate' -e 'tell application "Terminal" to do script "/Users/xxx/Desktop/main && read -n && exit"'
    # single `-e`
    osascript -e 'tell application "Terminal" to activate do script "clear && /Users/xxx/Desktop/main && read -n && exit"'
    
    • 1
    • 2
    • 3
    • 4

    稍加配置就可以直接在sublime中运行了, 这里的配置就不详细说了. 其实万变不离其宗, 都是通过修改后缀为.sublime-build的JSON文件实现的编译系统的配置. 下面主要以主流的iTerm为例进行配置.

    针对iTerm

    这里借鉴一位印度开发者的gist2, 这里我修改成直接能运行的配置, 如下:

    {
        "shell_cmd": "g++ $file_name -o ${file_base_name}.out && \"/Users/xxx/Library/Application Support/Sublime Text 3/Packages/User/run-in-iTerm.sh\" ${file_path}/${file_base_name}.out",
        "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
        "working_dir": "${file_path}",
        "selector": "source.c, source.c++, source.cxx, source.cpp",
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其中的run-in-iTerm.sh如下(其实还是Apple脚本):

    #!/bin/bash
    
    ################################################
    # https://stackoverflow.com/questions/32675804/how-do-i-execute-a-command-in-an-iterm-window-from-the-command-line
    # https://www.iterm2.com/documentation-scripting.html
    # Better Examples @ https://gitlab.com/gnachman/iterm2/wikis/Applescript
    ################################################
    
    osascript - "$@" <<EOF
    on run argv
    tell application "iTerm"
        activate
        set new_term to (create window with default profile)
        tell new_term
            tell the current session
                repeat with arg in argv
                   write text arg
                end repeat
            end tell
        end tell
    end tell
    end run
    EOF
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    但是我后来发现, 这个appleScript脚本还是有一些不方便的地方, 就比如每次执行之后都会创建一个新的iTerm窗口, 需要自己关闭, 我需要的是按下enter之后就销毁窗口(这点在vs或者dev-c++上就做得很好).

    于是我又找到另外一种脚本3, 如下:

    #!/bin/bash
    
    osascript - "$@" <<EOF
    on run argv
    tell application "iTerm"
        tell current session of current window
            repeat with arg in argv
                write text arg
            end repeat
      end tell
    end tell
    end run
    EOF
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    上面脚本的意思是通过现有的窗口完成程序的运行, 但是这个也有一个问题, 就是必须要有一个已经打开的iTerm窗口, 否则就会报错说找不到打开的iTerm窗口, 这个还是有点烦, 接着找…

    后来接连看了几篇回答和对应的外链(其实就是gist代码段和iTerm官方给出的代码), 分别是4,5, 发现Applescript已经被iTerm弃用了, 取而代之的是Python-API, 但是配置起来还是比较麻烦(其实就是因为自己没学过async)

    后来几经摸索, 我想出来了一个方案, 就是在前面给出的json的基础上, 设置一些参数, 使得Press ENTER to exit得以实现, 下面是最后的配置, 当然, 这里也参考了sublime的build system的主要配置参数6, 比较简单, 这里我直接贴出来代码了:

    {
        "shell_cmd": "g++ -std=c++20 $file_name -o ${file_base_name}.out && \"/Users/xxx/Library/Application Support/Sublime Text 3/Packages/User/run-in-iTerm.sh\" \"clear && ${file_path}/${file_base_name}.out && read 'word?Press ENTER to exit!' && exit\"",
        "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
        "working_dir": "${file_path}",
        "selector": "source.c, source.c++, source.cxx, source.cpp",
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通过捕获read命令的方式进行配置7, 这里也有一个坑, 就是之前的read -p "xxx"的方式在zsh上面失效了, 就必须采用read "name?what's your name?"的方式进行读取, 一个测试的例子如下:

    read "name?what's your name?"
    what's your name?paul
    ❯ echo $name
    paul
    
    # another format
    ❯ read name\?"what's your name?"
    what's your name?paul
    ❯ echo $name
    paul
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这里当然就是随便选取一个别名即可, 我取的就是Press ENTER to exit!

    这里有一个小插曲, 就是看第一段applescript中的代码, 里面的

    repeat with arg in argv
       write text arg
    end repeat
    
    • 1
    • 2
    • 3

    部分是不是很像Python的for i in range()呢? 其实就是逐参数读取的命令, 这里我设置了一连串的命令, 就是方便其在iTerm中执行:

    \"clear && ${file_path}/${file_base_name}.out && read 'word?Press ENTER to exit!' && exit\"
    
    • 1

    总体效果还是很不错的, 如下:

    aa

    参考


    1. macos - How to use osascript to open the Terminal App in a new window and make sure it’s on the top of all other windows? - Ask Different (stackexchange.com); ↩︎

    2. Sublime Text 3 CPP Basic Setup (on Mac). (github.com); ↩︎

    3. iterm_cmd.sh (github.com); ↩︎

    4. How do I execute a command in an iTerm window from the command line? - Stack Overflow; ↩︎

    5. Scripting - Documentation - iTerm2 - macOS Terminal Replacement; ↩︎

    6. Build Systems — Sublime Text Unofficial Documentation (sublime-text-unofficial-documentation.readthedocs.io); ↩︎

    7. bash - zsh: read:-p: no coprocess error while using read command with -p flag - Ask Ubuntu; ↩︎

  • 相关阅读:
    服务器通常会遭到哪些攻击手段?
    Mysql 45讲学习笔记(十二)MySQL会“抖”一下
    java:JDBC ResultSet结合Spring的TransactionTemplate事务模板的查询方式
    I/O提升50%,长江存储发布PCIe4.0固态硬盘致态TiPlus7100
    Spring IOC容器与 Bean 管理 第4关:根据 Bean 的生命周期修改属性值
    LeetCode第203题—移除链表元素
    Java条件控制语句
    Flink部署
    14:第二章:架构后端项目:10:封装“返回结果”;(也就是定义API统一返回对象)(同时,使用枚举类统一管理错误信息)
    OpenXlab应用部署踩坑记录
  • 原文地址:https://blog.csdn.net/qq_41437512/article/details/126257952