惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - Franky
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
LangChain Blog
WordPress大学
WordPress大学
H
Help Net Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog
Blog — PlanetScale
Blog — PlanetScale
MyScale Blog
MyScale Blog
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
有赞技术团队
有赞技术团队
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
博客园 - 【当耐特】
P
Proofpoint News Feed
D
DataBreaches.Net

Miriam Eric Suzanne

Butter bells, fresh from the kiln Butter bells, fresh from the kiln Butter bells, fresh from the kiln I had to look it up I Laser-cut pottery throwing gauge Tech continues to be political Aggregating my distributed self A web component for CodePen embeds? We don Eleventy buckets & cascade layers A slash-why proposal User styles on the web Custom element, two ways New year, same (terrible) Mia CSS @scope Reclaiming my time Cascade Layers Personal Histories Ancient Web Browsers Critical CSS? Not So Fast! CSS tie-dye gradient backgrounds Personal website redesign Request for Comments: Sass Color Spaces A long-term plan for logical properties? Container queries in browsers! I never let things be small A whole cascade of layers This content won No demo [website] reno
Javascript automation on Mac
2022-12-11 · via Miriam Eric Suzanne

I’ve been using Alfred for Mac as long as I can remember – occasionally installing ‘powerpack’ workflows or building simple flows with the graphic interface. The other day, I discovered one of my third-party workflows wasn’t working. It’s a word/character counter that I don’t use often, but like to have available.

Digging into it, I found a simple php script defining the entire word-count logic. That’s interesting, I didn’t know you could write Alfred workflows in php. I wonder what other languages are supported? Here’s the list provided in a dropdown:

  • /bin/bash
  • /bin/zsh
  • /usr/bin/php [not installed]
  • /usr/bin/ruby
  • /usr/bin/python [not installed]
  • /usr/bin/python3
  • /usr/bin/perl
  • /usr/bin/osascript (AppleScript)
  • /usr/bin/osascript (JavaScript)
  • /usr/bin/swift

Well, that explains why the php script wasn’t working – it must have broken when I got my new Mac. But JavaScript support means I can re-write this workflow myself, without learning a new language?

Yes! It turns out Apple now supports JavaScript for Automation as an alternative to AppleScript. You can do this in Automator as well as Alfred.

The basics of JS in Alfred

After selecting /usr/bin/osascript (JavaScript) from the language dropdown, I left the next option as-is: with input as {query}. That gives me the input pasted to Alfred.

For output, the docs recommend returning a JSON object. The object has a single items key, with an array of objects for each result row to be displayed. The essential properties of an item seem to be the title and arg keys. There’s more you can provide, but that’s enough to get started.

  • The title is what’s actually shown in the row
  • The arg is the value that gets passed along to any further actions (like copying to clipboard)

In my case, the result I want is:

{"items": [
  {
    "title": "Words: <word-count>",
    "arg": "<word-count>"
  },
  {
    "title": "Chars: <char-count>",
    "arg": "<char-count>"
  }
]}

There doesn’t seem to be much magic around using the {query} or returning the JSON. If we define a function called wordCounter() that accepts a single argument and returns a JSON string, we can run it like this:

wordCounter(`{query}`);

The {query} itself seems to be supplied as a direct text replacement before the script is run. If I remove the backticks or quotes around {query}, it assumes the first word is an undefined JS variable and throws an error.

My simple word counter

I didn’t put a lot of thought into edge cases beyond ‘the query is missing for some reason’, so we’ll see how well it holds up. Here’s the logic I used for counting:

const words = (text || '').trim().split(' ').length;
const chars = (text || '').length;

Nothing clever, and it seems to work even when I copy text with line-breaks – so that’s good enough for now. The rest is just to make sure the query is a string (maybe unnecessary since I’m already forcing it), and build the correct JSON from the results. Here’s the full script:

// generate an Alfred return item
const item = (title, arg) => ({
  title: arg ? `${title}: ${arg}` : title,
  arg,
});

// count words/chars and return as items
const count = (text) => {
  const words = (text || '').trim().split(' ').length;
  const chars = (text || '').length;

  return [
    item('Words', words),
    item('Chars', chars),
  ];
}

// count or error, and return as JSON string
const wordCounter = (txt) => {
  // error if query isn't text (maybe overkill?)
  const items = (typeof txt === 'string')
    ? count(txt)
    : [item('ERROR: please provide a string', null),];

  return JSON.stringify({ items });
}

// run the script
wordCounter(`{query}`);

That works great so far. The only other thing in the workflow is copying the output to the clipboard.

Now that I know how to do it, I wonder what other automations I might want to write!