Code Monkey home page Code Monkey logo

fzy's Introduction

fzy

fzy is a fast, simple fuzzy text selector for the terminal with an advanced scoring algorithm.

Try it out online!

It's been kind of life-changing. -@graygilmore
fzy works great btw -@alexblackie

Build Status

Why use this over fzf, pick, selecta, ctrlp, ...?

fzy is faster and shows better results than other fuzzy finders.

Most other fuzzy matchers sort based on the length of a match. fzy tries to find the result the user intended. It does this by favouring matches on consecutive letters and starts of words. This allows matching using acronyms or different parts of the path.

A gory comparison of the sorting used by fuzzy finders can be found in ALGORITHM.md

fzy is designed to be used both as an editor plugin and on the command line. Rather than clearing the screen, fzy displays its interface directly below the current cursor position, scrolling the screen if necessary.

Installation

macOS

Using Homebrew

brew install fzy

Using MacPorts

sudo port install fzy

Arch Linux/MSYS2: pacman -S fzy

FreeBSD: pkg install fzy

Gentoo Linux: emerge -av app-shells/fzy

Ubuntu/Debian: apt-get install fzy

pkgsrc (NetBSD and others): pkgin install fzy

openSUSE: zypper in fzy

From source

make
sudo make install

The PREFIX environment variable can be used to specify the install location, the default is /usr/local.

Usage

fzy is a drop in replacement for selecta, and can be used with its usage examples.

Use with Vim

fzy can be easily integrated with vim.

function! FzyCommand(choice_command, vim_command)
  try
    let output = system(a:choice_command . " | fzy ")
  catch /Vim:Interrupt/
    " Swallow errors from ^C, allow redraw! below
  endtry
  redraw!
  if v:shell_error == 0 && !empty(output)
    exec a:vim_command . ' ' . output
  endif
endfunction

nnoremap <leader>e :call FzyCommand("find . -type f", ":e")<cr>
nnoremap <leader>v :call FzyCommand("find . -type f", ":vs")<cr>
nnoremap <leader>s :call FzyCommand("find . -type f", ":sp")<cr>

Any program can be used to filter files presented through fzy. ag (the silver searcher) can be used to ignore files specified by .gitignore.

nnoremap <leader>e :call FzyCommand("ag . --silent -l -g ''", ":e")<cr>
nnoremap <leader>v :call FzyCommand("ag . --silent -l -g ''", ":vs")<cr>
nnoremap <leader>s :call FzyCommand("ag . --silent -l -g ''", ":sp")<cr>

Sorting

fzy attempts to present the best matches first. The following considerations are weighted when sorting:

It prefers consecutive characters: file will match file over filter.

It prefers matching the beginning of words: amp is likely to match app/models/posts.rb.

It prefers shorter matches: abce matches abcdef over abc de.

It prefers shorter candidates: test matches tests over testing.

See Also

fzy's People

Contributors

0mp avatar artdevjs avatar casprwang avatar casr avatar cisenor avatar d-e-s-o avatar duncaen avatar eraserhd avatar erichdongubler avatar erlliam avatar farisachugthai avatar gpanders avatar gyakovlev avatar henrymarshall avatar jhawthorn avatar keith avatar legendre6891 avatar lenormf avatar michaelmackus avatar mikeastock avatar momo-lab avatar neuschaefer avatar sanjaymsh avatar sbdchd avatar srstevenson avatar svenstaro avatar syrrim avatar theosotr avatar tstearns avatar wfxr 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fzy's Issues

Key bindings

Custom key bindings like fzf

fzf --bind=ctrl-j:accept,ctrl-k:kill-line

Also bash/zsh keybinds for movement (ctrl-b, ctrl-f, alt-b, alt-f, ctrl-a, ctrl-e)

fzy should ignore bracketed paste characters.

Zsh since 5.1 have a bracketed-paste support. When I run fzy via hotkey, and paste anything, additional characters are pasted into the output.

The zsh snippet:

# Insert path selected with fzy into command line on ^F press.
_select_path_with_fzy() {
    local selected_path
    if ! command -v fzy >/dev/null 2>&1; then
        echo 'No fzy binary found in $PATH.'
        return 1
    fi
    echo
    selected_path="$(find -L . | cut -c 3- | fzy)"
    if [ "${selected_path}" ]; then
        LBUFFER+="${(q)selected_path}"
    fi
    zle reset-prompt
}
zle -N _select_path_with_fzy
bindkey "^F" _select_path_with_fzy

fzf seems to ignore[1] them, how about fzy dropping them too?

[1] junegunn/fzf@b8737b7

Multi-select

Hi! I'd like to try out fzy as a replacement with fzf for my workflows because of the better ranking. (Thanks for the great software and simple Makefile). However, I have one use case that's important to me but fzy doesn't provide AFAIK: opening multiple files I've selected in Vim (in splits or buffers):

Simplified:

# Open files listed on stdin in $EDITOR.
vimin () {
    runargs ${EDITOR:-vim} -O
}

# Can select multiple files and have them open in splits.
ag | fzf -0 -1 -m | vimin

# No multi-select.
ag | fzy | vimin

(The lack of streaming matching is also a bit problematic, which is why I +1'd the issue discussing this. I often use a FUSE network filesystem which cannot reasonably be queried, but I like to get the first levels of matches with something like https://github.com/tavianator/bfs.)

handle high load

Thank you for creating a fzf alternative in C. I love it!

I just did a compare bw fzf and fzy with command

find / | fzf
find / | fzy

fzy waits, but fzf runs right away with result avaiable from find. I wish we could add that feature to fzy.

I think this feature is critical when we working with big projects.

Thank you

Support streaming

Current fzy implementation waits until stdin ends. Which is undesirable if input program takes a very long time or does not have the end. For example,

  • find . | fzy in Windows
  • cat ./unix_socket | fzy

I'm fzf user but I'm using fzy in Windows. If fzy supports streaming I can finally move away from fzf. Do you have any plan to support streaming?

Option to not highlight matching segments

Normally, when I search, the matching segments give little information to me. I am just scanning for the file name I am looking for and find them actually distracting (though interesting technically!).

The reverse video for the current selection is perfect though, since the current selection is prominent.

Would it be possible to have a flag to disable highlighting segments? I am the author of a minimalistic Vim colorscheme (https://github.com/fxn/vim-monochrome) and as a bonus aesthetically it would match the theme really well.

Cursor jumps to second line if enter is pressed before fzy starts

Hi,
I sometimes enter a search pattern (and press enter) faster than fzy starts up. I'd expect the first result to be selected in that case, but instead, the cursor moves to the second line.

Test case:

$ (echo a; echo b; echo c; sleep 1) | fzy<enter><enter>

I realize that this is because the code for CTRL-J is the same as '\n'. After fzy starts up, the enter key mapped to '\r', via termios.

Thus, a solution would involve:

  1. Reading the input once, non-blockingly; preferably before the terminal is configured with termios, to avoid false conversions from CTRL-J to '\r'
  2. Replacing all occurences of '\n' with '\r' in the early input
  3. Feeding the converted early input into the input state machine

I'm not sure the added complexity would be justified, so perhaps take this issue as the beginning of a discussion, rather than a bug report or feature request.

SHA1 is deprecated in brew

Warning: Calling Formula.sha1 is deprecated!
Use Formula.sha256 instead.
/usr/local/Library/Taps/jhawthorn/homebrew-fzy/Formula/fzy.rb:6:in `class:Fzy'
Please report this to the jhawthorn/fzy tap!

Custom ctrl-p match function

It would be nice to be able to combine the ctrl-p with fzy. The awesome fuzziness of fzy with the nice Vim integration of ctrl-p. I imagine it would be possible by creating a custom g:ctrlp_match_func. However my Vimscript knowledge is super poor, so I was kind of looking for help on the matter.

Feel free to close though if you feel this isn't relevant to fzy as a project. But I figured since you mention Vim integration (and ctrl-p) in the README, it might be worth a shot to ask.

CLI flag for "Match only, don't sort"

The sorting is spectacular, except when you are trying to do a Most Recently Used (MRU) list

vim $(awk '/^> /{ print substr($0, 3) }' ~/.viminfo | fzy)

You lose the "Recency" immediately after starting to type.

Exit fzy, exit script.

Hi

If I'm using fzy in a script, and I CTRL-C to abort, I would like to exit the script. Currently, fzy aborts, but the script continues.

Example:

#!/bin/sh

file=$(echo 'foo' | fzy)

cp "$file" ~/

CTRL-C while fzy is displaying 'foo' passes 'foo' to the cd command.

I currently work around this using, for example:

#!/bin/sh

file=$(echo 'foo' | fzy)
case "$?" in
	0) : ;;
	1) exit 1 ;;
esac

cp "$file" ~/

In this case, CTRL-C while fzy is displaying 'foo' will abort the script.

(It occurs to me that CTRL-C is undocumented, and maybe you're not interested?)

Segmentation fault

1. ls | fzy
2. type anything (more than a few words)
3. C-a
4. C-w (multiple times until everything is deleted; cursor goes suddenly right)
5. Space (maybe multiple times)
6. Segmentation fault

Multiple patterns delimited by spaces

Please add a mode to fzy so search with multiple patterns. (see the EXTENDED SEARCH MODE in fzf man page)
In this mode, spaces don't match a literal space character, but acts as delimiters of patterns, and each pattern is matched independently.
In this mode, with two patterns, a string should get lower score, if the two patterns matches directly next to each other.
A string should get a higher score, if the patterns match in the order they are given in the prompt.
(Currently, using this mode of fzf gives better results with less typing)

Feature request: Allow movement to the beginning/end of the query

It often happens that I start typing a query only to see that it's not matching what I want because I should have included some text at the beginning of the query. My only option at that point is to abort the query and start over.

It would be nice if instead of aborting and starting over, fzy allowed me to enter text at the beginning of the query without deleting what I've already typed, and then also allow moving to the end of the typed query to continue typing there as well (if necessary).

(Ultimately, it would be ideal (for me) if fzy supported something like vim editing commands -- maybe through readline support. But simply allowing one to add on to the beginning/end of the query would be a great enhancement.)

‘for’ loop initial declarations are only allowed in C99 mode

Pulled down master, ran make, got this:

osboxes@osboxes:~/bin/fzy(master)% make                                                                                                                                                                                                                                          {1}
cc -DVERSION=\"0.2\" -Wall -Wextra -g -O3 -pedantic -c -o fzy.o fzy.c
fzy.c: In function ‘clear’:
fzy.c:43:2: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
  size_t line = 0;
  ^
fzy.c: In function ‘draw_match’:
fzy.c:53:2: warning: ISO C90 forbids variable length array ‘positions’ [-Wvla]
  size_t positions[n + 1];
  ^
fzy.c:54:2: error: ‘for’ loop initial declarations are only allowed in C99 mode
  for (int i = 0; i < n + 1; i++)
  ^
fzy.c:54:2: note: use option -std=c99 or -std=gnu99 to compile your code
fzy.c:57:2: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
  double score = match_positions(search, choice, &positions[0]);
  ^
fzy.c:67:14: error: conflicting types for ‘i’
  for (size_t i = 0, p = 0; choice[i] != '\0'; i++) {
              ^
fzy.c:54:11: note: previous definition of ‘i’ was here
  for (int i = 0; i < n + 1; i++)
           ^
fzy.c:67:2: error: ‘for’ loop initial declarations are only allowed in C99 mode
  for (size_t i = 0, p = 0; choice[i] != '\0'; i++) {
  ^
fzy.c: In function ‘draw’:
fzy.c:96:2: error: ‘for’ loop initial declarations are only allowed in C99 mode
  for (size_t i = start; i < start + num_lines; i++) {
  ^
fzy.c:99:3: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
   const char *choice = choices_get(choices, i);
   ^
fzy.c: In function ‘run’:
fzy.c:128:2: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
  char ch;
  ^
fzy.c: In function ‘main’:
fzy.c:265:2: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
  choices_t choices;
  ^
fzy.c:277:3: error: ‘for’ loop initial declarations are only allowed in C99 mode
   for (int i = 0; i < benchmark; i++)
   ^
fzy.c:281:3: error: ‘for’ loop initial declarations are only allowed in C99 mode
   for (size_t i = 0; i < choices_available(&choices); i++) {
   ^
make: *** [fzy.o] Error 1

Not sure what other information would be helpful, please let me know how I can help debug.

Idea: multi-word mode as conjunction

Fzy has a really nice algorithm! One thing many other fuzzy file finders do is split the input on whitespace and use it as a conjunction, i.e. every word needs to match the line (but in any order). Currently, it's a bit hard to use fzy because all letters would need to be in correct order...

E.g. you want to find a pdf in your home folder belonging to project bar, then you need to type "homebarpdf" currently, but with my proposal, you could type "pdf home bar"... as long as all words match somewhere.

Bonus points for negation, e.g. "pdf -bar home" to remove matches for "bar".

Proper handling of UTF-8

Thanks for fixing the previous (utf-8) bug.
If the filename contains some non-ASCII character, fzy doesn't segfault anymore.
Having that in mind, it's not possible to insert (while seaching) some non-ASCII character.
If I insert characters like öäßéè etc., fzy doesn't show anything.

Best regards.

fzy: either allow -q to have no argument or accept any string as -q

I am trying to set up an alias like:

alias fzyfind=find . | fzy

but if I want to start with a query I have to specify the -qoption, and I cannot add it to the alias because then I cannot use the alias without specifying a start query.

Is the -q option necessary? Could not the argument that is not an option just always be the intital query?

Feature request: Literal search

I'd like to replace my shell's ordinary control-r history search completely with fzy, but I can't because fzy only does fuzzy searching and I sometimes need to ordinary, non-fuzzy, literal searches.

It would be nice if fzy allowed the user to switch search types from fuzzy to literal. Ideally, this could be done with either a command line option or via a keyboard shortcut. This way the user could switch from one to the other when the current search is not returning what they want without having to start all over.

[Idea] Server mode

I keep thinking on how awesome would be to have a server mode to give a much better IPC so that it's easier to build plugins with this kind of functionality, eg: a nvim plugin.

My current plan is to use Unix Domain sockets and to provide 4 operations:

  • Initialize Bucket: Will create and initialize a new bucket, which is basically a container for the provided inputs and can be searched multiple time.
  • Search: the actual fuzzy finder, which will return a list of matching for the given input in the given bucket. This should have some way to highlight characters in the same fashion as it already does. Would be nice to provide also the score and each pos to highlight, but this could come in a second iteration.
  • Insert: will insert values in a bucket. Basically an incremental insert
  • Remove: will remove the given values from the bucket. Same behavior as Insert

The buckets will be stored in memory for now, but next iterations could introduce a persisting operation.

Right now I think it would be easy to provide some custom protocol to build it on, like:

Search protocol:
1 Byte for OP
1 Byte for Bucket ID
N Byte for search term (up to 1024)
1 Null byte to signal termination

If succeeds, will respond with:
1 Null Byte for signaling Success
4 Byte Nr. of results
8 Byte Total nr. of searched strings
N Byte null byte separated results

If fails:
1 Non-Null Byte Error code

However I'm also considering to use msgpack for easier extensibility; the problem is that I've never used it and could take some time to start with xD

What do you think? Any suggestion? :)

Right align output by default

Currently long lines are simply cut off on the right, making it impossible to differenciate between lines that have the same beginning, like particulary long paths:

/home/jh/imagine/a/long/path/here/somefile.txt
/home/jh/imagine/a/long/path/here/otherfile.txt

... will display as:

/home/jh/imagine/a/long/pa
/home/jh/imagine/a/long/pa

... should rather display as:

th/here/somefile.txt
th/here/otherfile.txt

(BTW the speed advantage of fzy over fzf is impressive)

unit test fails in i386 platform

See https://bugs.debian.org/860207, it has the following error during build in i386 platform.


...
   dh_auto_test -a
	make -j4 test
make[1]: Entering directory '/«PKGBUILDDIR»'
cc -g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security -Wall -Wextra -g -std=c99 -O3 -pedantic  -Isrc -o test/fzytest test/fzytest.c src/match.o src/choices.o -lpthread
./test/fzytest
test "test_exact_scores" failed
   assert(match("a", "*a") == SCORE_GAP_LEADING) was false
   at test/fzytest.c:81

14 tests, 80 assertions, 1 failures
Makefile:28: recipe for target 'check' failed
make[1]: *** [check] Error 1

The prompt fills the screen if the search result line is too long

Sorry I thought #54 fixed this but I have just found another instance where this occurs with or without scores.

Test case:

cd /path/to/src/fzy
git reset --hard 0ee47c2
make clean ; make
ag --nogroup '^' | ./fzy

and at the prompt do type jjj and then repeatedly switch between having jj and jjj. The prompt soon fills up the screen.

Related to #47.

Visual defects in neovim

I tried the example from the README.md with neovim and found visual flaws. Lines are displayed indented as a ladder. If you enter a few characters, then nothing on the screen can be understood.

Shell integration (testing waters for a PR)?

I've been curious enough about shell integration for fzy that I've started studying the integration fzf has, to see what's possible for making something comparable. What I want to know is:

  • Would you be open to a PR contributing such an entrancement, pending further discussion on actual features associated?
  • Where would this go in the repo? The contrib folder?

Feature request: Regular expression search

Today I needed to search for something that I knew occurred exactly at the end of a line. I tried $ but fzy took that to be the literal character $. Then I tried \$ and fzy interpreted those as two literal characters: \ and $.

It would be great if fzy supported regular expression search. Even supporting the most basic regex sequences like ^ and $ would be really useful.

To maintain consistency with other regex engines, it would probably make sense to require the user to escape literals that clash with regexes, so that (for example) the user would have to type \$ to get a literal $ and $ without a leading backslash would be interpreted as a regex.

Disregard certain fields when selecting

When fuzzy searching paths, I find myself never typing first parts:

/home/jh/documents/about-catz.txt
/home/jh/downloads/donkey.png

If we fzy the string "do" in this example, we'd still get both lines as a result.

If we could tell fzy to display full lines, but disregard parts of the text upon selection - the first three directories in the hierarchy, in this case - it would be possible to just return a single result.

In fzf this would be done with --delimiter='/' --with-nth=4.., but maybe some other solution, like non-greedy regex would help too.
(Whatever causes less performance impact.)

[Question] Which is correct?

Thank you for this great product! This is awesome 👍

BTY, I wonder these behaviors.

(A).

$ cat file
ABC
abc
...
...
xyz
XYZ
$ cat file | fzy
>
ABC
abc
...
...
xyz
XYZ

(B).

$ cat file
ABC
abc
...
...
...
xyz
XYZ
$ cat file | fzy
>
...
abc
...
ABC
...
xyz
XYZ

(C).

$ cat file
ABC
abc
...
...
...
...
xyz
XYZ
$ cat file | fzy
>
XYZ
abc
...
...
...
...
xyz
ABC

It is no use increasing dots' lines. Which is correct? All? I hope (C) (A) behavior in any case. Thanks!

Make only part of input searchable

Suppose I want to fzy filter grep -rHn results. For me matches in file names are useless and just complicate things. If you would add something like fzy --filter='cut -d" " -f2, or something like that so that users could say what part of input is actually searchable this would solve this problem.

Wrong result dealing with control escape chars

escape

escape_semi

no_escape

Colored output contains escaped chars like \x1b[30m;, so pattern containing m or ; may results wrong matches.

I am aware there's always a workaround to remove the color. Or should fzy remove escape code while choices_fread?

Enabling scores causes the prompt to move if the line is too long

Example command: echo $(find . | fzy -s)

If you run the above and one of the matches exceeds the length of the line then the prompt moves further down the terminal.

In normal operation (i.e. without -s) the line length is clipped to the columns on the display. When matches are enabled it seems that the extra space required to show scores was not factored into the line clipping algorithm.

Tested on MacOS 10.12.4, zsh 5.3.1 and fzy 0.9

Provide Appimage

It would be great, if you could also provide an AppImage with your releases.

sha1 deprecation by homebrew

Warning: Calling Formula.sha1 is deprecated!
Use Formula.sha256 instead.
/usr/local/Library/Taps/jhawthorn/homebrew-fzy/Formula/fzy.rb:6:in `<class:Fzy>'
Please report this to the jhawthorn/fzy tap!

Warning: Calling SoftwareSpec#sha1 is deprecated!
Use SoftwareSpec#sha256 instead.
/usr/local/Library/Taps/jhawthorn/homebrew-fzy/Formula/fzy.rb:6:in `<class:Fzy>'
Please report this to the jhawthorn/fzy tap!

Warning: Calling Resource#sha1 is deprecated!
Use Resource#sha256 instead.
/usr/local/Library/Taps/jhawthorn/homebrew-fzy/Formula/fzy.rb:6:in `<class:Fzy>'
Please report this to the jhawthorn/fzy tap!

Fzy doesn't redraw screen after executing command

Hi, I'm using ArchLinux with st-256color terminal and tmux, with default install from AUR.
After executing vim $(find -type f | fzy) the last search line (10th) stay on screen after closing vim.

Automatically select the only match if --query is provided

When doing fzy --query="foobar" and "foobar" results in one single match, return it directly (see --select-1 switch in fzf).

This, in combination with "Exit immediately when there's no match" (--exit-0in fzf) is extremely useful in scripting as it allows for getting a matching result even faster.

Segfault when using fzy if the filename contains non-ASCII character(s)

If the directory contains, for example, the following name:

Edmund Husserl - Méditations cartésiennes - Introduction a la phénoménologie.pdf

and if I execute, for example:

ls -l | fzy

The program segfaults. (This é is the problem.)
Easily reproducible: just create a filename with the above name and run the above command.

Not working for large input. Buffering?

EDIT: Sorry, an issue already exists. Closing this.

cd ~/projects/fzy
find . type -f | fzy
# works as expected

cd $HOME
find . type -f | fzy
# waits a long time for find to complete before showing fzy prompt

I tried using unbuffered lines, but that doesn't work either: stdbuf -oL -eL find . -type f | fzy

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.