GithubHelp home page GithubHelp logo

kristopolous / ticktick Goto Github PK

View Code? Open in Web Editor NEW
579.0 17.0 55.0 105 KB

JSON in your Bash scripts

Home Page: http://9ol.es/TheEmperorsNewClothes.html

License: Other

Makefile 1.78% Shell 98.22%

ticktick's Introduction

Introduction

TickTick enables you to put JSON in bash scripts. Yes, just encapsulate them with two back-ticks.

Note: This is just a fun hack. You may want to consider using mature languages like Ruby or Perl to solve actual real life problems. Oh who am I kidding, I use whitespace and brainfuck every day.

Usage

Proper usage (if there is such a thing), is to place the following line right after the "shbang" at the top of your script. For instance:

#!/bin/bash
#
# Nuclear_meltdown_preventer.sh
#
# This is really important stuff. Don't edit it!
#
. ticktick.sh

..

See how that's near the tippity-top? That's where it's supposed to go. If you put it lower, all bets are off. :-(

API

Arrays

A few array manipulation runtime directives are supported:

  • [] (as new Array)
    ``arr = ["foo"]``
  • [] (to index)
    echo ``arr[0]``
  • length
    arr_len=``arr.length()``; echo ${arr_len}
  • push
    ``arr.push(${arr_len})``
  • pop
    echo ``arr.pop()``
  • shift
    echo ``arr.shift()``
  • delete
    echo ``key.value.delete()``
  • items
    for x in ``arr.items()``; do echo "${x}"; done

Notes:

  • These feature do not preclude having variables by those names. You can have key.delete = 1 and then key.delete.delete()
  • Since TickTick is a Bash-emitting transpiler, things that don't work in bash (such as modifying in-shell variables in double quotes) don't work in TickTick.

Objects

  • {} (as new Object)
    ``obj = { "foo": "bar", "baz": "qux" }``
  • [] (to index)
    echo ``obj["foo"]``
  • . (to index)
    echo ``obj.baz``

Miscellaneous

tickParse - parse things inline

  • Inline parsing: You can parse a file in with the tickParse routine (see the example).

tickVars - see the currently defined variables

  • Show all variables: You can see the current values defined in the TickTick world with the tickVars routine.
  • If you don't like the output, there are some options to customize it. Try tickVars -h for more information.

tickReset - clear the currently defined variables

  • Clear all variables: You can erace any JSON you have created/imported with the tickReset routine.

__tick_var_debug - See the interim bash code

  • Dry run (display compiled code): TickTick is a mini-compiler that emits bash. If you declare export __tick_var_debug=1 at the top of your code (before you source ticktick.sh), then the code will not run but instead print what it would have run.

Bash variables ($) in JSON

Along with assignment operations1, and Javascript like indexing into objects and arrays.

Additionally, bash variables (eg., "$name") are preserved in the TickTick blocks. For instance, once could do

`` Var.Data = [] ``
`` Var.Data.push($key) ``
bashvar=`` Var.Data.pop() ``

1Although Javascript supports $ prefixed variables, this does not.

Examples

Inline Parsing

#!/bin/bash

. ticktick.sh

bob=Bob

``
  people = {
    "HR" : [
      "Alice",
      $bob,
      "Carol"
    ],
    "Sales": {
      "Gale": { "profits" : 1000 },
      "Harry": { "profits" : 500 }
    }
  }
``

function printEmployees() {
  echo
  echo "  The ``people.Engineering.length()`` Employees listed are:"

  for employee in ``people.Engineering.items()``; do
    printf "    - %s\n" "${!employee}"
  done

  echo 
}

echo Base Assignment
`` people.Engineering = [ "Darren", "Edith", "Frank" ] ``
printEmployees

newPerson=Isaac
echo Pushed a new element by variable, $newPerson onto the array
`` people.Engineering.push($newPerson) ``
printEmployees

echo Shifted the first element off: `` people.Engineering.shift() ``
printEmployees

echo Popped the last value off: `` people.Engineering.pop() ``
printEmployees

echo Indexing an array, doing variable assignments

person0=``people.HR[0]``
echo $person0 ``people.HR[1]``

Using a File or cURL

#!/bin/bash
. ../ticktick.sh

# File
DATA=`cat data.json`
# cURL
#DATA=`curl http://foobar3000.com/echo/request.json`

tickParse "$DATA"

echo ``pathname``
echo ``headers["user-agent"]``

Mailing List

Join it over here.

LICENSE

This software is available under the following licenses:

  • MIT
  • Apache 2

Parts of this work are derived from JSON.sh, which is also available under the aforementioned licenses.

ticktick's People

Contributors

adamkijak avatar ingydotnet avatar kaos avatar kristopolous avatar xltechie 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

ticktick's Issues

TickTick hangs when initialized in an interactive shell

Initializing ticktick in an interactive bash shell causes the shell to hang

# Start a new bash shell without any extra environment variables
env - bash
# Try to initialize ticktick
. ticktick.sh

The source command doesn't complete. It just hangs.

Script ignores arguments and variables passed to script

Hi there, I'm trying to pass arguments to my script using ticktick. The arguments are understood before I source the file in my script, but all arguments and variables are forgotten after the sourcing of the file.

Even passing them like:

. ticktick.sh $@ or . ticktick.sh "$@" or . even ticktick.sh "hello" are all ignored after that point.

Is there any way to get this data passed along so I can work with it? (For instance, if I wanted to do a curl request against an arbitrary service and parse the JSON)?

Thanks in advance,

[ER] Emit Objects as JSON

``
curl_msg = { 
    "source": "https://$user_pass@$domain/$db", 
    "target": "$db",
    "create_target":true
}
``
echo $curl_msg
echo ``curl_msg.source``
echo ${curl_msg}
echo ``curl_msg``

i can echo parts of the object, but not the whole object (which is what i desire).

i see only one output, which is curl_msg.source

Parsing feed from mtgox not working

I was attempting to use TickTick to render the current price of BTC form MtGox via a terminal and Bash. It seems easy enough, however, I'm unable to get it to print the current price.

#!/bin/bash

. /root/.bin/ticktick.sh

DATA=`curl http://data.mtgox.com/api/2/BTCUSD/money/ticker`

tickParse "$DATA"

echo ``data["last"]``

Outputs:

root@ks4003010 .bin]$ sh btc
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
105  1367    0  1367    0     0   9669      0 --:--:-- --:--:-- --:--:-- 19253

root@ks4003010 .bin]$ 

The script itself seems to work just fine, it's simply not printing the requested information. Any advice?

Needs example with curl

How would I parse RESPONSE in this working example?

RESPONSE=`curl --silent 'http://foobar3000.com/echo/request.json'`
echo ${RESPONSE}

Will you please put the example for this in your README?

P.S. http://foobar3000.com and http://helloworld3000.com are a public echo servers I put up for just these sorts of occasions.

shift and pop work in some weird fun way

I'm not sure whether this is a useful thing or whether it should be changed, but as an artifact of how it was created, shift will "move the tree along". That is to say that

[ { a: [1, 2] }, { b: [3, 4] } }

shifted will result in

[ { a: [2, 3] }, { b: [4] } ]

As opposed to the more conventional

[ { b: [3, 4] } ]

We can call this a bug if we want - but only because it doesn't do what conventional languages do. We can also just reclassify this as a feature, legitimately, some kind of "esoteric full-depth shift".

But if this was to be the case, then it should at least get christened a new name.

I made a gist of the test code that illustrates this: https://gist.github.com/kristopolous/a48600348341007af943

Print the whole json

Is there a way (or a workaround) to print back the whole Json at the end ?

``
  people = {
    "HR" : [
      "Alice",
      $bob,
      "Carol"
    ],
    "Sales": {
      "Gale": { "profits" : 1000 },
      "Harry": { "profits" : 500 }
    }
  }
``
echo $people;

* is not parsed correctly

The following code is not working:

! /usr/bin/env bash

. ticktick.sh
DATA='{"a":"*"}'
tickParse "$DATA"
echo a

It outputs ls of the current directory. OS: MacOSX

"Portable" (no debug magic) mode using HERE-documents (<<'EOF')

A lot of people are requesting ticktick for some other shell xsh where debug facilities may be nonexistent. A way to get that job done is to write a function that reads from its stdin, transpiles the code, and runs eval -- no caller magic needed! It's going to work in interactive shells too!

# The function should look like this...
tt() {
  eval "$(__tick_fun_tokenize_expression | __tick_fun_parse_expression)"
}
# don't ask me about disabling the rest of the magic i don't know okay?

People can then write blocks of JSON for that in here-documents and one-line here-strings. They are a bit more tedious, but that is expected. For example, instead of the example, we can say:

#!/bin/bash
TICKTICK_NOMAGIC=1
. ticktick.sh

bob=Bob
tt <<'EOF'
  people = {
    "HR" : [
      "Alice",
      $bob,
      "Carol"
    ],
    "Sales": {
      "Gale": { "profits" : 1000 },
      "Harry": { "profits" : 500 }
    }
  }
EOF

function printEmployees() {
  echo
  echo "  The $(tt <<< 'people.Engineering.length()') Employees listed are:"

  for employee in $(tt <<< 'people.Engineering.items()'); do
    printf "    - %s\n" ${!employee}
  done

  echo 
}

echo Base Assignment
tt <<< 'people.Engineering = [ "Darren", "Edith", "Frank" ]'
printEmployees

newPerson=Isaac
echo Pushed a new element by variable, $newPerson onto the array
tt <<< 'people.Engineering.push($newPerson)'
printEmployees

echo Shifted the first element off: $(tt <<< 'people.Engineering.shift()')
printEmployees

echo Popped the last value off: $(tt <<< 'people.Engineering.pop()')
printEmployees

echo Indexing an array, doing variable assignments

person0=$(tt <<< 'people.HR[0]')
echo $person0 $(tt <<< 'people.HR[1]')

(Note the quotes on EOF -- that prevents the shell from expanding $bob on its own prematurely. And the quotes on (), because when they poke out they make a syntax error. The quotes on [0] is there because it can mean a glob, and you don't want to risk having a file called people.HR0 and messing this up.)


  • If you are going interactive, you can even type tt, paste stuff in, and Ctrl-D it. The possibilties are limitless!
  • People can put positional arguments in by calling tt as tt "$@", although I don't see much use for that. If they really want that, they can make an alias tta='tt "$@"' and make it work in scripts with shopt -s expand_aliases. (Aliases are wonderful; they are like macros for bash, lmao.)
  • We can write another function ttl() { printf %s "$1" | tt "${@:2}"; }, just for typing less <<<.

TickTick initialization in a script runs commands twice

Sourcing ticktick in a bash script causes all commands before the source command to be run again.

The output to this simple script

#!/bin/bash

echo "before ticktick initialized"

. ticktick.sh

echo "after ticktick initialized"

is

before ticktick initialized
before ticktick initialized
after ticktick initialized

where you expect the "before" echo should only occur once.

Consider removing the CMD + Shift +P shortcut for start/stop pomo.

The CMD + Shift + P keyboard shortcut is a common binding for developer tools, such as VS Code, to bring up the command palette.

After installing your program, which I love btw, it highjacked my ability to open the command palette in VS Code using the default shortcut. Also, now I will have to remember to remove the shortcut in TickTick's helper app anytime I setup a new machine.

Or, if possible, maybe detect if the window is on VS code and don't hijack there? idk. This really messed me up for about a week. Glad I finally figured it out and thought I'd share the frustration. Hopefully you guys can figure out an elegant fix to this.

Wider string support

This hearkens back to issue #29. Briefly the idea is that escaped characters and demarcation tokens ( '[', ']', ',', ':', etc.) need to be supported inside of strings when properly escaped (if necessary).

There's various heavy and light ways to implement this type of thing ... there's a test coming that will address it soon.

Busyboxy / ash support

Hi there,

I am very interested in using ticktick.sh. However, I am having a problem when running it on OpenWRT --> a distro that uses Busybox / ash (not bash).

I replaced the first line:

!/usr/bin/env bash

to be:

!/bin/sh

But when I try to run it, I get this:

./ticktick.sh

./ticktick.sh: line 332: syntax error: bad substitution

That is referring to this:

__tick_runtime_length() { echo $#; }
__tick_runtime_first() { echo ${!1}; }
__tick_runtime_last() { eval 'echo $'${!#}; }
__tick_runtime_pop() { eval unset ${!#}; }

Any ideas? Thanks!

Quoted arguments get broken up

TickTick provides, in my opinion, an API that is obviously much nicer than the other bash JSON parsers. So I was using it in my script.

Unfortunately, I had to switch to JSON.sh because I could not figure out (at least not in the hour or so I spent diagnosing and trying to fix this issue, I am not a bash expert) how to fix this problem: when passing arguments that are quoted for example myscript last Smith first John address "123 Main St." after the . ./ticktick.sh the last arguments change as if they were not quoted e.g. myscript last Smith first Smith address 123 Main St.. I am using shift in part of my script to read key/value pairs from the arguments and I was getting Main assigned as a key rather than part of the address value.

class with numbers doesn't work in parsing.

It's a great bash script.
I was parsing some sort of data like this:

test.json

{
    "test_1": {
        "origin" : {
            "name" : "test2" 
        },
    "test_2": {
        "origin": {
            "name": "test2"
        }
}

now i'm importing test.json from my bash script.

DATA=`cat ./test.json`
tickParse "$DATA"

echo ``test_1[origin[name]]``

but i only get blank.

so I was looking at the issue lists, i found way to debug, using __tick_var_debug=1
after then, I'm looking following output

#!/bin/bash
__tick_var_debug=1
. ticktick.sh

DATA=`cat ./test.json`
tickParse "$DATA"

echo ${__tick_data_test_000000000001_origin_name}

Now It seems like tickParse is rewriting numbers in my classes.
last line should be ${__tick_data_test_1_origin_name} not ${__tick_data_test_000000000001_origin_name}

Read json data from standard input or pipe ?

Maybe this is obvious but I'm a novice with shell scripts...

Can I use TickTick to take json data from standard input - or (which is equivalent I think) pipe output into a TickTick-based script ?

Assume the json data is well-formed and don't need to check it for validity.

Thank you for a nice project.

Incorrect output

Got from http://9ol.es/TheEmperorsNewClothes.html

#!/bin/bash
. ticktick.sh

``
  people = {
    "Writers": [
      "Rod Serling",
      "Charles Beaumont",
      "Richard Matheson"
    ],
    "Cast": {
      "Rod Serling": { "Episodes": 156 },
      "Martin Landau": { "Episodes": 2 },
      "William Shatner": { "Episodes": 2 }
    }
  }
``

function printDirectors() {
  echo "  The ``people.Directors.length()`` Directors are:"

  for director in ``people.Directors.items()``; do
    printf "    - %s\n" ${!director}
  done
}

`` people.Directors = [ "John Brahm", "Douglas Heyes" ] ``
printDirectors

newDirector="Lamont Johnson"
`` people.Directors.push($newDirector) ``
printDirectors

echo "Shifted: "``people.Directors.shift()``
printDirectors

echo "Popped: "``people.Directors.pop()``
printDirectors

Generates:

  The 2 Directors are:
    - John
    - Brahm
    - Douglas
    - Heyes
  The 3 Directors are:
    - John
    - Brahm
    - Douglas
    - Heyes
    - Lamont
    - Johnson
Shifted: John Brahm
  The 2 Directors are:
    - Douglas
    - Heyes
    - Lamont
    - Johnson
Popped: Lamont Johnson
  The 1 Directors are:
    - Douglas
    - Heyes

GNU bash, version 4.4.23(1)-release

Indexing With a Variable

Sorry to create a new issue if this should have been appended to an existing one instead, but I wanted it to be clear what I'm having an issue with.

I'm trying to iterate through a JSON array using TickTick and match a certain value. In this case, I'm accessing the RottenTomatoes API and doing a query. Since they have very basic query support, appending a year to the query doesn't help the results, and the first result from a query is usually wrong. They tend to provide results based on popularity rather than accuracy.

The value that I'm looking for in the search results is the year in order to improve the quality of my queries.

My thought was that I would iterate through the movie array, checking the year of each movie. Once I find a match, I can then use the index into the array for accessing other useful information about that particular movie. Unfortunately, I'm getting bad substitution errors the way I'm attempting to do this. From the output I'm seeing, it appears that the variable I'm trying to use as an index isn't getting expanded.

This is the error output that I'm getting when I try to use the variable $i as an index to the array 'movies' from this JSON data:

--: line 23: ${__tick_data_movies_$i_year}: bad substitution

Here is the way that I'm trying to make this happen:

for ((i=0;i<$PAGE_LIMIT;i++)); do
  if [ "``movies[$i]["year"]``" == "$MOVIE_YEAR" ]; then
    RESULT=$i
    break
  fi
done

I can confirm that the following, much like my initial example, results in a bad substitution error:

ZERO=0
FIRST_MOVIE_YEAR="``movies[$ZERO]["year"]``"

Conversely, I can confirm that the following works just fine:

FIRST_MOVIE_YEAR="``movies[0]["year"]``"

I tried implementing this using the pop() method, but I haven't gotten the results I expect with that method. This seems to me like it would be more effective for my purposes anyway, so I haven't pursued that too much further.

I also tried to use the items() method, but seems to be a tremendous waste for this purpose as well.

There may be a better way to do what I'm trying to do, and I'm fully open to suggestions for improvement. However, I do believe this is an issue with TickTick. I'm not sure if it was intended that this should work or not, but from what I read in the README I've drawn the conclusion that it should work just fine. Forgive me if I have made any error in drawing this conclusion.

Thank you very much for any help and/or feedback.

No spaces allowed in any part of JSON read through tickParse!

I was doing some testing related to the problems discovered in issue #35 and found this.

If you try to tickParse some JSON, any JSON, that contains spaces anywhere in it (keys, values, or interstitially), you will get one of these errors:

Most serious: In a value

ticktick.sh: eval: line 424: unexpected EOF while looking for matching `"'
ticktick.sh: eval: line 425: syntax error: unexpected end of file

Interstitially or in a key, like in #35

ticktick.sh: line 424: TICKTICK: command not found

@kristopolous I'm pretty sure that this issue and #35 are related to some eval and quote expansion interaction somewhere.

  • It is required that spaces be allowed in string values to JSON elements.
  • We can work around the interstitial case by removing spaces outside quotes while tokenizing.
  • I'm not sure if the JSON spec allows spaces in keys, but reading in JSON without tickParse (I.E. through the normal double backtick method) replaces the space with a number 32, which is fine.

Test 0015 * results in Bad substitution on bash 4.3.42(1)

~/development/TickTick/tests$ /bin/bash --version
GNU bash, version 4.3.42(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <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.
~/development/TickTick/tests$ ./runall.sh 
0001.dictionary.test.sh { OK }
0005.push_pop_quotes.test.sh {
   !!! FAILURE !!!
   1,2c1,2
   < This value: 4; __tick_runtime_pop __tick_data_data_000000000000 __tick_data_data_000000000001 __tick_data_data_000000000002 __tick_data_data_000000000003 should be 4.
   < This value: 4 should be 3.
   ---
   > This value: 4 should be 4.
   > This value: 3 should be 3.
}
0011.delete.test.sh { OK }
0015.iteration.test.sh --: line 11: ${__tick_data_people_*}: bad substitution
{
   ERROR: Expected file expected/0015.iteration.test.sh doesn't exist
   Assert failure:  != Alice 23;Bob 43;Harry 13;
}
0016.runtime.test.sh { OK }
0018.bracket.test.sh { OK }
0025.number_expansion.test.sh { OK }
0029.key_period.test.sh { OK }
0030a.wider_string_assign.test.sh { OK }
0030b.wider_string_access.test.sh { OK }

It doesn't look like 0015.iteration.test.sh is marked executable in the repos, tho. Did this ever work?

What's the correct way to do this type of iteration?

Fails to run on Mac OS X Mavericks (10.9)

When I try to use TickTick I get this errors (using the example.sh) and there is no parsing done:

egrep: repetition-operator operand invalid
egrep: repetition-operator operand invalid
egrep: repetition-operator operand invalid
egrep: repetition-operator operand invalid
egrep: repetition-operator operand invalid
egrep: repetition-operator operand invalid
egrep: repetition-operator operand invalid
egrep: repetition-operator operand invalid
egrep: repetition-operator operand invalid
Base Assignment

The Employees listed are:

Pushed a new element by variable, Isaac I onto the array

The Employees listed are:

Shifted the first element off:

The Employees listed are:

Popped the last value off:

The Employees listed are:

Indexing an array, doing variable assignments

  • Andy

Support Solaris/BSD (simple change needed)

The TickTick.sh script depends on GNU grep so it will not work on Solaris unless the following is added to the script:

# Script needs the GNU version of 'grep' !!
# Set up some defaults:
GREP=grep
EGREP=egrep

if [ `uname` == "SunOS" ]; then
  GREP=ggrep
  EGREP=gegrep
fi

Then everywhere in the script where 'grep' or 'egrep' is used I've replaced with $GREP and $EGREP.

Note to those who may find this posting:

On Solaris 10 GNU grep is installed by default and lives in /usr/sfw/bin. Note that the binaries have a prefixed 'g'.

On Solaris 11 GNU grep is installed by default in global zones but doesn't (by default) make it into the local zones. To install in local zone simply do 'pkg install gnu-grep'. In Solaris 11 the GNU tool chain is already part of the default path but with a 'g' prefixed on the binary (except for the cases where there's no name clash)

Iteration

#!/bin/bash                                                                                                                                                                                    

. ticktick.sh                                                                                                                                                                                  

``                                                                                                                                                                                             
people = {                                                                                                                                                                                     
    [                                                                                                                                                                                          
        {                                                                                                                                                                                      
            "name":"Alice",                                                                                                                                                                    
            "age":23                                                                                                                                                                           
        },                                                                                                                                                                                     
        {                                                                                                                                                                                      
            "name":"Bob",                                                                                                                                                                      
            "age":43                                                                                                                                                                           
        },                                                                                                                                                                                     
        {                                                                                                                                                                                      
            "name":"Harry",                                                                                                                                                                    
            "age":13                                                                                                                                                                           
        }                                                                                                                                                                                      
    ]                                                                                                                                                                                          
}                                                                                                                                                                                              
``          

How can I iterate through this structures in the array?
I mean want to do somthing like:

for person in ``peaople.items()``
  echo ``person.name``
  echo ``person.age``
done

length is unintuitively recursive

In addressing #17 I ran into this

database = [
{
"artist": "Ludwig Van Beethoven",
"title": "Moonlight Sonata"
},
{
"artist": "Johann Pachelbel",
"title": "Canon in D Major"
},
{
"artist": "Johann Sebastian Bach",
"title": "Air on a G String"
}
]
``

echo database.length()

which emitted 6. In the JS world we'd probably think this to be 3.

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.