Giter VIP home page Giter VIP logo

pipes.sh's People

Contributors

dsamarin avatar foggalong avatar johndduncaniii avatar livibetter avatar parkercoates avatar wkentaro 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

pipes.sh's Issues

Who is the original author of pipes.sh?

As I wrote in README:

The author of the original script is unknown to me. The first entry I can
find was posted at 2010-03-21 09:50:09 on Arch Linux Forums (doesn't mean the
poster is the author at all).

I really want to properly license this project, so I think we need a place to gather information, somebody must know something. If you know anything about pipes.sh, please leave a comment.

Update manpage and add history to README

  • -K and -c options (#20)
  • bring the version and date up to date
  • add COPYRIGHT section
  • add HISTORY section, use text from website.
    • also add to README
  • update AUTHOR section
    • add original author info
    • replace maintainer as maintained at Pipeseroni/pipes.sh
  • remove "more complete description" and fix the descriptions, manpage should be self-contained.

"error setting terminal attributes: Interrupted system call" when focusing back on the terminal

When focus is removed from the terminal onto any other application, on resuming focus onto the terminal, the following message appears where the cursor is currently at.

usr/local/bin/pipes.sh: line 101: read: error setting terminal attributes: Interrupted system call

This happens on macOS in both iTerm2 and Terminal. The length of time where the terminal is out of focus seems irrelevant. This also occurs when simply switching between tabs.

image

Organization for pipes

I've wanted to create an organization for some time, especially after v1.0.0 and seeing woolmark.

It would host these repositories, a place to keep those pipes and related stuff such as weave.sh:

Here is what needs to be done:

  1. I need a good name that can represent these pipes.

    Unfortunately, @pipes is already taken. Sadly, dot (.) isn't allowed in username, therefore pipes.sh is not possible and I actually don't want to use a name would imply shell script even that is the starting point.

  2. I hope @OneLastTry would agree to transfer Snakes to the new organization.

And possibly -- would not be done by me:

  1. encouraging people, who have ideas to improve pipes or would implement in other languages, to join.
  2. gh-pages (not of pipes.sh repository) shows crawling pipes behind the introduction of pipes with additional JavaScript implementation in new repository.
  3. giving more attention to the C version and hopefully getting into distributions.
  4. finding out the author #13.
  5. becoming the homepage of pipes.sh.
  6. inspiring stuff related to pipes.
  7. icon/avatar.

Please feel free to join the discussion and share your thoughts.

Changes the colour of the terminal text

Ubuntu terminator. Upon exiting pipes it changes the colour of the terminal text to the colour of the last pipe drawn until that terminal window is closed. It only affects the terminal pipes was ran in. This could almost be marketed as a feature instead of a bug but some of the pipes are white and black meaning that people with terminals of those colours won't be able to see their commands.

screenshot - 090314 - 11 10 17
screenshot - 090314 - 11 09 41
screenshot - 090314 - 11 09 27
screenshot - 090314 - 11 09 55
screenshot - 090314 - 11 09 09

No keys to exit with Bash versions < 4

There was an issue with Bash on Mac, which seems to be version 3.2 and the version doesn't support read with fractional timeout, although it's (hopefully, I don't have Mac to test) fixed in 8ef9045, it has another issue.

With Bash >= 4, you can press any key to quit the script, but not with < 4.

If the scripts sleep and read, the read never seems to get the input. Because the different behaviors between versions, I consider this is a bug.

If you have a fix for this, please create a pull request.

Error message produced on Mac

This is on Mac OS X El Capitan installed via homebrew

Terminal Window

The program itself works fine I just want to now how to silence the error message. It is also particularly bad when running tmux.

Script freezes when pressing arrow keys

When I press an arrow key the script should quit but instead if freezes, then I have to close it with Ctrl-C, when I press for example the A key the script closes correctly. It also freezes when pressing some strange key combination like Ctrl-Alt-A
I don't know bash scripting, but I started to comment lines until I found that the command that was stopping the script was in the cleanup() function. When I comment cat </dev/stdin>/dev/null pipes.sh closes correctly when pressing arrow keys
What is the purpose of cat </dev/stdin>/dev/null?
Sorry for my english

pipes.sh: 第 100 行:read: 设定终端属性时出错: Interrupted system call

pipes.sh: 第 100 行:read: 设定终端属性时出错: Interrupted system call

on Mac OS

# bash -version
GNU bash,版本 4.3.33(1)-release (x86_64-apple-darwin14.1.0)
Copyright (C) 2013 Free Software Foundation, Inc.
许可证 GPLv3+: GNU GPL 许可证第三版或者更新版本 <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Trouble installing

gawd@tushbox:~/Downloads$ tar -xvzf pipes.sh-1.3.0.tar.gz
pipes.sh-1.3.0/
pipes.sh-1.3.0/.github/
pipes.sh-1.3.0/.github/ISSUE_TEMPLATE.md
pipes.sh-1.3.0/.github/ISSUE_TEMPLATE/
pipes.sh-1.3.0/.github/ISSUE_TEMPLATE/BUG.md
pipes.sh-1.3.0/CONTRIBUTING.rst
pipes.sh-1.3.0/LICENSE
pipes.sh-1.3.0/Makefile
pipes.sh-1.3.0/README.rst
pipes.sh-1.3.0/i/
pipes.sh-1.3.0/i/pipes.png
pipes.sh-1.3.0/i/pipes.t0.png
pipes.sh-1.3.0/i/pipes.t1.png
pipes.sh-1.3.0/i/pipes.t2.png
pipes.sh-1.3.0/i/pipes.t3.png
pipes.sh-1.3.0/i/pipes.t4.png
pipes.sh-1.3.0/i/pipes.t5.png
pipes.sh-1.3.0/i/pipes.t6.png
pipes.sh-1.3.0/i/pipes.t7.png
pipes.sh-1.3.0/i/pipes.t8.png
pipes.sh-1.3.0/i/pipes.t9.png
pipes.sh-1.3.0/i/pipes.tc.png
pipes.sh-1.3.0/pipes.sh
pipes.sh-1.3.0/pipes.sh.6
gawd@tushbox:~/Downloads$ cd pipes.sh-1.3.0
gawd@tushbox:~/Downloads/pipes.sh-1.3.0$ make install
test -d /usr/local || mkdir -p /usr/local
test -d /usr/local/bin || mkdir -p /usr/local/bin
test -d /usr/local/share/man/man6 || mkdir -p /usr/local/share/man/man6
mkdir: cannot create directory ‘/usr/local/share/man/man6’: Permission denied
Makefile:15: recipe for target 'install' failed
make: *** [install] Error 1

Ubuntu 18.04, downloaded the latest release tarball, unpacked but having trouble installing.

Option for pipe to randomize location when wrapping

this is useful when running pipes in a small window, to avoid the pipes grouping up in one area like in this screenshot:

Screenshot_20240309_134013

I propose this to be an option because it can be nice to have the pipes warp, alternatively it can be worked into the -K option (or well, the inverse) so that pipes wrap when using -K but "respawn" when not using it

Don't clear screen option

It would be nice to have a command line option so that the screen is not cleared. Right now, if you suspend pipes (C-z), type some stuff, then resume pipes, it will draw on top of the dirty terminal and I think it looks really cool! It might be as simple as toggling tput clear on line 268? I'll give it a try when I have some time.

Pipes don't dissapear upon exiting.

Edited by @livibetter

The issue actually roots to the terminal capabilities, smcup and rmcup, as well as issue with tput reset. Without them there is no storing and restoring, therefore the cursor and screen data won't be restored to before pipes.sh is invoked.


Original message:

Ubuntu terminator, pipes do not disappear upon exiting the program. They do disappear once a command has being typed over the space they filled but only then.

screenshot - 090314 - 11 09 55

screenshot - 090314 - 11 09 41

Question mark instead of pipes.

I'm currently on Ubuntu 16.04, with various personalized font installed (font awesome, monaco, consolas). I've also installed consolas, that as far as i can see is the font on the readme file here on github, but when i run pipes, just question marks appears.

invalid timeout specification

I'm trying to run this on ZSH, OS X. I get this error, pointing to line 102 (can't really copy paste it, it flies by during runtime) and the script doesn't work.

Put this on AUR

I would love to see this put on the AUR. It would make updating and everything much easier. That would be awesome!

Request for Pacstall Support

Pacstall is a community-driven AUR-like package manager for Ubuntu. We have an ongoing pull request to add Pipes.sh to our repository.

We have a few questions for you:

  • Would you like to maintain the pacscript (similar to a PKGBUILD) yourself? We can maintain it for you if you decide not to.
  • Could you include a section in your documentation showing Pacstall as a valid method of installation for Pipes.sh for Debian/Ubuntu users? We could make a pull request for that if you want.

Merge in changes from Acidhub

A user @AcidHub has made some enhancements to pipes.sh that I'd like to merge in here, the most attractive of which to me is the repository streamlining. So they get credit for their work I'm going to create a branch of pipeseroni/pipes.sh which I'll merged their changes into, from there modifying it until a pull request can be made.

`-C` uses last pipe colour from previous invocation

If I run pipes.sh; pipes.sh -C, instead of drawing without colour, the second invocation always draws with the last colour drawn from the first invocation. Obviously some terminal escape state is lying around. This seems related to, but distinct from, #5.

I'm no expert on tput and friends, but I see two potential ways of fixing this, which both seem to work.

  1. Insert a call to tput reset just before entering the main animation loop. This ensures that drawing always starts from a clean state.

    stty -echo
    tput reset # <<<<<<<<<<<<<<<<<<<<< Added line
    tput smcup || FORCE_RESET=1
    tput civis
    tput clear
    # any key press exits the loop and this script
    while REPLY=; read -t 0.0$((1000/f)) -n 1 2>/dev/null; [[ -z $REPLY ]] ; do
    
  2. Insert a call to tput reset into cleanup. This ensures that the script always cleans up after itself.

    cleanup() {
        # clear up standard input
        read -t 0.001 && cat </dev/stdin>/dev/null
    
        # terminal has no smcup and rmcup capabilities
        ((FORCE_RESET)) && reset && exit 0
    
        tput reset # <<<<<<<<<<<<<<<<<<<<< Added line
        tput rmcup
        tput cnorm
        stty echo
        ((NOCOLOR)) && echo -ne '\e[0m'
        exit 0
    }
    

Personally I think the second option seems more responsible, but it could be that there's a third option that makes more sense. Again, I'm no expert on this stuff.

Terminal locker

Hey guys,

Author of file manager nnn here. Call it temptation but I was kind of compelled to add pipes.sh as the fallback locker. 🧀

Excellent work and I love the perfection with which it renders even in 8-bit. I work in a drab screen (with MOC playing in bg) most of the time but pipes.sh kind of brings the charm back every time I see it. ;)

Would it be possible to support terminal locking facility (something like bashlock)?

pipes.sh not working in termite

Hello!

When I run the command pipes.sh, I get the following error:

ryanm@sirinat0r:~/pipes.sh$ pipes.sh
tput: unknown terminal "xterm-termite"
ryanm@sirinat0r:~/pipes.sh$

Any suggestions or workarounds?

Pressing Ctrl+C puts ^C into the pipe.

Exactly as it sounds. Ctrl+C puts the ^C character into wherever is currently being drawn in the pipe. This looks like this in the terminal, reproduced with tty and all xterms.

screenshot - 180314 - 07 56 00

Pipes render incorrectly in iterm2

Running pipes.sh from iterm2-nightly Build 3.3.20190405-nightly on mac. Installed 1.3.0 via homebrew. When invoking pipes.sh it prints \e[1m\e[32m next to every "pipe" character. It also does not print in color.

Running ZSH

echo $TERM
xterm-256color
locale
LANG="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL=

Screen Shot 2019-04-05 at 15 51 30

Portal / Wormhole?

While in shower, I was transported a great distance:

2018-03-13--17 18 46

Although I am not so sure about adding this, thoughts?


0001-test-code-portal-wormhole.patch.txt:

From a1448c3d4b69be67b10aad05ae1331edc9549fc1 Mon Sep 17 00:00:00 2001
From: Yu-Jie Lin <[email protected]>
Date: Tue, 13 Mar 2018 17:20:20 +0800
Subject: [PATCH] test code portal/wormhole

---
 pipes.sh | 61 ++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 44 insertions(+), 17 deletions(-)

diff --git a/pipes.sh b/pipes.sh
index 79a6760..b56fd8a 100755
--- a/pipes.sh
+++ b/pipes.sh
@@ -176,6 +176,36 @@ init_screen() {
 }
 
 
+pipe_step()
+{
+    local i="$1"
+
+    # New position:
+    # l[] direction = 0: up, 1: right, 2: down, 3: left
+    # +_CP_newpos
+    ((l[i] % 2)) && ((x[i] += -l[i] + 2, 1)) || ((y[i] += l[i] - 1, 1))
+    # -_CP_newpos
+
+    # Loop on edges (change color on loop):
+    # +_CP_warp
+    ((!KEEPCT && (x[i] >= w || x[i] < 0 || y[i] >= h || y[i] < 0))) \
+    && ((c[i] = C[CN * RANDOM / M], v[i] = V[VN * RANDOM / M]))
+    ((x[i] = (x[i] + w) % w,
+      y[i] = (y[i] + h) % h, 1))
+    # -_CP_warp
+}
+
+
+pipe_print()
+{
+    local i="$1" s="$2"
+
+    echo -ne "\e[$((y[i] + 1));$((x[i] + 1))H\e[${BOLD}m"
+    ((NOCOLOR)) && echo -ne "\e[0m" || echo -ne "\e[3${c[i]}m"
+    echo -n "$s"
+}
+
+
 main() {
     local i
 
@@ -198,19 +228,19 @@ main() {
             ?) break;;
         esac
         for ((i = 0; i < p; i++)); do
-            # New position:
-            # l[] direction = 0: up, 1: right, 2: down, 3: left
-            # +_CP_newpos
-            ((l[i] % 2)) && ((x[i] += -l[i] + 2, 1)) || ((y[i] += l[i] - 1, 1))
-            # -_CP_newpos
-
-            # Loop on edges (change color on loop):
-            # +_CP_warp
-            ((!KEEPCT && (x[i] >= w || x[i] < 0 || y[i] >= h || y[i] < 0))) \
-            && ((c[i] = C[CN * RANDOM / M], v[i] = V[VN * RANDOM / M]))
-            ((x[i] = (x[i] + w) % w,
-              y[i] = (y[i] + h) % h, 1))
-            # -_CP_warp
+            pipe_step $i
+
+            # +_CP_portal
+            if ((100 * RANDOM < M)); then
+                pipe_print $i 'o'
+                local gap=$((7 * RANDOM / M + 3))
+                while ((gap--)); do
+                    pipe_step $i
+                done
+                pipe_print $i 'o'
+                pipe_step $i
+            fi
+            # -_CP_portal
 
             # new turning direction:
             # $((s - 1)) in $s, going straight, therefore n[i] == l[i];
@@ -228,11 +258,8 @@ main() {
             ))
             # -_CP_newdir
 
-            # Print:
             # +_CP_print
-            echo -ne "\e[$((y[i] + 1));$((x[i] + 1))H\e[${BOLD}m"
-            ((NOCOLOR)) && echo -ne "\e[0m" || echo -ne "\e[3${c[i]}m"
-            echo -n "${sets[v[i]]:l[i]*4+n[i]:1}"
+            pipe_print $i "${sets[v[i]]:l[i]*4+n[i]:1}"
             # -_CP_print
             l[i]=${n[i]}
         done
-- 
2.13.5

Multiple types

It'd be nice to have multiple types of pipes on single screen.

Each pipe should be randomly assigned with one type and possibly to handle like colors, that is changing after cross edges.

It'd be better to assign like:

$ pipes.sh -t 0 -t 3 -t 4

Store those type ID in an array, and randomly select from that array.

Cleanup doesn't work as expected

Sometimes, when I quit pipes.sh by pressing a key, the terminal keeps showing some pipes until they are overriden by new standard outputs.

Adding clean just before exit 0 on cleanup seems to fix this at least for me.

Here is a patch if I wasn't clear enough

I hope you find this useful!

Fixing coding style and improving readability

I've notice that we have coding style and readability issues.

Any discussions are welcome, please point out any issues we have in code. If you want to take on this, please comment first to announce and give an estimated finish time, then working on it after I assign this issue to you.

Currently noticed problems

Note: the following "To be" are just my preferences, any other styles are welcome as long as they have better readability.

Spaces Around Operators/Assignments

Some with one space, some without, I prefer with one space for readability, like Python PEP8, for example:

pipes.sh/pipes.sh

Lines 123 to 124 in 9b7d30c

((n[i]=(${n[i]}>1||${n[i]}==0)?${l[i]}:${l[i]}+${n[i]}))
((n[i]=(${n[i]}<0)?3:${n[i]}%4))

To be

        ((n[i] = (${n[i]} > 1 || ${n[i]} == 0) ? ${l[i]} : ${l[i]} + ${n[i]}))
        ((n[i] = (${n[i]} < 0) ? 3 : ${n[i]} % 4))

Long lines

((${x[i]}>=w||${x[i]}<0||${y[i]}>=h||${y[i]}<0)) && ((c[i]=RANDOM%8, v[i]=V[${#V[@]}*RANDOM/M]))

To be:

        ((${x[i]} >= w || ${x[i]} < 0 || ${y[i]} >= h || ${y[i]} < 0)) && ((c[i] = RANDOM % 8, v[i] = V[${#V[@]} * RANDOM / M]))

Then to be:

        ((${x[i]} >= w || ${x[i]} < 0 || ${y[i]} >= h || ${y[i]} < 0)) && \
            ((c[i] = RANDOM % 8, v[i] = V[${#V[@]} * RANDOM / M]))

Division by 0 in Cygwin

Sample output:

/usr/local/bin/pipes.sh: line 16: tput: command not found
/usr/local/bin/pipes.sh: line 16: tput: command not found
/usr/local/bin/pipes.sh: line 107: tput: command not found
/usr/local/bin/pipes.sh: line 108: tput: command not found
/usr/local/bin/pipes.sh: line 109: tput: command not found
/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[33m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[31m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[30m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[30m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[37m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[36m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[37m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[31m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[31m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[33m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")
/usr/local/bin/pipes.sh: line 127: tput: command not found
�[1m�[35m?/usr/local/bin/pipes.sh: line 118: x[i]=(x[i]+w)%w: division by 0 (error token is "w")
/usr/local/bin/pipes.sh: line 119: y[i]=(y[i]+h)%h: division by 0 (error token is "h")

Improve scripts/ readme

Currently the readme for scripts/ is not really as readable as the main one, but it's also obscure as it's not in the main directory. Isn't it better to have it as a section in the main readme, being well formatted aswell?

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.