kit icon indicating copy to clipboard operation
kit copied to clipboard

Preview is not rendered when searching for choices in choices

Open cedric-cle opened this issue 2 years ago β€’ 0 comments

Hi John πŸ‘‹

I'm a Windows User which implemented a own version of snippets

I have a json file which operates as my database

{
  "snippetGroups": [
    {
      "id": "439aea2c-a45d-46ef-9cdf-6feb78288dc9",
      "name": "JavaScript",
      "choices": [
        {
          "id": "d896362c-0229-4264-b932-b76084e8669b",
          "name": "Hello",
          "code": "console.log('hello world')",
          "description": "World",
          "language": "js",
          "group": "JavaScript"
        }
      ]
    },
    {
      "id": "ff87ad52-b632-43ef-ada1-d21078182b4f",
      "name": "Shell",
      "choices": [
        {
          "id": "ac60560a-38c7-4a54-804b-883c791a418a",
          "name": "WSL Ubuntu search",
          "code": "sudo apt-search pack",
          "language": "shell",
          "description": "Searches for packages",
          "group": "Shell"
        },
        {
          "id": "d5d95f81-0099-416f-812f-9f3e510ced0f",
          "name": "WSL Ubuntu remove package",
          "code": "sudo apt-get remove pack",
          "language": "shell",
          "description": "Removes given package",
          "group": "Shell"
        },
        {
          "id": "464f5ad4-2646-477a-bda9-bcb67cd7aa48",
          "name": "WSL Ubuntu update package list",
          "code": "sudo apt-get update",
          "language": "shell",
          "description": "Fetches new versions of installed packages",
          "group": "Shell"
        },
        {
          "id": "b2b33cae-592e-444f-82f0-131e31ebf223",
          "name": "WSL Ubuntu update packages",
          "code": "sudo apt-get upgrade",
          "language": "shell",
          "description": "Comes after the apt-get update --> Installs new updates for packages",
          "group": "Shell"
        },
        {
          "id": "42432726-0208-4f2f-b582-4288f90ed4e2",
          "name": "WSL Ubuntu install new packages",
          "code": "sudo apt-get install pa",
          "language": "shell",
          "description": "Installs new linux packages same like {npm install xyz}",
          "group": "Shell"
        },
        {
          "id": "c1ea9c6a-3f33-4337-8659-1bed6e0ca559",
          "name": "SDKMan List Java Version",
          "code": "sdk list java",
          "language": "shell",
          "description": "List available Java Versions",
          "group": "Shell"
        },
        {
          "id": "7ad54028-f1d5-46ba-879d-65daad78cd7c",
          "name": "npm update package helper",
          "code": "npx npm-check-updates",
          "description": "Command to update npm packages via npx.",
          "language": "shell",
          "group": "Shell"
        },
        {
          "id": "450b6686-3e36-4a5e-8e12-cbbc523129ac",
          "name": "docker remove unused images",
          "code": "docker rmi $(docker images --filter \"dangling=true\" -q --no-trunc)",
          "description": "Remove unused docker images.",
          "language": "shell",
          "group": "Shell"
        }
      ]
    },
    {
      "id": "2a1c8a00-0719-4328-bf14-9ee57ddb32b0",
      "name": "CSS",
      "choices": [
        {
          "id": "729bd81e-5d22-4757-b5d4-f3848fc7cb4f",
          "name": "SCSS color adjust lighter",
          "code": "color.adjust($some-color, $lightness: 45%)",
          "description": "Makes the given color lighter by a specific amount in %",
          "language": "scss",
          "group": "CSS"
        }
      ]
    }
  ]
}

My script:

// Shortcut: command shift option control f11
// Menu: Snippets
// Description: Easily organize your code snippets πŸ”₯
// Author: Altrim Beqiri + cle
// Group: Utility

import '@johnlindquist/kit'
import {PromptConfig} from '@johnlindquist/kit'

const wrapCode = (html: string): string => `<pre class="px-4">
<style type="text/css">
  code {
    font-size: 0.75rem !important;
    width: 100%;
    white-space: pre-wrap;
  }
  pre {
    display: flex;
  }
  p {
    margin-bottom: 1rem;
  }
</style>
  <code style="font-size:0.85rem !important">
${html.trim()}
  </code>
</pre>`

const highlightJavaScript = async ({contents, language}): Promise<string> => {
  const {default: highlight} = await npm('highlight.js')
  let highlightedContents = language
      ? highlight.highlight(contents, {language}).value
      : highlight.highlightAuto(contents).value

  return wrapCode(highlightedContents)
}

type SnippetGroup = {
  id: string
  name: string
  choices?: any // Choices are the actual snippets
}

type Snippet = {
  id: string
  code?: any
  description?: string
  group: string,
  html?: any
  language?: string,
  name: string
  preview?: any
  tags?: string[]
}

// Write saves the database in it's current state
const {snippetGroups, write}: {
  snippetGroups: SnippetGroup[];
  write: () => Promise<void>
} = await db('code-snippets-db', {
  snippetGroups: []
})

const onNoChoices = async (input) => {
  if (input) {
    setPanel(
        md(`## Creating snippet <code>${input}</code>
    
Creates a new code snippet with the contents of the clipboard.`)
    )
  } else {
    setPlaceholder(`Enter a snippet name`)
  }
}

const onChoices = async () => {
  setPanel(``)
}

const loadSnippets = async () => {
  try {
    return snippetGroups.filter((snippetGroup: Partial<SnippetGroup>) => {
      return snippetGroup.choices.map((snippet: Snippet) => {
        snippet.preview = async () => {
          if (snippet?.code) {
            return await highlightJavaScript({contents: snippet?.code, language: snippet?.language})
          }
          return ''
        }
        return snippet
      })
    })
  } catch (error) {
    return [error.message]
  }
}

const config: PromptConfig & Partial<{ onChoices: () => Promise<void> }> = {
  placeholder: 'Enter new snippet name',
  strict: false,
  onChoices,
  onNoChoices,
  width: 2200,
  height: 800,
  flags: {
    updateCode: {
      group: 'Actions',
      name: 'πŸ‘¨β€πŸ’» Code',
      description: 'Update the snippet code'
    },
    removeSnippet: {
      group: 'Actions',
      name: '❌ Remove',
      description: 'Delete snippet'
    },
    updateName: {
      group: 'Actions',
      name: '♾️ Name',
      description: 'Update the snippet name'
    },
    updateDescription: {
      group: 'Actions',
      name: 'πŸ“ Description',
      description: 'Update the snippet description'
    },
    updateLanguage: {
      group: 'Actions',
      name: '🧠 Language',
      description: 'Update the snippet code language'
    },
    updateGroup: {
      group: 'Actions',
      name: 'πŸ”΅ Group',
      description: 'Update the snippet group'
    }
  }
}

const manageSnippets = async () => {
  const snippet: Snippet | string = await arg(config, await loadSnippets())
  const availableSnippetGroups = snippetGroups.map((snippetGroup: SnippetGroup) => snippetGroup.name)

  // Condition is hit when user enters a new snippet
  if (typeof snippet === 'string' && snippet) {
    const group: string = await arg('Enter group', availableSnippetGroups)
    const clipboard: string = await paste()

    snippetGroups.find((snippetGroup: SnippetGroup) => snippetGroup.name === group).choices.push({
      group: group,
      id: uuid(),
      name: snippet,
      code: clipboard.trim()
    })

    await write()
    await manageSnippets()
    // Condition is hit when user updates existing snippets
  } else if (typeof snippet !== 'string' && snippet?.id) {
    const pendingSnippetGroup = snippetGroups.find((snippetGroup: SnippetGroup) => snippetGroup.choices.map((snippet: Snippet) => snippet.id).includes(typeof snippet !== 'string' ? snippet.id : ''))
    const pendingSnippetList = pendingSnippetGroup.choices
    
    const foundSnippet: Snippet = pendingSnippetList.find((s: Snippet): boolean => s?.id === snippet.id)

    if (flag?.updateDescription) {
      foundSnippet.description = await arg(foundSnippet.description)
      await write()
      await manageSnippets()
    }

    if (flag?.updateLanguage) {
      foundSnippet.language = await arg(foundSnippet.language)
      await write()
      await manageSnippets()
    }

    if (flag?.updateName) {
      foundSnippet.name = await arg(foundSnippet.name)
      await write()
      await manageSnippets()
    }

    if (flag?.updateCode) {
      foundSnippet.code = await editor({
        value: snippet.code,
        language: snippet.language,
        footer: `STRG + S - Save`
      })
      await write()
      await manageSnippets()
    }

    if (flag.updateGroup) {
      foundSnippet.group = await arg('New group', availableSnippetGroups)

      // Removing the snippet from the old group
      pendingSnippetGroup.choices = pendingSnippetGroup.choices.filter((snippet: {
        id: string
      }) => snippet.id !== foundSnippet.id)

      // Adding the snippet to the new group
      snippetGroups.find((snippetGroup: SnippetGroup) => snippetGroup.name === foundSnippet.group).choices.push(foundSnippet)


      await write()
      await manageSnippets()
    }

    if (flag?.removeSnippet) {
      let choice: string = await arg('Do you really want to remove the snippet?', [
        'Yes',
        'No'
      ])

      if (choice === 'No') {
        await manageSnippets()
      } else {
        const index: number = pendingSnippetList.findIndex((s: Snippet): boolean => s?.id === snippet.id)
        if (index > -1) {
          pendingSnippetList.splice(index, 1)
        }
        await write()
        await manageSnippets()
      }
    }

    await setSelectedText(foundSnippet.code)
  }
}


onTab('Snippets', manageSnippets)

So I adjusted my script that the actual snippets are grouped by a specific group. If I do scroll through the snippets without searching, the preview of those snippets is rendered just fine. But If I do enter a search so that choices (actual snippets) are listed, the preview does not work.

What am I missing here or maybe it really is a bug?

Also are you planning on improving the search for? e.g "WSL se" the search works but If I search for "WSL sea" it does not work anymore while the search term is actually more precise. That is kinda strange to me. Is this something that can be enhanced? Maybe there is a limit like 6 characters or some? :) Also would it be possible in the search to cover all possible permutations of a search input? Similar to the search in IntelliJ IDEA, if you're familiar with that πŸ˜…

I honestly love your work and really appreciate this project!

Would love to hear from you.

Kind regards, cle β˜€οΈ

cedric-cle avatar Sep 23 '23 00:09 cedric-cle