Emacs: rainbow-identifiers, customized #
A few months ago I had read Evan Brook's post about using text editor colors for identifiers instead of keywords. I tried the two Emacs modes for this: rainbow-identifiers and color-identifiers-mode. I wrote up my thoughts back then, and that blog post led to some features being added to rainbow-identifiers. Pros and cons:
rainbow-identifiers | color-identifiers | |
---|---|---|
colors are stable on reload/edit | better than | colors change on reload/edit |
same name has the same color across buffers | better than | the same name has different colors across buffers |
color assigned to every name | worse than | color assigned to important names |
colors might be similar to each other | worse than | colors chosen to be distinguishable |
universal configuration across modes | better than | separate configuration per mode |
Neither is a clear win. Try both and see. I ended up using rainbow-identifiers. However, there were too many identifiers being colored, which meant there were too many colors, which meant I couldn't really distinguish things anymore. Here's what color-identifiers looks like:
var edges = this.graph.edges_from(this.curr); for (var i = 0; i < edges.length; i++) { var next = edges[i]; var edge_weight = this.graph.edge_weight(this.curr, next); if (edge_weight != Infinity) { this.neighbors.push(next); mark_changed(next); if (!this.visited[next]) { this.g[next] = this.g[this.curr] + edge_weight; this.open.push(next); this.parent[next] = this.curr; this.visited[next] = true; } } }
And here's what rainbow-identifiers looks like:
var edges = this.graph.edges_from(this.curr); for (var i = 0; i < edges.length; i++) { var next = edges[i]; var edge_weight = this.graph.edge_weight(this.curr, next); if (edge_weight != Infinity) { this.neighbors.push(next); mark_changed(next); if (!this.visited[next]) { this.g[next] = this.g[this.curr] + edge_weight; this.open.push(next); this.parent[next] = this.curr; this.visited[next] = true; } } }
You can see that color-identifiers picks out local variables and not all names. And rainbow-identifiers colors lots of things, but it misses the variable declaration, which is important to color. So I configured rainbow-identifiers to do this:
var edges = this.graph.edges_from(this.curr); for (var i = 0; i < edges.length; i++) { var next = edges[i]; var edge_weight = this.graph.edge_weight(this.curr, next); if (edge_weight != Infinity) { this.neighbors.push(next); mark_changed(next); if (!this.visited[next]) { this.g[next] = this.g[this.curr] + edge_weight; this.open.push(next); this.parent[next] = this.curr; this.visited[next] = true; } } }
It's in between the default configuration of the two packages. I highlight declarations in bold, and in color. I highlight local variables. I highlight local fields (this.x). But I don't highlight all names. Here's my configuration:
;; Customized filter: don't mark *all* identifiers (defun amitp/rainbow-identifiers-filter (beg end) "Only highlight standalone words or those following 'this.' or 'self.'" (let ((curr-char (char-after beg)) (prev-char (char-before beg)) (prev-self (buffer-substring-no-properties (max (point-min) (- beg 5)) beg))) (and (not (member curr-char '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ??))) (or (not (equal prev-char ?\.)) (equal prev-self "self.") (equal prev-self "this."))))) ;; Filter: don't mark identifiers inside comments or strings (setq rainbow-identifiers-faces-to-override '(font-lock-type-face font-lock-variable-name-face font-lock-function-name-face)) ;; Set the filter (add-hook 'rainbow-identifiers-filter-functions 'amitp/rainbow-identifiers-filter) ;; Use a wider set of colors (setq rainbow-identifiers-choose-face-function 'rainbow-identifiers-cie-l*a*b*-choose-face) (setq rainbow-identifiers-cie-l*a*b*-lightness 45) (setq rainbow-identifiers-cie-l*a*b*-saturation 45))
I also turned off colors for the font-lock faces, and made font-lock-variable-name-face bold. I still think it may be too many colors, so I may end up turning off rainbow-identifiers and trying some of the things Wilfred Hughes has suggested.
Flying drone mesh network #
Photo: xdamman on flickr
We don't collect enough weather data from the atmosphere (or ocean). We also would like internet service everywhere on the planet. Let's solve both problems at once:
A 3D grid of tiny flying drones that collect temperature, humidity, wind from every location and elevation, and also serve as a mesh network ISP that provide internet access to everywhere on the planet.
Ok, maybe it wouldn't really work. Oh well.
Labels: future
Mac OS: index source code #
A few weeks ago I posted how to make Mac OS Spotlight index source code. Mac OS is already indexing my C, C++, ObjC, Java, Fortran, Shell, Python, Perl, Ruby, Pascal, Ada, Javascript, and HTML files, but it doesn't get the other languages and text files I use. Here's the followup post.
Problem to solve: I want to search the contents of *.css and other text files with Spotlight.
In my previous blog post, I went into the Spotlight configuration file and told it to index certain file types like dyn.ah62d4rv4ge80e8drru
, which I had determined was *.css. This wasn't satisfying. Instead of telling Spotlight, I wanted a solution at the Mac OS level.
Emacs: Find files anywhere #
Update: [2017-12-29] See the update for 2017
A typical way to use Emacs is to open lots of files as buffers. In the default Emacs setup, the command to switch to a file depends on whether the file is open:
File | Non-file | |
---|---|---|
Opened | C-x b | |
Not opened | C-x f | N/A |
I don't want to have to remember whether a file is open. Instead, I want the command to depend on whether I'm switching to a file or a non-file. I also want to find files without having to switch folders first, because I work on lots of small projects in different folders. I use these bindings:
File | Non-file | |
---|---|---|
Opened | Cmd T | C-x b |
Not opened | N/A |
In a previous post, I described my previous attempt, using helm-for-files
to open files from many different directories, using locate
(mdfind
on Mac). As part of that, I improved my Mac OS mdfind setup to include all my text files. I was hoping that I could make mdfind fast and precise enough that I'd use it all the time. Unfortunately I couldn't get the queries to run faster than 300 milliseconds, and it didn't feel fast enough to run on every keystroke. There are other emacs packages to do this but I ended up with my own custom setup to make this:
Labels: emacs
Mac OS: Spotlight and source code #
Mac OS X has a real time file indexing system called Spotlight. By itself, it's not terribly useful for me. What makes it useful is that it's accessible from the command line. I can search filenames:
locate mapgen2.as mdfind -name mapgen2.as
The locate
command relies on a database that's rebuilt nightly; mdfind
is updated in real time. Spotlight also indexes the contents, which gives me something similar to recursive fgrep:
fgrep -R word * mdfind -onlyin . word
It won't search for arbitrary regexps but for quickly narrowing down files to find certain words, it's useful.
Extracting Safari's Reading List #
I use Safari's Reading List to transfer pages from my phone to my computer. But I don't really want to read these in Safari on my desktop. I'd rather read them in Firefox, maybe through Pinboard, which has an API to write items and mark them as "to read". This blog post documents what I learned.
Update: [2014-06-07] Deleting items out of the reading list does not work properly. It's ok to read everything out of there but I haven't figured out how to properly modify it. So I guess I need to delete things manually after I read them out.
Update: [2014-09-18] With iOS 8, I'm switching from Reading List to something else, maybe Pinner, to make this process easier.
I searched the web for some resources, and learned that the reading list, as well as other Safari bookmarks, are stored in ~/Library/Safari/Bookmarks.plist
. I can use plutil
and PlistBuddy
to read and edit that file.
Emacs: rainbow-identifiers #
After reading Evan Brook's post about using text editor colors for identifiers instead of keywords, I decided to try the Emacs rainbow-identifiers and color-identifiers-mode. I find rainbow-identifiers easier to configure (it's language agnostic), and the color choices are stable while editing. I find color-identifiers to generate better output when reading code. It highlights only the local identifiers instead of all words, so the colors are more meaningful. Try both and see which works best for you.
Before, using colors for keywords:
var edges = this.graph.edges_from(this.curr); for (var i = 0; i < edges.length; i++) { var next = edges[i]; var edge_weight = this.graph.edge_weight(this.curr, next); if (edge_weight != Infinity) { this.neighbors.push(next); mark_changed(next); if (!this.visited[next]) { this.g[next] = this.g[this.curr] + edge_weight; this.open.push(next); this.parent[next] = this.curr; this.visited[next] = true; } } }
After, using rainbow-colors mode:
var edges = this.graph.edges_from(this.curr); for (var i = 0; i < edges.length; i++) { var next = edges[i]; var edge_weight = this.graph.edge_weight(this.curr, next); if (edge_weight != Infinity) { this.neighbors.push(next); mark_changed(next); if (!this.visited[next]) { this.g[next] = this.g[this.curr] + edge_weight; this.open.push(next); this.parent[next] = this.curr; this.visited[next] = true; } } }
After, using color-identifiers mode (notice how it uses colors for fewer identifiers, so they stand out better):
var edges = this.graph.edges_from(this.curr); for (var i = 0; i < edges.length; i++) { var next = edges[i]; var edge_weight = this.graph.edge_weight(this.curr, next); if (edge_weight != Infinity) { this.neighbors.push(next); mark_changed(next); if (!this.visited[next]) { this.g[next] = this.g[this.curr] + edge_weight; this.open.push(next); this.parent[next] = this.curr; this.visited[next] = true; } } }
Here's how — I first turned off font-lock colors:
(set-face-attribute 'font-lock-comment-face nil :foreground nil :slant 'italic) (set-face-attribute 'font-lock-comment-delimiter-face nil :slant 'italic) (set-face-attribute 'font-lock-constant-face nil :foreground nil :underline t) (set-face-attribute 'font-lock-type-face nil :foreground nil) (set-face-attribute 'font-lock-function-name-face nil :foreground nil :weight 'bold) (set-face-attribute 'font-lock-variable-name-face nil :foreground nil) (set-face-attribute 'font-lock-keyword-face nil :foreground nil :slant 'italic) (set-face-attribute 'font-lock-string-face nil :background "#e0e0e0") (set-face-attribute 'font-lock-builtin-face nil :foreground nil :slant 'italic)
Second, I want colors chosen from L*a*b* color space because it makes the perceived brightness consistent across colors. It turns out color-identifiers mode already uses L*a*b* colors. In rainbow-identifiers mode, I configured it like this:
(loop for i from 1 to 15 do (let* ((lightness 45) (saturation 40) (angle (* 2 pi (/ i 15.0))) (a (* saturation (cos angle))) (b (* saturation (sin angle)))) (set-face-attribute (intern (format "rainbow-identifiers-identifier-%s" i)) nil :foreground (apply 'color-rgb-to-hex (color-lab-to-srgb lightness a b)))))
This generates these colors:
rainbow-identifiers-identifier-1
rainbow-identifiers-identifier-2
rainbow-identifiers-identifier-3
rainbow-identifiers-identifier-4
rainbow-identifiers-identifier-5
rainbow-identifiers-identifier-6
rainbow-identifiers-identifier-7
rainbow-identifiers-identifier-8
rainbow-identifiers-identifier-9
rainbow-identifiers-identifier-10
rainbow-identifiers-identifier-11
rainbow-identifiers-identifier-12
rainbow-identifiers-identifier-13
rainbow-identifiers-identifier-14
rainbow-identifiers-identifier-15
Pretty! You can change the color selection by changing the lightness
and saturation
constants. I'll try this for a while. Update: [2014-05-15] rainbow-identifiers 0.1.3 now has an option for using L*a*b* colors without needing the above code. Use (setq rainbow-identifiers-choose-face-function 'rainbow-identifiers-cie-l*a*b*-choose-face)
Edit: [2014-05-18] The original post was about rainbow-identifiers mode; I updated it to also show color-identifiers mode.
Labels: emacs
Building Mac OS X Emacs 24 #
Update: [2014-10-23] After a long wait, Emacs 24.4 is finally out. The binaries for the Yamamoto Mitsuharu version are available from railwaycat. The blog post is updated for Emacs 25.1 release candidate. I have another blog post for Emacs 26 pretest.
I'm a long time Emacs user. When using a Mac, I've been using the builds from emacsformacosx.com. After reading about the new features in 24.4, I tried the Emacs nightly builds, and was mostly happy with them, but I somehow messed up my Emacs package configuration in a way that I can't go back to Emacs 23.3. No big deal, right? So I waited for the 24.3.90 pretest to go back to a somewhat "stable" version, and that just came out last week.
The problem is that the emacs 24.3.90 pretest from emacsformacosx.com is triggering a runaway distnoted process on my system, and is also running rather slowly. There are some patches floating around there, but I'd have to build from source. I've also been curious about the Yamamoto Mitsuharu version of Emacs; see this list of features. If I'm going to build from source, I might as well try his version, right?
Bluetooth tooth #
People sometimes get tooth implants to replace missing or decayed teeth. Currently they're milled or 3d printed. But I think we could do much more. Why not put bluetooth into your tooth? We'd get:
- Speaker so that you could listen to tunes streamed from your phone.
- Microphone attached to the bone so that you could make phone calls without nearby people overhearing what you say.
- Sensors to measure and report the status of your mouth. Real time graphs of saliva, food, and dental bacteria can be sent to your phone, like a Fitbit for your mouth.
It'll finally turn the "tooth fillings pick up radio signals" myth into reality. Would you get one? I would!
Labels: future
Scented sweat #
Many or perhaps all of the smells produced by your body are produced by the bacterial ecosystems living on and in you. Some of these smells are things we can detect; others we're unaware of. Certain strains of skin bacteria attract mosquitos. By altering the ecosystem on our skin, we can repel mosquitos. Cool!
With genetic engineering, we can do even more. We can replace the bacteria that turn sweat into unpleasant smells with bacteria that turn sweat into floral scents! No more deodorant!
Labels: future, speculation
Future tattoos #
Today's tattoos are boring. Future tech will bring:
- Bioluminescent tattoos: using bioluminescent chemicals, your tattoos will glow or pulse, either all the time, or synchronized with a clock, or triggered by movement or light or sound. Imagine going to a dance club with this.
- E-ink tattoos: with e-ink particles embedded in your skin, you'll be able to change the pattern by applying an external array of electric fields. You'll place the “printer” on your arm, apply a new pattern, and then it'll hold that pattern until you want to change it.
- Biosensor tattoos: with e-ink particles attached to a layer of biosensor molecules, you'll be able to find out what's going on in your blood. You'll set up blocks that are sensitive to 50, 100, 150, 200 mg/dL of glucose, and then by seeing how many bars are “lit up”, you'll have a rough estimate of your blood sugar. You could do this for everything in your bloodstream.
Cool? or creepy?
Labels: future, speculation
Bladder control #
I know there are lots of advanced technologies being developed for treating disease, but the same technologies could be used for non-disease applications. I wrote a little about this a few years ago. So I want to propose something that I think a lot of people would like:
Extra bladders
There are people working on 3d printed organs. Wouldn't it be cool to get a 3d printed bladder? Would you like to super-size that?
Even better, wouldn't it be cool if your supplemental bladder automatically ran tests on your urine, like these Japanese toilets do? The toilets developed in 2004 can measure glucose levels but I'm sure there are other tests that will be practical too. Plus, if it's done in your 3d printed bladder, it can be transmitted to your smartphone in real time over low energy bluetooth, like a Fitbit.
I'd want one. Wouldn't you?
Labels: future, speculation