Giter Club home page Giter Club logo

hardtime.nvim's People

Contributors

agoodshort avatar dtomvan avatar f1rstlady avatar github-actions[bot] avatar guilhas07 avatar heywhy avatar jay-babu avatar jobanmendpara avatar kang8 avatar kevintraver avatar lbiaggi avatar m4xshen avatar mikesmithgh avatar reyniersbram avatar rolv-apneseth avatar schilkp avatar uzaaft avatar weiberle17 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

hardtime.nvim's Issues

When I configure `hint = false` the plugin no longer seems to work

Describe the bug
When I configure hint = false the plugin no longer seems to work

Config options

    use {
      'm4xshen/hardtime.nvim',
      config = function()
        require('hardtime').setup {
          allow_different_key = true,
          hint = false,
          disabled_keys = {
            ["<Up>"] = {},
            ["<Down>"] = {},
            ["<Left>"] = {},
            ["<Right>"] = {},
          },
          restricted_keys = {
            ["-"] = {},
            ["+"] = {},
            ["gj"] = {},
            ["gk"] = {},
            ["<CR>"] = {},
            ["<C-M>"] = {},
            ["<C-N>"] = {},
            ["<C-P>"] = {},
          },
        }
      end
    }

To Reproduce
Steps to reproduce the behavior:

  1. Use the above config
  2. Press j a couple of times
  3. Notice your actions are not blocked and you don't get a notification

Expected behavior
Should be blocked and get a notification

Restricting <UP>, <DOWN>, <LEFT>, <RIGHT> act as disabling the keys

Hi!

  • Plugin version: add7c4c
  • Neovim version: v0.9.1

Expected Behavior

Setting the arrow keys as enabled while restricting them should trigger the count mechanism in their given mode.

Current Behavior

When setting the arrow keys as restricted while enabling them in the setup, they act as if they were disabled in the modes defined in the restricted_keys table, ie:

-- Hardtime
require('hardtime').setup {
  allow_different_key = true,
  enabled = true;
  restricted_keys = {
    ['<UP>'] = { 'n', 'x' },
    ['<DOWN>'] = { 'n', 'x' },
    ['<LEFT>'] = { 'n', 'x' },
    ['<RIGHT>'] = {'n', 'x' },
  },
  disabled_keys = {
    ['<UP>'] = {},
    ['<DOWN>'] = {},
    ['<LEFT>'] = {},
    ['<RIGHT>'] = {},
  },
}

And when I unset the tables for every arrow keys in the restricted_keys table like this:

-- ...
restricted_keys = {
    ['<UP>'] = {},
    ['<DOWN>'] = {},
    ['<LEFT>'] = {},
    ['<RIGHT>'] = {},
},
disabled_keys = {
    ['<UP>'] = {},
    ['<DOWN>'] = {},
    ['<LEFT>'] = {},
    ['<RIGHT>'] = {},
}

It allows me to use the arrow keys again.

Configuration used

Here is my configuration that triggers this behavior:

-- Hardtime
require('hardtime').setup {
  allow_different_key = true,
  enabled = true;
  restricted_keys = {
    ['<UP>'] = { 'n', 'x' },
    ['<DOWN>'] = { 'n', 'x' },
    ['<LEFT>'] = { 'n', 'x' },
    ['<RIGHT>'] = {'n', 'x' },
    ['+'] = {},
    ['-'] = {},
    ['g<UP>'] = { 'n', 'x' },
    ['g<DOWN>'] = { 'n', 'x' },
    ['<CR>'] = { 'n', 'x' },
    ['<C-M>'] = { 'n', 'x' },
    ['<C-N>'] = { 'n', 'x' },
    ['<C-P>'] = { 'n', 'x' },
  },
  disabled_keys = {
    ['<UP>'] = {},
    ['<DOWN>'] = {},
    ['<LEFT>'] = {},
    ['<RIGHT>'] = {},
  },
}

Have a nice day!

Hint message doesn't show, notification sometimes spams

First off, I am new to Nvim and this is probably the most useful plugin I found that force me to use Nvim more efficiently. So thank you so much for your work.

I am using LazyVim config and use the standard hardtime settings, with both hint and notification enabled. However, I cannot see the hint messages anywhere.

Another issue is that the notifications seems to be triggered everytime I click anything. Also, with disable_mouse enable, when I scroll down on my mouse (muscle memorry), the screen is filled with notifications, treating it like key DOWN button. Maybe we could add an option debounce it?
image

refactor: plugin state variables

There are currently two variables controlling the state of the plugin:

  • M.is_enabled: whether user enables this plugin
  • local disabled: whether the plugin should be disabled under current filetype, buftype...

Refine the code to solve following problems:

  • The name of the two variables are confusing.
  • The logic of disabled is defined twice at different places.

A way to keep the plugin enabled, report on bad habits, but not block the input

Describe the bug
An enhancement request. Could we have an option to set it to reporting mode only? For example, I want to still be productive at times, and disabling the plugin (e.g. toggle or Hardtime disable) does not report the times where we might have performed a bad habit.

I plan to review this report from time to time, and be more aware of the bad habits and see if I can improve them, without the hard block on the input key (e.g. when I need to get things done). I know this might not be for everyone, but it might help with the initial transition, or at least a way of using this plugin as a reporting/bad-habit-linter plugin.

Config options
Perhaps a report_only flag, or a enforce/report string. There's probably better sounding options.

Expected behavior
Plugin is enabled in reporting mode. Pressing J in quick succession would have triggered a print/notification and block the key. However since reporting mode is enabled, it only prints, logs and does NOT block the input. Further presses of the key during the threshold can continue to count towards the bad habits, as I would like this to not change too much of the core behaviour + timings.

Screenshots
N/A

Additional context
N/A - only trying to be productive, whilst having the ability to see points of improvements.

Question: disabling notifications in terminal

Hi, I've been using this plugin for a few weeks and enjoying it. I appreciate the hard work you've put into it.

I use the akinsho/toggleterm plugin to open a terminal within neovim, primarily for working with git without having to leave my current window. The problem I'm running into is that I'm getting hardtime alerts while writing commit messages. Is it possible to disable hardtime within the context of the terminal?

Hints containing modifier do not trigger

Describe the bug
When defining a hint with a key combination containing a modifier, for example
<C-W>, it will not trigger.

Config options
Consider the following hint:

hints = {
    ['<C-W>[hjkl]'] = {
        message = function(keys)
            return 'Use <A-' .. keys:sub(7) .. '> instead of ' .. keys
        end,
        length = 2,
    },
}

Expected behavior
When typing <C-W>h, the hint "Use instead of h" should be shown.

Screenshots
N/A

Additional context
N/A

Restricting <UP>, <DOWN>, <LEFT>, <RIGHT> does not work.

Hi!

Describe the bug
Setting up <UP>, <DOWN>, <LEFT> or <RIGHT> as restricted does not restrict them.

To Reproduce
Steps to reproduce the behavior:

  1. Enable <UP>, <DOWN>, <LEFT> or <RIGHT> in setup.disabled_keys
  2. Restrict <UP>, <DOWN>, <LEFT> or <RIGHT> in setup.restricted_keys
  3. Open a file
  4. Move around with <UP>, <DOWN>, <LEFT> or <RIGHT>
  5. See no notification popping up or restriction applied on <UP>, <DOWN>, <LEFT> or <RIGHT>

Expected behavior
Setting up <UP>, <DOWN>, <LEFT> or <RIGHT> in setup.restricted_keys should trigger the count mechanism.

Additional context
Here is my configuration triggering the issue:

-- Hardtime
require('hardtime').setup {
  allow_different_key = true,
  enabled = true;
  restricted_keys = {
    ['<UP>'] = { 'n', 'x' },
    ['<DOWN>'] = { 'n', 'x' },
    ['<LEFT>'] = { 'n', 'x' },
    ['<RIGHT>'] = {'n', 'x' },
    ['+'] = {},
    ['-'] = {},
    ['g<UP>'] = { 'n', 'x' },
    ['g<DOWN>'] = { 'n', 'x' },
  },
  disabled_keys = {
    ['<UP>'] = {},
    ['<DOWN>'] = {},
    ['<LEFT>'] = {},
    ['<RIGHT>'] = {},
  },
}

Have a nice day!

feat: maintain remapped behaviour

Currently, for example, setting j and k to gj and gk won't work since it will be overridden by this plugin.
(At least, I think this is what is happening, as the example situation in question only seems to appear when I have this plugin enabled.)

'yy' and 'p' don't work.

Describe the bug
When I used this plugin, I found the normal yank and paste functions don't work, for example 'yy' and 'p' as follows.

Config options

  "m4xshen/hardtime.nvim",
  lazy = false,
  dependencies = { "MunifTanjim/nui.nvim", "nvim-lua/plenary.nvim" },
  opts = { -- Add "oil" to the disabled_filetypes
    disabled_filetypes = { "qf", "netrw", "NvimTree", "lazy", "mason", "oil" },
    restricted_keys = {
      ["h"] = {},
      ["j"] = {},
      ["k"] = {},
      ["l"] = {},
    },
  },

j/k function keymap blocks navigation

Describe the bug
Out of pure ignorance on my part, why does this keymap work correctly:

vim.keymap.set({ "n", "x" }, "j", 'v:count || mode(1)[0:1] == "no" ? "j" : "gj"', { noremap = true, expr = true, desc = "Move down by display lines" })
vim.keymap.set({ "n", "x" }, "k", 'v:count || mode(1)[0:1] == "no" ? "k" : "gk"', { noremap = true, expr = true, desc = "Move up by display lines" })

while this one completely blocks j/k navigation:

vim.keymap.set({ "n", "x" }, "j", function()
	return vim.v.count > 0 and "j" or "gj"
end, { noremap = true, expr = true })
vim.keymap.set({ "n", "x" }, "k", function()
	return vim.v.count > 0 and "k" or "gk"
end, { noremap = true, expr = true })

Both keymaps work correctly without hardtime.nvim!

Config options

  • I'm not lazy loading the plugin
  • Hardtime is started after the keymaps are set
  • I use the default configuration

To Reproduce
Steps to reproduce the behavior:

  1. Use the second presented keymap
  2. Try to navigate with j/k

Expected behavior
Both keymaps should be valid to use on hardtime.

Ability to disable certain file/buffer types

I love this plugin, but it doesn't always work in every situation.

For example: neogit doesn't really support using 3j instead of jj. Or: neotree technically works, but it's really not ideal when you're digging through sub-directories to have to stop and make sure you hit have proper syntax.

Sure, you can make sure you disable/re-enable, but if it gets to be too much of a hassle, then it just has to be disabled permanently.

Idea: Add AI (even tho i hate it) to figure out better shortcuts

My idea is to have an ai lear all the vim motions and suggest you what you could have done better. Because it is impossible to write a config for every optimal key combination i think an ai could help suggesting those. It sees your current motion inputs and if you type for example diw i it could suggest you to use ciw instead. I don't know if this is a good idea. I think it's hard to implement and it might not even work in the end as intended. What do you think?

Not picking up j/k repeating when using NvChad distro

Firstly, thanks for making this amazing plugin! I am using the NvChad distro, and I have installed hardtime.nvim using Lazy and set lazy = false so the plugin is enabled on startup. I have run into a odd situation where it hardtime.nvim does not pick up j/k repeating. I can fix this issue by running ":Hardtime toggle" twice (or ":Hardtime disable" and then ":Hardtime enable") in order to switch hardtime.nvim off/on. Any thoughts on why this might occurring would be appreciated!

mini-files disable_filetypes support

Describe the bug
hardtime not disabled in mini-files after adding "minifiles" in disable_filetypes config option.

Config options
disable_filetypes = { "minifiles" }

To Reproduce
Steps to reproduce the behavior:

  1. open mini-files
  2. press j 3 times

Expected behavior
hardtime being disabled when in mini-files buffer

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Add any other context about the problem here.

Don't trigger a warning when pressing different restricted keys

I have noticed that when I repeatedly hit certain restricted keys, such as "jkjk...", I receive a warning from hardtime that I have pressed the keys too quickly. However, I believe that this warning should only be given if I repeatedly press the same key, such as "jjjj...". It seems unreasonable to receive a warning for pressing different combinations of restricted keys, as some of these combinations may be still necessary. I am unsure if this is a reasonable idea or not. Correct me if there is something wrong.
Anyway, are there any options available to avoid this problem? Thanks.

Feature: disable every keys individually

Describe the bug
First, thank you for your great plugin!
If you press j and then k, and then again j, k would be disabled too.
But these keys are different and if I hit the limit on using one of them, others should be able to work.

Config options
Default

To Reproduce
Explained in the description

Expected behavior
Each key's timeout should be separated

Report seems to be a bit off

Describe the bug
When running the report to see what should I improve, all the messages seem to be cutting the first 3 characters.

Config options
Default

To Reproduce
Steps to reproduce the behavior:

  1. run :Hardtime report

Expected behavior
The report should display correctly the suggestions.

Screenshots
image

Additional context
I am using LazyVim if matters.

Feature: `cond` function

I don't want hardtime in the way when recording macros, at all. The macro
pressure is enough, you know :)

My solution is at follows: introduce a cond configuration function. It could
be used as follows.

require('hardtime').setup {
    cond = function(_key)
        return #vim.fn.reg_recording() == 0
    end,
}

The nvim . or file name and nvim with lazy package manager

Using lazyvim as base

When launching neovim with

nvim . or nvim index.html

Hardtime loads correctly and have issues with remap issues with keys like x, where x is remapped as _x

Launching nvim only and launches the alpha board

nvim

Hardtime loads keys remapped like x is correctly loading but the gk and gj remaps from lazyvim isnt overriden by hardtime.

added hardtime like this

{ "m4xshen/hardtime.nvim", --hardtime practice event = "VeryLazy", dependencies = "neovim/nvim-lspconfig", opts = {}, },
remapped x like this.

map("v", "x", "_x", { noremap = true, silent = true, desc = "Delete character without yanking" })

i just noticed this as i hardly launch nvim with parameters.

feat: daily / weekly / monthly hardtime report

Add the feature of checking hardtime report under different time scope.

Ideas

At the top of report popup window there should be some tabs that user can select using keys just like the menu of lazy.nvim.

image

4 tabs:
All Time (A) Daily (D) Weekly (W) Monthly (M)

All Time (A) is selected by default.

can't use C-A C-X to increment/decrement

Hi with hardtime enabled I can't use https://github.com/tpope/vim-speeddating (using lazy.nvim as plugin manager)
Config options
default opts

To Reproduce
Steps to reproduce the behavior:
Enable hardtime and speeddating

  1. Enter a number e.g. 1
  2. go to normal mode
  3. press <C-A>
    Result:
    221: ~/.local/share/nvim/lazy/hardtime.nvim/lua/hardtime/init.lua:113>

Expected behavior
Number/date incremented / decremented

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Add any other context about the problem here.

Feature: Swap to `restriction_mode = 'hint'` when running a macro

This plugin has been very helpful to say the least, especially whilst in block mode.

However, I think it would be great if there was an option/ability to swap to hint mode when running a macro, since the blocking can mess up the result, especially if repeated multiple times.

I don't even know if this is possible, so if there is a preferred workaround, please let me know.

What is the useful of resetting_keys section ?

I use yy (double y) to lazy load yank.nvim plugin, but when hardtime.nvim set resetting_keys section for y key that lead yank.nvim can not normal loaded. When i set resetting_keys section empty, it can good work.

Plugin overwrites keymaps of `restricted_keys`

Describe the bug
installing the plugin disables shortcuts for e.g. CTRL+P which opens builtin.git_files in telescope or - is
is a bind for oil.nvim. This is how I mainly navigate between files. Hardtime also doesn't give me an error message
telling me that that's suboptimal, so I think it may be a bug.

Config options
Nothing, I really just added hardtime to lazy as per the readme.

Expected behavior
hardtime gives me a hard time but still lets me navigate between files.

Additional context
See my dotfiles repo for my neovim config.

Hints containing modifier do not trigger

Describe the bug
A clear and concise description of what the bug is.

Config options
The options table passed into the setup() function.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Add any other context about the problem here.

Invisible hint messages when showmode is enabled

Hi,

Lovely plugin, thanks for sharing! After a few minutes of playing around I noticed that when the set showmode setting is enabled, the hint messages are pretty much invisible.

I haven't really dug in to the code yet to see how these are printed but I would assume it's the regular print() function that is used. Perhaps one way to solve this would be to display the messages in a floating window?

No way to re-enable the arrow keys

I want to be able to use the arrow keys to move around, but they are disabled by default, and it no longer seems possible to change this

Previously, I set disabled_keys to an empty table and that worked, but it no longer does, I've also tried

disabled_keys = {
	["<UP>"] = nil,
	["<DOWN>"] = nil,
	["<LEFT>"] = nil,
	["<RIGHT>"] = nil,
}

but that did not work

feat: undo user action if done with suboptimal key combination

Sorry. It is not a bug...

I wish there is an option for forcing me to do things in a certain way, and if I choose the suboptimal way, like di"i instead of ci" the plugin should undo my action and warn me that I'm doing it "wrong".
Of course it can be opt-in...

Only display a notification once

When using nvim-notifiy to display the notification, keeping a key pressed for a few seconds displays a lot of notifications (e.g. keep pressing k to scroll down).

image

Suggestion: Apply logic to only display the notification message once

Not Getting Recommendations

So maybe this has something to do with another plugin, but I was testing hitting the down arrow. I was expecting the hey there is a better way, but it never tells me the better way

image

Config can be found here

{
    "m4xshen/hardtime.nvim",
    opts = {
      hint = true,
    }
  },

Adding more disabled filetypes by default OR...

How about adding more by default, or must the user specify these explicitly?

disabled_filetypes = { "qf", "netrw", "NvimTree", "lazy", "mason", 
"dashboard", 
"dapui_stacks", "dapui_console", "dapui-repl", "dapui_watches", "dapui_breakpoints" -- Example: DAP
},

{OR}

Is there a way for another plugin to specify this so that hardtime.nvim can integrate these directly from another plugin without the user explicitly specifying these? (Example:)

-- Another plugin
integrations  = {
    hardtime_nvim ={
        enabled = true,
        disabled_filetypes = {
            "my_plugin_ft_1",
            "my_plugin_ft_2", -- etc...
        }
    }
}

Prehaps this is not necessarily a hardtime.nvim specific question, but having an example to integrate this with other plugins by default would be a nice touch. :D

Rate limit or disable notifications

Can we add a way to rate limit and/or disable notifications for repeated actions. Being able to set a limit on how many notifications can show for a time period for each key would be great. Using things like notify it spams popups for each key press or if I bump my scrollwheel.

Detect more complicated actions / commands

Thanks for the plugin! While I haven't tried it myself, it seems like the scope of this plugin is currently mostly focused around Vim movements such as hjkl. In the past, there have been other requests for a plugin that can detect more complex actions / Vim motions and suggest better alternatives. So my first question is: is that even something you would consider for this plugin or should it stay relatively simple in scope?

As an example, I could imagine things like:

  • if the user uses daw + i, suggest caw instead
  • $ + a => A; ^ + i => I; y$ => Y (y$ has been remapped to Y by default in Neovim)

While the above suggestions should be relatively simple to implement, there are many many others that can get arbitrarily more complicated since they require analyzing a part of the buffer's edit history (i.e. the last n changes).
Examples:

  • the user changes ex|ample (| is the cursor position) to sample but uses ciwsample => suggest cbs instead
  • the user appends the same string to multiple consecutive lines (e.g. with dot repeat) => suggest to use <c-i> (blockwise visual mode) or the norm command

One could even suggest plugins to simplify certain actions:

  • the user changes local x to -- local x in a Lua file but enters insert mode (e.g. I-- <esc>) => suggest a commenting plugin such as mini.comment
  • the user changes some |word here to some (word)| here but enters insert mode (e.g. i(<esc>ea)<esc>) => suggest a surrounding plugin such as nvim-surround

Ideally, it should be possible to dismiss certain suggestions in which case it won't be shown for the current session or never again. Let me know if you could imagine such suggestions as part of the plugin or not! :)

Altered yank behavior in visual mode

When hardtime is enabled (default settings), pressing Y in visual mode has
different behavior. It now acts the same as y in that it no longer yanks the
entire lines.

Description in help pages: :help v_Y vs :help v_y

Workaround

As a workaround, you can explicitly remove Y and y from the resetting_keys table.

- resetting_keys = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "c", "C", "d", "x", "X", "y", "Y", "p", "P" }
+ resetting_keys = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "c", "C", "d", "x", "X", "p", "P" }

Key bindings with Space as <leader> stop working

Describe the bug
When the plugin is enabled key bindings that (seemingly) have restricted keys in them stop working properly.

Config options

require('hardtime').setup({
  restriction_mode = 'hint',
})

vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

vim.cmd [[ nmap <space>h :lua print('Hello')<cr> ]]

To Reproduce
Steps to reproduce the behavior:

  1. Have the plugin installed.
  2. Spam h, j, k, and l to make the notification trigger. Keep spamming.
  3. Try to use the binding above (<space>h).
  4. See it doesn't work.

Expected behavior
The key binding should work.

Additional context
Add any other context about the problem here.

Mouse is not re-enabled when entering buffer with buftype terminal

Describe the bug
hardtime.nvim does not toggled off when entering buffer with buftype terminal, such as entering :term.

Config options
None.

To Reproduce
Steps to reproduce the behavior:

  1. Open Neovim and have hardtime.nvim enabled.
  2. Open buftype=terminal buffer, such as :term.
  3. Trying to exit out of Terminal mode by clicking mouse.
  4. Stuck.

Expected behavior
hardtime.nvim are toggled off when entering buffer with buftype terminal.

Screenshots
None.

Additional context
None.

Question: Location of `hardtime.nvim.log`

Hi, this isn't really a bug, but rather a quality of life remark.

The log file is currently stored under ~/.cache/nvim/, so when I clear my cache, I lose this report. According to the XDG Base Directory Specification, the advised place for log files is $XDG_STATE_HOME, often set to ~/.local/state/.

Would it be possible to move the log file to this directory, of create an option to choose the location for it? Or is there a reason it is stored under .cache?

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.