Re: Setting up a FreeBSD VM for Nim development
True, performance will obviously also depend upon the host OS performance as well. On a side note, I'm very happy to see your PR #14634, thanks for doing the investigative work necessary!
Re: Setting up a FreeBSD VM for Nim development
The NetBSD images are just linux running QEMU as a hypervisor to run a NetBSD VM. Last time I looked at it, the docker images were still using NetBSD 8.1, where NetBSD 9.0 is the current release (released 2020-02-14). I believe the containers also have to run in privileged mode with the KVM device passed through. As far as I'm aware, there aren't any images set up to do the same for FreeBSD and honestly I think just running a VM yourself is probably easier - especially if you use a Mac! If using a Mac, Docker desktop already uses a VM running Linux under the hood so you'd have macOS Host -> Docker -> Linux VM -> NetBSD VM. In that scenario, I'm not sure the nested netBSD VM running in QEMU would have hardware virtualisation support either so I doubt performance would be anything to write home about. Of course, the other option is a cheap VPS. [RamNode](https://ramnode.com) offer a VPS with 512MB RAM and 1 core for $3/mo ($0.0045/hr), or 1Gb RAM and 2 cores for $5/mo ($0.0075/hr). They allow you to upload custom ISOs too. I've currently got a NetBSD VPS running with them that I'm currently setting up to test and work on Nim with.
Re: Setting up a FreeBSD VM for Nim development
I'd be more than happy for it to become a blog post or wiki entry if it would be helpful.
Re: Setting up a FreeBSD VM for Nim development
Note: One thing I purposefully missed out is assigning more CPUs to the VM. By default, VirtualBox seems to assign a single CPU on my machine, but my machine has plenty of resources to share some more, so I tend to ramp it up a bit in the VM settings to 4 cores.
Setting up a FreeBSD VM for Nim development
This post was requested by @timotheecour on [GitHub](https://github.com/nim-lang/Nim/issues/13166#issuecomment-631905175). In it, I’ll walk through my process of setting up a [FreeBSD](https://www.freebsd.org) Virtual Machine for the purposes of working on the Nim compiler and standard library. I’ll be using macOS as a host, but this guide should work for any environment that supports [VirtualBox](https://www.virtualbox.org). # Setting up the hypervisor We’ll be using VirtualBox as our hypervisor as it is supported on the majority of operating systems. You can of course using other hypervisors such as Hyper-V or QEMU, though the instructions will differ slightly for those platforms. Head to [the VirtualBox downloads page](https://www.virtualbox.org/wiki/Downloads) and download the latest release for your platform, then run through the installer process. # Downloading the FreeBSD installer image The next step is to download FreeBSD. Head to [the FreeBSD downloads page](https://www.freebsd.org/where.html) and select the amd64 installer image for the most recent release. At the time of writing, this is FreeBSD 12.1-RELEASE. In the directory index for the release, download the -amd64-disc1.iso file - this is currently [FreeBSD-12.1-RELEASE-amd64-disc1.iso](https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/12.1/FreeBSD-12.1-RELEASE-amd64-disc1.iso). # Creating the FreeBSD VM Now that you have a hypervisor setup and the installer for FreeBSD downloaded, it’s time to create a VM. 1. In VirtualBox, select the New button. 2. Set a name for the Virtual machine - I will call it FreeBSD 12.1 Nim Environment. 3. VirtualBox should automatically select BSD as the VM type and FreeBSD (64-bit) as the VM version. 4. Select a folder to save the VM to - I usually just use the default location for a development VM. 5. Press Continue. 6. Set the amount of memory to use for the VM. My host machine has plenty of memory, so I’m assigning 6GB to the VM (6,144MB). [FreeBSD’s hardware requirements](https://www.freebsd.org/doc/handbook/bsdinstall-hardware.html) recommend 2-4GB RAM for a general purpose desktop system at the minimum. 7. Press Continue. 8. Select Create a virtual hard disk now. 9. Press Create. 10. Select VDI (VirtualBox Disk Image). 11. Press Continue. 12. Select Dynamically allocated. 13. Press Continue. 14. Select a location to save the virtual disk image to - I usually just use the default location for a development VM. 15. Select a size for the virtual disk image - I usually just use the default size of 16GB. [FreeBSD’s hardware requirements](https://www.freebsd.org/doc/handbook/bsdinstall-hardware.html) recommend 8GB for a general purpose desktop system at the minimum. 16. Press Create. You could now tweak the VM settings to attach serial devices, allocate more video memory, etc. but I have no need to do that at the moment. # Installing FreeBSD within the VM In the VirtualBox interface, press Start to start the VM. You will be prompted to select a virtual optical disk file or a physical optical drive to start the VM from. Click the folder icon to open the media explorer, then click Add. Browse to the FreeBSD ISO you downloaded earlier and open it. Once the ISO is selected in the media explorer, click Choose to select the ISO. Press the Start button to start the VM using the ISO. The VM should start up, and after a while you should reach the FreeBSD installer welcome screen. Now’s the time to preform the install. 1. Press the Enter key on your keyboard to select the Install option. 2. Select a keyboard layout from the list - use the arrow keys on your keyboard to navigate the list, then press the Enter key on your keyboard to select. I will be using United Kingdom. 3. After choosing a keyboard layout, navigate to the Continue with X.kbd keymap (where X is your chosen keyboard layout - uk.kbd in my case) entry and press Enter key on your keyboard. 4. Enter a hostname for your VM, then press the Enter key on your keyboard. I will be using freebsd-nim-vm. 5. Select the Distributions you wish to install - the defaults should be fine. You can select entries using the Space key on your keyboard. Upon completion, press the Enter key on your keyboard. 6. Select Auto (ZFS) in the partitioning screen. 7. You may then alter some parameters for the disk partitioning. I will be leaving them at the default for this development VM, though would normally select Encrypt Swap for a production machine and would normally configure mirroring. Press the Enter key on your keyboard to continue. 8. In the ZFS configuration screen, select stripe. In a production machine, I would normally configure mirroring. Press the Enter key on your keyboard to continue. 9. In the disk selection screen, select the VirtualBox hard disk option, using the Space key on your keyboard to select it. Press the Enter key on your
Re: Proposal for a more reliable CI
Circle CI certainly supports scheduled jobs that support a cron syntax for specifying the schedule. See the docs here: [https://circleci.com/docs/2.0/workflows/#scheduling-a-workflow](https://circleci.com/docs/2.0/workflows/#scheduling-a-workflow)
Re: Nim in CircleCI
> But both examples say version: 2. Why are there 2 examples, and which is > better? I originally added the 2nd example as the firstw as for the old way that Circle CI did things (v1). It seems the other example has now been updated: [https://github.com/nim-lang/Nim/wiki/BuildServices/_compare/cc4ad91c2478b5fef2e0d88ad7cc48ba8e298f55...d18466d165a66983617344489308e4304ae31c42](https://github.com/nim-lang/Nim/wiki/BuildServices/_compare/cc4ad91c2478b5fef2e0d88ad7cc48ba8e298f55...d18466d165a66983617344489308e4304ae31c42) The 2 examples that exist at the moment are very similar, though the second builds on Alpine Linux and on Ubuntu.
Re: Httpclient and hangs
First point, why does your proc return a string, when no result is actually set? Second, why does it request the content twice, but only use it once? I'd rewrite your proc as follows: import httpclient, asyncdispatch, strutils const MAX_REDIRECTS = 5 TIMEOUT = 2000 proc getPage*(client: HttpClient | AsyncHttpClient, host: string): Future[void] {.multisync.} = let url = "http://; & host try: echo "HTTP/S Probe: ", host let content = await client.getContent(url) for line in content.splitLines(): if "Invalid URL" in line: echo "Invalid URL \n" elif "IIS7" in line: echo "Found IIS Portal \n" elif "bitnami-xampp" in line: echo "Default XAMPP Server \n" elif "Bad Request" in line: red("[-]Bad Request \n") elif "Bluehost.Com" in line: echo "Default Blue Host Server \n" else: red("[~]Check Manually\n") errorHandler(3, host) break except: errorHandler(2, host) when isMainModule: let client = newHttpClient(maxRedirects = MAX_REDIRECTS, timeout = TIMEOUT) getPage(client, "google.com") Run Looking at your code, you seem to be looping indefinitely testing several hosts. Ideally, you should create one HTTP client instance and re-use it for every loop iteration, which is why the above code passes the client in. I also made the above function take either an async or sync http client, leaving you the option to use an asynchronous version at a later date - as you seem to be trying to scan a bunch of random IP addresses, you could probably do a few at a time with an async version.
Re: How to run this language on Mac
Or use Choosenim: [https://github.com/dom96/choosenim](https://github.com/dom96/choosenim) To install using choosenim, run the following in Terminal.app: curl https://nim-lang.org/choosenim/init.sh -sSf | sh Run
Re: Cross-compiling [Win->Lin]
The easiest solution I've found for building for Linux on WIndows is using Docker. You can use one of the [official Nim Docker](https://hub.docker.com/r/nimlang/nim/) images to compile your program and create a Linux executable.
Re: How do I compile an example with SQLite using db_sqlite?
@pavil You need to install the sqlite librayr on your system. I assume you're running on Linux, judging by your error emssages. It depends on the distribution you use, but for Debian you will need to install the libsqlite3-dev package: apt install libsqlite3-dev Run I've never tried to static link to SQLite before, I've always just relied on having the required packages on the target system. You can also add this requirement to your program's .nimble file too by adding something like this: when defined(nimdistros): import distros if detectOs(Debian) or detectOs(Ubuntu): foreignDep "libsqlite3-dev" else: foreignDep "libsqlite3" Run For some documentation on this feature, [please see here](https://github.com/nim-lang/nimble#external-dependencies).
Re: Nim partners with Status.im
Brilliant news, very excited to see what lies ahead!
Re: how to send udp datagram?
@mashingan the documentation explicitly contains the following as an example of using UDP, which is what @luntik2012 was referring to: var socket = newSocket() socket.sendTo("192.168.0.1", Port(27960), "status\n") Run I have submitted a PR to update the documentation: [https://github.com/nim-lang/Nim/pull/8475/files](https://github.com/nim-lang/Nim/pull/8475/files)
prod. ready async PostgreSQL driver
I started writing a Postgres client using asyncdispatch a while back, but never got around to finishing it: [https://github.com/euantorano/postgres.nim](https://github.com/euantorano/postgres.nim) It currently supports basic queries, but doesn't yet support prepared statements (well, it can prepare a statement but not actually run it yet). The tests are a good way to see what's currently supported: [https://github.com/euantorano/postgres.nim/blob/master/tests/postgres_async.nim](https://github.com/euantorano/postgres.nim/blob/master/tests/postgres_async.nim) I do want to finish it off, I just need to find the time to do so...
Re: How to get the last error from db_mysql?
**@luntik2012** use insertId rather than tryInsertId instead: [https://nim-lang.org/docs/db_mysql.html#insertId,DbConn,SqlQuery,varargs[string,](https://nim-lang.org/docs/db_mysql.html#insertId,DbConn,SqlQuery,varargs\[string,)]
Re: Question about sockets
Buffered sockets don't work with UDP due to the way that UDP works. Buffering only works with streaming sockets. If you need per-client buffering of data, you need to implement that yourself by determining how to represent each client.
Re: Question about sockets
Yep, see the following example: import net let listener = newSocket(sockType=SOCK_DGRAM, protocol=IPPROTO_UDP) # listen on port listener.bindAddr(Port()) var data = newString(1024) # receive buffer of 1024 bytes senderAddress: string senderPort: Port numReceived: int while true: numReceived = listener.recvFrom(data, 1024, senderAddress, senderPort) echo "Received ", numReceived, " bytes from address ", senderAddress, ":", senderPort, " - ", data[0..numReceived] This will listen on port and continuously receive UDP packets. Received packets are writtent to the data buffer (max size of 1024 bytes here), the actual number of bytes in the packet are in numReceived and the sender address and port are in senderAddress/senderPort respectively.
Re: General hacking in the Nim ecosystem.
> Is there perhaps some kind of Nim equivalent to "Find something Rusty to work > on"? There is not, as far as I'm aware. It's been talked about a few times, but to my knowledge nobody has ever had a chance to work on such a thing. Would certainly be nice to have.
Re: Nim newbie request/challenge
I've been considering creating a Snap package and/or AppImage for Nim for a while. Maybe I'll have a proper look at it after my holiday.
Re: Editor profiles fo Nim
Regarding a table of what editors can do with regard to Nim integration, see here: [https://github.com/nim-lang/Nim/wiki/Editor-Support](https://github.com/nim-lang/Nim/wiki/Editor-Support) As this is a GitHub wiki, anybody can feel free to update and ammend the entry with any other plugins/editors as they see fit.
Re: What are you writing using nim? :)
I'm currently using Nim at work as a replacement for some old scripts, mostly for provisioning servers (as part of our Ansible deployment setup). The tools in question preform tasks such as creating MySQL databases and the required tables/relationships and importing initial data and downloading a set of applications from our SVN server, zipping them up (using the zipfiles module) and then deploying them onto the servers. We've also written some other small utilities in Nim that would have been written in Python or other languages in the past to do tasks such as monitoring data coming in from a serial port and logging that data with timestamps per packet.
Re: In-Memory Database
There are semi-official Redis bindings here: [https://github.com/nim-lang/redis](https://github.com/nim-lang/redis) Redis would probably be my recommended approach, as it can do replication and all sorts of fancy things. The semi-official just recently got async support too.
Re: Tutorials and documentation for a nim project
I am still around and do plan to eventually find time to work further on the GitBook project I started, just been super busy at work for the last several months.
Re: Nim vs D
The [recent blog post](https://nim-lang.org/blog/2017/05/25/faster-command-line-tools-in-nim.html) I wrot eon the Nim blog also explored performance and build times in D/Nim based upon a blog post on the D site. In it you can see that D and Nim achieve similar speeds in that particular benchmark (with Nim being faster when using Clang, but slower when using GCC according to [this issue](https://github.com/euantorano/faster-command-line-tools-in-nim/issues/1)). What I found most interesting in that performance comparison though was how easy it was to write an optimal version of the Nim program - the standard library CSV parser was my first choice of tool and I didn't have to then dig around for more optimisations (like D's 5 steps to get an optimal version using things like "splitter" and "appender!") which says a lot about how well written Nim's standard library and the language itself is in my eyes.
Re: Progress Bar using stdout.write and eraseLine()
I also have a handy library in Nimble to simplify creating progress bars that might help too: [https://github.com/euantorano/progress.nim](https://github.com/euantorano/progress.nim)
Re: Reproducible builds (stop mentioning nimble install)
**@dom96** The idea is that any release zip of source code would contain the vendor libraries. Most of the time you wouldn't check them in. The NuGet package manager for .net does something similar (as does nom), in that packages for a project are local to the project, and stored in a "packages" folder. The NuGet package system relies on centralised package feeds though, rather than decentralised Git repositories. A good lock format would solve the concerns that vendoring solve for definite though. Both approaches aim to solve the same thing in the end
Re: choosenim - the Nim toolchain installer/multiplexer
Nice one, this should make life much easier, thanks!
Re: Announcing Karax -- Single page applications for Nim
Looks neat, might have to give this a go for some upcoming stuff I was going to write in React. Can I ask what exactly the "Benchmark" graph is meant to show in the readme? Because this isn't very descriptive
Re: New website released!
If there's the possibility of a dropdown for the documentation, might also make sense for one for the Community tab to make the forum slightly more prominent.
Re: Exception Hierarchy Docs
Looks like it's been fixed on the devel branch, so should be fixed next time the docs are regenerated (next release): [https://github.com/nim-lang/Nim/blob/devel/lib/system.nim#L424](https://github.com/nim-lang/Nim/blob/devel/lib/system.nim#L424)
Re: Thread-local persistence
Maybe something like this? I haven't played much with threads in Nim yet: [https://github.com/nim-lang/Nim/blob/4f062c3be08fa2bc3e167e1a6b9842c92bc8c8f7/tests/threads/tonthreadcreation.nim](https://github.com/nim-lang/Nim/blob/4f062c3be08fa2bc3e167e1a6b9842c92bc8c8f7/tests/threads/tonthreadcreation.nim) import locks var thr: array[0..3, Thread[int]] L: Lock top {.threadvar.}: seq[string] proc threadDied() {.gcsafe.} = echo "Dying: ", top proc foo(i: int) {.thread.} = onThreadDestruction threadDied {.gcsafe.}: top = @["hello", "world"] acquire(L) echo "Top in thread ", i, ": ", top release(L) proc main = initLock(L) for i in 0..high(thr): createThread(thr[i], foo, i) joinThreads(thr) main() Seems to work on my machine (Windows) for that very basic example. [In the stdlib, `onThreadCreation`](https://github.com/nim-lang/Nim/blob/4f062c3be08fa2bc3e167e1a6b9842c92bc8c8f7/lib/pure/httpclient.nim#L342) is used, but [it seems to have been removed from `devel`](https://github.com/nim-lang/Nim/commit/4f062c3be08fa2bc3e167e1a6b9842c92bc8c8f7)
Re: Nim video tutorials
Regarding the above comment about annunciation and making sure the audio is clear and easy to understand, it would be a good idea to make sure it's open for people to submit closed captions for other languages to help aid that effort.
Re: How to compile only to C
Hi, There are a few options. * To simply compile to C, use the "-c" option: nim c -c test.nim This will create a nimcache directory containing your C source. * To specify a specific C compiler, as described here: [https://forum.nim-lang.org/t/2387](https://forum.nim-lang.org/t/2387) There are quite a lot of options that can be passed to the compiler to change the behaviour: [https://nim-lang.org/docs/nimc.html](https://nim-lang.org/docs/nimc.html)
Re: Nim Podcast
I'd definitely be interested in something like "This Week in Nim", similar to "This Week in Rust". I already listen to a bunch of podcasts, and I find development focused podcasts difficult to concentrate to. I listened to the phptownhall podcast for a while, but eventually bounced off of the repetitive content. Written content is much easier to focus on and follow for me.
Re: Please , can we stop spams?
I agree that requiring a GitHub account will do more harm than good. It may be worth hooking in to the StopForumSpam API which would help block bots (but not much help for humans). Realistically, human spam is very difficult to combat without impacting the user experience for legitimate users.
Re: Cross compile to OS X
Pretty cool, thanks for sharing.
Re: Subrange field not initialized
Hi, Personally, I would write your code [as follows](https://glot.io/snippets/ekzfjeht1v): type Keypad = ref object position: range[1..9] proc newKeypad(): Keypad = result = Keypad(position: 5) let keypad = newKeypad() Note that method isdynamically dispatched, whilst proc isstatically dispatched. Methods can't be removed with dead code elimination, so proc is usually preferred. The convention newX is also used throughout the standard library. Also note that object initialization uses the colon (:) to specify the value of a field.
Re: General Performance tips?
**@OderWat**: I definitely see where you're coming from, but it would be hard for me to drop my bad habits now ;)
Re: General Performance tips?
**@OderWat**: I rarely ever write my test code inside modules, I use the _unittest_ module for that :) It all comes down to personal preference really, and my background and past experience makes me favour splitting my test code into other areas.
Re: General Performance tips?
**@OderWat**: True, I personally use it for sanity as it makes it easy to search within projects for things that may be ran globally.
Re: General Performance tips?
Use a main() proc combined with when isMainModule: rather than putting main code in the top level.
Re: Nim Documentation - a GitBook version
**@honhon**: Actually, GitBook the tool is open source, but GitBook the commercial hosted company is not. We would be self hosting the actual generated documentation rather than using their hosted service :) And yes, Django has some of the nicest documentation I've seen. I'd love to see libraries and the standard library documented in such a way, and it's definitely improving recently which is excellent! This project is more aimed at [the tutorials](http://forum.nim-lang.org///nim-lang.org/docs/tut1.html) than the library documentation, similar to [Django's tutorial](https://docs.djangoproject.com/en/1.10/intro/tutorial01/). **@jlp765** I would look at it, but I've never actually written much C and doubt I could offer much advice/help on that front I'm afraid!
Re: Nim Documentation - a GitBook version
**@Kerp** Yep, you're correct, there are a couple of "Nim for X programmers" on GitHub in the Nim Wiki - they should probably be better surfaced: * [Nim for C programmers](https://github.com/nim-lang/Nim/wiki/Nim-for-C-programmers) * [Nim for Python programmers](https://github.com/nim-lang/Nim/wiki/Nim-for-Python-Programmers) My plan is to include some kind of glossary of terms with some simple explanations and links to relevant areas of discussion. I also plan to ship some examples of usage with the documentation I'm writing too. **@jlp765** Yes, I think a roundup/review of what needs improving in the documentation every so often could be immensely useful. I can't contribute too much to the core or standard library or such due to time constraints, but editing a paragraph or two o documentation a night is something I can easily do (and I suspect others are in a similar position). Knowing what to focus on would definitely help and is one of the ideas behind this topic.
Nim Documentation - a GitBook version
As was made clear in the [community survey results](http://forum.nim-lang.org///forum.nim-lang.org/t/2512), many see the Nim documentation as being an area for improvement. I recently started a project to work on this exact area, by creating a version of the Nim guide/tutorial as a [GitBook](https://github.com/GitbookIO/gitbook). There are several reasons this is advantageous in my eyes: * Documentation is written in markdown, a syntax many are familiar with. * The online version of the documentation has tools to change the font size and font style, as well as changing the background between dark style background and light style background (different styles are better for day/night time) * The online version is searchable * The documentation can be created as HTML for browsing online * It can also be used to create a PDF or an EPUB ebook automatically (for offline usage, which is extremely handy!) I've only just started this project so far, but have a couple of early sections available. There's a live version available here: [http://nim-docs.euant.webfactional.com/index.html](http://forum.nim-lang.org///nim-docs.euant.webfactional.com/index.html), and the code is all available on GitHub, here: [https://github.com/euantorano/nim-docs](https://github.com/euantorano/nim-docs). I'd be interested to know what people think such a guide should cover, and in what kind of order. Ideally I'd like it to be able to serve as a complete introduction and I plan to cover both beginner topics (what is a variable, what is a procedure/function, etc.) and advanced features that make Nim what it is (templates, macros, etc.). I'd welcome any kind of feedback or contribution on this - would anybody actually se such a version of the guide/documentation? If you were/are just starting to learn Nim, would this kind of guide be useful? I'm aware I might be stepping on @dom96's toes slightly here given his existing book, and I don't intend to draw any focus away from that ;)
Re: dts2nim: A TypeScript -> Nim bridge
Oh, wow that's neat. Nice work! I've been meaning to look at TypeScript for a long time now, but have never got around to it.
Re: httpclient extraHeaders not working
@dom96: That reminds me that I was going to submit a PR for that...
Re: DEB & RPM packages
@abbat Nice. I might look into doing some automated builds as having repositories would be pretty useful for me.
Re: Execution speed Nim vs. Python
@didlybom: In C#, we call them IEnumerable which is quite a good name. Something like enumerable[int] or iterable[int] might make more sense than openarray does, though it's a fairly substantial change.
Re: spawninig of more than 8 threads problem
Hi, I believe the below code does the same thing as you're trying to achieve, though I think I might be misunderstanding your aim - as it stands, there seems to be no reason to use threads whatsoever? import unicode, threadpool, locks, os proc lenU*(s: string): int = result = s.runeLen proc charAtPosU*(s: string, pos: int): string = assert(pos >= 0 and pos < s.runeLen) result = s.runeAtPos(pos).toUTF8() var lk: Lock proc printCharInString(r: Rune) = lk.acquire() defer: lk.release() stdout.write($r) proc multithreadedPrint(msg: string, iters: int) = let msgLen = msg.lenU numCalls = msgLen * iters if msgLen > 0: if msgLen > MaxDistinguishedThread: quit("Your string is too long. Maximum allowed is " & $MaxDistinguishedThread & "!") setMinPoolSize(msgLen) setMaxPoolSize(msgLen) initLock(lk) defer: deinitLock(lk) echo("Total threads: ", msgLen) echo("Total calls: ", numCalls) for i in 0..
Re: StackOverflow Nim Documentation Proposal
@wulfklaue: I don't believe the intention is to replace the standard docs, but the StackOverflow docs would instead be more concentrated around providing examples, which I personally am all for.
Re: Love nim but at the same time starting to hate it...
I definitely agree the documentation needs a bit of work - some more examples certainly wouldn't hurt, and improving the search ability (not just on-site but via Google too) would be a massive bonus. For instance, it took me a while (and I eventually asked on IRC) to work out that indexOf in Nim was called find and was in the struts module. Ideally, a search for Nim indexOf would have taken me somewhere explaining the actual proc with an example of its usage (and it's variations grouped in one place). I did notice that Crystal uses [GitBook](https://www.gitbook.com) to generate [their docs](https://crystal-lang.org/docs/), which are very well laid out, easy to read, searchable and seem to be surfaced on Google much more readily. Possibly there's a way to optionally hook into that somehow?