Show HN: TabNine, an autocompleter for all languages
tabnine.com
tabnine.com
> Its paid features are always enabled when completing Rust code, in acknowledgment of the fact that TabNine could not exist without the Rust ecosystem.
Thanks for this, Jacob!
[0] - https://www.reddit.com/r/rust/comments/9uhc1x/tabnine_an_aut...
Following your logic, nobody should show appreciation for anything.
Or maybe he's serious, maybe the Rust ecosystem literally saved him from death or something like that.
Alternatively you could read it as “I wouldn’t have bothered doing this if rust wasn’t there.”
I don't think it was intended to be interpreted literally. The intent and the feeling behind what he was communicating was represented clearly.
He might also not have chased the project if he weren't working in an ecosystem he particularly liked, so who knows, maybe it wouldn't have happened without Rust.
But you never know, maybe in another language he would have done a much better project, maybe not. Actually, in alternative universes everything would probably be different. If Python didn't exist this project would maybe not exist too, and would be at least a little different in any case, so he could have opened the full version to Python codebases too, and that applies to all other languages.
Actors do not win Oscars doing great performances in bad movies.
Scientists do not win Nobel prizes working alone or in bad work conditions.
I always take these appreciations at face value.
That said, not trying to undercut anyone's appreciative statements, especially the one from OP in his repo towards Rust! Obviously people (and programming languages, for that matter) aren't simple drop-in replacements for each other in real life. You have to be inspired and empowered by them.
That personal motivation or rapport component is probably what was being missed in the post to which I replied.
This is valid for both programming and human languages.
Note that they talk about the ecosystem, not just the language. If you want a high performance, compiled language, with a good ecosystem of packages that you can leverage then Rust is a great choice. Arguably Go is the only other language that would fit the bill, but for some people the simpler type system doesn't allow the abstractions they want.
So, give your proprietary software both network access and access to all my source code?
I have very few complaints about the Jedi autocomplete library, which is neither proprietary nor requires network access.
I welcome innovation in dev tools, but I wish you had found a monetization strategy that didn't require us to trust you so completely.
The private keys used to sign releases are kept offline and would not be available to an attacker even if they compromised my online accounts.
Finally, TabNine will work correctly if you deny it network access (say, by blacklisting update.tabnine.com).
> TabNine makes web requests only for the purposes of downloading updates and validating registration keys.
Also, AFAIK most understandings of MIT, BSD, and Apache 2.0 licenses require you to acknowledge the copyright holders of the source code you compile into your binary, even if the licenses permit binary distribution. I can't find your "Copyright (c) 2018 Tokio Contributors" or "Copyright (c) 2014 The Rust Project Developers" that I'd expect based on `strings TabNine | grep github`. Maybe you've got a lawyer that suggests otherwise? Your plea of "trust me, I have good hygiene" carries less weight when I have to `strings` your stuff to know what shoulders of which giants you're standing on.
Can't you make the same complaint about any auto-update functionality in any software? Even if it's BSD licensed, you're still counting on whomever has authority to push an update to not push malicious code.
This doesn't seem to have anything to do with the fact that his code is proprietary nor his monetisation strategy, so why are you singling him out for those?
DRM/monetisation - the product as of my comment didn't seem to acknowledge the open source works compiled into the binary, and I didn't think that was a good look for someone with the authority to push out malicious code.
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
It's up to a court to decide what "copies or substantial portions of the Software" means.
Personally, I've always very much interpreted that to mean both binary and source.
Personally I would still include it in both, but I always had the impression that MIT was looser than BSD-2-Clause about this. BSD-2-Clause explicitly states that binary distribution needs to include the notice in "the documentation and/or other materials provided with the distribution", and I have a feeling that the license authors might've had a reason to want to be explicit about it.
Just to clarify - would it still work if I deny network acess for the TabNine binary, _after_ validating my license key? Or is the key validation invoked on every launch (hence requiring network access)?
(License key validation requests go to tabnine.com, so you should blacklist that too if you want to deny all network access.)
Ie, could we write a monitoring proxy where if enabled, all traffic goes through this proxy. This proxy enables the end user to monitor 100% of traffic, all http requests, and could even have a secondary documentation flow that explains the I/O for security minded individuals.
Then you'd shut off remote network access to the binary, monitor all traffic, and feel secure knowing that it's only sending what it says it's sending, and why.
With that said, I imagine you could do the same thing with a sniffer. Perhaps a documentation standard could be built into request/responses, so a monitoring program like Wireshark could snuff the I/O and see what it is.
Do you have any thoughts on how someone could both network-license, and make you feel secure in their I/O? Ie, no trust needed?
In this particular case, the use of TLS (good!) makes it relatively challenging to inspect. Assuming the author isn't shipping a cert in his binary (doesn't look like it) - I'd have to spinup a new VM, load a custom root cert, and mess with a TLS terminating proxy / forwarding solution, and hope he's not using a secondary stream cipher on top of TLS. Maybe I get lucky and https://mitmproxy.org/ or something just works out of the box. In any case, lots of effort to know he's not siphoning up all the source code on the local machine and using it to train v2 of his project. And the more robust the DRM solution, the less feasible it is to inspect.
[0] https://github.com/jwise/28c3-doctorow/blob/master/transcrip...
I’m not suggesting this is perfect in any case, but it would at least place an upper bound on whatever amount of IP leakage you think might happen.
With such a setup, users can see exactly what data is outgoing, have a reasonable belief they know what's incoming is harmess, main app gets no network access, agent has no access to secrets/system, and agent can be open source (entirely or mostly).
So, there's a quick brainstorm from how I did privilege-minimization for high-assurance security. This is basically a proxy architecture. That's a generic pattern you can always consider since it can help protect lots of risky apps both ways.
I'd imaging TabNine has this problem in spades, since it does such long autocompletes. It could suggest "unsigned long long" when I've typed "unsi" and I really want "unsigned long int". Seems like a tough UX problem. ¯\_(ツ)_/¯
This is just based on the site, I've not tried it yet. YMMV
It'd be nice to long press "Work" at step one, get that completed without a space being inserted, then tap 'i' to get ("Working", "Workings", "Workingmen")
When I click just after the initial letter (pipe representing caret that would be) eg "w|orking" the chances of me wanting to type "worked" are pretty slim; instead it should offer "Dorking" (a UK placename), "borking" and such; according to my frecency scores.
Similarly if I click to place the caret at "work|s" I'm probably after "words" or "worts" (beer stuff), or similar. Again "working|" and I'm probably going to change to a different suffix - works, workers, worked.
I'm amazed that gboard (Google's Android keyboard) doesn't already do that? Perhaps I missed a setting.
What I fear is that the autocomplete can reveal my NSFW jargon. It’s the same keyboard even when Safari is in Private Mode, right?
By that I mean if you have 2 autocompletion options `addDefaultFoo()` and `addDefaultBar()`, and you type `add` to get those options, hitting Tab will fill in `addDefault`, and then hitting Tab again will fill in the rest of the selection.
Which is The Good Place of computer languages?
Then, once you've worked out how to deal with the brackets, it's pretty forking sweet.
def foo(bar):
n
it suggested the entire completion of "= len(bar)". It has a really cool way of picking up your coding style that makes it stand out to me.Full disclosure that I know the author.
Thinking about it more, I wonder how useful that type of autocompletion is for those who can type fast. I wonder how much time it takes my brain to context switch away from "code authoring and typing mode" to recognize the " = len(bar)" in the autocomplete options list. It seems like it would be faster to just type out the " = len(bar)" for those who type a solid 60+ words a minute?
Just wonderful. All dev tools should be like this.
I got great results for a PHP/JS project straight away — an instant upgrade for me just to support continued development.
Overall after a couple of hours of playing with this. My mind is quite blown away. This is absolutely amazing.
Hopefully Microsoft or someone acquires this technology for a fat sum and open sources it.
I've thought about code completion smarts for a long time. You actually executed and delivered a product. Kudos! Take my money!
$30 is a pretty cheap price for a pattern based completion engine.
It’s the first time I’ve seen it work well. It was completing fairly long statements and I was pleasantly surprised how close the first few results were to what I wanted.
The whole configurationless, all language completion using pattern analysis and fast index lookups in a very easy to install delivery is great execution.
This are the kinds of little small things that make me think “why didn’t I do this?”
I wish the author gave, 30 day free premium trial. A lot people would be willing to spend on the license IMHO.
Well, there's a 30-day money back guarantee.
PS: I just bought it, loving so far.
My main issue is when I type a '.', the C# extension gives me an accurate list of members, but TabNine intersperses its own guesses, which are often wrong.
Possible fixes or mitigations (VSCode API permitting):
- After a '.', discard the TabNine completions whose prefix doesn't match one of the C# completions.
- After a '.', discard all one-word TabNine completions.
- Give all TabNine completions a different icon and maybe sort them all at the top or bottom.
This makes me very happy as a new Rust learner.
I'm using this in Vim and would like to know if there's a way to configure it such that the dropdown does not show up until I hit <C-n> or <C-p>? I realize that this is supposed to be a zero-config tool, and I'm asking for a configuration!
Great job with pricing as well. Going to use this for a week before I commit to the license but $29 is a no-brainer for how much use I'll get out of this autocomplete.
So you can imagine the ML engine generating the suggestions with the static analyzer ranking the suggestions intelligently.
It's kind of similar to the original AlphaGo where you have the model generate the potential moves that are then ranked by the Monte Carlo Tree Search algorithm.
[0] https://www.gnu.org/software/emacs/manual/html_node/autotype...
The limit exists because otherwise latency or RAM usage might be too high.
[1]: https://github.com/phiresky/deep-intellisense Video https://www.reddit.com/r/programmerhumor/comments/8xrwr5/_/
https://github.com/zxqfl/tabnine-vim/blob/master/COPYING.txt
He just changed it so that it uses TabNine as that server.
I noticed in some of the examples that the autocompletions were multi-word (for the language involved). This makes sense and I have no real problem with that it limited cases. What I wonder is have you found any issues with autocompletions resulting in less DRY code?
- and -
Since it's not parsing, is it possible to tell it to not show autocompletions based on a pattern? This is no deal breaker, it just annoys me when code comments accidentally invoke the drop-down and I'd imagine that a similar problem could happen with strings.
I'm seriously hyped, I just hope it works as well as it claims.
edit: Can you provide some help/FAQ on using it from the CLI? I'd like to add support for my own editor, but I'm not yet sure if that's possible.
Thanks!
I just added a 30-day money back guarantee.
Or are the editor plugins implemented in such a way that it gets mixed in to what you already have?
Heads up, it's not necessarily uncommon for JS developers to include node_modules in their git repos. If you're developing something like an Electron project or a website instead of a library, it's even sometimes advised to do so -- there's a line of thought that your static dependencies should be tracked as part of your source control.
It might not be a terrible idea to have an alternate config for this that allows excluding other directories. Even if a developer doesn't include their dependencies, they might have old code that they don't want integrated into their suggestions if they're in the middle of a refactor or something.
It's obviously not right for every project, I wouldn't classify it as default behavior or even a standard behavior. But if you're already using Vagrant/Docker to standardize environments across your entire stack, there's an argument to be made that there's really no need to not to have your dependencies precompiled and local to the project.
If you can get rid of complexity, it's worth considering whether or not doing so might be a good idea. Across standardized environments, fetching dependencies is extra complexity.
Eg in pythonland, I’m pretty sure I’ve never seen a repo with packages stored in the repo.
So what happened in jsland that makes the difference?
Node installs packages locally to the project itself. This was partially a direct response to languages like Ruby and Python; the early community felt like system-wide dependencies were usually bad practice. So you can install packages globally in Node, but it's not the default.
When you move away from global dependencies to storing everything in a local folder, suddenly you have the ability to commit things. And at the time, there weren't a ton of resources for hashing a dependency; managers like Yarn didn't exist. So checking into source turns out to be an incredibly straightforward answer to the question of, "how do I guarantee that I will always get the same bytes out?"
People are free to fight me on it, but I would claim that this was not particularly controversial when Node came out, and it is a recent trend that now package managers are advising Orgs to just use lockfiles by default. Although to be fair, a lot of the community ignored that advice back then too, so it's never been exactly common practice in Open Source JS code.
Standard practice atm is to install packages locally to a project by using venv, or rather pipenv. Afaik, lockfiles remain sufficient. I assume ruby is in a similar state, but im not familiar with its ecosystem
>And at the time, there weren't a ton of resources for hashing a dependency
I suppose that’d be a big reason, but isn’t that basically equivalent to version pinning? (Whats the point of versioning, if multiple different sources can be mapped to the same project-version in the npm repo?)
It seems odd to me because it seems like it’d screw with all the tooling around vcs (eg github statistics), conflates your own versioning with other projects, and is the behavior you’d expect when package management doesn’t exist like in a C/++ codebase.
rust/python/ruby/haskell don’t see this behavior commonly, specifically because utilizing the package manager is generally sufficient. 62That njs would commonly only use npm for the initial fetch seems like a huge indictment of npm; its apparently failing half its job? It seems really weird to me that the js community would accept a package manager..that isn’t managing packages.. to the point that adding packages to your vcs becomes the norm, instead of getting fed up with npm
Adding to it is that, afaik, package management is mostly a solved problem for the common case, and there are enough examples to copy fron that I’d expect npm to be in a decent state... but apparently its not trusted at all?
Thanks for letting me know. This is a good thing to know, it makes me more likely to jump back into Python in the future.
I suppose it is to a certain point an indictment of NPM, certainly I expected more people to start doing this after the left-pad fiasco. But it's also an indictment of package-managers in general.
So let's assume you're using modern NPM or an equivalent. You have a good package manager with both version pinning and (importantly) integrity checks, so you're not worried about it getting compromised. You maintain a private mirror that you host yourself, so you're not worried that it'll go down 5-10 years from now or that the URLs will change. You know that your installation environment will have access to that URL, and you've done enough standardization to know that recompiling your dependencies won't produce code that differs from production. You also only ever install packages from your own mirror, so you don't need to worry about a package that's installed directly from a Github repo vanishing either.
Even in that scenario, you are still going to have to make a network request when your dependencies change. No package manager will remove that requirement. If you're regularly offline, or if your dependencies change often, that's not a solved problem at all. A private mirror doesn't help with that, because your private mirror will still usually need to be accessed over a network (and in any case, how many people here actually have a private package mirror set up on their home network right now?) A cache sort of helps, except on new installs you still have the question of "how do I get the cache? Is it on a flash drive somewhere? How much of the cache do I need?"
If you're maintaining multiple versions of the same software, package install times add up. I've worked in environments where I might jump back forth between a "new" branch and an "old" branch 10 or 15 times a day. And to avoid common bugs in that environment, you have to get into the habit of re-fetching dependencies every checkout. When Yarn came out, faster install times were one of its biggest selling points.
I don't think it's a black-and-white thing. All of the downsides you're talking about exist. It does bloat repo size, it does mess with Github stats (if you care about those). It makes tools like this a bit harder to use. Version conflation doesn't seem like a real problem to me, but it could be I suppose. If you're working across multiple environments or installing things into a system path it's probably not a good idea.
But there are advantages to knowing:
A) 100% that when someone checks out a branch, they won't be running outdated dependencies, even if they forget to run a reinstall.
B) If you checkout a branch while you're on a plane without Internet, it'll still work, even if you've never checked it out before or have cleared your package cache.
C) Your dependency will still be there 5 years from now, and you won't need to boot up a server or buy a domain name to make sure it stays available.
So it's benefits and tradeoffs, as is the case with most things.
Although one factor I just realized is that pip also ships pre-compiled binaries (wheels) instead of the actual source, when available. Which would generally be pretty dumb to want in your repo, since its developer-platform specific; assuming js only has text files, it would be a more viable strategy in that ecosystem to have as a common case
Regarding B and C, its not like you’re wiping out your libraries every commit; the common case is install once on git clone, and only again on the uncommon library update. A and C is a bit of an obtuse concern for most projects; I can see it happening and being useful, but eg none of my public project repos in python have the issue of A or B(they’re not big enough to have version dependency upgrades last more than a day, on a single person, finished in a single go) and for C, its much more likely my machine(s) will die long before all the pypy mirrors do;
Which I’m pretty sure is true of like 99% of packages on pypy, and on npm; which makes the divergent common practice weird to me. It makes sense in a larger team environment, but if npm tutorials are also recommending it (or node_modules/ isn’t in standard .gitignores), its really weird.
And now that you’ve pointed it out, I’m pretty sure I’ve seen this behavior in most js projects I’ve peeked at (where there’ll be a commit with 20k lines randomly in the history), which makes me think this is recommended practice
It's highly uncommon, and I've never seen an active, maintained, or popular project with it.
They've since switched to recommending private repositories like Artifactory instead, which to be fair is usually better for very large organizations nowadays. But that wasn't always the case, and even as recent as 2013, it was the flat-out prevailing advice from package managers like Bower, and there are organizations who are still using and maintaining codebases that were set up in 2013.
You won't see a lot of projects on Github that rely on it, because:
A) Usually Open Source projects are designed to be built on multiple environments/OSes.
B) The majority of Open Source Javascript projects are designed to be installed via NPM anyway, and of course you wouldn't include dependencies for something like that.
However, you want to be careful not to make the mistake of assuming that every project has the same concerns as a standard Open Source project. Especially if an Org is going all in on standardizing dev environments through Vagrant or Docker, the question becomes, "why would you want an extra checkout/build step on top of that?"
Remember that one of the benefits of Git is that it's distributed. Even if you are hosting your own npm mirror, relying on it gets rid of that distributed advantage. It doesn't help you to be able to clone from the person next to you if you can't build without making a network request.
I'm not saying that this should be the norm for everyone. It obviously shouldn't be the norm for libraries. But it's not inherently a crazy or harmful idea.
Is there something I'm missing that makes those examples particularly abnormal? Has consensus radically shifted since the last time I looked into this?
[0]: https://groups.google.com/forum/#!msg/golang-dev/nMWoEAG55v8...
* make .gitignore logic optional, we always have the system we’re working with ignored and only include our extension but we really need autocompletion from the whole project
* Emacs plugin
> When using the Sublime Text client for TabNine, the keyboard shortcut to select the ninth suggestion is Tab+9.
Before reading that I thought it was loosely named after the old T9 (Text on 9 keys) predictve system for mobile phones with numeric keypads only.
That being said, while I'm still passively learning to code and may not need a full license yet, it's a well-priced gift idea for friends who are full-time developers.
I'm curious if this explanation is needed on HN
https://marketplace.visualstudio.com/items?itemName=VisualSt...
It seems to work as promised. Would be great if it could support unsaved files too.
(Disclaimer: I wrote deoplete's original version of the "file" source, which completes file paths).
I'm pretty interested in your project, the way it seems to be able to learn from the way you type matches my workflow better than the usual "clever" auto-expander. I also have no issues paying for good tools (and $29 is really negligible as far as I'm concerned when it's for productivity tools, my keyboard alone costs an order of magnitude more).
However, and I know I'm probably in the minority here, I won't even consider using your program if I can't get the source. I'm not even asking for a FLOSS license or anything, even if it just came with a tarball that I can't redistribute I would consider it. But as it stands I would be completely relying on you maintaining the code and porting it to whatever platform I may want to use later. As it stands for instance it seems that you don't provide binaries for the BSDs: https://github.com/zxqfl/tabnine-vim/tree/master/binaries/0.... . I'm sure I could get it to work with Linux binary compatibily on FreeBSD but why even bother? What if Apple releases an ARM-based desktop a few years from now and you've stopped maintaining your project? Then I have to replace it with something else if I have to code on a Mac. The price is a non-issue but having to work around the closed source nature of the software is not something I want to bother with.
Again, I know that I'm probably in the minority and that many people on HN have no issues using mostly closed source development stacks but I genuinely wonder if you'd have much to lose if you kept the same business model but provided the source. I mean, if people want to pirate your program I'm sure they'll find a way even if it's just the binary, so I doubt you gain much from that. Then the risk is people stealing your code but is there really that much secret sauce in an autocomplete program? If people really care won't they just reverse-engineer it anyway? Aren't they even more likely to try and reverse-engineer it if it's the only way to get an open source version that they control?
Maybe I'm overthinking this.
Anyway, I hope I don't appear too negative, that's just my opinion. I'm happy to see people working on improving our code editing experience in any way or form, sometimes it feels like we're still in the stone age with our dumb ASCII files and relatively primitive tooling.
If there won't be any demand for this tool in a few years this could mean 2 things: Either people think it's not worth it (in this case, you don't lose anything by not using it) or there are better/cheaper alternatives (and you can use them)
There is a lot of reason for someone to stop maintaining a project event if there is demand, they get bored, they change job and don't have time anymore, they get a new hobby…
And it works everywhere. It will also complete this long name I just typed in a markdown document into the filename when creating a new file, and into the class name after that. Yes, there are better methods (like templates) for many use cases if you bother to set them up. But it's amazing how far this single stupid tool already takes you.
TabNine seems to take this one step further. It's really exciting that this concept gets more mindshare. I'm not going to use it (license) but next time I think about upgrading my autocompletion I'll have a better idea into which direction to take it. I'm always toying with the idea of implementing my own.
I tested it in Sublime Text, and it's a bit odd that i can tab after i first pressed the tab button and the autocomplete window disappeared, but i think i can work with that :)
It seems to work with a small Ruby app, but not with a big Ruby on Rails application. Is it because it's too large? How can I check for errors or index status?
Using it with Sublime Text.
[edit] Ok, it just took a bit before showing the tab competitions and the license message. Will be useful to know where the index process is at.
[edit2] Just bought a license. Keep up the good work!
Also how do you enter in VSCode that you purchased the pro extension?
The confusion stems from the fact that a human can tolerate a certain amount of "wrong" and still give the "right answer". For example you don't need to speak with perfect grammar to be understood. Humans won't choke on syntax errors the same way a browser chokes on malformed html.
Machines are much more rigid and can't understand context and intent. But this is starting to slowly change in the age of machine learning. For example if I make a small typo, I expect an autocompleter to still understand what I was trying to type. It wouldn't be too absurd to believe that in a not too distant future, it would also be able to autocomplete away common/obvious bugs. Maybe it can even autocomplete/rewrite code from near pseudocode if the intent is clear enough.
A blank Ruby on Rails app is several times that amount, and the yarn.lock file alone is nearly 300KB.
Also really awesome of you to provide premium features to the Rust ecosystem for free.
Very impressive work. Best software purchase in a long time.
Holy shit.
TabNine will be more reliable (it will work correctly with malformed, ill-typed, or half-written code) and it can find patterns in your code, like you can see in the pictures on the website.