Skip to content

dangduc/fzf-native

Repository files navigation

fzf-native

https://github.com/dangduc/fzf-native/actions/workflows/test.yaml/badge.svg https://github.com/dangduc/fzf-native/actions/workflows/cmake.yaml/badge.svg https://github.com/dangduc/fzf-native/actions/workflows/format.yaml/badge.svg

This is a package that provides fuzzy match scoring based on the fzf algorithm by junegunn. The main contribution is a wrapper over the C implementation of fzf from the project telescope-fzf-native.nvim. Elisp functions for scoring are exported through an Emacs dynamic module.

This package does one thing – For a given STR and QUERY compute and return a score and matching indices. If you’re looking for a fuzzy auto-completion engine, see the Use Cases section for how this package can be used in a completion-style.

;; Example of basic usage
(fzf-native-score "Hot-Topic" "hp")
;; (41 0 6)
;; Example of no match
(fzf-native-score "Hot-Topic" "2")
;; (0)
;; Example of slab re-use
(let ((slab (fzf-native-make-default-slab)))
  (fzf-native-score "Hello World" "er" slab)
  (fzf-native-score "Example of slab re-use" "xu" slab))
;; (24 1 19)

See test cases for more examples.

Supported Platforms

Linux, macOS (incl. Apple silicon), and Windows are supported. Pre-built shared libraries are in the bin/ directory.

Installation

MELPA

Not yet on MELPA.

Manually

Clone / download this repository and modify your load-path:

(add-to-list 'load-path (expand-file-name "/path/to/fzf-native/" user-emacs-directory))

Straight Examples

; Configuration that builds dynamic module locally.
(use-package fzf-native
  :straight
  (:repo "dangduc/fzf-native"
   :host github
   :files (:defaults "*.c" "*.h" "*.txt"))
  :init
  (setq fzf-native-always-compile-module t)
  :config
  (fzf-native-load-own-build-dyn))
; Configuration that uses pre-built dynamic module.
(use-package fzf-native
  :straight
  (:repo "dangduc/fzf-native"
   :host github
   :files (:defaults "bin"))
  :config
  (fzf-native-load-dyn))

Multibyte character support

Work around the lib’s lack of support for multibyte chars. Add this advice if you want accurate indices for multibyte chars. Don’t add this advice if you want better run time performance or you don’t need accurate indices for multibyte chars.

(advice-add 'fzf-native-score :around #'fzf-native--fix-score-indices)

Use Cases

Fussy: fzf-native is used as one of several choose-your-own scoring backends in fussy, a package that provides a completing-style for intelligent matching and sorting.

Building the Native Libraries

mkdir build && cmake -B build -DCMAKE_C_FLAGS='-O3 -march=native' && cmake --build build

Debugging fzf-native with emacs/lldb (EXAMPLE)

Building Emacs

cd Code/emacs
brew install autoconf automake pkg-config ncurses gnutls libjpeg libgif libtiff libxpm libx11 libxt libxml2
autoreconf -isvf
./autogen.sh
./configure CFLAGS="-g -O0" LDFLAGS="-g" --with-ns
make bootstrap

Building fzf-native

$ pwd
~/.emacs.d/packages/emacs_31/elpaca/repos/fzf-native
$ rm -Rf build; mkdir build && cmake -B build -DCMAKE_C_FLAGS='-O0 -g -march=native' && cmake --build build

From LLDB

$ pwd
~/Code/emacs/src
$ lldb --local-lldbinit ./emacs

From Emacs

Refer to https://github.com/svaante/dape?tab=readme-ov-file#c-c-and-rust—lldb-dap on how to install LLDB-dap.

$ brew install llvm
($(brew --prefix --installed llvm)/bin)  # PREPEND (OSX already has a binary on $PATH) to $PATH.
(use-package dape
  :init
  ;; Enable repeat mode for more ergonomic `dape' use
  (use-package repeat
    :ensure nil
    :config
    (repeat-mode))
  :config
  (push
   '(lldb-dap
     modes (c-mode c-ts-mode c++-mode c++-ts-mode)
     command "lldb-dap"
     command-args ["--local-lldbinit"]
     ensure dape-ensure-command
     :type "lldb-dap"
     :cwd "/Users/james/Code/emacs/src"
     :program "/Users/james/Code/emacs/src/emacs")
   dape-configs)
  ;; Turn on global bindings for setting breakpoints with mouse
  (dape-breakpoint-global-mode)
  ;; Info buffers to the right
  (setq dape-buffer-window-arrangement 'right)
  ;; Info buffers like gud (gdb-mi)
  (setq dape-buffer-window-arrangement 'gud)
  (setq dape-info-hide-mode-line nil)
  ;; Pulse source line (performance hit)
  (add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)
  ;; Showing inlay hints
  (setq dape-inlay-hints t)
  ;; Save buffers on startup, useful for interpreted languages
  (add-hook 'dape-start-hook (lambda () (save-some-buffers t t)))
  ;; Kill compile buffer on build success
  (add-hook 'dape-compile-hook 'kill-buffer)
  ;; Projectile users
  (setq dape-cwd-fn 'projectile-project-root))

;; M-x dape in fzf-native-module.c
;; Set breakpoints with mouse.

Credit

All credit for fzf.c goes to the telescope-fzf-native.nvim project. Much credit for Emacs module binding code goes to the hotfuzz project.