Coder Social home page Coder Social logo

atom-community / zadeh Goto Github PK

View Code? Open in Web Editor NEW
24.0 4.0 8.0 4.94 MB

Blazing fast library for fuzzy filtering, matching, and other fuzzy things!

Home Page: https://www.npmjs.com/package/zadeh

License: Apache License 2.0

Python 5.62% C++ 55.42% JavaScript 19.44% C 0.47% CMake 0.15% TypeScript 18.90%
fuzzaldrin fuzzy fuzzy-search node-modules native fast hacktoberfest atom

zadeh's Introduction

Blazing fast library for fuzzy filtering, matching, and other fuzzy things!

CI

Zadeh

Zadeh is a blazing fast library for fuzzy filtering, matching, and other fuzzy things. Zadeh is a multithreaded library written in C++ with the goal to search through a dataset with 1M entries in a few hundred milliseconds.

The name "Zadeh" refers to Lofti Zadeh, the creator of fuzzy logic and fuzzy systems.

features

  • Fuzzy filter through an array of candidates (StringArrayFilterer)
  • Fuzzy filter through nested tree-like objects (TreeFilterer)
  • Special treatment for strings that have separators (space , hyphen -, underline_)
  • Special treatment for path-like strings (string separated by \ or //)
  • give an array of indices at which the query matches the given string (match)
  • score the given string against the given query (score)
  • give an HTML/Markdown string that highlights the range for which the match happens (wrap)
  • Allows setting the candidates only once using StringArrayFilterer and TreeFilterer classes, and then perform filter multiple times, which is much more efficient than calling the filter or filterTree functions directly every time.
  • Bindings for Nodejs (more to come)

Usage

Usage from C++

This is a header-only library. Include ./src/zadeh.h and build it in your application.

examples/example1.cpp:

#include "../src/zadeh.h"  // include zadeh.h
#include <string>
#include <iostream>

using namespace std;

int main() {
  // the data to fuzzy search on
  auto data = vector<string>{"eye", "why", "bi"};

  // setup StringArrayFilterer
  auto strArrFilterer = zadeh::StringArrayFilterer<vector<string>, string>{};
  strArrFilterer.set_candidates(data);

  // filter the indices that match the query
  auto filtered_indices = strArrFilterer.filter_indices("ye");

  // print the filtered data
  for (auto ind: filtered_indices) {
    cout << data[ind] << '\n';
  }
}

Cmake file:

cmake_minimum_required(VERSION 3.17)

project(example1 LANGUAGES CXX)
add_executable(example1 ./examples/example1.cpp)
target_compile_features(example1 PRIVATE cxx_std_17)

Build:

cmake -S . -B ./build && cmake --build ./build --config Debug

Usage from Nodejs

Installation:

npm install zadeh

To import all the functions:

import * as zadeh from "zadeh"

or

const zadeh = require("zadeh")

StringArrayFilterer

StringArrayFilterer is a class that allows setting the candidates only once and perform filtering on them multiple times. This is much more efficient than calling the filter function directly.

`StringArrayFilterer` API
export class StringArrayFilterer {
  /**
   * Make a `StringArrayFilterer` for the candidates that are going to be filtered.
   *
   * @param candidates An array of strings.
   */
  constructor(candidates?: Array<string>)

  /**
   * Filter the already set array of strings
   *
   * @param query A string query to match each candidate against.
   * @param options Options
   * @returns Returns an array of candidates sorted by best match against the query.
   */
  filter(query: string, options: StringArrayFilterOptions = {}): Array<string>

  /**
   * Filter the already set array of objects and get the indices of the chosen candidate
   *
   * @param query A string query to match the dataKey of each candidate against.
   * @param options Options
   * @returns Returns an array of numbers indicating the index of the chosen candidate sorted by the best match against the query.
   */
  filterIndices(query: string, options: StringArrayFilterOptions = {}): Array<number>

  /**
   * Allows setting the candidates (if changed or not set in the constructor).
   *
   * @param candidates An array of strings.
   */
  setCandidates(candidates: Array<string>)
}

Example:

const { StringArrayFilterer } = require("zadeh")

// create class
const strArrFilterer = new StringArrayFilterer()

// set the candidates
strArrFilterer.setCandidates(["Call", "Me", "Maybe"])

// call filter multiple times
strArrFilterer.filter("me")
strArrFilterer.filter("all")

ObjectArrayFilterer

ObjectArrayFilterer is a class that performs filtering on an array of objects based on a string stored in the given dataKey for each object

`ObjectArrayFilterer` API
export class ObjectArrayFilterer<DataKey extends string | number = string> {
  /**
   * Make an `ObjectArrayFilterer` for the candidates that are going to be filtered.
   *
   * @param candidates An array of objects.
   * @param dataKey The key which is indexed for each object, and filtering is done based on the resulting string
   */
  constructor(candidates?: Array<ObjectWithKey<DataKey>>, dataKey?: DataKey)

  /**
   * Filter the already set objects
   *
   * @param query A string query to match the dataKey of each candidate against.
   * @param options Options
   * @returns Returns an array of objects sorted by the best match against the query.
   */
  filter(query: string, options: ObjectArrayFilterOptions = {}): Array<ObjectWithKey>

  /**
   * Filter the already set array of strings and get the indices of the chosen candidate
   *
   * @param query A string query to match each candidate against.
   * @param options Options
   * @returns Returns an array of numbers indicating the index of the chosen candidate sorted by the best match against the query.
   */
  filterIndices(query: string, options: StringArrayFilterOptions = {}): Array<number>

  /**
   * Allows setting the candidates (if changed or not set in the constructor).
   *
   * @param candidates An array of objects.
   * @param dataKey The key which is indexed for each object, and filtering is done based on the resulting string
   */
  setCandidates(candidates: Array<ObjectWithKey<DataKey>>, dataKey: DataKey)
}

Example:

const { ObjectArrayFilterer } = require("zadeh")

const candidates = [
  { name: "Call", id: 1 },
  { name: "Me", id: 2 },
  { name: "Maybe", id: 3 },
]

// create a class and set the candidates
const objArrFilterer = new ObjectArrayFilterer(candidates, "name") // filter based on their name

// call filter multiple times
objArrFilterer.filter("me") // [{ name: 'Me', id: 2 }, { name: 'Maybe', id: 3}] // finds two objects
objArrFilterer.filter("all") // [{ name: 'Call', id: 1 }]

TreeFilterer

TreeFilterer filters the given query in the nodes of the given array of trees and returns an array of filtered trees (or the indices of the filter candidates). A tree object is an object in which each entry stores the data in its dataKey, and it has (may have) some children (with a similar structure) in its childrenKey

`TreeFilterer` API
export class TreeFilterer<DataKey extends string, ChildrenKey extends string> {
  /**
   * The method to set an array of trees that are going to be filtered
   *
   * @param candidates An array of tree objects.
   * @param dataKey The key of the object (and its children) which holds the data (defaults to `"data"`)
   * @param childrenKey The key of the object (and its children) which hold the children (defaults to `"children"`)
   */
  constructor(
    candidates?: Tree<DataKey, ChildrenKey>[],
    dataKey: DataKey = "data",
    childrenKey: ChildrenKey = "children"
  )

  /**
   * The method to set an array of trees that are going to be filtered
   *
   * @param candidates An array of tree objects.
   * @param dataKey The key of the object (and its children) which holds the data (defaults to `"data"`)
   * @param childrenKey The key of the object (and its children) which hold the children (defaults to `"children"`)
   */
  setCandidates(
    candidates: Tree<DataKey, ChildrenKey>[],
    dataKey: DataKey = "data",
    childrenKey: ChildrenKey = "children"
  )

  /**
   * Filter the already set trees
   *
   * @param query A string query to match the dataKey of each candidate against.
   * @param options Options
   * @returns {Tree[]} An array of filtered trees. In a tree, the filtered data is at the last level (if it has
   *   children, they are not included in the filtered tree)
   */
  filter(query: string, options: TreeFilterOptions = {}): Tree<DataKey, ChildrenKey>[]

  /**
   * The method to perform the filtering on the already set candidates
   *
   * @param query A string query to match the dataKey of each candidate against.
   * @param options Options
   * @returns {TreeFilterIndicesResult[]} An array candidate objects in form of `{data, index, parentIndices}` sorted by
   *   best match against the query. Each object has the address of the object in the tree using `index` and `parent_indices`
   */
  filterIndices(query: string, options: TreeFilterOptions = {}): TreeFilterIndicesResult[]
}

Example:

const { TreeFilterer } = require("zadeh")

const treeFilterer = new TreeFilterer()

const candidates = [
  { data: "bye1", children: [{ data: "hello" }] },
  { data: "Bye2", children: [{ data: "_bye4" }, { data: "hel" }] },
  { data: "eye" },
]
treeFilterer.setCandidates(candidates, "data", "children")
treeFilterer.filter("hel")

returns

;[
  { data: "Bye2", children: [{ data: "hel" }] },
  { data: "bye1", children: [{ data: "hello" }] },
]
treeFilterer.filter("bye")

returns

;[
  { data: "bye1", children: [] },
  { data: "Bye2", children: [{ data: "_bye4" }] },
  { data: "Bye2", children: [] },
]
treeFilterer.filterIndices("bye")

returns

;[
  { data: "bye1", index: 0, parent_indices: [] },
  { data: "_bye4", index: 0, parent_indices: [1] },
  { data: "Bye2", index: 1, parent_indices: [] },
]

score

score(string, query, options = {})

Score the given string against the given query.

  • string - the string to score.
  • query - The query to score the string against.
const { score } = require('zadeh')

score('Me', 'me')    # 0.17099999999999999
score('Maybe', 'me') # 0.0693

match

match(string, query, options = {})

Gives an array of indices at which the query matches the given string

const { match } = require("zadeh")

match("Hello World", "he") // [0, 1]
match("Hello World", "wor") // [6, 7, 8]
match("Hello World", "elwor") // [1, 2, 6, 7, 8]

wrap

wrap (string, query, options = {})

Gives an HTML/Markdown string that highlights the range for which the match happens

wrap("helloworld", "he")

helloworld

wrap("Hello world", "he")

Hello world

options

In all the above functions, you can pass an optional object with the following keys

{
    /** only for `filter` function */
    /** The key to use when candidates is an object */
    key?: T extends string ? never : keyof T

    /** only for `filter` function */
    maxResults?: number

    /** @default false */
    allowErrors?: boolean

    /** @default true */
    usePathScoring?: boolean

    /** @default false */
    useExtensionBonus?: boolean

    pathSeparator?: '/' | '\\' | string
}

Deprecated functions

These deprecated functions are provided to support the API of fuzzaldrin and fuzzaldrin-plus. However, you should replace their usage with StringArrayFilterer or ObjectArrayFilterer classes that allow setting the candidates only once and perform filtering on those candidates multiple times. This is much more efficient than filter or filterTree functions.

`filter` function

filter

filter(candidates, query, options = {})

Sort and filter the given candidates by matching them against the given query.

  • candidates - An array of strings or objects.
  • query - A string query to match each candidate against.
  • options - the options. You should provide a key in the options if an array of objects is passed.

Returns an array of candidates sorted by best match against the query.

const { filter } = require("zadeh")

// With an array of strings
let candidates = ["Call", "Me", "Maybe"]
let results = filter(candidates, "me") // ['Me', 'Maybe']

// With an array of objects
const candidates = [
  { name: "Call", id: 1 },
  { name: "Me", id: 2 },
  { name: "Maybe", id: 3 },
]

results = filter(candidates, "me", { key: "name" }) // [{name: 'Me', id: 2}, {name: 'Maybe', id: 3}]

Deprecation Note: use StringArrayFilterer or ObjectArrayFilterer class instead. filter internally uses this class, and in each call, it sets the candidates from scratch, which can slow down the process.

Comparison with other libraries

Zadeh vs Fuzzaldrin and Fuzzaldrin-plus

API is backward compatible with Fuzzaldrin and Fuzzaldrin-plus. Additional functions are provided to achieve better performance that could suit your needs

Zadeh achieves 10x-20x performance improvement over Fuzzaldrin plus for chromium project with 300K files. This high performance is achieved using the following techniques.

  • Uses native C++ bindings that provide ~4x performance benefit.
  • Use multiple threads to parallelize computation to achieve another ~4x performance benefit.
  • Some miscellaneous improvements provide additional benefits.

This project potentially solves the following Atom fuzzy-finder issues if used. atom/fuzzy-finder#271 and atom/fuzzy-finder#88

zadeh's People

Contributors

aminya avatar cdaguerre avatar dependabot[bot] avatar rajendrant avatar renovate-bot avatar snyk-bot avatar uzitech avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

zadeh's Issues

Add C++ interface

This library should be usable directly from C++

  • Changed the folder structure.
  • Make the files header-only
  • Add an index file that is callable from C++ (it should include the implementations from binding/node.cc

Higher score to filename matches

Thanks for this great library, it's really fast!

Summary

Prioritize (either by default or with some option) matches in the filename (i.e. not any of the folders/rest of path).

Additional context

Simple example:

> const zadeh = require('zadeh')
undefined
> zadeh.filter(['foo/bar/baz_qux.js', 'foo/bazqux/a.js'], 'bazqux')
Zadeh: deprecated function. Use 'StringArrayFilterer' instead
[ 'foo/bazqux/a.js', 'foo/bar/baz_qux.js' ]

In my usage, I would generally actually prefer the result for baz_qux.js because I remember and search mostly based on filename.

I do see useExtensionBonus option, couldn't find any clear documentation on what that actually means but it doesn't seem to make any difference.

Appveyor x86 fails

For some reason, Appveyor x86 fails to build the native modules

https://ci.appveyor.com/project/aminya/fuzzaldrin-plus-fast-se2je

> node-gyp-build
Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
  nothing.c
  win_delay_load_hook.cc
  nothing.vcxproj -> C:\projects\fuzzaldrin-plus-fast-se2je\node_modules\@parcel\source-map\build\Release\\nothing.lib
  SourceMap.cpp
  MappingContainer.cpp
  MappingLine.cpp
  Mapping.cpp
  win_delay_load_hook.cc
     Creating library C:\projects\fuzzaldrin-plus-fast-se2je\node_modules\@parcel\source-map\build\Release\sourcemap.lib and object C:\projects\fuzzaldrin-plus-fast-se2je\node_modules\@parcel\source-map\build\Release\sourcemap.exp
SourceMap.obj : error LNK2001: unresolved external symbol "struct std::atomic<bool> Napi::details::needs_objectwrap_destructor_fix" (?needs_objectwrap_destructor_fix@details@Napi@@3U?$atomic@_N@std@@A) [C:\projects\fuzzaldrin-plus-fast-se2je\node_modules\@parcel\source-map\build\sourcemap.vcxproj]
C:\projects\fuzzaldrin-plus-fast-se2je\node_modules\@parcel\source-map\build\Release\sourcemap.node : fatal error LNK1120: 1 unresolved externals [C:\projects\fuzzaldrin-plus-fast-se2je\node_modules\@parcel\source-map\build\sourcemap.vcxproj]
gyp ERR! build error 
gyp ERR! stack Error: `C:\Program Files (x86)\MSBuild\14.0\bin\MSBuild.exe` failed with exit code: 1
gyp ERR! stack     at ChildProcess.onExit (C:\projects\fuzzaldrin-plus-fast-se2je\node_modules\node-gyp\lib\build.js:194:23)
gyp ERR! stack     at ChildProcess.emit (events.js:314:20)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:276:12)
gyp ERR! System Windows_NT 6.3.9600
gyp ERR! command "C:\\Program Files (x86)\\nodejs\\node.exe" "C:\\projects\\fuzzaldrin-plus-fast-se2je\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
gyp ERR! cwd C:\projects\fuzzaldrin-plus-fast-se2je\node_modules\@parcel\source-map
gyp ERR! node -v v14.6.0
gyp ERR! node-gyp -v v6.1.0
gyp ERR! not ok 
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"ia32"})
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @parcel/source-map@2.0.0-alpha.4.13 install: `node-gyp-build`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the @parcel/source-map@2.0.0-alpha.4.13 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\appveyor\AppData\Roaming\npm-cache\_logs\2020-09-02T05_31_48_721Z-debug.log
Command exited with code 1

Choose a better name for the library

fuzzaldrin-plus-fast is exceedingly long, and it is not catchy at all. We should choose a better name for this library that is catchy and unique.

We don't have to follow the historical reasons for naming. The name should be independent of Atom, as this library can be directly used from C++ or other environments.

No zadeh prebuild for darwin-arm64

Prerequisites

Description

See pulsar-edit/pulsar#580 - I'm getting module load failures on an M1 mac perhaps because there is no matching prebuild.

It looks like the prebuild for arm macs is currently commented out in the CI.yml file, could we turn it back on and push a new version to NPM?

Steps to Reproduce

  1. Open Pulsar
  2. Have ide-rust or atom-ide-outline active
  3. Open a .rs file, ide-rust and atom-ide-outline fail to load zadeh

Expected behavior:

The packages to work even if a prebuild is missing

Actual behavior:

The loader fails with a node-gyp-build thrown error

Reproduces how often:

All the time

Versions

Pulsar: 1.105.0 arm64
Electron: 12.2.3
OS: macOS 13.4 (Darwin mobutu.local 22.5.0 Darwin Kernel Version 22.5.0: Mon Apr 24 20:52:24 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T6000 arm64)

zadeh v3.0.0-beta.4

ide-rust 1.1.2 
atom-ide-outline 3.2.0 

Additional Information

Failed to activate the atom-ide-outline package

At No native build was found for platform=darwin arch=arm64 runtime=electron abi=87 uv=1 armv=8 libc=glibc node=14.16.0 electron=12.2.3
    loaded from: /Users/nathan/.pulsar/packages/atom-ide-outline/node_modules/zadeh


Error: No native build was found for platform=darwin arch=arm64 runtime=electron abi=87 uv=1 armv=8 libc=glibc node=14.16.0 electron=12.2.3
    loaded from: /Users/nathan/.pulsar/packages/atom-ide-outline/node_modules/zadeh

    at Function.load.resolve.load.path (/packages/ide-rust/node_modules/node-gyp-build/node-gyp-build.js:60:9)
    at load (/packages/ide-rust/node_modules/node-gyp-build/node-gyp-build.js:22:30)
    at /packages/ide-rust/node_modules/zadeh/index.js:1:2743)
    at /packages/ide-rust/node_modules/zadeh/index.js:4:3)
    at Module._compile (/app.asar/src/native-compile-cache.js:120:30)
    at Object.value [as .js] (/Users/nathan/sources/pulsar/src/compile-cache.js:252:23)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12913)
    at Function.o._load (electron/js2c/renderer_init.js:33:379)
    at Module.require (internal/modules/cjs/loader.js:959:19)
    at require (/app.asar/src/native-compile-cache.js:67:27)
    at /packages/atom-ide-outline/dist/main.js:1:248)
    at /packages/atom-ide-outline/dist/main.js:4:3)
    at Module._compile (/app.asar/src/native-compile-cache.js:120:30)
    at Object.value [as .js] (/Users/nathan/sources/pulsar/src/compile-cache.js:252:23)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12913)
    at Function.o._load (electron/js2c/renderer_init.js:33:379)
    at Module.require (internal/modules/cjs/loader.js:959:19)
    at require (/app.asar/src/native-compile-cache.js:67:27)
    at requireModule (/Users/nathan/sources/pulsar/src/module-utils.js:3:17)
    at Package.requireMainModule (/app.asar/src/package.js:909:27)
    at Package.activateNow (/app.asar/src/package.js:232:34)
    at /app.asar/src/package.js:1085:18
    at Function.simpleDispatch (/app.asar/node_modules/event-kit/dist/emitter.js:64:14)
    at Emitter.emit (/app.asar/node_modules/event-kit/dist/emitter.js:257:28)
    at PackageManager.triggerDeferredActivationHooks (/Users/nathan/sources/pulsar/src/package-manager.js:804:34)
    at /Users/nathan/sources/pulsar/src/package-manager.js:733:12

Consecutive characters return more matches than expected

Description

If I filter for strings like aaaaa or tttt it returns more items than expected, both with filter and with ObjectArrayFilterer (didn't tested other filtering methods)

Steps to Reproduce

const z = require('zadeh')
z.filter(['one two', 'It is a test'], 'aaaaaa')
// => Returns ['It is a test'], even when there's only one "a" on it

Expected behavior:

To return nothing

Reproduces how often:

100%

Versions

3.0.0-beta.4

Faster way to convert a Napi::Array to a vector of string

Summarized from nodejs/node-addon-api#862

The problem

I have written an algorithm that works on a vector string. However, I am not sure if the way I convert a Napi::Array to a vector of the string is the most efficient way to do so. There is no documentation on this topic.

The conversion part currently takes 22ms which is half of the whole execution time of the program!

Here is a simplified example.

Napi::Value MyClass::makeVector(const Napi::CallbackInfo &info) {
  auto arr = info[0].As<Napi::Array>();
  const auto N = arr.Length();
  for (auto i = 0; j < N ; i++) {
      MyClass::myVector[i].emplace_back(static_cast<Napi::Value>(arr[j]).ToString().Utf8Value());
  }
  return Napi::Boolean();
}

The code:
Getting std::string from Napi::Array in C++
The loop for making vector of std::string
JS side

The context:

The data comes in an array of JavaScript strings.

The suggestions:

  1. Originally posted by @mhdawson in this comment

I made this suggestion in an issue a while back which I think addresses the same question: nodejs/node-addon-api#429 (comment)

If you need to more efficiently transfer an array between JS and Native, then Napi::ArrayBuffer may be better than using Napi::Array.


  1. Originally posted by @NickNaso in this comment

we discussed this in the documentation about Napi::Array here https://github.com/nodejs/node-addon-api/blob/master/doc/array.md.

Napi::TypedArray and Napi::ArrayBuffer correspond to JavaScript data types such as Napi::Int32Array and Napi::ArrayBuffer, respectively, that can be used for transferring large amounts of data from JavaScript to the native side. An example illustrating the use of a JavaScript-provided ArrayBuffer in native code is available here.

In general, the conversion from JavaScript type to native type has a cost. In your code for example I can imagine that your JavaScript code is something like this:

// ...
const NUMBER_OF_ELEMENTS = 1000
const arr = []
for (let i = 0; i <NUMBER_OF_ELEMENTS; i++) {
    arr.push(${i})
}
addon.makeVector(arr);
// ...

On the native side when you call Napi::String::Utf8Value() method you are creating a new std::string so the value is copied from the underlying JavaScript value to the native std::string.
This clould be more clear if you take a look at the implementation of Napi::String::Utf8Value():

inline std::string String::Utf8Value() const {
  size_t length;
  napi_status status = napi_get_value_string_utf8(_env, _value, nullptr, 0, &length);
  NAPI_THROW_IF_FAILED(_env, status, "");

  std::string value;
  value.reserve(length + 1);
  value.resize(length);
  status = napi_get_value_string_utf8(_env, _value, &value[0], value.capacity(), nullptr);
  NAPI_THROW_IF_FAILED(_env, status, "");
  return value;
}

  1. Originally posted by @aminya in this comment

So, if I convert my JavaScript array of string to an ArrayBuffer, and then pass it to my native addon, that would improve the speed? or this JavaScript-side conversion is an anti-pattern.

I am not sure if I can change my interface to use ArrayBuffer from the beginning. It can be a new interface.

By conversion on the JavaScript side, I mean something like this:

const textEncoder = new TextEncoder();
function encodeString(str) {
	return textEncoder.encode(str)
}

function encodeArrayString(arr) {
	const len = arr.length
	const result = new Array(len)
	for (let i = 0; i < len; i++) {
		result[i] = textEncoder.encode(arr[i])
	}
	return result
}

Cannot update to the latest version on Arch Linux

Hello,
My current version of Atom is 1.56.0 x64

I have installed an older version of atom-ide-vue - 1.3.1 which is working fine. But now i want to update to the latest version (1.4.6).
But when i try to update to the latest version there is an error:

> [email protected] install /tmp/apm-install-dir-2021410-6757-zo74x0.n9he/node_modules/atom-ide-vue/node_modules/zadeh
> node-gyp-build


npm WARN deprecated [email protected]: TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.
sh: line 1: /tmp/apm-install-dir-2021410-6757-zo74x0.n9he/node_modules/atom-ide-vue/node_modules/.bin/node-gyp-build: Permission denied
npm WARN enoent ENOENT: no such file or directory, open '/tmp/apm-install-dir-2021410-6757-zo74x0.n9he/package.json'
npm WARN apm-install-dir-2021410-6757-zo74x0.n9he No description
npm WARN apm-install-dir-2021410-6757-zo74x0.n9he No repository field.
npm WARN apm-install-dir-2021410-6757-zo74x0.n9he No README data
npm WARN apm-install-dir-2021410-6757-zo74x0.n9he No license field.

npm ERR! code ELIFECYCLE
npm ERR! errno 126
npm ERR! [email protected] install: `node-gyp-build`
npm ERR! Exit status 126
npm ERR! 
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

I have other addons that just got updated successfully.
I'm using Archlinux.

Registering 1.0.0

@rajendrant Can we release 1.0.0? The repo has reached a good stable state. I want to include the prebuilt binaries in the npm package, so the users don't have to rebuild

Writing a native `match` function

Currently match and some other functions are provided using the original fuzzaldrin-plus. It would be nice to write their native version.

Fuzzy search inside a tree data structure

In Atom-IDE packages, such as atom-ide-outline, we use tree data structure a lot. It would be nice if we can search through them!

Each entry has some children which each may have some! If we can search through these and return the address of the found Nodes somehow, it would be awesome. For example,

search(tree, "hello") 

would return something like: tree[1].entries[1].entries[2].entries[3] or something similar which we can use to query quickly in JavaScript.

https://github.com/atom-ide-community/atom-ide-outline/blob/ed10b82e4cfedc591a3816744383c2c1e4ee4816/src/outlineView.ts#L3

The easiest way to implement this is to convert the tree to a big array, then search through it, and then return the address for the elements.

Here is a JavaScript code for the old atom-ide-ui:
https://github.com/facebookarchive/atom-ide-ui/blob/710f8477607d3788aeadcbdd55079925241ce40d/modules/atom-ide-ui/pkg/atom-ide-outline-view/lib/OutlineViewSearch.js#L52

There is quite similar functionality in fuse.js:
https://fusejs.io/examples.html#nested-search

Make Tree an independent class

Currently, a Tree is made on each call to filterTree. However, we can do much better if we make Tree an independent class which exposes setCandidates similar to Fuzzaldarin class.

Document setCandidates methods

We need to add setCandidates methods to the readme. In a lot of applications, the candidates are prepared only once. We should not convert them every time from JavaScript on each call to filter or filterTree.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.