use-command-registry-source.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import { useCallback, useMemo } from 'react'
  2. import MiniSearch from 'minisearch'
  3. import { CommandPaletteSearchResult, CommandPaletteSource } from '../types'
  4. import {
  5. Command,
  6. useCommandRegistry,
  7. } from '@/features/ide-react/context/command-registry-context'
  8. const ENABLED_COMMANDS: string[] = [
  9. 'new_file',
  10. 'new_folder',
  11. 'upload_file',
  12. 'open-settings',
  13. 'show_version_history',
  14. 'word_count',
  15. 'view-pdf-presentation-mode',
  16. 'comment',
  17. 'compile',
  18. 'stop-compile',
  19. 'recompile-from-scratch',
  20. 'synctex-sync-to-pdf',
  21. 'synctex-sync-to-code',
  22. ]
  23. const useCommandRegistrySource = (): CommandPaletteSource => {
  24. const { registry } = useCommandRegistry()
  25. const commands = useMemo(() => {
  26. const enabled = new Set(ENABLED_COMMANDS)
  27. return [...registry.values()].filter(
  28. c => enabled.has(c.id) && !c.disabled && c.handler
  29. )
  30. }, [registry])
  31. const defaults = useCallback((): CommandPaletteSearchResult[] => {
  32. return commands.map(command => ({
  33. title: command.label,
  34. onSelect: () => command.handler!({ location: 'command-palette' }),
  35. score: 1,
  36. }))
  37. }, [commands])
  38. const index = useMemo(() => {
  39. const miniSearch = new MiniSearch<Command>({
  40. fields: ['label'],
  41. storeFields: ['id'],
  42. idField: 'id',
  43. })
  44. miniSearch.addAll(commands)
  45. return miniSearch
  46. }, [commands])
  47. return useMemo<CommandPaletteSource>(
  48. () => ({
  49. id: 'command-registry',
  50. search(query) {
  51. const results = index.search(query, {
  52. prefix: true,
  53. fuzzy: term => (term.length > 3 ? 0.2 : false),
  54. })
  55. return results.flatMap(({ id, score }) => {
  56. const command = registry.get(id)
  57. if (!command?.handler) return []
  58. return [
  59. {
  60. title: command.label,
  61. onSelect: () => command.handler!({ location: 'command-palette' }),
  62. score,
  63. },
  64. ]
  65. })
  66. },
  67. defaults,
  68. }),
  69. [index, registry, defaults]
  70. )
  71. }
  72. export default useCommandRegistrySource