my vim completion setting

本人从事web前端开发,一直用vim作为开发工具。

最近一直在折腾completion这事,先后尝试了youcompletemeneocomplete等工具,甚至直接使用vim内置的ins-completion,不过都不尽人意。

一顿折腾之后,总算弄了一套自己用着还算顺手的配置。

我期望completion可以干以下这些事

  • 标识符补全
  • 智能补全(omni completion)
  • 路径补全
  • snippets

这些补全其实ins-completion已经可以搞定了,但是比较费劲,<c-x><c-o><c-x><c-f>…好多按键…

所以有了youcompletemeneocomplete等工具。

试用了一番,neocomplete比较卡,放弃了,最后选择了youcompleteme

youcompleteme

基本配置如下:

1
2
3
4
5
6
let g:ycm_min_num_of_chars_for_completion = 3 
let g:ycm_autoclose_preview_window_after_completion=1
let g:ycm_complete_in_comments = 1
let g:ycm_key_list_select_completion = ['<tab>', '<c-n>', '<Down>']
let g:ycm_key_list_previous_completion = ['<c-p>', '<Up>']
let g:ycm_confirm_extra_conf = 0

阅读全文

服务器推技术之EventSource

最近在看服务器推技术时,发现了一项新的技术:EventSource

w3c上有个草案描述了它:Server-Send Events

回想一下我们之前用到的服务器推技术:

  • polling:客户端不断轮询。
  • long polling:服务端在数据未就绪时,挂起请求。

这两种技术都存在一定的局限,我们需要服务器主动推送数据。

于是有了WebSocket,但它是双向的(服务端<——>客户端)。

有的时候,我们并不需要从客户端发送消息,我们只需要从服务端推送消息,EventSource应运而生。

EventSource是单向的(服务端——>客户端),它直接使用http协议来传输数据(与WebSocket不同,EventSource不需要专门的协议)。

阅读全文

将NodeList转成Array

NodeList是一个Dom概念,其定义如下:

interface NodeList {
    Node               item(in unsigned long index);
    readonly attribute unsigned long    length;
};

它有一个方法和一个属性,可以通过item方法来获得指定的元素:

1
nodeList.item(1);

也可以像数组一样,用下标来访问:

1
nodeList[1];

但它不是数组,其原型链如下:

myNodeList ——> NodeList.prototype ——> Object.prototype ——> null

而数组的原型链则为:

myArray ——> Array.prototype ——> Object.prototype ——> null

NodeList没有数组的那些方法,对它进行遍历不是很方便,我们得先把它转成数组。

借助call以及Array.prototype.slice可以做到:

1
var myArray = Array.prototype.slice.call(myNodeList);

call是把Array.prototype中的this指向myNodeList,slice方法要求this所指的对象有一个length参数,而刚好NodeList就有。

Array.prototype.slice具体如何工作的,参见ecma

nerdcommenter注释符后添加空格

在vim中使用nerdcommenter注释时,我们一般用<leader>c<space>来自动添加或者去掉注释。

假设代码如下:

1
var name = "hushicai";

将鼠标移到该行代码上,用<leader>c<space>进行注释,注释后应该是这样的:

1
//var name = "hushicai";

然而,这可能会不符合某些团队的代码规范,比如我们团队,进行jshint之后,会提示这样的warning:

1
edp WARN → line 1, col 0: Missing space after line comment

意思就是要在单行注释的注释分隔符后面加个空格:

1
// var name = "hushicai";

好吧,既然是规范,那我就不得不遵守了。

看了一眼nerdcommenter的文档,发现有这么一个配置可以解决问题:

1
let NERDSpaceDelims=1

ok,现在我们再使用<leader>c<space>进行自动注释,就可以按照规范在注释符后加一个空格了。

ios fixed定位问题

在ios5之前,我们如果要实现fixed导航条,我们得依赖iscroll来支持。

不过从ios5.1以来,fixed定位就已经支持了,但很遗憾,ios现在对它还只是半支持。

在大部分情况下,fixed表现得没有什么问题。

但是在某些情况下,会出现一些比较奇葩的问题,比如fixed元素中存在输入框子元素,这个时候就会跪了。

阅读全文

v8的词法分析

本文将探讨v8是如何对utf8编码的js文件进行词法分析的!

简介

v8提供了一个Scanner类作为词法分析器,在该类中有这么一个指针:

1
Utf16CharacterStream* stream_;

这是个啥玩意?看一下源代码中对这个类的解释:

// Buffered stream of UTF-16 code units, using an internal UTF-16 buffer.

大概就是说,Utf16CharacterStream就是一个UTF-16代码单元的缓冲流。

啥是代码单元?v8的解释如下:

// A code unit is a 16 bit value representing either a 16 bit code point
// or one part of a surrogate pair that make a single 21 bit code point.

这就涉及到了unicode规范,在unicode字符集中,每个unicode字符都有一个唯一的代码点

在utf8、utf16等编码形式中,代码点被映射到一个或者多个代码单元。

代码单元是各个编码形式中的最小单元,其大小:

  • UTF-8 中的代码单元由 8 位组成。
  • UTF-16 中的代码单元由 16 位组成。

每个代码点需要多少个代码单元呢?不同编码形式不一样:

  • UTF-8中,每个代码点被映射到一个、两个、三个或者四个代码单元。
  • UTF-16中,值小于等于U+FFFF的代码点被映射到单个代码单元中,对于值大于U+FFFF的代码点,每个代码点需要两个代码单元。在UTF-16 中,这些代码单元对有一个独特的术语:“Unicode 代理对”。

综上,我们可以知道Utf16CharacterStream中每一个UTF-16代码单元的含义:

UTF-16中,一个代码单元要么是一个16位的代码点,要么是“Unicode代理对”中的一半,其中“unicode代码对”是一个21位的代码点。

简而言之,Utf16CharacterStream中的每个代码单元,要么是一个独立的unicode字符,要么是一个unicode字符的一半(和下一个代码单元组合起来才能形成一个unicode字符)。

v8实际上就是基于utf16对输入字符序列进行词法分析的!这也是Ecmascript规范所要求的:

ECMAScript 源代码文本使用 Unicode 3.0 或更高版本的字符编码的字符序列来表示。
符合 ECMAScript 的实现不要求对文本执行正规化,也不要求将其表现为像执行了正规化一样。
本规范的目的是假定 ECMAScript 源代码文本都是由16位代码单元组成的序列。
像这样包含16位代码单元序列的源文本可能不是有效的 UTF-16 字符编码。
如果实际源代码文本没有用16位代码单元形式的编码,那就必须把它看作已经转换为 UTF-16 一样处理。

v8词法分析首先要做的是把输入字符序列转换成utf16 stream。

那如何把utf8编码的js文件转换成utf16 stream呢?

阅读全文

mac osx下编译v8

v8相信大家都不陌生,本文将介绍一下,如何在mac osx下编译v8,并用一个例子来试验编译结果。

编译

首先获取一下源代码,v8在github上有镜像,可以直接clone github上的。

1
git clone https://github.com/v8/v8.git

代码量较大,请耐心等待…

下载完成后,我们还需要下载编译前的依赖。

1
make builddeps

Note: 以上命令都比较悲剧,因为要跨越我朝的墙…建议使用vpn吧,用goagent也可以,不过会很慢。

依赖下载完成之后,我们就可以正式build了:

1
make

更多编译选项,请查看官网

阅读全文

关于页面首屏时间

什么是首屏?英文叫above the fold,google一下above the fold,可以发现在维基百科上有专门的条目

正如维基百科上所说,above the fold这个概念最早出现在报纸上,也就是我们通常所说的报纸头条!

这个概念后来被沿用到web上,web中的above the fold,维基百科是这么解释的:

Above the fold is also used in website design (along with “above the scroll”) to refer to the portion of the webpage
that is visible without scrolling. As screen sizes vary drastically there is no set definition for the number of
pixels that define the fold. This is because different screen resolutions will show different portions of the website
without scrolling. Further complicating matters, many websites adjust their layout based on the size of the browser
window, such that the fold is not a static feature of the page.

如上文所说,web中的首屏不同于报纸头条,它的区域是动态的,因为用户的屏幕分辨率是不同的。

那我们应该怎么确定这个首屏范围呢?这个范围需要根据用户的浏览器分辨率数据来制定。

在web中,一般我们只需要敲定一个高度,然后得到一条首屏线

首屏线以上的内容通常是一个站点想优先展现给用户的东西,它能不能及时展示是能不能留住用户一个非常重要的因素。

阅读全文

mac osx命令行下利用goagent作代理

今天在使用brew安装vim7.4时,遭遇了伟大的GFW墙:LuaJit这货总是下载不下来。

于是就开始找代理了,但是手头上只有goagent,没有vpn,咋整?

偶然在一篇文章上发现了curl、wget等http应用程序会调用http_proxyhttps_proxy这两环境变量进行代理,于是我就尝试设置一下:

1
2
export http_proxy=http://127.0.0.1:8087
export https_proxy=$http_proxy

PS:别用ping对以上代理进行测试,不管用。

试着重新安装vim7.4,果然不再被墙,成功下载了!并且在goagent的log上也可以观察到:

INFO - [Apr  8 16:13:33] 127.0.0.1:60865 "GAE GET http://luajit.org/download/LuaJIT-2.0.3.tar.gz HTTP/1.1" 206 271735 

这说明brew的curl确实使用了我刚才设置的代理。

大伙可以在~/.zshrc或者~/.bash_profile中添加这样的alias:

1
2
alias goproxy='export http_proxy=http://127.0.0.1:8087 https_proxy=http://127.0.0.1:8087'
alias disproxy='unset http_proxy https_proxy'

这样下次就可以很方便地切换proxy了!

mac osx下无法安装brew问题

今天很倒霉,本来想update brew的,结果update半天没成功,一怒之下把它删了重装,悲剧就从删除时刻开始上演!!!

捣鼓了一个下午,始终没法重新装上brew,没道理啊,我就按照官网上干的:

1
ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

但是执行完以上命令之后,却卡住了:

  • 命令上一直显示Downloading and installing Homebrew...
  • 经过一段漫长的时间后,会出现unable to fetch https://github.com/Homebrew/homebrew.git

研究很久,没有找到原因,直到晚上的时候,发现python的https_open方法也挂了?这就很不寻常了。

很有可能系统的ssl有问题!查看了系统的openssl版本,发现不是最新的,我当场就决定先更新一下openssl试试。

阅读全文