本文为稀土技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!

大家好,本系列第四篇为 Alfred 篇,介绍如安在 Cheetah for Alfred 1.0 的基础上引进前面完结开发的中心模块。

Cheetah for Alfred 1.0 版本是 Cheetah 的开山之作,经过身边朋友测试运用后,修正了许多问题,比方某些情况下查找项目时报错未处理导致项目查找不完全,无法查找 git submodule 等等,这些都抽离到了中心模块中,让 Cheetah 在不同平台下能够复用,1.0 版本的开发进程能够检查作者发布在团队账号上的文章《提效80%的Git 项目发动东西开发思路》。

已然有了中心模块,也需求回过头来好好升级一下 Cheerah for Alfred 1.5 版本了~

本文仅论述与 1.0 版本有差别的当地,少水一点 。

项目装备

引进中心模块

1.51.0 最大的区别就是引进了之前抽离的中心模块,替换掉 1.0 代码中与中心模块重合的逻辑。

npm install cheetah-core
# or
yarn add cheetah-core

将中心模块添加到依赖今后,就能够直接调用了。

types

不只中心模块内有运用 txiki.jsAPI,Alfred 项目内也有许多当地用到了 txiki.jsAPI,这边引进了 txiki.jstypes 界说,便利后续开发。

cheetah-for-alfred
├─ ...
├─ declares
│  ├─ ffi.d.ts
│  └─ txikijs.d.ts
├─ ...

tsconfig.json 中的 include 字段添加 declares 目录即可:

// tsconfig.json
{
  ...
  "include": [
    "src/**/*",
    "declares/**/*" // 看这里
  ],
  ...
}

runtime

此次除了引进中心模块外,还对项目中的 txiki.js 可履行文件进行了升级,从本来的 v19.0.0-alpha 升级为 v22.4.1,API 运用方面有一些区别,可是迥然不同。

功用完结

Alfred 区别于 uTools 插件开发的方法,许多操作需求在 Workflows 中运用功用块处理,在流程关键位置运用 txiki.js 运行 js 文件(任意语言,只要有运行环境即可)完结处理后,成果运用指定格局输出到控制台,下一个流程即可获取运用。

1.51.0 一致,别离有以下三个 js,在构建时需求有三个进口,rollup 装备如下:

import typescript from 'rollup-plugin-typescript';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import { uglify } from 'rollup-plugin-uglify';
const production = process.env.NODE_ENV === 'production';
const devInput = {
  test: 'src/test.ts',
};
const productionInput = {
  index: 'src/index.ts',
  hits: 'src/hits.ts',
  choose: 'src/choose.ts'
};
export default {
  // 这里input要改成数组方式或许目标方式,目标方式能够修正打包的文件名,键对应的就是打包的文件名
  input: production ? productionInput : devInput,
  // 输出装备要改成拆分包的装备,认为多进口打包默许会履行打包拆分的特性。所以输出格局要改成amd
  output: {
    dir: 'dist',
    format: 'esm'
  },
  plugins: [
    resolve(),
    commonjs(),
    typescript(),
    production && uglify(),
  ]
}

由于 Alfred Workflows 仅支撑文件导出方式的发布,没有插件商场,这边能够运用混杂紧缩,进一步减少导出的插件文件体积。

查找项目并输出列表

查找项目并输出列表的进口在 Script Filter 功用块中运用,输入框中接收到的值会传递到 $1 中,在 txiki.js 履行进口文件后能够作为运行时参数获取,用于挑选项目。

猎豹Cheetah插件开发 - Alfred 篇

import { filterWithCache, filterWithSearchResult, Project } from 'cheetah-core';
import { output, initCore, errorHandle } from './utils';
import { ResultItem } from './types';
// 判断是否需求改写缓存
const needRefresh: boolean = Array.from(tjs.args).includes('--r');
// 项目查找关键词
const keyword: string = (Array.from(tjs.args).pop() as string) ?? '';
(async () => {
  try {
    initCore();
    let projects: Project[] = await filterWithCache(keyword);
    let fromCache = true;
    // 假如缓存成果为空或许需求改写缓存,则从头查找
    if (!projects.length || needRefresh) {
      projects = await filterWithSearchResult(keyword);
      fromCache = false;
    }
    const result: ResultItem[] = output(projects);
    // 假如是从缓存中获取的内容,最终加上改写的进口
    if (fromCache) {
      result.push({
        title: '疏忽缓存从头查找',
        subtitle: '以上成果从缓存中取得,挑选本条将从头查找项目并更新缓存',
        arg: keyword,
        valid: true,
        icon: {
          path: 'assets/refresh.png',
        },
      });
    }
    if (!result.length) {
      result.push({
        title: `没有找到称号包含 ${keyword} 的项目`,
        subtitle: '请测验替换关键词',
        arg: keyword,
        valid: false,
        icon: {
          path: 'assets/empty.png',
        },
      });
    }
    console.log(JSON.stringify({ items: result }));
  } catch (error) {
    errorHandle(error);
  }
})()

基本逻辑没有改变,将本来项目内的项目查找函数替换为中心模块供给的函数。
另添加了 initCore 函数用于初始化中心模块,添加 errorHandle 处理错误。

export function initCore() {
  const workspaces = (getEnv('workspace') || '').split(/[,,]/);
  const PlatformTypeMap = {
    darwin: PlatformType.MAC,
    windows: PlatformType.WINDOWS,
    linux: PlatformType.LINUX,
  };
  let platformType: PlatformType =
    PlatformTypeMap?.[tjs.platform] ?? PlatformType.MAC;
  init({
    cachePath,
    workspaces: workspaces.join(','),
    platformType, // Alfred 下没什么用
  });
}

initCore 向中心模块注册了缓存文件位置,工作区装备,这样中心模块就能从 global 目标上获取并运用这两个参数了。

errorHandle 在下面详解。

翻开项目并更新点击量

项目每一次被挑选后其点击量都会加 1,点击量越高,项目在查找列表中的排序越前,便利用户下一次挑选运用。

import { readCache, writeCache, getEnv, Project } from 'cheetah-core';
import { errorHandle, initCore } from './utils';
// 项目查找关键词
const projectPath: string = (Array.from(tjs.args).pop() as string) ?? '';
const force = getEnv('force', '0') === '1';
(async () => {
  try {
    initCore();
    // 获取途径对应的项目概况
    const { cache: cacheList = [], editor } = await readCache();
    const targetProject = cacheList.find(
      (item: Project) => item.path === projectPath
    );
    if (!targetProject) {
      return;
    }
    // 更新点击量
    targetProject.hits += 1;
    await writeCache(cacheList);
    const { idePath, type } = targetProject;
    // 自界说编辑器掩盖默许环境变量中装备的编辑器
    const priorityIdePath = force
      ? tjs.getenv('idePath')
      : idePath || editor[type] || tjs.getenv('idePath');
    // 输出两个参数,以英文逗号切割
    console.log([projectPath, priorityIdePath].join(','));
  } catch (error: any) {
    errorHandle(error, true);
  }
})();

上面的代码主要是引进了中心模块中的缓存读写函数,读取到项目信息今后,给点击量加 1,然后从头写入缓存。

完结点击量添加操作后,获取当时环境变量中的默许运用 idePath,假如环境变量中 force1 则取 环境变量中 idePath 的值,否则将依照下面的顺序决议翻开项目的运用: 缓存文件内项目中装备的idePath > 缓存文件内装备的项目类型运用 > 环境变量中idePath 的值。

获取到项目绝对途径以及翻开运用的称号后,即可运用 Run Script 功用块履行翻开命令了:

open -a "$idePath" {query}

猎豹Cheetah插件开发 - Alfred 篇

为项目指定运用

与 uTools 版插件一致,也添加了一个为项目快速装备编辑器的进口。
同样是运用了中心模块供给的缓存读写函数,在查找后挑选项目后即可翻开文件挑选窗口,挑选想要为项目装备的运用。

import { readCache, writeCache, getEnv, Project } from 'cheetah-core';
import path from 'path-browserify';
const projectPath = getEnv('projectPath');
import { errorHandle, initCore } from './utils';
(async () => {
  try {
    initCore();
    // 项目查找关键词
    let idePath: string = (Array.from(tjs.args).pop() as string) ?? '';
    idePath = idePath.split(',')?.[0] ?? '';
    if (!idePath) return;
    idePath = path.basename(idePath);
    // 获取途径对应的项目概况
    const { cache: cacheList = [] } = await readCache();
    const targetProject = cacheList.find(
      (item: Project) => item.path === projectPath
    );
    if (!targetProject) {
      return;
    }
    // 更新编辑器
    targetProject.idePath = idePath;
    await writeCache(cacheList);
  } catch (error: any) {
    errorHandle(error, true);
  }
})();

由于 Alfred Workfows 功用块间传输数据时会替换上一个模块的输出,所以要将项目绝对途径先存在运行时的环境变量内,在进口文件履行时再取出运用,挑选的运用称号则作为运行时参数运用。

猎豹Cheetah插件开发 - Alfred 篇

猎豹Cheetah插件开发 - Alfred 篇

获取到项目绝对途径与运用称号后即可写入缓存完结装备了。

错误处理

项目中创立了一个错误处理函数如下:

export function errorHandle(error: any, notice: boolean = false) {
  const errorCode: number = error.message;
  const errorMessage = ErrorCodeMessage[errorCode];
  if (notice) {
    console.log(`Error:${errorMessage}`);
    return
  }
  console.log(
    JSON.stringify({
      items: [
        {
          title: 'Error',
          subtitle: errorMessage,
          arg: '',
          valid: false,
          icon: {
            path: 'assets/empty.png',
          },
        },
      ],
    })
  );
}

Script Filter 功用块中报错为直接输出到列表:

猎豹Cheetah插件开发 - Alfred 篇

假如需求体系告诉的话,需求 Workflows 的功用块合作,这边直接输出报错信息即可,后续处理进程如下:

新建判断功用块,假如输入内容以 Error 开头则判断为报错信息,后面衔接一个参数拆分器,其效果与 js 中的split 类似。

猎豹Cheetah插件开发 - Alfred 篇

猎豹Cheetah插件开发 - Alfred 篇

最终衔接发送体系提示功用块,text 输入框为上一个功用块处理完的成果,取第二个参数。

猎豹Cheetah插件开发 - Alfred 篇

构建发布

猎豹Cheetah插件开发 - Alfred 篇
Alfred Workflows 的发布比较简单,项目构建完今后直接在 Alfred 中右键插件称号,在菜单中挑选 Export,后在导出面板中填写插件信息,插件描绘等信息,点击 Export 后挑选一个寄存途径就完结了。

猎豹Cheetah插件开发 - Alfred 篇

小结

至此 Cheetah for Alfred 1.5 的开发、发布现已完结,相信各位看官现已对 Alfred Workflows 开发有必定的了解了,能够测验创立一些工作流,替代自己完结一些繁复机械的工作。

下一篇将介绍 Cheetah for Raycast 的开发,敬请期待~