Giter Club home page Giter Club logo

ghcid's Introduction

ghcid Hackage version Stackage version Build status

Either "GHCi as a daemon" or "GHC + a bit of an IDE". To a first approximation, it opens ghci and runs :reload whenever your source code changes, formatting the output to fit a fixed height console. Unlike other Haskell development tools, ghcid is intended to be incredibly simple. In particular, it doesn't integrate with any editors, doesn't provide access to the ghci it starts, doesn't depend on GHC the library and doesn't start web servers.

Acknowledgements: This project incorporates significant work from JPMoresmau, who is listed as a co-author.

Using it

Run stack install ghcid or cabal update && cabal install ghcid to install it as normal. Then run ghcid "--command=ghci Main.hs". The command is how you start your project in ghci. If you omit --command then it will default to stack ghci if you have the stack.yaml file and .stack-work directory, default to ghci if you have a .ghci file in the current directory, and otherwise default to cabal repl.

Personally, I always create a .ghci file at the root of all my projects, which usually reads something like:

:set -fwarn-unused-binds -fwarn-unused-imports
:set -isrc
:load Main

After that, resize your console and make it so you can see it while working in your editor. On Windows you may wish to pass --topmost so the console will sit on top of all other windows. On Linux, you probably want to use your window manager to make it topmost or use a tiling window manager.

What you get

On every save you'll see a list of the errors and warnings in your project. It uses ghci under the hood, so even relatively large projects should update their status pretty quickly. As an example:

Main.hs:23:10:
    Not in scope: `verbosit'
    Perhaps you meant `verbosity' (imported from System.Console.CmdArgs)
Util.hs:18:1: Warning: Defined but not used: `foo'

Or, if everything is good, you see:

All good

Please report any bugs you find.

Editor integration

There are a few plugins that integrate Ghcid into editors, notably:

Usage tips

In general, to use ghcid, you first need to get ghci working well for you. In particular, craft a command line or .ghci file such that when you start ghci it has loaded all the files you care about (check :show modules). If you want to use --test check that whatever expression you want to use works in that ghci session. Getting ghci started properly is one of the hardest things of using ghcid, and while ghcid has a lot of defaults for common cases, it doesn't always work out of the box.

Evaluation

Using the ghci session that ghcid manages you can also evaluate expressions:

  • You can pass any ghci expression with the --test flag, e.g. --test=:main, which will be run whenever the code is warning free (or pass --warnings for when the code is merely error free).

  • If you pass the --allow-eval flag then comments in the source files such as -- $> expr will run expr after loading - see this blog post for more details. Multiline comments are also supported with the following syntax:

    {- $>
    expr1
    expr2
    ...
    exprN
    <$ -}
    

Expressions that read from standard input are likely to hang, given that Ghcid already uses the standard input to interact with Ghci.

FAQ

This isn't as good as full IDE

I've gone for simplicity over features. It's a point in the design space, but not necessarily the best point in the design space for you. Other points in the design space include:

If I delete a file and put it back it gets stuck.

Yes, that's a bug in GHCi. If you see GHCi getting confused just kill ghcid and start it again.

I want to run arbitrary commands when arbitrary files change.

This project reloads ghci when files loaded by ghci change. If you want a more general mechanism, consider:

I want syntax highlighting in the error messages.

One option is to use Neovim or Emacs and run the terminal in a buffer whose file type is set to Haskell. Another option is to pipe ghcid through source-highlight (ghcid | source-highlight -s haskell -f esc).

I'm not seeing pattern matching warnings.

Ghcid automatically appends -fno-code to the command line, which makes the reload cycle about twice as fast. Unfortunately GHC 8.0 and 8.2 suffer from bug 10600 which means -fno-code also disables pattern matching warnings. On these versions, either accept no pattern match warnings or use -c to specify a command line to start ghci that doesn't include -fno-code. From GHC 8.4 this problem no longer exists.

I get "During interactive linking, GHCi couldn't find the following symbol"

This problem is a manifestation of GHC bug 8025, which is fixed in GHC 8.4 and above. Ghcid automatically appends -fno-code to the command line, but for older GHC's you can supress that with --test "return ()" (to add a fake test) or -c "ghci ..." to manually specify the command to run.

I only see source-spans or colors on errors/warnings after the first load.

Due to limitations in ghci, these flags are only set after the first load. If you want them to apply from the start, pass them on the command line to ghci with something like -c "ghci -ferror-spans -fdiagnostics-color=always".

I want to match on the file/line/column to get jump-to-error functionality in my editor.

You will variously see file:line:col:message, file:line:col1-col2:msg and file:(line1,col1)-(line2,col2):message, as these are the formats GHC uses. To match all of them you can use a regular expression such as ^(\\S*?):(?|(\\d+):(\\d+)(?:-\\d+)?|\\((\\d+),(\\d+)\\)-\\(\\d+,\\d+\\)):([^\n]*).

What if the error message is too big for my console?

You can let ghcid print more with --no-height-limit. The first error message might end up outside of the console view, so you can use --reverse-errors to flip the order of the errors and warnings. Further error messages are just a scroll away. Finally if you're going to be scrolling, you can achieve a cleaner experience with the --clear flag, which clears the console on reload.

I use Alex (.x) and Happy (.y) files, how can I check them?

Ghcid only notices when the .hs files change. To make it respond to other files you can pass the .x and .y files to --restart, e.g. --restart=myparser.y. As long as you set the initial command to something that runs Happy/Alex (e.g. cabal repl) then when those files change everything will restart, causing the initial command to be rerun.

How do I run pass command arguments with --test?

ghcid ... --test Main.main --setup ":set args myargs"

Why do I get "addWatch: resource exhausted (No space left on device)" or "openFile: resource exhausted (Too many open files)" on my Mac?

The Mac has a fairly low limit on the number of file handles available. You can increase it with: sudo sysctl -w fs.inotify.max_user_watches=262144; sudo sysctl -p

ghcid's People

Contributors

aiya000 avatar akrmn avatar alex-tan avatar alexfmpe avatar basile-henry avatar bitemyapp avatar chrismwendt avatar cloudhead avatar dependabot[bot] avatar domenkozar avatar fosskers avatar gabriella439 avatar goolord avatar isovector avatar istathar avatar jonascarpay avatar jpmoresmau avatar kaoskorobase avatar lspitzner avatar luigy avatar martijnbastiaan avatar matthewbauer avatar meiersi avatar merijn avatar mitchellwrosen avatar ndmitchell avatar pkamenarsky avatar vyorkin avatar wjwh avatar yairchu 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

ghcid's Issues

Ignore certain warnings

Some warnings are irrelevant in ghci, as an example:

-O conflicts with --interactive; -O ignored.

Produced by adding to the top of a file:

{-# OPTIONS_GHC -O2 #-}

Running tests suite

I have a test suite which I can run inside of cabal repl test, with a simple main call.

Is there an existing way to make the test suite run every time I write a file?

Custom command for reloading

Due to some circumstance, my project doesn't reload properly with :reload. I need to write :load app/Main.hs for it to work properly. It would be nice if we could provide a custom reload command.

Apply some automatic fixes

There are certain classes of errors where the error points immediately to the solution. Certain language extensions are easy to turn on and obvious when required, and for certain functions you know where they live and could add an import. I'm particularly interested in cases where currently I have to go to the top of the file, as that's annoying and breaks my flow, and is usually just boilerplate. (It goes without saying, this would have to be opt-in.) Some examples of errors we could catch:

Illegal `..' in record pattern
Use -XRecordWildCards to permit this

Or:

Not in scope: `when'

Or:

The import of `Data.List' is redundant
  except perhaps to import instances from `Data.List'
To import instances alone, use: import Data.List()

Add a space before ...

Loading ghci foo.hs...

Should add a space before the ... - more consistent with what ghci does, and if you do -i.. it doesn't look crazy.

Check executables in addition to library modules?

When I use ghcid I often want to know if my cabal file's executable entries will compile in addition to knowing whether library modules do. Right now, since ghcid doesn't check those, I run cabal install or similar after ghcid ceases to report errors in order to check my entire package. Would it be possible to make ghcid check my programs as well? (Without running them, of course.)

Order of warnings switches on save

Given:

module A where
import Data.List
import B
a = b

module B where
import Data.Maybe
b = 1

Running with warnings, if you save A.hs or B.hs then the order of warnings switches. Should I warn based on module load list order?

Appveyor exceptions

Appveyor currently fails using GHC 7.10.3 on Windows with the error:

  Exception: waitForProcess: invalid argument (Bad file descriptor)

I worked around that with 2136e32, but it would be good to get to the source.

Consider -fno-code

Loading Shake with ghci -fno-code is a big win - I load in 3.61s instead of 5.55s, and working set memory is 130Mb instead of 200Mb. The downside is that you can't actually execute code. In general most .ghci files won't execute code, but they potentially can. The test command if present will almost certainly execute code. Therefore I suggest we:

  • Add -fno-code by default, unless:
    • Either: The user passes --code or some similar flag.
    • Or: the user passes a --test expression.

Errors should say so

Compare:

src\Idea.hs:8:1: Warning:
    The import of `Control.Arrow' is redundant

And:

src\Idea.hs:8:8:
    Could not find module `Control.ArrowX'
    Perhaps you meant Control.Arrow (from base-4.8.1.0)
    Use -v to see a list of the files searched for.

Would be nice if the second said Error explicitly, as suggested in #59 by @rvion.

Use color/style

Putting the file name in bold would make it easier to pick out the key bits. Perhaps the warnings/errors in different colors too. Using the ansi-terminal package here probably makes sense.

Configurable number of lines for error messages?

It would seem that ghcid is truncating error messages to 3 (?) lines. That's somewhat counter to what I was used to. I can imagine why you did it (sometimes you want to see all the errors, not just the first one) but I find myself having to ^C, run stack build manually to see the full error, then back to ghcid.

Am I missing something?

AfC

help improvement suggestion

minor help text improvement suggestion:

current:

     --reload=FILE      Reload if any of these files change (defaults to
                        none)
     --restart=FILE     Restart the command if any of these files change
                        (defaults to .ghci or .cabal)

suggestion:

  • replace FILE by PATH
  • replace (defaults to .ghci or .cabal) by (defaults to .ghci and .cabal)
  • replace any of these files (that let one think that we can pass several files space separated using shell expansion) by something like given file or folder files or { given file | files in given folder } (no strong opinion on specific wording, but current one seems to imply I can pass --reload="foo foro/bar baz" which doesn't work
     --reload=PATH      Reload when { given file | files in given folder } change (defaults to
                        none)
     --restart=PATH     Restart the command when given file or folder files change
                        (defaults to .ghci and .cabal)

Output file feature

I would like an optional flag like --output-file somefile which would be written each time ghcid recompiles the program and would have the same information as the one displayed by ghcid. That way I could watch that file and invoke other utilities on successful compilation.

Multi-project stack does not properly reload

@ndmitchell I have a problem with ghcid 0.6.1

*It is currently impossible to start ghcid so it reloads my code when some .hs file change in my multi-package project

I use stack, I have a set of ~10 packages within one same folder.
All of them have a src folder containing module tree (Foo.hs, Foo/Bar.hs, etc.)
I have one empty package at the top level importing all other packages to simplify compatibility with cabal specific stuff (like haskell-ide-atom).

  • default doesn't work

    ghcid --> never reload when any file changes

    (this is probably a bug 🐛 related to this message printed in ghci: )

    * * * * * * * *
    The main module to load is ambiguous. Candidates are:
    1. Package `app' component exe:app-example with main-is file: /Users/rvion/dev/cogito/app/Main.hs
    2. Package `pghs' component exe:pg2hs with main-is file: /Users/rvion/dev/cogito/pghs/Main.hs
    You can specify which one to pick by:
     * Specifying targets to stack ghci e.g. stack ghci app:exe:app-example
    Specify main module to use (press enter to load none): Not loading any main modules, as no valid     module selected
     * Specifying what the main is e.g. stack ghci --main-is app:exe:app-example
    
     * Choosing from the candidate above [1..2]
    * * * * * * * *
    
  • command to load top level package doesn't work because it doesn't watch local deps change

    `ghcid -c "stack ghci toplevelpackage"

  • one reload param with list of file doesn't watch

    ghcid --test="testFunction" --reload="**/*.hs" -> loop weirdly because of "*/.hs"

  • one --reload per folder doesn't work because no recursivity

    ghcid --reload pkg1 --reload pkg2 --> never reload when pkg1/src/*/.hs change because only watch for pkg1/* (direct folder, no recursive)

So far: the only 2 solutions I thought about were

  1. make a giant cmd like

    ghcid ... \
       --reload pkg1/src/ \
       --reload pkg1/src/Foo \
       --reload pkg1/src/Foo/Bar \
    
       --reload pkg2/src/ \
      -- ...

    possible partial workaround:

    ghcid  $(ls **/*.hs | while read -r line; do dirname "$line"; done | uniq | sed 's/^/--reload=/' | tr '\n' ' ' | sed 's/ $//g')
  2. start one ghcid cmd per package

I went with (1) but then I found a bug 🐛 in ghcid:

ghcid --reload=pkg1/src/

doens't reload anything unless I'm specifying a target.
since I have several executables, not specifying a target shows

* * * * * * * *
The main module to load is ambiguous. Candidates are:
1. Package `app' component exe:app-example with main-is file: /Users/rvion/dev/cogito/app/Main.hs
2. Package `pghs' component exe:pg2hs with main-is file: /Users/rvion/dev/cogito/pghs/Main.hs
You can specify which one to pick by:
 * Specifying targets to stack ghci e.g. stack ghci app:exe:app-example
Specify main module to use (press enter to load none): Not loading any main modules, as no valid module selected
 * Specifying what the main is e.g. stack ghci --main-is app:exe:app-example

 * Choosing from the candidate above [1..2]
* * * * * * * *

and then no reload occurs at all

so I did

ghcid -c "stack ghci toplevelpackage" --reload=pkg1/src/ --reload=pkg1/src/Foo --reload=...

but arg again: ghci don't reload files in pkg1 since I specified toplevelpackage. so toplevelpackage reload when I change pkg1, but it doesn't pick changes in pkg1

Otherwise, great project ! Thanks

Error if no/partial prelude

I'm in a hurry, so I'm afraid this won't have much detail.
When either using -XNoImplicitPrelude or import Prelude (a, few, functions), ghcid gets stuck.

Accept key input

@fegu suggests that instead of All good the tool should say something like:

All good
   Press R to reload
   Press P to pause
   Press B to build
   Press H to HLint

I am particularly keen on the R option, which would kill ghci and restart from scratch, as it provides some workaround for #7, especially if you are using cabal repl and change the .cabal file. The P option would also be useful when I'm on a train, at the moment ghcid sucks my battery flat in about the duration of my train ride, sometimes slightly sooner.

Add Mac specific ghcid tips

On iterm2/3 (osx)

  • one can Cmd+click on filepaths to open the file in any editor at the right line/column. Sublime and atom even find the best window to reuse to open the file (the window where the project containing the file is open by default)

image

image

  • one can configure specific triggers:

image

image

to color the text for instance:
image

ghcid reports "can't find file" while editing with Vim

While editing a file with Vim, ghcid -v reports:

%WAITING: GHCidTest.hs

Reloading...
  GHCidTest.hs
%GHCINP: :reload
%GHCERR: 
%GHCERR: <no location info>: can't find file: GHCidTest.hs
%GHCOUT: #~GHCID-START~##~GHCID-START~#Failed, modules loaded: none.
%GHCOUT: #~GHCID-START~##~GHCID-FINISH~#
%GHCERR: *** Exception: #~GHCID-FINISH~#
%GHCINP: :show modules
%GHCOUT: #~GHCID-START~##~GHCID-START~##~GHCID-START~##~GHCID-FINISH~#
%GHCERR: *** Exception: #~GHCID-FINISH~#
%ACTIVE: []
%LOAD: []

All good

%WAITING: 

It only happens with Vim, not with other editors, and only after a few edits have been made (and for which ghcid did report errors and warnings correctly). I'm not sure it's a ghcid bug, it might be something specific to my system.

See also #21.

I'm using version 0.3.2 and the command ghcid --command='ghci GHCidTest.hs' on Ubuntu Linux.

File not found error

Unfortunately our work to reduce wakeups in #27 doesn't work when the editor is vi[m]. ghcid errors out with:

src/MostExcellentProgram.hs: Can't find file

the moment the source file in question is updated. Bummer.

When saving, some editors — like vi — write out a new file, then delete the original one and atomically move the replacement to the original's name (this avoids an interrupted write from leaving a corrupt half empty file).

The particular set of inotify(7) flags I used in my original branch at #27 were specifically chosen to accommodate this case ("deleted", "closed write" in addition to "modified").

Since you've adopted fsnotify, we'll need to work out what the equivalent trick will be with that wrapper. At present ghcid is unusable, unfortunately.

AfC

Reformat for long lines

Sometimes the lines exceed the length of the console, then the useful messages are pushed off the screen after a wrap. We should either truncate long lines, or account for their size properly.

Default height hides file and line info

If I start ghcid without arguments it scrolls to just below the line src/Handlers.hs:19:52: (or the line an error is found at). So I can see the warning but not the line info which makes the default pretty useless. If I specify the height manually it works just fine.

stack integration

stack unfortunately (or fortunately) is yet another tool projects can be built with. I believe it deprecates cabal sandboxes and cabal install entirely. A stack-based project can jump into a ghci session with stack ghci.

Errors don't show up

Using 6.0.1. I have a stack project with extra projects linked to it through the packages flag in stack.yaml. I run the repl with stack repl my-main-project so I've provided that in the --command flag.

The problem is I don't see any errors. I see All good (10 modules) and when I introduce an error I see All good (9 modules) without any messages.

Excessive wakeups

powertop(8) on Linux reports the most expensive process in terms of processor wakups is ghcid.

     Usage     Events/s     Category       Description
  4.5 ms/s     108.8        Process        ghcid --command=cabal exec ghci tests/Experiment.hs

this represents about a quarter of the user-space power draw on this machine when on battery!

Originally I thought you were using inotify(7) so assumed that it wouldn't be doing any wakeups at all. When I saw it sucking down power like this, I had a look and just realized you're not using hnotify. Oh.

Is that deliberate? Assuming not, would you countenance a dependency on fsnotify (which purports to be a cross-platform wrapper around the different filesystem notification mechanisms)?

AfC

some way to pass in the cabal files extensions?

i'm not entirely sure if this is the job of ghcid, but i'm using the NoImplicitPrelude extension, and thus my ghcid command starts off like ...:

ghcid --command="stack ghci --ghci-options -XNoImplicitPrelude ...

it'll get more crazy as i care about more extensions. but shouldn't we just be able to load with the extensions that are found in the cabal file? am i missing some reason that this isn't a good idea?

identifier not shown because of extra line break in "variable not in scope"

when ghc(i) outputs an error message

src/Matchbox/Automaton/Plain.hs:180:27: error:
    • Variable not in scope:
        domainL
          :: R.Rel p q (Path q1)
             -> t0 containers-0.5.7.1:Data.IntSet.Base.Key

then ghcid does not show the name:

src/Matchbox/Automaton/Plain.hs:180:27: error:
    • Variable not in scope:
src/Matchbox/Relation.hs:103:1: warning:

I guess this is because of the extra line break, because it works if the error message is like this

src/Matchbox/Automaton/Plain.hs:49:31: error:
    • Variable not in scope: auto :: Aut Q c0 (Path Q)

then ghcid handles this fine.

I think haskell-mod has the same problem. The extra line break could be flagged as a bug (misfeature) in ghc?

Can't detect reloaded files when using `:set -package <PKG>`

I have the following lines in my ~/.ghci:

:set -package pretty-show
:set -package hscolour

With those two lines present, when I :reload in ghci no message is printed, and ghcid then bails out because it can't detect any reloaded files.

Is this perhaps a problem that needs to reported upstream to GHC?

Fails to detect certain load failure messages

When I delete the file being monitored, or if it didn't exist to begin with, ghcid always reports "All good". This is confusing, because it hides the fact something is probably wrong.

I'm using version 0.3.2 and the command ghcid --command='ghci GHCidTest.hs' on Ubuntu Linux.

Issues with "Prelude.hs" in the same folder

Prelude.hs

module Prelude where

A.hs

module A where

Situation 1 Structure:

./Prelude.hs
./A.hs
./.ghci

where ./.ghci is

:load A

Situation 2 Structure:

src/Prelude.hs
src/A.hs
./.ghci

where ./.ghci is

:set -isrc
:load A

Running ghcid in situation 1 gives: ghcid.exe: UnexpectedExit "ghci" ""

Running ghcid in situation 2 gets stuck in Loading... forever

Abbreviate the module import error

Following #42, now that I show the full output, the import warnings are excessive and unhelpful:

src\General\BigString.hs:6:1: Warning:
    The import of `Data.Time.Clock' is redundant
      except perhaps to import instances from `Data.Time.Clock'
    To import instances alone, use: import Data.Time.Clock()

The last two lines are very low information density. I should special case them and remove them.

Sometimes Ctrl-C doesn't always work

Seems to have started around the time I switched to the filesystem watcher. Not sure what's going on. Not all the time, but it certainly fails some of the time.

Running ghcid fails in project with compile errors

Running ghcid -v in a project with an (artificial) compile error produces:

%GHCINP: 
%GHCERR: Warning: The package list for the local repo
%GHCERR: '/Users/sk/projects/samplecount/shake-language-c/.cabal-sandbox/packages' is
%GHCERR: missing. The repo is invalid.
%GHCOUT: Preprocessing library shake-language-c-0.6.0...
%GHCOUT: [16 of 19] Compiling Development.Shake.Language.C.Rules ( Development/Shake/Language/C/Rules.hs, dist/build/Development/Shake/Language/C/Rules.o )
%GHCERR: 
%GHCERR: Development/Shake/Language/C/Rules.hs:91:15:
%GHCERR:     Not in scope: ‘ToolCain.defaultBuildFlags’
%GHCERR:     Perhaps you meant ‘ToolChain.defaultBuildFlags’ (imported from Development.Shake.Language.C.ToolChain)
ghcid: UnexpectedExit "cabal repl" ""

This is with ghcid 0.2 installed in a cabal sandbox.

Default to exec'ing ghci in sandbox if present?

It just took me the better part of an hour to remember how to use this. I tried

$ ghcid
$ cabal exec ghcid
$ ghcid tests/Experiment.hs

and many variations. You get the idea, I'm sure. What worked in the end was this:

$ ghcid --command="cabal exec ghci tests/Experiment.hs"

which, I think you'd agree, is a mouthful.

It would be nice if

a) ghcid was cabal sandbox aware, automatically using cabal exec to get into ghci [I gather it's a no-op in the absence of a sandbox, so perhaps that's viable as a default]

b) ghcid took an argument to be interpreted as a filename [or cabal repl target?] to be what is :loaded.

Am I totally missing the plot here? I know you can have a .ghci file with commands in it, but that doesn't seem to be so great when you're quickly trying to build and test lots of different snippet test prorams.

AfC

Oneshot mode for scripting

ghcid is the quickest way for me to test my code, faster than cabal test and stack test. I'd like to use ghcid in a pre-commit hook but ghcid doesn't support a oneshot mode as far as I understand it.

Simply using echo test | cabal repl doesn't work for me because cabal repl's return codes aren't meaningful.

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.