Prompt the user for input

Hi everyone, I would like to know if there is a way to prompt input from the user using JavaScript, AppleScript, or any other extension for PopClip.

This would be great in conjunction with existing GPT extensions such as the one created by @hirakujira (GitHub - hirakujira/ChatGPT-Grammar-Check-PopClip-Extension). I am currently using it, and I am very impressed with how it helps to save time (thank you!). However, I believe it would be helpful (next-level) to have the option for more varied input. For example, it could be used to indicate to OpenAI that only spell-checking is needed or more informal grammar corrections are desired, or to specify the intended audience for the text being written (similar to Grammarly’s enumerated input).

I am visualizing a user interface similar to a static combo, perhaps organized into categories with labels or multi-toggles like those in Grammarly. These could serve as UI elements (commons ones) to construct the GPT completions API query, instead of being limited to fixed options. Additionally, there could be an option for freeform input text to manually write the query, instead of relying on the tabulated options.

If it is possible to achieve this with PopClip extensions (I am a newbie), I think it would be an incredibly powerful tool. While I understand that native support might not be available, I am open to workarounds and would appreciate any suggestions from the experts here. I’m particularly interested in exploring smoother options rather than clunky ones.

Thanks in advance!

Hi, prompting for user input natively in PopClip is not currently possible but that’s high on my wish list.

It is possible for AppleScripts to prompt for input but it probably falls in the clunky bucket.

3 Likes

I’ve ended up doing some custom quick access, each one separated by “topic” based on original hirakujira extension, so I will paste my ideas here and maybe someone finds it useful too, thanks again Nick, definitely I will wait for the sleek choice in the near term to add some options before prompting openIA (maybe optional by conf)

Anyway, something to keep in mind always is the fact that any LLM of the GPT class will not be deterministic at all and not being a domain thing (talking about grammar improvements) make it a little hard to follow some very specific details or instructions, like the letter-case and punctuation thing and that awful workaround I’ve made on the purest spell-check action :sweat_smile: (see below):

# PopClip custom extensions using OpenAI based on: https://github.com/hirakujira/ChatGPT-Grammar-Check-PopClip-Extension
# icons from https://icon-sets.iconify.design/

# popclip GPT Grammar
name: GPT Grammar
icon: iconify:logos:grammarly-icon
entitlements: [network]
javascript: |
  const axios = require("axios");
  const openai = axios.default.create({
    baseURL: "https://api.openai.com/v1",
    headers: { Authorization: `Bearer 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` },
  });
  const prompt = "Correct the grammar and polish the following sentences, do not provide any translation, comments, or notes, keep the informal or formal tone based on the sentence itself, and use the same language as input:\n\n";
  const { data } = await openai.post("chat/completions", {
    model: "gpt-3.5-turbo",
    messages: [
      { role: "system", content: prompt }, 
      { role: "user", content: popclip.input.text }
    ],
  });
  const response = data.choices[0].message.content.trim();
  return response;
after: paste-result

# --------------------------------------------------------------------------------------- #

# popclip GPT Spellcheck
name: GPT Spellcheck
icon: iconify:vscode-icons:file-type-word
entitlements: [network]
javascript: |
  const axios = require("axios");
  const openai = axios.default.create({
    baseURL: "https://api.openai.com/v1",
    headers: { Authorization: `Bearer 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` },
  });
  const prompt = "Spell check the following sentences, do not add any translation, puntuation, comments, or notes, do not change any letter to uppercase or lowercase even after a punctuation mark, and use the same language as input:\n\n";
  const { data } = await openai.post("chat/completions", {
    model: "gpt-3.5-turbo",
    messages: [
      { role: "system", content: prompt }, 
      { role: "user", content: popclip.input.text }
    ],
  });
  let first_characters = [];
  popclip.input.text.split('\n').forEach(line => first_characters.push(line[0]));
  const response = data.choices[0].message.content.trim();
  let idx = 0;
  const response_fixes = response.split('\n').map(line => {
    const gpt_char = line[0];
    const popclip_char = first_characters[idx++];
    if (gpt_char.toLowerCase() == popclip_char.toLowerCase() && gpt_char != popclip_char) {
      line = popclip_char + line.slice(1);
    }
    return line.replace(/\.$/, '');
  });
  const result = response_fixes.join('\n');
  return result;
after: paste-result

# --------------------------------------------------------------------------------------- #

# popclip GPT Thesaurus
name: GPT Thesaurus
icon: iconify:noto:light-bulb
entitlements: [network]
javascript: |
  const axios = require("axios");
  const openai = axios.default.create({
    baseURL: "https://api.openai.com/v1",
    headers: { Authorization: `Bearer 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` },
  });
  const prompt = "Rephrase the following sentences using as much synonyms as possible, and use the same language as input:\n\n";
  const { data } = await openai.post("chat/completions", {
    model: "gpt-3.5-turbo",
    messages: [
      { role: "system", content: prompt }, 
      { role: "user", content: popclip.input.text }
    ],
  });
  const response = data.choices[0].message.content.trim();
  return response;
after: paste-result

# --------------------------------------------------------------------------------------- #

# popclip GPT Translate English
name: GPT Translate English
icon: iconify:emojione:flag-for-united-states
entitlements: [network]
javascript: |
  const axios = require("axios");
  const openai = axios.default.create({
    baseURL: "https://api.openai.com/v1",
    headers: { Authorization: `Bearer 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` },
  });
  const prompt = "Translate the following sentences to English:\n\n";
  const { data } = await openai.post("chat/completions", {
    model: "gpt-3.5-turbo",
    messages: [
      { role: "system", content: prompt }, 
      { role: "user", content: popclip.input.text }
    ],
  });
  const response = data.choices[0].message.content.trim();
  return response;
after: paste-result

# --------------------------------------------------------------------------------------- #

# popclip GPT Translate Spanish
name: GPT Translate Spanish
icon: iconify:emojione:flag-for-spain
entitlements: [network]
javascript: |
  const axios = require("axios");
  const openai = axios.default.create({
    baseURL: "https://api.openai.com/v1",
    headers: { Authorization: `Bearer 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` },
  });
  const prompt = "Translate the following sentences to Spanish:\n\n";
  const { data } = await openai.post("chat/completions", {
    model: "gpt-3.5-turbo",
    messages: [
      { role: "system", content: prompt }, 
      { role: "user", content: popclip.input.text }
    ],
  });
  const response = data.choices[0].message.content.trim();
  return response;
after: paste-result

# --------------------------------------------------------------------------------------- #

# popclip GPT Code Bash
name: GPT Code Bash
icon: iconify:logos:bash-icon
entitlements: [network]
javascript: |
  const axios = require("axios");
  const openai = axios.default.create({
    baseURL: "https://api.openai.com/v1",
    headers: { Authorization: `Bearer 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` },
  });
  let prompt = "Translate the folling instructions written in natural language into Bash Script code, use english for all variables and comments created, avoid companion comments, generate only executable code:\n\n";
  if (popclip.modifiers.shift) {
    prompt = "Prettify the folling Bash Script code:\n\n";
  }
  const { data } = await openai.post("chat/completions", {
    model: "gpt-3.5-turbo",
    messages: [
      { role: "system", content: prompt }, 
      { role: "user", content: popclip.input.text }
    ],
  });
  const response = data.choices[0].message.content.trim();
  return response;
after: paste-result

# --------------------------------------------------------------------------------------- #

# popclip GPT Code Javascript
name: GPT Code Javascript
icon: iconify:tabler:brand-javascript
entitlements: [network]
javascript: |
  const axios = require("axios");
  const openai = axios.default.create({
    baseURL: "https://api.openai.com/v1",
    headers: { Authorization: `Bearer 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` },
  });
  let prompt = "Translate the folling instructions written in natural language into Javascript code, use english for all variables and comments created, avoid companion comments, generate only executable code:\n\n";
  if (popclip.modifiers.shift) {
    prompt = "Prettify the folling Javascript code:\n\n";
  }
  const { data } = await openai.post("chat/completions", {
    model: "gpt-3.5-turbo",
    messages: [
      { role: "system", content: prompt },
      { role: "user", content: popclip.input.text }
    ],
  });
  const response = data.choices[0].message.content.trim();
  return response;
after: paste-result

# --------------------------------------------------------------------------------------- #

# popclip extension to search for synonyms on thesaurus.com
name: Thesaurus
icon: symbol:pencil.and.outline # Apple SF Symbols
url: https://www.thesaurus.com/browse/***

2 Likes

These are awesome and really ineteresting! Thank you for sharing.

It’d be really useful if you could give me an idea of what you might make if there were user prompts available. What kind of inputs might you ask for? A couple of concrete examples will help me with my thinking and design process.

Also as an aside (and you may well know this, but I want to publicise it generally), there is now an alternative format for snippets containing code, which I think of as an improvement. It looks like this, based on your first example:

// # popclip GPT Grammar
// name: GPT Grammar
// icon: iconify:logos:grammarly-icon
// entitlements: [network]
// after: paste-result
// language: javascript
const axios = require("axios");
const openai = axios.default.create({
  baseURL: "https://api.openai.com/v1",
  headers: { Authorization: `Bearer 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` },
});
const prompt = "Correct the grammar and polish the following sentences, do not provide any translation, comments, or notes, keep the informal or formal tone based on the sentence itself, and use the same language as input:\n\n";
const { data } = await openai.post("chat/completions", {
  model: "gpt-3.5-turbo",
  messages: [
    { role: "system", content: prompt }, 
    { role: "user", content: popclip.input.text }
  ],
});
const response = data.choices[0].message.content.trim();
return response;

So that’s actually a snippet itself. The YAML data is added at the top as comment lines, and everything after the YAML is interpreted as the source code. I really like writing snippets this way because we can get proper syntax highlighting and it allows the use of editor magic.

The pure YAML format is still supported, and I’ve no intention to withdraw it, but I’d encourage people to use this format if you find it more readable and easier to edit.

p.s. in the Discourse editor you can specify the language for the syntax highlighter after the first backticks, like this:

```javascript

```yaml

etc.