use-command-registry-source.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. 'insert-inline-math',
  23. 'insert-display-math',
  24. 'insert-figure-from-computer',
  25. 'insert-figure-from-project-files',
  26. 'insert-figure-from-another-project',
  27. 'insert-figure-from-url',
  28. 'insert-table',
  29. 'insert-citation',
  30. 'insert-link',
  31. 'insert-cross-reference',
  32. ]
  33. const useCommandRegistrySource = (): CommandPaletteSource => {
  34. const { registry } = useCommandRegistry()
  35. const commands = useMemo(() => {
  36. const enabled = new Set(ENABLED_COMMANDS)
  37. return [...registry.values()].filter(
  38. c => enabled.has(c.id) && !c.disabled && c.handler
  39. )
  40. }, [registry])
  41. const defaults = useCallback((): CommandPaletteSearchResult[] => {
  42. return commands.map(command => ({
  43. title: command.label,
  44. onSelect: () => command.handler!({ location: 'command-palette' }),
  45. score: 1,
  46. }))
  47. }, [commands])
  48. const index = useMemo(() => {
  49. const miniSearch = new MiniSearch<Command>({
  50. fields: ['label'],
  51. storeFields: ['id'],
  52. idField: 'id',
  53. })
  54. miniSearch.addAll(commands)
  55. return miniSearch
  56. }, [commands])
  57. return useMemo<CommandPaletteSource>(
  58. () => ({
  59. id: 'command-registry',
  60. search(query) {
  61. const results = index.search(query, {
  62. prefix: true,
  63. fuzzy: term => (term.length > 3 ? 0.2 : false),
  64. })
  65. return results.flatMap(({ id, score }) => {
  66. const command = registry.get(id)
  67. if (!command?.handler) return []
  68. return [
  69. {
  70. title: command.label,
  71. onSelect: () => command.handler!({ location: 'command-palette' }),
  72. score,
  73. },
  74. ]
  75. })
  76. },
  77. defaults,
  78. }),
  79. [index, registry, defaults]
  80. )
  81. }
  82. export default useCommandRegistrySource