zoukankan      html  css  js  c++  java
  • 一个在编程时“玲姐”语音各种称赞你的 IDEA 扩展插件,萝莉音带耳机!IDEA 彩虹屁插件!

    是否听说过程序员鼓励师,不久前出了一款vscode的插件rainbow-fart,可以在写代码的时候,匹配到特定关键词就疯狂的拍你马屁。

    vscode的下载尝试过,但是作为日常将IDEA作为主力生产工具的同学来说,如何体验呢? 于是假期花了一点时间,写了一个idea版本的插件idea-rainbow-fart。

    安装方法

    先到下载最新的插件。关注公众号Java精选,扫描下方二维码,回复彩虹屁,即可获取下载文件。直接放到对应目录即可应用,试一试被疯狂拍你马屁的插件吧!!!

    qrcode.jpg

    image.png

    下载rainbow-fart-1.0-SNAPSHOT.zip,然后打开Idea的插件目录,比如笔者的目录是C:Program FilesJetBrainsIntelliJ IDEA 2018.2.4plugins

    将rainbow-fart-1.0-SNAPSHOT.zip解压到plugins目录,如图所示:

    image.png

    解压

    然后重启IDEA即可。

    使用内置语音包

    打开设置:

    将voice package type设置为builtin

    可以选择内置语音包,共三个,一个官方的中文和英文,一个tts合成的(玲姐姐)

    image.png

    使用第三方语音包

    image.png

    将voice package type设置为custom

    可以到 https://github.com/topics/vscode-rainbow-fart 查找语音包。

    点击确定生效。

    使用TTS(推荐)

    本插件特色功能,支持自定义关键词和文本,鼠标点击表格可以修改关键词和回复语,修改时enter回车换行,一行代表一个

    image.png

    TTS 使用科大讯飞提供的流式API。

    原理

    没啥原理,就是一款简单的idea插件,对没写过插件的我来说,需要先看下官方文档,基本上看下面这一篇就OK:

    https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started.html

    读取语音包

    先来看下语音包的设计:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    {
      "name""KugimiyaRie",
      "display-name""KugimiyaRie 钉宫理惠 (Japanese)",
      "avatar""louise.png",
      "avatar-dark""shana.png",
      "version""0.0.1",
      "description""傲娇钉宫,鞭写鞭骂",
      "languages": [
        "javascript"
      ],
      "author""zthxxx",
      "gender""female",
      "locale""jp",
      "contributes": [
        {
          "keywords": [
            "function",
            "=>"
          ],
          "voices": [
            "function_01.mp3",
            "function_02.mp3",
            "function_03.mp3"
          ]
        },
    ...
    ]
    }

    对Java来说,定义两个bean类,解析json即可:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    /**
         * 加载配置
         */
        public static void loadConfig() {
            try {
                //
                FartSettings settings = FartSettings.getInstance();
                if (!settings.isEnable()) {
                    return;
                }
                String json = readVoicePackageJson("manifest.json");
                Gson gson = new Gson();
                Manifest manifest = gson.fromJson(json, Manifest.class);
                // load contributes.json
                if (manifest.getContributes() == null) {
                    String contributesText = readVoicePackageJson("contributes.json");
                    Manifest contributes = gson.fromJson(contributesText, Manifest.class);
                    if (contributes.getContributes() != null) {
                        manifest.setContributes(contributes.getContributes());
                    }
                }
                Context.init(manifest);
            catch (IOException e) {
            }
        }

    监控用户输入

    自定义一个Handler类继承TypedActionHandlerBase即可,需要实现的方法原型是:

    1
    public void execute(@NotNull Editor editor, char charTyped, @NotNull DataContext dataContext)

    chartTyped就是输入的字符,我们可以简单粗暴的将这些组合到一起即可,用一个list缓存,然后将拼接后的字符串匹配关键词。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     private List<String> candidates = new ArrayList<>();
        @Override
        public void execute(@NotNull Editor editor, char charTyped, @NotNull DataContext dataContext) {
            candidates.add(String.valueOf(charTyped));
            String str = StringUtils.join(candidates, "");
            try {
                List<String> voices = Context.getCandidate(str);
                if (!voices.isEmpty()) {
                    Context.play(voices);
                    candidates.clear();
                }
            }catch (Exception e){
                // TODO
                candidates.clear();
            }
            if (this.myOriginalHandler != null) {
                this.myOriginalHandler.execute(editor, charTyped, dataContext);
            }
        }

    匹配关键词更简单,将读取出来的json,放到hashmap中,然后遍历map,如果包含关键词就作为语音候选:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public static List<String> getCandidate(String inputHistory) {
            final List<String> candidate = new ArrayList<>();
            FartSettings settings = FartSettings.getInstance();
            if (!settings.isEnable()) {
                return candidate;
            }
            if (keyword2Voices != null) {
                keyword2Voices.forEach((keyword, voices) -> {
                    if (inputHistory.contains(keyword)) {
                        candidate.addAll(voices);
                    }
                });
            }
            if (candidate.isEmpty()) {
                candidate.addAll(findSpecialKeyword(inputHistory));
            }
            return candidate;
        }

    如果找到候选,就播放。

    播放

    为了防止同时播放多个语音,我们用一个单线程线程池来搞定。播放器使用javazoom.jl.player.Player

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    /**
         * play in a single thread pool
         */
        static ExecutorService playerTheadPool;
    static {
            ThreadFactory playerFactory = new ThreadFactoryBuilder()
                    .setNameFormat("player-pool-%d").build();
            playerTheadPool = new ThreadPoolExecutor(11,
                    0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<>(1024), playerFactory, new ThreadPoolExecutor.AbortPolicy());
        }
    public static void play(List<String> voices) {
            FartSettings settings = FartSettings.getInstance();
            if (!settings.isEnable()) {
                return;
            }
            // play in single thread
            playerTheadPool.submit(() -> {
                String file = voices.get(new Random().nextInt() % voices.size());
                try {
                    InputStream inputStream = null;
                    if (StringUtils.isEmpty(settings.getCustomVoicePackage())) {
                        inputStream = Context.class.getResourceAsStream("/build-in-voice-chinese/" + file);
                    else {
                        File mp3File = Paths.get(settings.getCustomVoicePackage(), file).toFile();
                        if (mp3File.exists()) {
                            try {
                                inputStream = new FileInputStream(mp3File);
                            catch (FileNotFoundException e) {
                            }
                        else {
                            return;
                        }
                    }
                    if (inputStream != null) {
                        Player player = new Player(inputStream);
                        player.play();
                        player.close();
                    }
                catch (JavaLayerException e) {
                }
            });
        }

    开源地址: https://github.com/jadepeng/idea-rainbow-fart,欢迎fork代码,贡献代码。

    插件参考,感谢原作者的贡献

    插件开发参考 https://github.com/izhangzhihao/intellij-rainbow-fart

    语音包和插件icon源于 https://github.com/SaekiRaku/vscode-rainbow-fart

    作者:jqpeng的技术记事本

    来源:https://www.cnblogs.com/xiaoqi/p/idea-rainbow-fart.html


    欢迎扫码关注公众号:“Java精选”(w_z90110),回复关键字领取资料:如Mysql,Hadoop,Dubbo,CAS源码等等,免费领取视频教程、资料文档和项目源码。

    欢迎扫码小程序:“Java精选面试题”,内涵3000+道面试题及6000+道选择题,免费在线刷题,选择题带有答案解析,支持随时随地刷题!

    公众号涵盖:各大流行框架(Mybatis、Spring、Spring Boot等)、大数据技术(Storm、Hadoop、MapReduce、Spark等)、数据库(Mysql、Oracle、NoSQL等)、职业规划、算法与数据结构、面试专题、面试技巧经验、职业规划以及优质开源项目等。

  • 相关阅读:
    nodejs 异步转同步整理
    使用async-utility 转换异步请求为同步
    cube.js schemaVersion npm 包
    开发一个cube.js schemaVersion 包装
    cube.js 多租户参考设计说明
    cube.js 调度&&查询队参考参数
    cube.js 自定义首页显示信息
    cube.js data-blending一些说明
    cube.js 新版本的一些特性
    cube.js TimeoutError: ResourceRequest timed out 问题参考解决方法
  • 原文地址:https://www.cnblogs.com/MrYoodb/p/15247167.html
Copyright © 2011-2022 走看看