theryangeary / choose Goto Github PK
View Code? Open in Web Editor NEWA human-friendly and fast alternative to cut and (sometimes) awk
License: GNU General Public License v3.0
A human-friendly and fast alternative to cut and (sometimes) awk
License: GNU General Public License v3.0
like piping to column -t
. I generally pipe aligned input to choose
, then pipe the output to column
. This is common enough that I'd like a short option for it, and I imagine others also work this way. Maybe when passed -t
?
I'm happy to open a PR if you like this idea.
It would nice to to able to install it with cargo install choose
Debian package would be nice. I use Fedora most of the time but sometimes need to connect to a Ubuntu server (ew)
I would like to integrate similar functionality to the cut
Unix utility and, of course, this tool to a Rust cli app. However, this crate is just a binary, but I need a library. Do you know of any rust libraries with similar functionality to this? Would you ever consider splitting this project into a library and then a front-end cli tool?
In grep I can print what it finds between values using easy to remember syntax for perl-regexp. Could choose
be extended to also find text between matches that is easier to use than perl-regexp?
choose -m string1 string2
to print the value found after matching string1 and stopping at string2.
choose -M string1 string2
to print the value including the matched string1 and string2. adding 0 1 2 ... could then print specific characters inside the matched result.
choose -a string1
will look for string1 and print all the text on that line after matching string1.
choose -A string1
will look for string1 and print all the text on that line including string1 that matched. adding 0 1 2 ... could then print specific characters inside the matched result.
Here are some grep examples:
Text to match
$ gdu --version
Version: v5.20.0
Built time: Sat Oct 22 10:48:31 PM CEST 2022
Built user: dundee
gdu --version | grep -oP '(?<=Version:\t\s).*'
Output:
v5.20.0
Text to match
$ openssl x509 -noout -enddate -in /etc/ssl/certs/COMODO_Certification_Authority.pem
notAfter=Dec 31 23:59:59 2029 GMT
Keep only value
openssl x509 -noout -enddate -in /etc/ssl/certs/COMODO_Certification_Authority.pem | grep -oP '(?<=notAfter=).*'
Dec 31 23:59:59 2029 GMT
Text to match
docker inspect 9512b532dcaf1 | grep tls
"/etc/dockers/conf/web/tls:/etc/ssl/nginx:ro",
"Source": "/etc/dockers/conf/web/tls",
docker inspect 9512b532dcaf1 | grep -oP '(?<="Source": ").*(tls)'
/etc/dockers/conf/web/tls
vs
docker inspect 9512b532dcaf1 | grep -oP '(?<="Source": ").*(?=tls)'
/etc/dockers/conf/web
This project is quite similar to one I came across a couple months ago: fex (field extraction). It has a different syntax for selecting fields, and only supports single character delimiters, but it also has some nice features:
Given the input a:b::c:::d
, a standard selection of fields 0:2
would print a:b:c
, whilst a non-greedy selection would print a:b:
. This would probably be hard to implement due to regex delimiters.
Field selections could have multiple stages, so that each split string could be split with another delimiter and another field selected within. There's a great example on the project for splitting web-server access logs like so.
194.25.90.180 - - [19/Jan/2015:12:58:19 +0000] "GET /run?command=ls HTTP/1.1" 200 115 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
Piping this to fex 1 '"2 2'
, split the line by spaces and select field 1, then split the line by double-quotes, select field 2, split that by spaces, and select field 2 from the result. This gives:
194.25.90.180 /run?command=ls
Any field that matches the regular expression /regexp/
would be selected.
Nice program!
Can have Window Version?
I'd like choose
to take an option under which it treats the first row as headers, and allows selecting columns by name. This saves counting, and is especially nice in scripts where it's more clear what is going on and somewhat more resilient to changes in the input format. Not sure if it should be exact-match, prefix, case-insensitive....
I'm happy to open a PR if you like this idea.
Trying to pipe into head results in repeated Failed to write to output: Broken pipe (os error 32)
messages.
Hi,
I work on quite old linux machines and it is not possible to install anything.
Could you provide musl binaries for linux (in the same way ripgrep and fd do)
Many thanks
Hi, Im appreciate your nice works.
I just want to request new feature.
Could you support escape character?
For example:
--field-separator
as ,
for .csv
file."hello, this is me","123",smaple
.I want to choose first field: hello, this is me
but i got a just hello
.
Thank you.
choose
helpfully offers compatibility with Python's style of 0-indexing, inclusive start, and exclusive end, with -x
(which the docs make sound like it uses an exclusive range, while it uses an inclusive start):
$ s=(1 2 3 4 5 6)
$ print $s | choose 2:4
3 4 5
$ print $s | choose -x 2:4
3 4
But when I'm in a shell, using ZSH tools, cut
, etc., I expect 1-indexing, inclusive start, inclusive end:
$ s=(1 2 3 4 5 6)
$ print $s[2,4]
2 3 4
$ print $s | cut -d' ' -f2-4
2 3 4
Since the context I'd use choose
in is the same I'd use ZSH and cut
in, it would lessen the mental load and chance of user error if I could get it to match the indexing and slicing of ZSH (default config) and cut
.
Here's the same data as a table, where s
is an array of the numbers 1
through 6
:
Context | Command | Result | Index | Start | End |
---|---|---|---|---|---|
python |
s[2:4] |
(3, 4) |
0 |
Inclusive | Exclusive |
zsh |
print $s[2,4] |
2 3 4 |
1 |
Inclusive | Inclusive |
cut |
print $s | cut -d' ' -f2-4 |
2 3 4 |
1 |
Inclusive | Inclusive |
choose |
print $s | choose 2:4 |
3 4 5 |
0 |
Inclusive | Inclusive |
choose |
print $s | choose -x 2:4 |
3 4 |
0 |
Inclusive | Exclusive |
It would be nice to have an inline syntax for explicitly inclusive and explicitly exclusive ranges, not just a separate -x
option that changes the behavior of :
. That way, it'd be possible to specify both inclusive and exclusive ranges on the same command line, and to not have to go back and change options when typing ranges.
For example, using Rust's syntax:
Syntax | Meaning |
---|---|
2..5 |
2 to 5, not including 5 |
2..=5 |
2 to 5, including 5 |
2:5 |
2 to 5; including 5 by default, excluding 5 if -x passed |
(A different syntax would be fine, as long as it's self-explanatory.)
Hello! I'm trying package to debian, but have some errors. Do you know what it could be?
test tests::test_process_escapes::test_unicode_crab_emoji ... FAILED test tests::test_process_escapes::test_unicode_u7fff ... FAILED failures: ---- tests::test_process_escapes::test_unicode_crab_emoji stdout ---- thread 'tests::test_process_escapes::test_unicode_crab_emoji' panicked at 'not implemented: escape_ unicode
is not yet implemented', src/lib.rs:50:5 stack backtrace: 0: rust_begin_unwind at /usr/src/rustc-1.59.0/library/std/src/panicking.rs:498:5 1: core::panicking::panic_fmt at /usr/src/rustc-1.59.0/library/core/src/panicking.rs:116:14 2: backslash::escape_unicode at /usr/share/cargo/registry/backslash-0.2.0/src/lib.rs:50:5 3: backslash::tests::test_process_escapes::test_unicode_crab_emoji at /usr/share/cargo/registry/backslash-0.2.0/src/lib.rs:219:17 4: backslash::tests::test_process_escapes::test_unicode_crab_emoji::{{closure}} at /usr/share/cargo/registry/backslash-0.2.0/src/lib.rs:216:9 5: core::ops::function::FnOnce::call_once at /usr/src/rustc-1.59.0/library/core/src/ops/function.rs:227:5 6: core::ops::function::FnOnce::call_once at /usr/src/rustc-1.59.0/library/core/src/ops/function.rs:227:5 note: Some details are omitted, run with RUST_BACKTRACE=full
for a verbose backtrace. ---- tests::test_process_escapes::test_unicode_u7fff stdout ---- thread 'tests::test_process_escapes::test_unicode_u7fff' panicked at 'not implemented: escape_unico de
is not yet implemented', src/lib.rs:50:5 stack backtrace:
I've come across several issues with inclusivity / exclusivity:
The readme.md
says:
choose :3 # print the beginning of the line to the 3rd item,
# exclusive
Which I take to mean that the item with index 3 won't be included when :3
is used, i.e:
echo 0 1 2 3 | choose :3
should output 0 1 2
. However, it outputs 0 1 2 3
. Is the readme.md
wrong? Did you intend to add a -x
there and forgot? Or is that a bug?
Claiming choose
is Python like and then requiring -x
for exclusivity is wrong in my opinion, to aim to be more Python-like, choose
should be exclusive by default.
In [1]: [0,1,2,3][:3]
Out[1]: [0, 1, 2]
$ echo 0 1 2 3 | choose :3
0 1 2 3
-x
Since I want choose
to be more Python-like, I created an alias alias c='choose -x'
so it's always exclusive by default. However, when I try to use it like this:
$ echo 0 1 2 3 | c 2
Nothing is output, as shown.
What do you think?
version: commit 97b3abf
environment: linux x86_64
When an input has no newline at EOF, --field-separator
option does not work correctly.
$ /bin/echo 'a:b' | target/debug/choose -f ':' 1
b
$ /bin/echo -n 'a:b' | target/debug/choose -f ':' 1
(expected "b", but no output)
Moreover, if an input contains non-ASCII characters, choose
can panic:
$ /bin/echo -n 'あ:い' | target/debug/choose -f ':' 1
thread 'main' panicked at 'byte index 6 is not a char boundary; it is inside 'い' (bytes 4..7) of `あ:い`', src/main.rs:77:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
I guess this code causes the issue:
Lines 76 to 80 in 97b3abf
This code seems to trim the last character unconditionally, but it will have to check if a line actually has a newline.
$ identify 11095193_p0.jpg
11095193_p0.jpg JPEG 1200x1200 1200x1200+0+0 8-bit sRGB 695510B 0.000u 0:00.002
$ identify 11095193_p0.jpg | gawk '{split($3,sizes,"x"); print $1,sizes[1]/sizes[2]}'
11095193_p0.jpg 1
I'd like to use choose
to replace awk
because the filename
sometime include whitespace that lead to error, how to rewrite this by choose
Hi,
although the compile process went smooth on my macOS, is there any chance to push this as the brew package? The installation would be much easier...
Thanks,
Lubos
$ cargo build --release
error: failed to parse lock file at: /home/pete/stuff/choose/Cargo.lock
Caused by:
invalid serialized PackageId for key package.dependencies
Would be nice to have a argument to filter by the nth line, similar as the nth element of each line.
$echo "a b c d
e f g
h i j" | choose 1 -l 1
f
what is rust
'\n' as output separator doesn't work. It works literally. Other system utilities, like tr, understand that this is newline.
❯ echo "Hello world" | choose : -o '\n'
Hello\nworld
❯ echo "Hello world" | tr ' ' '\n'
Hello
world
-x
Since I want choose
to be more Python-like, I created an alias alias c='choose -x'
so it's always exclusive by default. However, when I try to use it like this:
$ echo 0 1 2 3 | c 2
Nothing is output, as shown.
What do you think?
Should be overridden by an inclusive flag on the cli.
This ruins pre-formatted tables and requires extra chaining to return the output to its original state, meaning choose
is not a transparent translation utility as much as a complete refactoring.
Examples:
➜ sdiff <(choose 0:4 -i mnemonics.tmp | head ) <(head mnemonics.tmp )
0x2813: 0x0a, 0, 2, 2 | 0x2813: 0x0a, 0, 2, 2
0xb537: 0x2d, 6, 17, 34 | 0xb537: 0x2d, 6, 17, 34
0x460c: 0x11, 2, 5, 170 | 0x460c: 0x11, 2, 5, 170
0x4615: 0x11, 2, 5, 850 | 0x4615: 0x11, 2, 5, 850
0xd814: 0x36, 9, 29, 24650 | 0xd814: 0x36, 9, 29, 24650
0xa901: 0x2a, 5, 13, 320450 | 0xa901: 0x2a, 5, 13, 320450
0xf7f4: 0x3d, 11, 37, 11856650 | 0xf7f4: 0x3d, 11, 37, 11856650
0x2800: 0x0a, 0, 2, 23713300 | 0x2800: 0x0a, 0, 2, 23713300
0xda06: 0x36, 9, 29, 687685700 | 0xda06: 0x36, 9, 29, 687685700
0x4244: 0x10, 1, 3, 2063057100 | 0x4244: 0x10, 1, 3, 2063057100
even with columns -t
it is slightly off in terms of justification:
➜ sdiff <(choose 0:4 -i mnemonics.tmp | head | column -t) <(head mnemonics.tmp )
0x2813: 0x0a, 0, 2, 2 | 0x2813: 0x0a, 0, 2, 2
0xb537: 0x2d, 6, 17, 34 | 0xb537: 0x2d, 6, 17, 34
0x460c: 0x11, 2, 5, 170 | 0x460c: 0x11, 2, 5, 170
0x4615: 0x11, 2, 5, 850 | 0x4615: 0x11, 2, 5, 850
0xd814: 0x36, 9, 29, 24650 | 0xd814: 0x36, 9, 29, 24650
0xa901: 0x2a, 5, 13, 320450 | 0xa901: 0x2a, 5, 13, 320450
0xf7f4: 0x3d, 11, 37, 11856650 | 0xf7f4: 0x3d, 11, 37, 11856650
0x2800: 0x0a, 0, 2, 23713300 | 0x2800: 0x0a, 0, 2, 23713300
0xda06: 0x36, 9, 29, 687685700 | 0xda06: 0x36, 9, 29, 687685700
0x4244: 0x10, 1, 3, 2063057100 | 0x4244: 0x10, 1, 3, 2063057100
reformatting is technically possible with column -t -R 3,4,5
, but -R
is unsupported on default builds of column
. Additionally, this requires specifying all column numbers to be right-justified, which is infeasible for files with large numbers of right-justified columns
➜ choose --version
choose 1.3.0
Hi!
Cool project, I like it!
And easy to use, too, but with tab completions it is even easier. I added some for fish shell:
complete choose --no-files
#flags:
complete choose -s c -l character-wise -d "Choose fields by character number"
complete choose -s d -l debug -d "Activate debug mode"
complete choose -s x -l exclusive -d "Use exclusive ranges, similar to array indexing in many programming languages"
complete choose -x -s h -l help -d "Prints help information"
complete choose -s n -l non-greedy -d "Use non-greedy field separators"
complete choose -l one-indexed -d "Index from 1 instead of 0"
complete choose -s V -l version -d "Prints version information"
#options:
complete choose -x -s f -l field-separator -d "Specify field separator other than whitespace, using Rust `regex` syntax"
complete choose -r -s i -l input -d "Specify input file"
complete choose -x -s o -l output-field-separator -d "Specify output field separator"
Do you want to bundle them with the project, or would you like me to create a pull request in the fish shell repo instead?
The readme.md
says:
choose :3 # print the beginning of the line to the 3rd item,
# exclusive
Without the -x
flag, it shouldn't be exclusive.
Hi! Cool project, very nice alternative to awk
/cut
.
It would be nice to be able to use choose
on an endless stream, passing on output as new lines arrives on stdin. Some examples:
ping 8.8.8.8 | choose -2 | choose -f "=" 1
tail -f log.log | choose 0
Of course using the approach of printing the match after each line is highly inefficient working on files. Maybe it could be a setting --release-output
which by default is not used when reading files, but used when reading from stdin
?
$ choose --version
choose 1.3.2
$ export RUST_BACKTRACE=full
$ echo "0 1 2 3 4" | choose 0
0
$ echo "0 1 2 3 4" | choose -1
4
$ echo "" | choose 0
$ echo "" | choose -1
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/choice.rs:186:18
stack backtrace:
0: 0x55784c8bbf00 - std::backtrace_rs::backtrace::libunwind::trace::ha5edb8ba5c6b7a6c
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
1: 0x55784c8bbf00 - std::backtrace_rs::backtrace::trace_unsynchronized::h0de86d320a827db2
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x55784c8bbf00 - std::sys_common::backtrace::_print_fmt::h97b9ad6f0a1380ff
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/sys_common/backtrace.rs:67:5
3: 0x55784c8bbf00 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h14be7eb08f97fe80
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/sys_common/backtrace.rs:46:22
4: 0x55784c8d805f - core::fmt::write::h2ca8877d3e0e52de
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/fmt/mod.rs:1094:17
5: 0x55784c8b9f55 - std::io::Write::write_fmt::h64f5987220b618f4
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/io/mod.rs:1584:15
6: 0x55784c8bde7b - std::sys_common::backtrace::_print::h7f1a4097308f2e0a
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/sys_common/backtrace.rs:49:5
7: 0x55784c8bde7b - std::sys_common::backtrace::print::h1f799fc2ca7f5035
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/sys_common/backtrace.rs:36:9
8: 0x55784c8bde7b - std::panicking::default_hook::{{closure}}::hf38436e8a3ce1071
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:208:50
9: 0x55784c8bd94d - std::panicking::default_hook::he2f8f3fae11ed1dd
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:225:9
10: 0x55784c8be48d - std::panicking::rust_panic_with_hook::h79a18548bd90c7d4
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:591:17
11: 0x55784c8bdff7 - std::panicking::begin_panic_handler::{{closure}}::h212a72cc08e25126
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:495:13
12: 0x55784c8bc39c - std::sys_common::backtrace::__rust_end_short_backtrace::hbd6897dd42bc0fcd
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/sys_common/backtrace.rs:141:18
13: 0x55784c8bdf89 - rust_begin_unwind
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:493:5
14: 0x55784c7c7cf1 - core::panicking::panic_fmt::h77ecd04e9b1dd84d
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/panicking.rs:92:14
15: 0x55784c7c7c3d - core::panicking::panic::h60569d8a39169222
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/panicking.rs:50:5
16: 0x55784c7cadb9 - choose::choice::Choice::print_choice::h9aad0eebfbda9462
17: 0x55784c7d22a4 - choose::main::h34b573cbb97faa1e
18: 0x55784c7ce263 - std::sys_common::backtrace::__rust_begin_short_backtrace::h58c37d283637d79b
19: 0x55784c7ce279 - std::rt::lang_start::{{closure}}::h1dfc6e7cf9a3fc13
20: 0x55784c8be88a - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::hc4354216bf39217c
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/ops/function.rs:259:13
21: 0x55784c8be88a - std::panicking::try::do_call::hb68eb312780385cf
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:379:40
22: 0x55784c8be88a - std::panicking::try::h22b8e08595060b8b
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:343:19
23: 0x55784c8be88a - std::panic::catch_unwind::hc64f1a6a0e71b1fc
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panic.rs:431:14
24: 0x55784c8be88a - std::rt::lang_start_internal::h4461fc58637f04f8
at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/rt.rs:34:21
25: 0x55784c7d2a62 - main
26: 0x7f496544db25 - __libc_start_main
27: 0x55784c7c840e - _start
28: 0x0 - <unknown>
Issue environment:
If I open a rather long file with many lines,
cat file | choose 0 | less
after existing less
, choose will print out the error message with many
Failed to write to output: Broken pipe (os error 32)
Please add an aarch64 linux version as well to your CI.
I'd like to package this for the AUR, but since the project has no license it makes it hard for me to do so.
Personally, I'd recommend something like the ISC or MIT license.
Can I select the 'n' field from 'x' line on multiline input ?
Desired example
$ cat demo.txt
This is a
multiline test
$ cat demo.txt | choose 1 {--line 1} # Desired line selection
test # Desired output
Please check the test result below.
~% echo "1/2/3/4/5" | choose -f '/' -o '/' 1:-1
2/3/4/5
~% echo "1/2/3/4/5" | choose -f '/' -o '/' 1:-2
2/3/4
~% echo "1/2/3/4/5" | choose -f '/' -o '/' 1:-3
2/3
~% echo "1/2/3/4/5" | choose -f '/' -o '/' 1:-4
~%
I expected "2" from the last run. But nothing returned.
Hey there
Would you mind adding a pre-build binary to your GH release ? I never tried building & publishing Rust based code before, but from a past experience using rust based tool, here's a starter.
name: Publish binary
on:
push:
jobs:
ebook:
name: Build and upload
runs-on: ubuntu-latest
steps:
# Install Rust & its package manager Cargo
- name: Install cargo
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
# Cache installation assets
- name: Cache cargo registry
uses: actions/cache@v1
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v1
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v1
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
# BUILD HERE
- name: build
run: cargo ???
# Publish
- name: Create Release
id: create-release
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Upload to release
id: upload-release-asset
uses: actions/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create-release.outputs.upload_url }}
asset_path: ./PATH
asset_name: NAME
Best regards,
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.