├── .gitignore ├── .travis.yml ├── Gemfile ├── README.md ├── Rakefile ├── VimFlavor ├── autoload └── unite │ ├── kinds │ ├── dropbox.vim │ ├── gist.vim │ ├── issue.vim │ └── media.vim │ ├── libs │ ├── emoji.dict │ ├── gh_event.vim │ ├── http.vim │ └── uri.vim │ └── sources │ ├── apropos.vim │ ├── douban.vim │ ├── dropbox.vim │ ├── emoji.vim │ ├── gist_search.vim │ ├── gist_user.vim │ ├── github_activity.vim │ ├── github_issue.vim │ ├── github_search.vim │ ├── music163.vim │ ├── reddit.vim │ ├── toilet.vim │ ├── turing.vim │ ├── twitter.vim │ ├── v2ex.vim │ ├── wikipedia.vim │ ├── youdao.vim │ ├── youtube.vim │ └── zhihu.vim ├── plugin └── workflow.vim ├── screenshots ├── apropos.png ├── douban.png ├── dropbox.png ├── emoji.png ├── gist_user.png ├── github_event.png ├── github_issue.png ├── music163.png ├── reddit.png ├── toilet.png ├── twitter.png ├── v2ex.png └── youdao.png ├── t ├── douban_book.vim ├── douban_movie.vim ├── douban_music.vim ├── github_search.vim ├── music163.vim ├── pre.vim ├── reddit.vim ├── turing.vim ├── v2ex.vim ├── wikipedia.vim ├── youdao.vim ├── youtube.vim └── zhihu.vim └── vimrc /.gitignore: -------------------------------------------------------------------------------- 1 | *.lock 2 | .vim-flavor 3 | .bundle 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0 4 | 5 | script: rake ci 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'vim-flavor', '~> 2.0' 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ci](https://travis-ci.org/blindFS/unite-workflow.svg) 2 | 3 | ## What the hell? 4 | 5 | I suppose you know what alfred-workflow is. 6 | This vim plugin is a collection of unite.vim extentions as a alternative to it. 7 | 8 | ### github events 9 | 10 | ![ge](./screenshots/github_event.png) 11 | 12 | Fetch recent github events of a certain user. 13 | 14 | ### github feeds 15 | 16 | Fetch github timeline of a certain user(defaults to g:github_user). 17 | 18 | ### github repository searching 19 | 20 | Search for github repos by keywords. 21 | 22 | ### github issues 23 | 24 | NOTE: 25 | 26 | * In order to edit issues or create new issue, you'll need [github-issues.vim](https://github.com/jaxbot/github-issues.vim) 27 | * The default repository(if input omitted) is fetched by `git remote -v`. 28 | * You could use input to specify a certain project, in the format of 'owner/repo' 29 | 30 | ![gi](./screenshots/github_issue.png) 31 | 32 | ### gist user 33 | 34 | NOTE:This feature requires [gist-vim](https://github.com/mattn/gist-vim). 35 | 36 | ![gu](./screenshots/gist_user.png) 37 | 38 | List public gists created by a certain user(defaults to g:github_user). 39 | Actions: 40 | 41 | * edit, open with `:Gist id`. 42 | * start, open in a browser. 43 | 44 | ### gist searching 45 | 46 | Search for gists. 47 | Similar to gist-user. 48 | 49 | ### reddit 50 | 51 | Fetch hot topics from reddit. 52 | use `g:unite#workflow#reddit#front` to specify user front feed json url. 53 | Should be like this `http://www.reddit.com/.json?feed={hash}&user={username}`. 54 | If not, the fetching scope will be 'all'. 55 | If used with input, the input is taken as subreddit like this: 56 | 57 | ![re](./screenshots/reddit.png) 58 | 59 | ### twitter 60 | 61 | Twitter. 62 | 63 | Available actions: tweet/retweet/reply/favorite. 64 | 65 | ![tw](./screenshots/twitter.png) 66 | 67 | ### dropbox 68 | 69 | * files/directories hierarchy list 70 | * search 71 | 72 | ![db](./screenshots/dropbox.png) 73 | 74 | ### wikipedia 75 | 76 | Search for wiki, list matching entries, open selected in a browser. 77 | 78 | ### youtube 79 | 80 | Search youtube, playlist/channel/video ... 81 | 82 | ### apropos 83 | 84 | Fast manpage access. 85 | 86 | ![ap](./screenshots/apropos.png) 87 | 88 | ### toilet 89 | 90 | Note: this feature requires executable 'toilet' or 'figlet'. 91 | 92 | Use `g:unite#workflow#figlet_fonts#dir` to specify where the fonts are stored, 93 | defaults to `/usr/share/figlet`. 94 | 95 | ![tl](./screenshots/toilet.png) 96 | 97 | ### emoji 98 | 99 | Note: You may need extra font packages for correct displaying. 100 | For example, arch users need ttf-symbola in AUR. 101 | 102 | Search for emoji by description. 103 | 104 | ![em](./screenshots/emoji.png) 105 | 106 | ### v2ex 107 | 108 | Latest topics of http://www.v2ex.com 109 | 110 | ![v2](./screenshots/v2ex.png) 111 | 112 | ### youdao 113 | 114 | 有道词典/翻译 115 | 116 | ![yd](./screenshots/youdao.png) 117 | 118 | ### music163 119 | 120 | 网易云音乐搜索 121 | 122 | ![163](./screenshots/music163.png) 123 | 124 | ### douban 125 | 126 | 豆瓣 音乐/电影/图书 127 | 128 | ![db](./screenshots/douban.png) 129 | 130 | ### zhihu 131 | 132 | 知乎日报 133 | 134 | ### turing 135 | 136 | [图灵机器人](http://www.tuling123.com/openapi/cloud/home.jsp) 137 | 138 | ## Installation 139 | 140 | You need these plugins installed and loaded. 141 | 142 | * [unite.vim](https://github.com/shougo/unite.vim) 143 | * [webapi-vim](https://github.com/mattn/webapi-vim) 144 | 145 | Suggested plugins: 146 | 147 | * [github-issues.vim](https://github.com/jaxbot/github-issues.vim) for github issue editing/creating. 148 | * [gist-vim](https://github.com/mattn/gist-vim) for gist sources. 149 | 150 | Then just use your preferred managing tool for this plugin. 151 | If you'd like to load just a part of these features. I suggest that you use neobundle.vim: 152 | 153 | ``` vim 154 | NeoBundleLazy 'farseer90718/unite-workflow', { 155 | \ 'unite_sources' : [ your-list ], 156 | \ 'depends' : [ 157 | \ 'mattn/webapi-vim', 158 | \ 'mattn/gist-vim', 159 | \ 'jaxbot/github-issues.vim'] 160 | \ } 161 | ``` 162 | 163 | ## Customization 164 | 165 | * `g:unite#workflow#show_icon` 0 to disable avatar display. 166 | * `g:unite#workflow#reddit#front` as described above. 167 | * `g:unite#workflow#figlet_fonts#dir` as described above. 168 | * `g:unite#workflow#player` defaults to 'mplayer'. 169 | 170 | Example: 171 | 172 | ``` vim 173 | let g:unite#workflow#reddit#front = 'http://www.reddit.com/.json?feed=foo&user=bar' 174 | call unite#custom#profile( 175 | \ 'source/github/search, source/github/event, '. 176 | \ 'source/github/feed, source/gist/search, '. 177 | \ 'source/gist/user, source/v2ex, '. 178 | \ 'source/reddit, source/wikipedia', 179 | \ 'context', { 180 | \ 'keep_focus' : 1, 181 | \ 'no_quit' : 1 182 | \ }) 183 | call unite#custom#profile( 184 | \ 'source/youdao, source/toilet', 185 | \ 'context', { 186 | \ 'max_multi_lines' : 20, 187 | \ 'winheight' : 20 188 | \ }) 189 | nnoremap t :Unite youdao: 190 | ``` 191 | 192 | ## Tips 193 | 194 | * Press `` to refresh (change input in a faster way) in some sources. 195 | * Some sources may have specialized actions, you can check the action list to find out. 196 | 197 | ## Contributing 198 | 199 | * Bug report, feature request, other discussions are always welcome. 200 | * Pull requests of new workflows are even better. 201 | 202 | ## License 203 | 204 | MIT 205 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | 3 | task :ci => [:dump, :test] 4 | 5 | task :dump do 6 | sh 'vim --version' 7 | end 8 | 9 | task :test do 10 | sh 'bundle exec vim-flavor test' 11 | end 12 | -------------------------------------------------------------------------------- /VimFlavor: -------------------------------------------------------------------------------- 1 | flavor 'mattn/webapi-vim' 2 | flavor 'mattn/gist-vim' 3 | flavor 'blindFS/unite.vim', '~> 6.1' 4 | -------------------------------------------------------------------------------- /autoload/unite/kinds/dropbox.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! unite#kinds#dropbox#define() 5 | return s:kind 6 | endfunction 7 | 8 | let s:kind = { 9 | \ 'name' : 'dropbox', 10 | \ 'default_action' : 'start', 11 | \ 'action_table' : {}, 12 | \ 'parents' : ['file'] 13 | \ } 14 | 15 | let s:kind.action_table.start = { 16 | \ 'description' : 'cd or open.', 17 | \ 'is_quit' : 1 18 | \ } 19 | 20 | function! s:kind.action_table.start.func(candidate) 21 | if a:candidate.action__mime == 'dir' 22 | call unite#start([['dropbox/files', a:candidate.action__path]]) 23 | return 24 | endif 25 | if a:candidate.action__mime =~ 'text' 26 | let path = unite#kinds#dropbox#download(a:candidate.action__path) 27 | execute 'e '.escape(path, ' \') 28 | else 29 | let path = unite#kinds#dropbox#download(a:candidate.action__path) 30 | let cand = deepcopy(a:candidate) 31 | let cand.action__uri = path 32 | call unite#take_parents_action('start', cand, {}) 33 | endif 34 | endfunction 35 | 36 | function! unite#kinds#dropbox#download(path) 37 | let path = expand(unite#util#input('where? ', 38 | \ $HOME.'/Dropbox', 'file'). 39 | \ a:path) 40 | let path_dir = fnamemodify(path, ':p:h') 41 | if !isdirectory(path_dir) 42 | call mkdir(path_dir, 'p') 43 | endif 44 | if filereadable(path) 45 | return path 46 | endif 47 | let ctx = unite#kinds#dropbox#authorize() 48 | let url = 'https://api-content.dropbox.com/1/files/auto'. 49 | \ substitute(a:path, ' ', '%20', 'g') 50 | call unite#libs#http#oauth_dl(url, ctx, path) 51 | return path 52 | endfunction 53 | 54 | function! unite#kinds#dropbox#authorize() 55 | let ctx = {} 56 | let config_dir = unite#get_data_directory().'/dropbox' 57 | if !isdirectory(config_dir) 58 | call mkdir(config_dir, 'p') 59 | endif 60 | let configfile = config_dir.'/auth.json' 61 | 62 | if filereadable(configfile) 63 | let ctx = eval(join(readfile(configfile), "")) 64 | else 65 | let ctx.consumer_key = '8928ehq03mtarpp' 66 | let ctx.consumer_secret = '3teavk0kticeauj' 67 | 68 | let request_token_url = 'https://api.dropbox.com/1/oauth/request_token' 69 | let auth_url = 'https://www.dropbox.com/1/oauth/authorize' 70 | let access_token_url = 'https://api.dropbox.com/1/oauth/access_token' 71 | 72 | let ctx = webapi#oauth#request_token(request_token_url, ctx) 73 | let redir_url = auth_url.'?oauth_token='.ctx.request_token 74 | if has('win32') || has('win64') 75 | exe '!start rundll32 url.dll,FileProtocolHandler '.redir_url 76 | elseif executable('xdg-open') 77 | call system("xdg-open '".redir_url."'") 78 | elseif executable('open') 79 | call system("open '".redir_url."'") 80 | else 81 | return [] 82 | endif 83 | call input('press any key to continue') 84 | let ctx = webapi#oauth#access_token(access_token_url, ctx, {'oauth_verifier': ''}) 85 | call writefile([string(ctx)], configfile) 86 | endif 87 | 88 | return ctx 89 | endfunction 90 | 91 | function! unite#kinds#dropbox#list_path(path) 92 | let ctx = unite#kinds#dropbox#authorize() 93 | let url = 'https://api.dropbox.com/1/metadata/auto'.a:path 94 | let res = webapi#oauth#get(url, ctx, {}, {'list' : 'true'}) 95 | if res.status != '200' 96 | echom 'http error code:'.res.status 97 | return [] 98 | endif 99 | let content = webapi#json#decode(res.content) 100 | if !has_key(content, 'contents') 101 | return [] 102 | endif 103 | return map(content.contents, 's:extract_entry(v:val)') 104 | endfunction 105 | 106 | function! unite#kinds#dropbox#search(keywords) 107 | let ctx = unite#kinds#dropbox#authorize() 108 | let url = 'https://api.dropbox.com/1/search/auto' 109 | let res = webapi#oauth#get(url, ctx, {}, {'query' : a:keywords}) 110 | if res.status != '200' 111 | echom 'http error code:'.res.status 112 | return [] 113 | endif 114 | let content = webapi#json#decode(res.content) 115 | return map(content, 's:extract_entry(v:val)') 116 | endfunction 117 | 118 | function! s:extract_entry(dict) 119 | let mime = get(a:dict, 'mime_type', 'dir') 120 | return { 121 | \ 'word' : '【'.mime.'】'. 122 | \ split(a:dict.path, '/')[-1], 123 | \ 'kind' : 'dropbox', 124 | \ 'source' : 'dropbox', 125 | \ 'action__mime' : mime, 126 | \ 'action__path' : a:dict.path 127 | \ } 128 | endfunction 129 | 130 | let &cpo = s:save_cpo 131 | unlet s:save_cpo 132 | -------------------------------------------------------------------------------- /autoload/unite/kinds/gist.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! unite#kinds#gist#define() 5 | return s:kind 6 | endfunction 7 | 8 | let s:kind = { 9 | \ 'name' : 'gist', 10 | \ 'default_action' : 'start', 11 | \ 'action_table' : {}, 12 | \ 'parents' : ['uri'] 13 | \ } 14 | 15 | let s:kind.action_table.edit = { 16 | \ 'description' : 'Edit the gist as a file.', 17 | \ 'is_selectable' : 1 18 | \ } 19 | 20 | function! s:kind.action_table.edit.func(candidates) 21 | for candidate in a:candidates 22 | execute 'Gist '.candidate.action__id 23 | endfor 24 | endfunction 25 | 26 | function! unite#kinds#gist#on_syntax(args, context) 27 | syntax match uniteSource__gist_user /.*\ze\// 28 | \ contained containedin=uniteSource__gist 29 | syntax match uniteSource__gist_fname /\S\+\s\+\zs\S\+/ 30 | \ contained containedin=uniteSource__gist 31 | highlight default link uniteSource__gist_user Constant 32 | highlight default link uniteSource__gist_fname Keyword 33 | endfunction 34 | 35 | 36 | let &cpo = s:save_cpo 37 | unlet s:save_cpo 38 | -------------------------------------------------------------------------------- /autoload/unite/kinds/issue.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! unite#kinds#issue#define() 5 | return s:kind 6 | endfunction 7 | 8 | let s:kind = { 9 | \ 'name' : 'issue', 10 | \ 'default_action' : 'start', 11 | \ 'action_table' : {}, 12 | \ 'parents' : ['uri'] 13 | \ } 14 | 15 | let s:kind.action_table.edit = { 16 | \ 'description' : 'View the issue.', 17 | \ 'is_quit' : 1, 18 | \ 'func' : function('unite#kinds#issue#edit') 19 | \ } 20 | 21 | let s:kind.action_table.add = { 22 | \ 'description' : 'Create a new issue.', 23 | \ 'is_quit' : 1 24 | \ } 25 | 26 | function! s:kind.action_table.add.func(candidate) 27 | if !exists(':Giadd') 28 | echom 'You need to load jaxbot/github-issues.vim first.' 29 | return 30 | endif 31 | Giadd 32 | endfunction 33 | 34 | function! unite#kinds#issue#edit(candidate) 35 | let number = matchstr(a:candidate.action__uri, 'issues/\zs\d\+$') 36 | if number == '' 37 | return 38 | endif 39 | if !exists(':Giedit') 40 | echom 'You need to load jaxbot/github-issues.vim first.' 41 | return 42 | endif 43 | echo 'Opening #'.number.' with Giedit ...' 44 | execute 'Giedit '.number.' '.a:candidate.action__repo 45 | endfunction 46 | 47 | let &cpo = s:save_cpo 48 | unlet s:save_cpo 49 | -------------------------------------------------------------------------------- /autoload/unite/kinds/media.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! unite#kinds#media#define() 5 | let g:unite#workflow#player = get(g:, 'unite#workflow#player', 'mplayer') 6 | return s:kind 7 | endfunction 8 | 9 | let s:kind = { 10 | \ 'name' : 'media', 11 | \ 'default_action' : 'start', 12 | \ 'action_table' : {}, 13 | \ 'parents' : ['uri'] 14 | \ } 15 | 16 | let s:kind.action_table.open = { 17 | \ 'description' : 'Open with you-get', 18 | \ 'is_quit' : 0 19 | \ } 20 | 21 | function! s:kind.action_table.open.func(candidate) 22 | if !executable('you-get') 23 | echom 'You want to play it directly? You should have you-get installed.'. 24 | return 25 | endif 26 | if !executable(g:unite#workflow#player) 27 | echom 'No '.g:unite#workflow#player.' in $PATH, you may need to change g:unite#workflow#player.' 28 | endif 29 | try 30 | echo 'opening with '.g:unite#workflow#player 31 | call system('pkill '.g:unite#workflow#player) 32 | call system('you-get -p '.g:unite#workflow#player.' '.a:candidate.action__uri.' &') 33 | catch 34 | echom 'Failed to play the selected song.' 35 | endtry 36 | endfunction 37 | 38 | let s:kind.action_table.stop = { 39 | \ 'description' : 'Stop the player.', 40 | \ 'is_quit' : 0 41 | \ } 42 | 43 | function! s:kind.action_table.stop.func(candidate) 44 | call system('pkill '.g:unite#workflow#player) 45 | call system('pkill you-get') 46 | echo 'stopped' 47 | endfunction 48 | 49 | let &cpo = s:save_cpo 50 | unlet s:save_cpo 51 | -------------------------------------------------------------------------------- /autoload/unite/libs/emoji.dict: -------------------------------------------------------------------------------- 1 | 😄 😄 SMILING FACE WITH OPEN MOUTH AND SMILING EYES 2 | 😃 😃 SMILING FACE WITH OPEN MOUTH 3 | 😀 😀 GRINNING FACE 4 | 😊 😊 SMILING FACE WITH SMILING EYES 5 | ☺ ☺ WHITE SMILING FACE 6 | 😉 😉 WINKING FACE 7 | 😍 😍 SMILING FACE WITH HEART-SHAPED EYES 8 | 😘 😘 FACE THROWING A KISS 9 | 😚 😚 KISSING FACE WITH CLOSED EYES 10 | 😗 😗 KISSING FACE 11 | 😙 😙 KISSING FACE WITH SMILING EYES 12 | 😜 😜 FACE WITH STUCK-OUT TONGUE AND WINKING EYE 13 | 😝 😝 FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES 14 | 😛 😛 FACE WITH STUCK-OUT TONGUE 15 | 😳 😳 FLUSHED FACE 16 | 😁 😁 GRINNING FACE WITH SMILING EYES 17 | 😔 😔 PENSIVE FACE 18 | 😌 😌 RELIEVED FACE 19 | 😒 😒 UNAMUSED FACE 20 | 😞 😞 DISAPPOINTED FACE 21 | 😣 😣 PERSEVERING FACE 22 | 😢 😢 CRYING FACE 23 | 😂 😂 FACE WITH TEARS OF JOY 24 | 😭 😭 LOUDLY CRYING FACE 25 | 😪 😪 SLEEPY FACE 26 | 😥 😥 DISAPPOINTED BUT RELIEVED FACE 27 | 😰 😰 FACE WITH OPEN MOUTH AND COLD SWEAT 28 | 😅 😅 SMILING FACE WITH OPEN MOUTH AND COLD SWEAT 29 | 😓 😓 FACE WITH COLD SWEAT 30 | 😩 😩 WEARY FACE 31 | 😫 😫 TIRED FACE 32 | 😨 😨 FEARFUL FACE 33 | 😱 😱 FACE SCREAMING IN FEAR 34 | 😠 😠 ANGRY FACE 35 | 😡 😡 POUTING FACE 36 | 😤 😤 FACE WITH LOOK OF TRIUMPH 37 | 😖 😖 CONFOUNDED FACE 38 | 😆 😆 SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES 39 | 😋 😋 FACE SAVOURING DELICIOUS FOOD 40 | 😷 😷 FACE WITH MEDICAL MASK 41 | 😎 😎 SMILING FACE WITH SUNGLASSES 42 | 😴 😴 SLEEPING FACE 43 | 😵 😵 DIZZY FACE 44 | 😲 😲 ASTONISHED FACE 45 | 😟 😟 WORRIED FACE 46 | 😦 😦 FROWNING FACE WITH OPEN MOUTH 47 | 😧 😧 ANGUISHED FACE 48 | 😈 😈 SMILING FACE WITH HORNS 49 | 👿 👿 IMP 50 | 😮 😮 FACE WITH OPEN MOUTH 51 | 😬 😬 GRIMACING FACE 52 | 😐 😐 NEUTRAL FACE 53 | 😕 😕 CONFUSED FACE 54 | 😯 😯 HUSHED FACE 55 | 😶 😶 FACE WITHOUT MOUTH 56 | 😇 😇 SMILING FACE WITH HALO 57 | 😏 😏 SMIRKING FACE 58 | 😑 😑 EXPRESSIONLESS FACE 59 | 👲 👲 MAN WITH GUA PI MAO 60 | 👳 👳 MAN WITH TURBAN 61 | 👮 👮 POLICE OFFICER 62 | 👷 👷 CONSTRUCTION WORKER 63 | 💂 💂 GUARDSMAN 64 | 👶 👶 BABY 65 | 👦 👦 BOY 66 | 👧 👧 GIRL 67 | 👨 👨 MAN 68 | 👩 👩 WOMAN 69 | 👴 👴 OLDER MAN 70 | 👵 👵 OLDER WOMAN 71 | 👱 👱 PERSON WITH BLOND HAIR 72 | 👼 👼 BABY ANGEL 73 | 👸 👸 PRINCESS 74 | 😺 😺 SMILING CAT FACE WITH OPEN MOUTH 75 | 😸 😸 GRINNING CAT FACE WITH SMILING EYES 76 | 😻 😻 SMILING CAT FACE WITH HEART-SHAPED EYES 77 | 😽 😽 KISSING CAT FACE WITH CLOSED EYES 78 | 😼 😼 CAT FACE WITH WRY SMILE 79 | 🙀 🙀 WEARY CAT FACE 80 | 😿 😿 CRYING CAT FACE 81 | 😹 😹 CAT FACE WITH TEARS OF JOY 82 | 😾 😾 POUTING CAT FACE 83 | 👹 👹 JAPANESE OGRE 84 | 👺 👺 JAPANESE GOBLIN 85 | 🙈 🙈 SEE-NO-EVIL MONKEY 86 | 🙉 🙉 HEAR-NO-EVIL MONKEY 87 | 🙊 🙊 SPEAK-NO-EVIL MONKEY 88 | 💀 💀 SKULL 89 | 👽 👽 EXTRATERRESTRIAL ALIEN 90 | 💩 💩 PILE OF POO 91 | 🔥 🔥 FIRE 92 | ✨ ✨ SPARKLES 93 | 🌟 🌟 GLOWING STAR 94 | 💫 💫 DIZZY SYMBOL 95 | 💥 💥 COLLISION SYMBOL 96 | 💢 💢 ANGER SYMBOL 97 | 💦 💦 SPLASHING SWEAT SYMBOL 98 | 💧 💧 DROPLET 99 | 💤 💤 SLEEPING SYMBOL 100 | 💨 💨 DASH SYMBOL 101 | 👂 👂 EAR 102 | 👀 👀 EYES 103 | 👃 👃 NOSE 104 | 👅 👅 TONGUE 105 | 👄 👄 MOUTH 106 | 👍 👍 THUMBS UP SIGN 107 | 👎 👎 THUMBS DOWN SIGN 108 | 👌 👌 OK HAND SIGN 109 | 👊 👊 FISTED HAND SIGN 110 | ✊ ✊ RAISED FIST 111 | ✌ ✌ VICTORY HAND 112 | 👋 👋 WAVING HAND SIGN 113 | ✋ ✋ RAISED HAND 114 | 👐 👐 OPEN HANDS SIGN 115 | 👆 👆 WHITE UP POINTING BACKHAND INDEX 116 | 👇 👇 WHITE DOWN POINTING BACKHAND INDEX 117 | 👉 👉 WHITE RIGHT POINTING BACKHAND INDEX 118 | 👈 👈 WHITE LEFT POINTING BACKHAND INDEX 119 | 🙌 🙌 PERSON RAISING BOTH HANDS IN CELEBRATION 120 | 🙏 🙏 PERSON WITH FOLDED HANDS 121 | ☝ ☝ WHITE UP POINTING INDEX 122 | 👏 👏 CLAPPING HANDS SIGN 123 | 💪 💪 FLEXED BICEPS 124 | 🚶 🚶 PEDESTRIAN 125 | 🏃 🏃 RUNNER 126 | 💃 💃 DANCER 127 | 👫 👫 MAN AND WOMAN HOLDING HANDS 128 | 👪 👪 FAMILY 129 | 👬 👬 TWO MEN HOLDING HANDS 130 | 👭 👭 TWO WOMEN HOLDING HANDS 131 | 💏 💏 KISS 132 | 💑 💑 COUPLE WITH HEART 133 | 👯 👯 WOMAN WITH BUNNY EARS 134 | 🙆 🙆 FACE WITH OK GESTURE 135 | 🙅 🙅 FACE WITH NO GOOD GESTURE 136 | 💁 💁 INFORMATION DESK PERSON 137 | 🙋 🙋 HAPPY PERSON RAISING ONE HAND 138 | 💆 💆 FACE MASSAGE 139 | 💇 💇 HAIRCUT 140 | 💅 💅 NAIL POLISH 141 | 👰 👰 BRIDE WITH VEIL 142 | 🙎 🙎 PERSON WITH POUTING FACE 143 | 🙍 🙍 PERSON FROWNING 144 | 🙇 🙇 PERSON BOWING DEEPLY 145 | 🎩 🎩 TOP HAT 146 | 👑 👑 CROWN 147 | 👒 👒 WOMANS HAT 148 | 👟 👟 ATHLETIC SHOE 149 | 👞 👞 MANS SHOE 150 | 👡 👡 WOMANS SANDAL 151 | 👠 👠 HIGH-HEELED SHOE 152 | 👢 👢 WOMANS BOOTS 153 | 👕 👕 T-SHIRT 154 | 👔 👔 NECKTIE 155 | 👚 👚 WOMANS CLOTHES 156 | 👗 👗 DRESS 157 | 🎽 🎽 RUNNING SHIRT WITH SASH 158 | 👖 👖 JEANS 159 | 👘 👘 KIMONO 160 | 👙 👙 BIKINI 161 | 💼 💼 BRIEFCASE 162 | 👜 👜 HANDBAG 163 | 👝 👝 POUCH 164 | 👛 👛 PURSE 165 | 👓 👓 EYEGLASSES 166 | 🎀 🎀 RIBBON 167 | 🌂 🌂 CLOSED UMBRELLA 168 | 💄 💄 LIPSTICK 169 | 💛 💛 YELLOW HEART 170 | 💙 💙 BLUE HEART 171 | 💜 💜 PURPLE HEART 172 | 💚 💚 GREEN HEART 173 | ❤ ❤ HEAVY BLACK HEART 174 | 💔 💔 BROKEN HEART 175 | 💗 💗 GROWING HEART 176 | 💓 💓 BEATING HEART 177 | 💕 💕 TWO HEARTS 178 | 💖 💖 SPARKLING HEART 179 | 💞 💞 REVOLVING HEARTS 180 | 💘 💘 HEART WITH ARROW 181 | 💌 💌 LOVE LETTER 182 | 💋 💋 KISS MARK 183 | 💍 💍 RING 184 | 💎 💎 GEM STONE 185 | 👤 👤 BUST IN SILHOUETTE 186 | 👥 👥 BUSTS IN SILHOUETTE 187 | 💬 💬 SPEECH BALLOON 188 | 👣 👣 FOOTPRINTS 189 | 💭 💭 THOUGHT BALLOON 190 | 🐶 🐶 DOG FACE 191 | 🐺 🐺 WOLF FACE 192 | 🐱 🐱 CAT FACE 193 | 🐭 🐭 MOUSE FACE 194 | 🐹 🐹 HAMSTER FACE 195 | 🐰 🐰 RABBIT FACE 196 | 🐸 🐸 FROG FACE 197 | 🐯 🐯 TIGER FACE 198 | 🐨 🐨 KOALA 199 | 🐻 🐻 BEAR FACE 200 | 🐷 🐷 PIG FACE 201 | 🐽 🐽 PIG NOSE 202 | 🐮 🐮 COW FACE 203 | 🐗 🐗 BOAR 204 | 🐵 🐵 MONKEY FACE 205 | 🐒 🐒 MONKEY 206 | 🐴 🐴 HORSE FACE 207 | 🐑 🐑 SHEEP 208 | 🐘 🐘 ELEPHANT 209 | 🐼 🐼 PANDA FACE 210 | 🐧 🐧 PENGUIN 211 | 🐦 🐦 BIRD 212 | 🐤 🐤 BABY CHICK 213 | 🐥 🐥 FRONT-FACING BABY CHICK 214 | 🐣 🐣 HATCHING CHICK 215 | 🐔 🐔 CHICKEN 216 | 🐍 🐍 SNAKE 217 | 🐢 🐢 TURTLE 218 | 🐛 🐛 BUG 219 | 🐝 🐝 HONEYBEE 220 | 🐜 🐜 ANT 221 | 🐞 🐞 LADY BEETLE 222 | 🐌 🐌 SNAIL 223 | 🐙 🐙 OCTOPUS 224 | 🐚 🐚 SPIRAL SHELL 225 | 🐠 🐠 TROPICAL FISH 226 | 🐟 🐟 FISH 227 | 🐬 🐬 DOLPHIN 228 | 🐳 🐳 SPOUTING WHALE 229 | 🐋 🐋 WHALE 230 | 🐄 🐄 COW 231 | 🐏 🐏 RAM 232 | 🐀 🐀 RAT 233 | 🐃 🐃 WATER BUFFALO 234 | 🐅 🐅 TIGER 235 | 🐇 🐇 RABBIT 236 | 🐉 🐉 DRAGON 237 | 🐎 🐎 HORSE 238 | 🐐 🐐 GOAT 239 | 🐓 🐓 ROOSTER 240 | 🐕 🐕 DOG 241 | 🐖 🐖 PIG 242 | 🐁 🐁 MOUSE 243 | 🐂 🐂 OX 244 | 🐲 🐲 DRAGON FACE 245 | 🐡 🐡 BLOWFISH 246 | 🐊 🐊 CROCODILE 247 | 🐫 🐫 BACTRIAN CAMEL 248 | 🐪 🐪 DROMEDARY CAMEL 249 | 🐆 🐆 LEOPARD 250 | 🐈 🐈 CAT 251 | 🐩 🐩 POODLE 252 | 🐾 🐾 PAW PRINTS 253 | 💐 💐 BOUQUET 254 | 🌸 🌸 CHERRY BLOSSOM 255 | 🌷 🌷 TULIP 256 | 🍀 🍀 FOUR LEAF CLOVER 257 | 🌹 🌹 ROSE 258 | 🌻 🌻 SUNFLOWER 259 | 🌺 🌺 HIBISCUS 260 | 🍁 🍁 MAPLE LEAF 261 | 🍃 🍃 LEAF FLUTTERING IN WIND 262 | 🍂 🍂 FALLEN LEAF 263 | 🌿 🌿 HERB 264 | 🌾 🌾 EAR OF RICE 265 | 🍄 🍄 MUSHROOM 266 | 🌵 🌵 CACTUS 267 | 🌴 🌴 PALM TREE 268 | 🌲 🌲 EVERGREEN TREE 269 | 🌳 🌳 DECIDUOUS TREE 270 | 🌰 🌰 CHESTNUT 271 | 🌱 🌱 SEEDLING 272 | 🌼 🌼 BLOSSOM 273 | 🌐 🌐 GLOBE WITH MERIDIANS 274 | 🌞 🌞 SUN WITH FACE 275 | 🌝 🌝 FULL MOON WITH FACE 276 | 🌚 🌚 NEW MOON WITH FACE 277 | 🌑 🌑 NEW MOON SYMBOL 278 | 🌒 🌒 WAXING CRESCENT MOON SYMBOL 279 | 🌓 🌓 FIRST QUARTER MOON SYMBOL 280 | 🌔 🌔 WAXING GIBBOUS MOON SYMBOL 281 | 🌕 🌕 FULL MOON SYMBOL 282 | 🌖 🌖 WANING GIBBOUS MOON SYMBOL 283 | 🌗 🌗 LAST QUARTER MOON SYMBOL 284 | 🌘 🌘 WANING CRESCENT MOON SYMBOL 285 | 🌜 🌜 LAST QUARTER MOON WITH FACE 286 | 🌛 🌛 FIRST QUARTER MOON WITH FACE 287 | 🌙 🌙 CRESCENT MOON 288 | 🌍 🌍 EARTH GLOBE EUROPE-AFRICA 289 | 🌎 🌎 EARTH GLOBE AMERICAS 290 | 🌏 🌏 EARTH GLOBE ASIA-AUSTRALIA 291 | 🌋 🌋 VOLCANO 292 | 🌌 🌌 MILKY WAY 293 | 🌠 🌠 SHOOTING STAR 294 | ⭐ ⭐ WHITE MEDIUM STAR 295 | ☀ ☀ BLACK SUN WITH RAYS 296 | ⛅ ⛅ SUN BEHIND CLOUD 297 | ☁ ☁ CLOUD 298 | ⚡ ⚡ HIGH VOLTAGE SIGN 299 | ☔ ☔ UMBRELLA WITH RAIN DROPS 300 | ❄ ❄ SNOWFLAKE 301 | ⛄ ⛄ SNOWMAN WITHOUT SNOW 302 | 🌀 🌀 CYCLONE 303 | 🌁 🌁 FOGGY 304 | 🌈 🌈 RAINBOW 305 | 🌊 🌊 WATER WAVE 306 | 🎍 🎍 PINE DECORATION 307 | 💝 💝 HEART WITH RIBBON 308 | 🎎 🎎 JAPANESE DOLLS 309 | 🎒 🎒 SCHOOL SATCHEL 310 | 🎓 🎓 GRADUATION CAP 311 | 🎏 🎏 CARP STREAMER 312 | 🎆 🎆 FIREWORKS 313 | 🎇 🎇 FIREWORK SPARKLER 314 | 🎐 🎐 WIND CHIME 315 | 🎑 🎑 MOON VIEWING CEREMONY 316 | 🎃 🎃 JACK-O-LANTERN 317 | 👻 👻 GHOST 318 | 🎅 🎅 FATHER CHRISTMAS 319 | 🎄 🎄 CHRISTMAS TREE 320 | 🎁 🎁 WRAPPED PRESENT 321 | 🎋 🎋 TANABATA TREE 322 | 🎉 🎉 PARTY POPPER 323 | 🎊 🎊 CONFETTI BALL 324 | 🎈 🎈 BALLOON 325 | 🎌 🎌 CROSSED FLAGS 326 | 🔮 🔮 CRYSTAL BALL 327 | 🎥 🎥 MOVIE CAMERA 328 | 📷 📷 CAMERA 329 | 📹 📹 VIDEO CAMERA 330 | 📼 📼 VIDEOCASSETTE 331 | 💿 💿 OPTICAL DISC 332 | 📀 📀 DVD 333 | 💽 💽 MINIDISC 334 | 💾 💾 FLOPPY DISK 335 | 💻 💻 PERSONAL COMPUTER 336 | 📱 📱 MOBILE PHONE 337 | ☎ ☎ BLACK TELEPHONE 338 | 📞 📞 TELEPHONE RECEIVER 339 | 📟 📟 PAGER 340 | 📠 📠 FAX MACHINE 341 | 📡 📡 SATELLITE ANTENNA 342 | 📺 📺 TELEVISION 343 | 📻 📻 RADIO 344 | 🔊 🔊 SPEAKER WITH THREE SOUND WAVES 345 | 🔉 🔉 SPEAKER WITH ONE SOUND WAVE 346 | 🔈 🔈 SPEAKER 347 | 🔇 🔇 SPEAKER WITH CANCELLATION STROKE 348 | 🔔 🔔 BELL 349 | 🔕 🔕 BELL WITH CANCELLATION STROKE 350 | 📢 📢 PUBLIC ADDRESS LOUDSPEAKER 351 | 📣 📣 CHEERING MEGAPHONE 352 | ⏳ ⏳ HOURGLASS WITH FLOWING SAND 353 | ⌛ ⌛ HOURGLASS 354 | ⏰ ⏰ ALARM CLOCK 355 | ⌚ ⌚ WATCH 356 | 🔓 🔓 OPEN LOCK 357 | 🔒 🔒 LOCK 358 | 🔏 🔏 LOCK WITH INK PEN 359 | 🔐 🔐 CLOSED LOCK WITH KEY 360 | 🔑 🔑 KEY 361 | 🔎 🔎 RIGHT-POINTING MAGNIFYING GLASS 362 | 💡 💡 ELECTRIC LIGHT BULB 363 | 🔦 🔦 ELECTRIC TORCH 364 | 🔆 🔆 HIGH BRIGHTNESS SYMBOL 365 | 🔅 🔅 LOW BRIGHTNESS SYMBOL 366 | 🔌 🔌 ELECTRIC PLUG 367 | 🔋 🔋 BATTERY 368 | 🔍 🔍 LEFT-POINTING MAGNIFYING GLASS 369 | 🛁 🛁 BATHTUB 370 | 🛀 🛀 BATH 371 | 🚿 🚿 SHOWER 372 | 🚽 🚽 TOILET 373 | 🔧 🔧 WRENCH 374 | 🔩 🔩 NUT AND BOLT 375 | 🔨 🔨 HAMMER 376 | 🚪 🚪 DOOR 377 | 🚬 🚬 SMOKING SYMBOL 378 | 💣 💣 BOMB 379 | 🔫 🔫 PISTOL 380 | 🔪 🔪 HOCHO 381 | 💊 💊 PILL 382 | 💉 💉 SYRINGE 383 | 💰 💰 MONEY BAG 384 | 💴 💴 BANKNOTE WITH YEN SIGN 385 | 💵 💵 BANKNOTE WITH DOLLAR SIGN 386 | 💷 💷 BANKNOTE WITH POUND SIGN 387 | 💶 💶 BANKNOTE WITH EURO SIGN 388 | 💳 💳 CREDIT CARD 389 | 💸 💸 MONEY WITH WINGS 390 | 📲 📲 MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT 391 | 📧 📧 E-MAIL SYMBOL 392 | 📥 📥 INBOX TRAY 393 | 📤 📤 OUTBOX TRAY 394 | ✉ ✉ ENVELOPE 395 | 📩 📩 ENVELOPE WITH DOWNWARDS ARROW ABOVE 396 | 📨 📨 INCOMING ENVELOPE 397 | 📯 📯 POSTAL HORN 398 | 📫 📫 CLOSED MAILBOX WITH RAISED FLAG 399 | 📪 📪 CLOSED MAILBOX WITH LOWERED FLAG 400 | 📬 📬 OPEN MAILBOX WITH RAISED FLAG 401 | 📭 📭 OPEN MAILBOX WITH LOWERED FLAG 402 | 📮 📮 POSTBOX 403 | 📦 📦 PACKAGE 404 | 📝 📝 MEMO 405 | 📄 📄 PAGE FACING UP 406 | 📃 📃 PAGE WITH CURL 407 | 📑 📑 BOOKMARK TABS 408 | 📊 📊 BAR CHART 409 | 📈 📈 CHART WITH UPWARDS TREND 410 | 📉 📉 CHART WITH DOWNWARDS TREND 411 | 📜 📜 SCROLL 412 | 📋 📋 CLIPBOARD 413 | 📅 📅 CALENDAR 414 | 📆 📆 TEAR-OFF CALENDAR 415 | 📇 📇 CARD INDEX 416 | 📁 📁 FILE FOLDER 417 | 📂 📂 OPEN FILE FOLDER 418 | ✂ ✂ BLACK SCISSORS 419 | 📌 📌 PUSHPIN 420 | 📎 📎 PAPERCLIP 421 | ✒ ✒ BLACK NIB 422 | ✏ ✏ PENCIL 423 | 📏 📏 STRAIGHT RULER 424 | 📐 📐 TRIANGULAR RULER 425 | 📕 📕 CLOSED BOOK 426 | 📗 📗 GREEN BOOK 427 | 📘 📘 BLUE BOOK 428 | 📙 📙 ORANGE BOOK 429 | 📓 📓 NOTEBOOK 430 | 📔 📔 NOTEBOOK WITH DECORATIVE COVER 431 | 📒 📒 LEDGER 432 | 📚 📚 BOOKS 433 | 📖 📖 OPEN BOOK 434 | 🔖 🔖 BOOKMARK 435 | 📛 📛 NAME BADGE 436 | 🔬 🔬 MICROSCOPE 437 | 🔭 🔭 TELESCOPE 438 | 📰 📰 NEWSPAPER 439 | 🎨 🎨 ARTIST PALETTE 440 | 🎬 🎬 CLAPPER BOARD 441 | 🎤 🎤 MICROPHONE 442 | 🎧 🎧 HEADPHONE 443 | 🎼 🎼 MUSICAL SCORE 444 | 🎵 🎵 MUSICAL NOTE 445 | 🎶 🎶 MULTIPLE MUSICAL NOTES 446 | 🎹 🎹 MUSICAL KEYBOARD 447 | 🎻 🎻 VIOLIN 448 | 🎺 🎺 TRUMPET 449 | 🎷 🎷 SAXOPHONE 450 | 🎸 🎸 GUITAR 451 | 👾 👾 ALIEN MONSTER 452 | 🎮 🎮 VIDEO GAME 453 | 🃏 🃏 PLAYING CARD BLACK JOKER 454 | 🎴 🎴 FLOWER PLAYING CARDS 455 | 🀄 🀄 MAHJONG TILE RED DRAGON 456 | 🎲 🎲 GAME DIE 457 | 🎯 🎯 DIRECT HIT 458 | 🏈 🏈 AMERICAN FOOTBALL 459 | 🏀 🏀 BASKETBALL AND HOOP 460 | ⚽ ⚽ SOCCER BALL 461 | ⚾ ⚾ BASEBALL 462 | 🎾 🎾 TENNIS RACQUET AND BALL 463 | 🎱 🎱 BILLIARDS 464 | 🏉 🏉 RUGBY FOOTBALL 465 | 🎳 🎳 BOWLING 466 | ⛳ ⛳ FLAG IN HOLE 467 | 🚵 🚵 MOUNTAIN BICYCLIST 468 | 🚴 🚴 BICYCLIST 469 | 🏁 🏁 CHEQUERED FLAG 470 | 🏇 🏇 HORSE RACING 471 | 🏆 🏆 TROPHY 472 | 🎿 🎿 SKI AND SKI BOOT 473 | 🏂 🏂 SNOWBOARDER 474 | 🏊 🏊 SWIMMER 475 | 🏄 🏄 SURFER 476 | 🎣 🎣 FISHING POLE AND FISH 477 | ☕ ☕ HOT BEVERAGE 478 | 🍵 🍵 TEACUP WITHOUT HANDLE 479 | 🍶 🍶 SAKE BOTTLE AND CUP 480 | 🍼 🍼 BABY BOTTLE 481 | 🍺 🍺 BEER MUG 482 | 🍻 🍻 CLINKING BEER MUGS 483 | 🍸 🍸 COCKTAIL GLASS 484 | 🍹 🍹 TROPICAL DRINK 485 | 🍷 🍷 WINE GLASS 486 | 🍴 🍴 FORK AND KNIFE 487 | 🍕 🍕 SLICE OF PIZZA 488 | 🍔 🍔 HAMBURGER 489 | 🍟 🍟 FRENCH FRIES 490 | 🍗 🍗 POULTRY LEG 491 | 🍖 🍖 MEAT ON BONE 492 | 🍝 🍝 SPAGHETTI 493 | 🍛 🍛 CURRY AND RICE 494 | 🍤 🍤 FRIED SHRIMP 495 | 🍱 🍱 BENTO BOX 496 | 🍣 🍣 SUSHI 497 | 🍥 🍥 FISH CAKE WITH SWIRL DESIGN 498 | 🍙 🍙 RICE BALL 499 | 🍘 🍘 RICE CRACKER 500 | 🍚 🍚 COOKED RICE 501 | 🍜 🍜 STEAMING BOWL 502 | 🍲 🍲 POT OF FOOD 503 | 🍢 🍢 ODEN 504 | 🍡 🍡 DANGO 505 | 🍳 🍳 COOKING 506 | 🍞 🍞 BREAD 507 | 🍩 🍩 DOUGHNUT 508 | 🍮 🍮 CUSTARD 509 | 🍦 🍦 SOFT ICE CREAM 510 | 🍨 🍨 ICE CREAM 511 | 🍧 🍧 SHAVED ICE 512 | 🎂 🎂 BIRTHDAY CAKE 513 | 🍰 🍰 SHORTCAKE 514 | 🍪 🍪 COOKIE 515 | 🍫 🍫 CHOCOLATE BAR 516 | 🍬 🍬 CANDY 517 | 🍭 🍭 LOLLIPOP 518 | 🍯 🍯 HONEY POT 519 | 🍎 🍎 RED APPLE 520 | 🍏 🍏 GREEN APPLE 521 | 🍊 🍊 TANGERINE 522 | 🍋 🍋 LEMON 523 | 🍒 🍒 CHERRIES 524 | 🍇 🍇 GRAPES 525 | 🍉 🍉 WATERMELON 526 | 🍓 🍓 STRAWBERRY 527 | 🍑 🍑 PEACH 528 | 🍈 🍈 MELON 529 | 🍌 🍌 BANANA 530 | 🍐 🍐 PEAR 531 | 🍍 🍍 PINEAPPLE 532 | 🍠 🍠 ROASTED SWEET POTATO 533 | 🍆 🍆 AUBERGINE 534 | 🍅 🍅 TOMATO 535 | 🌽 🌽 EAR OF MAIZE 536 | 🏠 🏠 HOUSE BUILDING 537 | 🏡 🏡 HOUSE WITH GARDEN 538 | 🏫 🏫 SCHOOL 539 | 🏢 🏢 OFFICE BUILDING 540 | 🏣 🏣 JAPANESE POST OFFICE 541 | 🏥 🏥 HOSPITAL 542 | 🏦 🏦 BANK 543 | 🏪 🏪 CONVENIENCE STORE 544 | 🏩 🏩 LOVE HOTEL 545 | 🏨 🏨 HOTEL 546 | 💒 💒 WEDDING 547 | ⛪ ⛪ CHURCH 548 | 🏬 🏬 DEPARTMENT STORE 549 | 🏤 🏤 EUROPEAN POST OFFICE 550 | 🌇 🌇 SUNSET OVER BUILDINGS 551 | 🌆 🌆 CITYSCAPE AT DUSK 552 | 🏯 🏯 JAPANESE CASTLE 553 | 🏰 🏰 EUROPEAN CASTLE 554 | ⛺ ⛺ TENT 555 | 🏭 🏭 FACTORY 556 | 🗼 🗼 TOKYO TOWER 557 | 🗾 🗾 SILHOUETTE OF JAPAN 558 | 🗻 🗻 MOUNT FUJI 559 | 🌄 🌄 SUNRISE OVER MOUNTAINS 560 | 🌅 🌅 SUNRISE 561 | 🌃 🌃 NIGHT WITH STARS 562 | 🗽 🗽 STATUE OF LIBERTY 563 | 🌉 🌉 BRIDGE AT NIGHT 564 | 🎠 🎠 CAROUSEL HORSE 565 | 🎡 🎡 FERRIS WHEEL 566 | ⛲ ⛲ FOUNTAIN 567 | 🎢 🎢 ROLLER COASTER 568 | 🚢 🚢 SHIP 569 | ⛵ ⛵ SAILBOAT 570 | 🚤 🚤 SPEEDBOAT 571 | 🚣 🚣 ROWBOAT 572 | ⚓ ⚓ ANCHOR 573 | 🚀 🚀 ROCKET 574 | ✈ ✈ AIRPLANE 575 | 💺 💺 SEAT 576 | 🚁 🚁 HELICOPTER 577 | 🚂 🚂 STEAM LOCOMOTIVE 578 | 🚊 🚊 TRAM 579 | 🚉 🚉 STATION 580 | 🚞 🚞 MOUNTAIN RAILWAY 581 | 🚆 🚆 TRAIN 582 | 🚄 🚄 HIGH-SPEED TRAIN 583 | 🚅 🚅 HIGH-SPEED TRAIN WITH BULLET NOSE 584 | 🚈 🚈 LIGHT RAIL 585 | 🚇 🚇 METRO 586 | 🚝 🚝 MONORAIL 587 | 🚋 🚋 TRAM CAR 588 | 🚃 🚃 RAILWAY CAR 589 | 🚎 🚎 TROLLEYBUS 590 | 🚌 🚌 BUS 591 | 🚍 🚍 ONCOMING BUS 592 | 🚙 🚙 RECREATIONAL VEHICLE 593 | 🚘 🚘 ONCOMING AUTOMOBILE 594 | 🚗 🚗 AUTOMOBILE 595 | 🚕 🚕 TAXI 596 | 🚖 🚖 ONCOMING TAXI 597 | 🚛 🚛 ARTICULATED LORRY 598 | 🚚 🚚 DELIVERY TRUCK 599 | 🚨 🚨 POLICE CARS REVOLVING LIGHT 600 | 🚓 🚓 POLICE CAR 601 | 🚔 🚔 ONCOMING POLICE CAR 602 | 🚒 🚒 FIRE ENGINE 603 | 🚑 🚑 AMBULANCE 604 | 🚐 🚐 MINIBUS 605 | 🚲 🚲 BICYCLE 606 | 🚡 🚡 AERIAL TRAMWAY 607 | 🚟 🚟 SUSPENSION RAILWAY 608 | 🚠 🚠 MOUNTAIN CABLEWAY 609 | 🚜 🚜 TRACTOR 610 | 💈 💈 BARBER POLE 611 | 🚏 🚏 BUS STOP 612 | 🎫 🎫 TICKET 613 | 🚦 🚦 VERTICAL TRAFFIC LIGHT 614 | 🚥 🚥 HORIZONTAL TRAFFIC LIGHT 615 | ⚠ ⚠ WARNING SIGN 616 | 🚧 🚧 CONSTRUCTION SIGN 617 | 🔰 🔰 JAPANESE SYMBOL FOR BEGINNER 618 | ⛽ ⛽ FUEL PUMP 619 | 🏮 🏮 IZAKAYA LANTERN 620 | 🎰 🎰 SLOT MACHINE 621 | ♨ ♨ HOT SPRINGS 622 | 🗿 🗿 MOYAI 623 | 🎪 🎪 CIRCUS TENT 624 | 🎭 🎭 PERFORMING ARTS 625 | 📍 📍 ROUND PUSHPIN 626 | 🚩 🚩 TRIANGULAR FLAG ON POST 627 | 🇯🇵 🇯🇵 REGIONAL INDICATOR SYMBOL LETTERS JP 628 | 🇰🇷 🇰🇷 REGIONAL INDICATOR SYMBOL LETTERS KR 629 | 🇩🇪 🇩🇪 REGIONAL INDICATOR SYMBOL LETTERS DE 630 | 🇨🇳 🇨🇳 REGIONAL INDICATOR SYMBOL LETTERS CN 631 | 🇺🇸 🇺🇸 REGIONAL INDICATOR SYMBOL LETTERS US 632 | 🇫🇷 🇫🇷 REGIONAL INDICATOR SYMBOL LETTERS FR 633 | 🇪🇸 🇪🇸 REGIONAL INDICATOR SYMBOL LETTERS ES 634 | 🇮🇹 🇮🇹 REGIONAL INDICATOR SYMBOL LETTERS IT 635 | 🇷🇺 🇷🇺 REGIONAL INDICATOR SYMBOL LETTERS RU 636 | 🇬🇧 🇬🇧 REGIONAL INDICATOR SYMBOL LETTERS GB 637 | 1⃣ 1⃣ KEYCAP 1 638 | 2⃣ 2⃣ KEYCAP 2 639 | 3⃣ 3⃣ KEYCAP 3 640 | 4⃣ 4⃣ KEYCAP 4 641 | 5⃣ 5⃣ KEYCAP 5 642 | 6⃣ 6⃣ KEYCAP 6 643 | 7⃣ 7⃣ KEYCAP 7 644 | 8⃣ 8⃣ KEYCAP 8 645 | 9⃣ 9⃣ KEYCAP 9 646 | 0⃣ 0⃣ KEYCAP 0 647 | 🔟 🔟 KEYCAP TEN 648 | 🔢 🔢 INPUT SYMBOL FOR NUMBERS 649 | #⃣ #⃣ HASH KEY 650 | 🔣 🔣 INPUT SYMBOL FOR SYMBOLS 651 | ⬆ ⬆ UPWARDS BLACK ARROW 652 | ⬇ ⬇ DOWNWARDS BLACK ARROW 653 | ⬅ ⬅ LEFTWARDS BLACK ARROW 654 | ➡ ➡ BLACK RIGHTWARDS ARROW 655 | 🔠 🔠 INPUT SYMBOL FOR LATIN CAPITAL LETTERS 656 | 🔡 🔡 INPUT SYMBOL FOR LATIN SMALL LETTERS 657 | 🔤 🔤 INPUT SYMBOL FOR LATIN LETTERS 658 | ↗ ↗ NORTH EAST ARROW 659 | ↖ ↖ NORTH WEST ARROW 660 | ↘ ↘ SOUTH EAST ARROW 661 | ↙ ↙ SOUTH WEST ARROW 662 | ↔ ↔ LEFT RIGHT ARROW 663 | ↕ ↕ UP DOWN ARROW 664 | 🔄 🔄 ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS 665 | ◀ ◀ BLACK LEFT-POINTING TRIANGLE 666 | ▶ ▶ BLACK RIGHT-POINTING TRIANGLE 667 | 🔼 🔼 UP-POINTING SMALL RED TRIANGLE 668 | 🔽 🔽 DOWN-POINTING SMALL RED TRIANGLE 669 | ↩ ↩ LEFTWARDS ARROW WITH HOOK 670 | ↪ ↪ RIGHTWARDS ARROW WITH HOOK 671 | ℹ ℹ INFORMATION SOURCE 672 | ⏪ ⏪ BLACK LEFT-POINTING DOUBLE TRIANGLE 673 | ⏩ ⏩ BLACK RIGHT-POINTING DOUBLE TRIANGLE 674 | ⏫ ⏫ BLACK UP-POINTING DOUBLE TRIANGLE 675 | ⏬ ⏬ BLACK DOWN-POINTING DOUBLE TRIANGLE 676 | ⤵ ⤵ ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS 677 | ⤴ ⤴ ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS 678 | 🆗 🆗 SQUARED OK 679 | 🔀 🔀 TWISTED RIGHTWARDS ARROWS 680 | 🔁 🔁 CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS 681 | 🔂 🔂 CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY 682 | 🆕 🆕 SQUARED NEW 683 | 🆙 🆙 SQUARED UP WITH EXCLAMATION MARK 684 | 🆒 🆒 SQUARED COOL 685 | 🆓 🆓 SQUARED FREE 686 | 🆖 🆖 SQUARED NG 687 | 📶 📶 ANTENNA WITH BARS 688 | 🎦 🎦 CINEMA 689 | 🈁 🈁 SQUARED KATAKANA KOKO 690 | 🈯 🈯 SQUARED CJK UNIFIED IDEOGRAPH-6307 691 | 🈳 🈳 SQUARED CJK UNIFIED IDEOGRAPH-7A7A 692 | 🈵 🈵 SQUARED CJK UNIFIED IDEOGRAPH-6E80 693 | 🈴 🈴 SQUARED CJK UNIFIED IDEOGRAPH-5408 694 | 🈲 🈲 SQUARED CJK UNIFIED IDEOGRAPH-7981 695 | 🉐 🉐 CIRCLED IDEOGRAPH ADVANTAGE 696 | 🈹 🈹 SQUARED CJK UNIFIED IDEOGRAPH-5272 697 | 🈺 🈺 SQUARED CJK UNIFIED IDEOGRAPH-55B6 698 | 🈶 🈶 SQUARED CJK UNIFIED IDEOGRAPH-6709 699 | 🈚 🈚 SQUARED CJK UNIFIED IDEOGRAPH-7121 700 | 🚻 🚻 RESTROOM 701 | 🚹 🚹 MENS SYMBOL 702 | 🚺 🚺 WOMENS SYMBOL 703 | 🚼 🚼 BABY SYMBOL 704 | 🚾 🚾 WATER CLOSET 705 | 🚰 🚰 POTABLE WATER SYMBOL 706 | 🚮 🚮 PUT LITTER IN ITS PLACE SYMBOL 707 | 🅿 🅿 NEGATIVE SQUARED LATIN CAPITAL LETTER P 708 | ♿ ♿ WHEELCHAIR SYMBOL 709 | 🚭 🚭 NO SMOKING SYMBOL 710 | 🈷 🈷 SQUARED CJK UNIFIED IDEOGRAPH-6708 711 | 🈸 🈸 SQUARED CJK UNIFIED IDEOGRAPH-7533 712 | 🈂 🈂 SQUARED KATAKANA SA 713 | Ⓜ Ⓜ CIRCLED LATIN CAPITAL LETTER M 714 | 🛂 🛂 PASSPORT CONTROL 715 | 🛄 🛄 BAGGAGE CLAIM 716 | 🛅 🛅 LEFT LUGGAGE 717 | 🛃 🛃 CUSTOMS 718 | 🉑 🉑 CIRCLED IDEOGRAPH ACCEPT 719 | ㊙ ㊙ CIRCLED IDEOGRAPH SECRET 720 | ㊗ ㊗ CIRCLED IDEOGRAPH CONGRATULATION 721 | 🆑 🆑 SQUARED CL 722 | 🆘 🆘 SQUARED SOS 723 | 🆔 🆔 SQUARED ID 724 | 🚫 🚫 NO ENTRY SIGN 725 | 🔞 🔞 NO ONE UNDER EIGHTEEN SYMBOL 726 | 📵 📵 NO MOBILE PHONES 727 | 🚯 🚯 DO NOT LITTER SYMBOL 728 | 🚱 🚱 NON-POTABLE WATER SYMBOL 729 | 🚳 🚳 NO BICYCLES 730 | 🚷 🚷 NO PEDESTRIANS 731 | 🚸 🚸 CHILDREN CROSSING 732 | ⛔ ⛔ NO ENTRY 733 | ✳ ✳ EIGHT SPOKED ASTERISK 734 | ❇ ❇ SPARKLE 735 | ❎ ❎ NEGATIVE SQUARED CROSS MARK 736 | ✅ ✅ WHITE HEAVY CHECK MARK 737 | ✴ ✴ EIGHT POINTED BLACK STAR 738 | 💟 💟 HEART DECORATION 739 | 🆚 🆚 SQUARED VS 740 | 📳 📳 VIBRATION MODE 741 | 📴 📴 MOBILE PHONE OFF 742 | 🅰 🅰 NEGATIVE SQUARED LATIN CAPITAL LETTER A 743 | 🅱 🅱 NEGATIVE SQUARED LATIN CAPITAL LETTER B 744 | 🆎 🆎 NEGATIVE SQUARED AB 745 | 🅾 🅾 NEGATIVE SQUARED LATIN CAPITAL LETTER O 746 | 💠 💠 DIAMOND SHAPE WITH A DOT INSIDE 747 | ➿ ➿ DOUBLE CURLY LOOP 748 | ♻ ♻ BLACK UNIVERSAL RECYCLING SYMBOL 749 | ♈ ♈ ARIES 750 | ♉ ♉ TAURUS 751 | ♊ ♊ GEMINI 752 | ♋ ♋ CANCER 753 | ♌ ♌ LEO 754 | ♍ ♍ VIRGO 755 | ♎ ♎ LIBRA 756 | ♏ ♏ SCORPIUS 757 | ♐ ♐ SAGITTARIUS 758 | ♑ ♑ CAPRICORN 759 | ♒ ♒ AQUARIUS 760 | ♓ ♓ PISCES 761 | ⛎ ⛎ OPHIUCHUS 762 | 🔯 🔯 SIX POINTED STAR WITH MIDDLE DOT 763 | 🏧 🏧 AUTOMATED TELLER MACHINE 764 | 💹 💹 CHART WITH UPWARDS TREND AND YEN SIGN 765 | 💲 💲 HEAVY DOLLAR SIGN 766 | 💱 💱 CURRENCY EXCHANGE 767 | © © COPYRIGHT SIGN 768 | ® ® REGISTERED SIGN 769 | ™ ™ TRADE MARK SIGN 770 | ❌ ❌ CROSS MARK 771 | ‼ ‼ DOUBLE EXCLAMATION MARK 772 | ⁉ ⁉ EXCLAMATION QUESTION MARK 773 | ❗ ❗ HEAVY EXCLAMATION MARK SYMBOL 774 | ❓ ❓ BLACK QUESTION MARK ORNAMENT 775 | ❕ ❕ WHITE EXCLAMATION MARK ORNAMENT 776 | ❔ ❔ WHITE QUESTION MARK ORNAMENT 777 | ⭕ ⭕ HEAVY LARGE CIRCLE 778 | 🔝 🔝 TOP WITH UPWARDS ARROW ABOVE 779 | 🔚 🔚 END WITH LEFTWARDS ARROW ABOVE 780 | 🔙 🔙 BACK WITH LEFTWARDS ARROW ABOVE 781 | 🔛 🔛 ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE 782 | 🔜 🔜 SOON WITH RIGHTWARDS ARROW ABOVE 783 | 🔃 🔃 CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS 784 | 🕛 🕛 CLOCK FACE TWELVE OCLOCK 785 | 🕧 🕧 CLOCK FACE TWELVE-THIRTY 786 | 🕐 🕐 CLOCK FACE ONE OCLOCK 787 | 🕜 🕜 CLOCK FACE ONE-THIRTY 788 | 🕑 🕑 CLOCK FACE TWO OCLOCK 789 | 🕝 🕝 CLOCK FACE TWO-THIRTY 790 | 🕒 🕒 CLOCK FACE THREE OCLOCK 791 | 🕞 🕞 CLOCK FACE THREE-THIRTY 792 | 🕓 🕓 CLOCK FACE FOUR OCLOCK 793 | 🕟 🕟 CLOCK FACE FOUR-THIRTY 794 | 🕔 🕔 CLOCK FACE FIVE OCLOCK 795 | 🕠 🕠 CLOCK FACE FIVE-THIRTY 796 | 🕕 🕕 CLOCK FACE SIX OCLOCK 797 | 🕖 🕖 CLOCK FACE SEVEN OCLOCK 798 | 🕗 🕗 CLOCK FACE EIGHT OCLOCK 799 | 🕘 🕘 CLOCK FACE NINE OCLOCK 800 | 🕙 🕙 CLOCK FACE TEN OCLOCK 801 | 🕚 🕚 CLOCK FACE ELEVEN OCLOCK 802 | 🕡 🕡 CLOCK FACE SIX-THIRTY 803 | 🕢 🕢 CLOCK FACE SEVEN-THIRTY 804 | 🕣 🕣 CLOCK FACE EIGHT-THIRTY 805 | 🕤 🕤 CLOCK FACE NINE-THIRTY 806 | 🕥 🕥 CLOCK FACE TEN-THIRTY 807 | 🕦 🕦 CLOCK FACE ELEVEN-THIRTY 808 | ✖ ✖ HEAVY MULTIPLICATION X 809 | ➕ ➕ HEAVY PLUS SIGN 810 | ➖ ➖ HEAVY MINUS SIGN 811 | ➗ ➗ HEAVY DIVISION SIGN 812 | ♠ ♠ BLACK SPADE SUIT 813 | ♥ ♥ BLACK HEART SUIT 814 | ♣ ♣ BLACK CLUB SUIT 815 | ♦ ♦ BLACK DIAMOND SUIT 816 | 💮 💮 WHITE FLOWER 817 | 💯 💯 HUNDRED POINTS SYMBOL 818 | ✔ ✔ HEAVY CHECK MARK 819 | ☑ ☑ BALLOT BOX WITH CHECK 820 | 🔘 🔘 RADIO BUTTON 821 | 🔗 🔗 LINK SYMBOL 822 | ➰ ➰ CURLY LOOP 823 | 〰 〰 WAVY DASH 824 | 〽 〽 PART ALTERNATION MARK 825 | 🔱 🔱 TRIDENT EMBLEM 826 | ◼ ◼ BLACK MEDIUM SQUARE 827 | ◻ ◻ WHITE MEDIUM SQUARE 828 | ◾ ◾ BLACK MEDIUM SMALL SQUARE 829 | ◽ ◽ WHITE MEDIUM SMALL SQUARE 830 | ▪ ▪ BLACK SMALL SQUARE 831 | ▫ ▫ WHITE SMALL SQUARE 832 | 🔺 🔺 UP-POINTING RED TRIANGLE 833 | 🔲 🔲 BLACK SQUARE BUTTON 834 | 🔳 🔳 WHITE SQUARE BUTTON 835 | ⚫ ⚫ MEDIUM BLACK CIRCLE 836 | ⚪ ⚪ MEDIUM WHITE CIRCLE 837 | 🔴 🔴 LARGE RED CIRCLE 838 | 🔵 🔵 LARGE BLUE CIRCLE 839 | 🔻 🔻 DOWN-POINTING RED TRIANGLE 840 | ⬜ ⬜ WHITE LARGE SQUARE 841 | ⬛ ⬛ BLACK LARGE SQUARE 842 | 🔶 🔶 LARGE ORANGE DIAMOND 843 | 🔷 🔷 LARGE BLUE DIAMOND 844 | 🔸 🔸 SMALL ORANGE DIAMOND 845 | 🔹 🔹 SMALL BLUE DIAMOND 846 | -------------------------------------------------------------------------------- /autoload/unite/libs/gh_event.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! unite#libs#gh_event#on_syntax(args, context) 5 | syntax match uniteSource__github_user /.*\ze\s*---/ 6 | \ contained containedin=uniteSource__github_event 7 | syntax match uniteSource__github_repo /\s\+[^ ]\{-}\/[^ ]*/ 8 | \ contained containedin=uniteSource__github_event 9 | \ contains=uniteCandidateInputKeyword 10 | syntax match uniteSource__github_time /\d\+[mhd] ago/ 11 | \ contained containedin=uniteSource__github_event 12 | highlight default link uniteSource__github_user Constant 13 | highlight default link uniteSource__github_repo Keyword 14 | highlight default link uniteSource__github_time String 15 | endfunction 16 | 17 | function! unite#libs#gh_event#get_event(target, source) 18 | let api_base = 'https://api.github.com/' 19 | let api_suff = a:source == 'event' ? 'events' : 'received_events' 20 | if match(a:target, '/') == -1 21 | let api_addr = api_base.'users/'.a:target.'/'.api_suff 22 | else 23 | let api_addr = api_base.'repos/'.a:target.'/'.api_suff 24 | endif 25 | let res = webapi#http#get(api_addr) 26 | if res.status != '200' 27 | echom 'http error code:'.res.status 28 | return [] 29 | endif 30 | let events = webapi#json#decode(res.content) 31 | return map(events, 's:extract_entry(v:val, a:source)') 32 | endfunction 33 | 34 | function! s:extract_entry(dict, source) 35 | let repo = a:dict.repo.name 36 | let html_pre = 'https://github.com/' 37 | let user = a:dict.actor.login 38 | if a:dict.type == 'PushEvent' 39 | let words = user.' --- pushed to '.repo 40 | let url = html_pre.repo. 41 | \ '/commit/'.a:dict.payload.commits[0].sha 42 | elseif a:dict.type == 'PullRequestEvent' 43 | let words = user.' --- '.a:dict.payload.action.'_PR to '.repo 44 | let url = html_pre.repo.'/pull/'.a:dict.payload.number 45 | elseif a:dict.type == 'IssuesEvent' 46 | let words = user.' --- '.a:dict.payload.action.'_IS to '.repo 47 | let url = a:dict.payload.issue.html_url 48 | elseif a:dict.type == 'WatchEvent' 49 | let words = user.' --- '.a:dict.payload.action.' '.repo 50 | let url = html_pre.repo 51 | elseif a:dict.type == 'ForkEvent' 52 | let words = user.' --- forked '.repo 53 | let url = html_pre.a:dict.payload.forkee.full_name 54 | elseif a:dict.type == 'IssueCommentEvent' 55 | let words = user.' --- commented on '.repo 56 | let url = a:dict.payload.issue.html_url 57 | elseif a:dict.type == 'PullRequestReviewCommentEvent' 58 | let words = user.' --- commented on '.repo 59 | let url = a:dict.payload.comment.html_url 60 | elseif a:dict.type == 'CommitCommentEvent' 61 | let words = user.' --- commented on '.repo 62 | let url = a:dict.payload.comment.html_url 63 | elseif a:dict.type == 'CreateEvent' 64 | let words = user.' --- created '.repo 65 | let url = html_pre.repo 66 | elseif a:dict.type == 'DeleteEvent' 67 | let words = user.' --- deleted a '. 68 | \ a:dict.payload.ref_type . 69 | \ ' on '.repo 70 | let url = html_pre.repo 71 | elseif a:dict.type == 'GollumEvent' 72 | let words = user.' --- gollum '.repo 73 | let url = a:dict.payload.pages[0].html_url 74 | elseif a:dict.type == 'MemberEvent' 75 | let words = user.' --- '. 76 | \ a:dict.payload.action . ' '. 77 | \ a:dict.payload.member.login . ' to '.repo 78 | let url = html_pre.repo 79 | elseif a:dict.type == 'PublicEvent' 80 | let words = user.' --- opened '.repo 81 | let url = html_pre.repo 82 | elseif a:dict.type == 'ReleaseEvent' 83 | let words = user.' --- published '. 84 | \ a:dict.payload.release.tag_name 85 | \ .' of '.repo 86 | let url = a:dict.payload.release.html_url 87 | else 88 | let words = '' 89 | let url = html_pre 90 | endif 91 | return { 92 | \ 'action__id' : a:dict.actor.id, 93 | \ 'action__icon' : a:dict.actor.avatar_url, 94 | \ 'action__uri' : url, 95 | \ 'action__repo' : repo, 96 | \ 'word' : words.s:date_diff(a:dict.created_at), 97 | \ 'kind' : 'uri', 98 | \ 'source' : 'github/'.a:source 99 | \ } 100 | endfunction 101 | 102 | function! s:date_diff(date) 103 | python << EOF 104 | import vim 105 | import time 106 | from datetime import datetime 107 | 108 | date = vim.eval('a:date') 109 | d1 = datetime.strptime(date, '%Y-%m-%dT%H:%M:%SZ') 110 | d2 = datetime.fromtimestamp(time.mktime(time.gmtime())) 111 | if (d2-d1).days > 0: 112 | diff = str((d2-d1).days) + 'd ago' 113 | elif (d2-d1).seconds/3600 > 0: 114 | diff = str((d2-d1).seconds/3600) + 'h ago' 115 | else: 116 | diff = str((d2-d1).seconds/60) + 'm ago' 117 | 118 | vim.command('return " '+diff+'"') 119 | EOF 120 | endfunction 121 | 122 | let &cpo = s:save_cpo 123 | unlet s:save_cpo 124 | -------------------------------------------------------------------------------- /autoload/unite/libs/http.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! unite#libs#http#oauth_dl(url, ctx, file, ...) 5 | let params = a:0 > 0 ? a:000[0] : {} 6 | let getdata = a:0 > 1 ? a:000[1] : {} 7 | let headdata = a:0 > 2 ? a:000[2] : {} 8 | let query = {} 9 | let time_stamp = localtime() 10 | let nonce = time_stamp . " " . time_stamp 11 | let nonce = webapi#sha1#sha1(nonce)[0:28] 12 | let query["oauth_consumer_key"] = a:ctx.consumer_key 13 | let query["oauth_nonce"] = nonce 14 | let query["oauth_request_method"] = "GET" 15 | let query["oauth_signature_method"] = "HMAC-SHA1" 16 | let query["oauth_timestamp"] = time_stamp 17 | let query["oauth_token"] = a:ctx.access_token 18 | let query["oauth_version"] = "1.0" 19 | if type(params) == 4 20 | for key in keys(params) 21 | let query[key] = params[key] 22 | endfor 23 | endif 24 | if type(getdata) == 4 25 | for key in keys(getdata) 26 | let query[key] = getdata[key] 27 | endfor 28 | endif 29 | let query_string = query["oauth_request_method"] . "&" 30 | let query_string .= webapi#http#encodeURI(a:url) 31 | let query_string .= "&" 32 | let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query)) 33 | let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&" . webapi#http#encodeURI(a:ctx.access_token_secret), query_string) 34 | let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1) 35 | if type(getdata) == 4 36 | for key in keys(getdata) 37 | call remove(query, key) 38 | endfor 39 | endif 40 | let auth = 'OAuth ' 41 | for key in sort(keys(query)) 42 | let auth .= key . '="' . webapi#http#encodeURI(query[key]) . '", ' 43 | endfor 44 | let auth = auth[:-3] 45 | let headdata["Authorization"] = auth 46 | call unite#libs#http#download(a:url, a:file, getdata, headdata) 47 | endfunction 48 | 49 | function! unite#libs#http#download(url, file, ...) 50 | let getdata = a:0 > 0 ? a:000[0] : {} 51 | let headdata = a:0 > 1 ? a:000[1] : {} 52 | let url = a:url 53 | let getdatastr = webapi#http#encodeURI(getdata) 54 | if strlen(getdatastr) 55 | let url .= "?" . getdatastr 56 | endif 57 | if executable('curl') 58 | let command = 'curl -s -k -o "'.a:file.'"' 59 | let quote = &shellxquote == '"' ? "'" : '"' 60 | for key in keys(headdata) 61 | if has('win32') 62 | let command .= " -H " . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote 63 | else 64 | let command .= " -H " . quote . key . ": " . headdata[key] . quote 65 | endif 66 | endfor 67 | let command .= " ".quote.url.quote 68 | call system(command) 69 | elseif executable('wget') 70 | let command = 'wget --save-headers --server-response -q -O "'.a:file.'"' 71 | let quote = &shellxquote == '"' ? "'" : '"' 72 | for key in keys(headdata) 73 | if has('win32') 74 | let command .= " --header=" . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote 75 | else 76 | let command .= " --header=" . quote . key . ": " . headdata[key] . quote 77 | endif 78 | endfor 79 | let command .= " ".quote.url.quote 80 | call = system(command) 81 | else 82 | throw "require `curl` or `wget` command" 83 | endif 84 | endfunction 85 | 86 | let &cpo = s:save_cpo 87 | unlet s:save_cpo 88 | -------------------------------------------------------------------------------- /autoload/unite/libs/uri.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:signs = {} 5 | let s:procs = {} 6 | function! unite#libs#uri#show_icon(download, context, candidates) 7 | if !executable('wget') || !has('gui_running') || 8 | \ !unite#util#has_vimproc() || !g:unite#workflow#show_icon 9 | return 1 10 | endif 11 | let dir = unite#get_data_directory().'/'.split(a:context.source.name, '/')[0].'/' 12 | if finddir(dir) == '' 13 | call mkdir(dir, 'p') 14 | endif 15 | let bufn = bufnr('[unite] - '.a:context.buffer_name) 16 | if bufwinnr(a:context.buffer_name) == -1 17 | return 0 18 | endif 19 | execute 'sign unplace * buffer=' . bufn 20 | 21 | let finished = 1 22 | let prompt = getline(1) =~ '^[\t ]*'.a:context.prompt 23 | for index in range(len(a:candidates)) 24 | let cand = a:candidates[index] 25 | let icon = dir. cand.action__id . '.png' 26 | let line = a:context.direction =~ '^b' ? 27 | \ (len(a:candidates) - index) : 28 | \ (index+prompt+1) 29 | if !filereadable(icon) && a:download 30 | let finished = 0 31 | let proc = vimproc#popen2('wget ' . cand.action__icon . ' -O '.icon) 32 | let s:procs[proc.pid] = proc 33 | else 34 | if a:download 35 | let s:signs[cand.action__id] = 1 36 | endif 37 | try 38 | execute 'sign define workflow_' . cand.action__id . ' icon='.icon 39 | execute 'sign place ' . (index+10) . ' line='.line.' name=workflow_' 40 | \ . cand.action__id . ' buffer=' . bufn 41 | catch 42 | let finished = 0 43 | endtry 44 | endif 45 | endfor 46 | 47 | if !a:download 48 | augroup workflow_icon 49 | autocmd! 50 | augroup END 51 | endif 52 | if finished 53 | call unite#libs#uri#wait4children() 54 | endif 55 | return finished 56 | endfunction 57 | 58 | function! unite#libs#uri#clear_sign() 59 | execute 'sign unplace * buffer=' . bufnr('%') 60 | for id in keys(s:signs) 61 | try 62 | execute 'sign undefine workflow_'.id 63 | catch 64 | endtry 65 | endfor 66 | endfunction 67 | 68 | function! unite#libs#uri#wait4children() 69 | for pid in keys(s:procs) 70 | call s:procs[pid].waitpid() 71 | endfor 72 | endfunction 73 | 74 | let &cpo = s:save_cpo 75 | unlet s:save_cpo 76 | -------------------------------------------------------------------------------- /autoload/unite/sources/apropos.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:unite_source = { 5 | \ 'name': 'apropos', 6 | \ 'description' : 'Search for manpage using apropos.', 7 | \ 'required_pattern_length': 2, 8 | \ 'is_volatile': 1, 9 | \ 'hooks' : {}, 10 | \ 'action_table': {}, 11 | \ 'syntax' : 'uniteSource__Apropos' 12 | \ } 13 | 14 | if executable('apropos') 15 | let s:command = 'apropos %s' 16 | else 17 | echom 'Apropos is not executable on your system.' 18 | endif 19 | 20 | let s:unite_source.action_table.execute= { 21 | \ 'description' : 'view man page', 22 | \ 'is_quit' : 1, 23 | \ } 24 | 25 | function! s:unite_source.action_table.execute.func(candidate) 26 | let name = matchstr(a:candidate.word, '.*\ze\s\+(.*)\s\+-') 27 | let cate = matchstr(a:candidate.word, '(\zs\d.*\ze)\s\+-') 28 | execute "Man ".cate." ".name 29 | endfunction 30 | 31 | function! s:unite_source.hooks.on_syntax(args, context) 32 | syntax match uniteSource__Apropos_name /.\{-}\ze\s\+(\d/ 33 | \ contained containedin=uniteSource__Apropos 34 | syntax match uniteSource__Apropos_desc /\s-\s\zs.*/ 35 | \ contained containedin=uniteSource__Apropos 36 | \ contains=uniteCandidateInputKeyword 37 | highlight default link uniteSource__Apropos_desc String 38 | highlight default link uniteSource__Apropos_name Keyword 39 | endfunction 40 | 41 | function! s:unite_source.gather_candidates(args, context) 42 | return map( 43 | \ split(unite#util#system( 44 | \ printf(s:command, a:context.input) 45 | \ ), '\n'), 46 | \ '{"word": v:val, 47 | \ "kind": "command", 48 | \ "source": "apropos", 49 | \ }') 50 | endfunction 51 | 52 | function! unite#sources#apropos#define() 53 | if !exists(':Man') 54 | runtime ftplugin/man.vim 55 | endif 56 | return exists('s:command')? s:unite_source : [] 57 | endfunction 58 | 59 | 60 | let &cpo = s:save_cpo 61 | unlet s:save_cpo 62 | -------------------------------------------------------------------------------- /autoload/unite/sources/douban.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | 6 | function! unite#sources#douban#define() 7 | let sources = [] 8 | for sou in ['book', 'movie', 'music'] 9 | let source = { 10 | \ 'name' : 'douban/'.sou, 11 | \ 'description' : 'douban '.sou, 12 | \ 'hooks' : {}, 13 | \ 'syntax' : 'uniteSource__douban' 14 | \ } 15 | 16 | function! source.hooks.on_init(args, context) 17 | let input = get(a:args, 0, '') 18 | let input = input != '' ? input : 19 | \ unite#util#input('Please input search words: ', '') 20 | let s:kind = split(a:context.source.name, '/')[1] 21 | call s:refresh(input) 22 | endfunction 23 | 24 | function! source.hooks.on_close(args, context) 25 | call unite#libs#uri#clear_sign() 26 | endfunction 27 | 28 | function! source.hooks.on_syntax(args, context) 29 | syntax match uniteSource__douban_title /.*\ze --/ 30 | \ contained containedin=uniteSource__douban 31 | \ contains=uniteSource__douban_rank 32 | syntax match uniteSource__douban_rank /☆ [0-9.]* / 33 | \ contained containedin=uniteSource__douban_title 34 | syntax match uniteSource__douban_people /【.\{-}】/ 35 | \ contained containedin=uniteSource__douban 36 | \ contains=uniteCandidateInputKeyword 37 | highlight default link uniteSource__douban_title String 38 | highlight default link uniteSource__douban_people Constant 39 | highlight default link uniteSource__douban_rank Todo 40 | endfunction 41 | 42 | function! source.hooks.on_post_filter(args, context) 43 | let s:context = a:context 44 | augroup workflow_icon 45 | autocmd! TextChanged,TextChangedI 46 | \ call unite#libs#uri#show_icon(0, s:context, s:context.candidates) 47 | augroup END 48 | endfunction 49 | 50 | function! source.gather_candidates(args, context) 51 | if a:context.is_redraw 52 | if a:context.input != '' 53 | let input = a:context.input 54 | call s:refresh(input) 55 | let a:context.is_async = 1 56 | endif 57 | endif 58 | return s:candidates 59 | endfunction 60 | 61 | function! source.async_gather_candidates(args, context) 62 | if unite#libs#uri#show_icon(1, a:context, s:candidates) 63 | let a:context.is_async = 0 64 | endif 65 | return [] 66 | endfunction 67 | 68 | call add(sources, source) 69 | endfor 70 | return sources 71 | endfunction 72 | 73 | function! s:http_get(input) 74 | let html_pre = 'https://api.douban.com/v2/' 75 | if s:kind == 'movie' 76 | if a:input == '' 77 | let param = {} 78 | let url = html_pre.'movie/us_box' 79 | else 80 | let param = { 81 | \ 'q': a:input, 82 | \ } 83 | let url = html_pre.'movie/search' 84 | endif 85 | let key = 'subjects' 86 | else 87 | let param = { 88 | \ 'q' : a:input 89 | \ } 90 | let url = html_pre.s:kind.'/search' 91 | let key = s:kind.'s' 92 | endif 93 | 94 | let res = webapi#http#get(url, param) 95 | if res.status != '200' 96 | echom 'http error code:'.res.status 97 | return [] 98 | endif 99 | 100 | let content = webapi#json#decode(res.content) 101 | if !has_key(content, key) 102 | return [] 103 | endif 104 | return map(content[key], 's:extract_entry(v:val, a:input)') 105 | endfunction 106 | 107 | function! s:extract_entry(dict, input) 108 | let dict = a:input == '' ? a:dict.subject : a:dict 109 | let icon = s:kind == 'music' ? dict.image : dict.images.small 110 | let result = { 111 | \ 'action__id' : dict.id, 112 | \ 'action__icon' : icon, 113 | \ 'kind' : 'uri', 114 | \ 'source' : 'douban/'.s:kind, 115 | \ 'action__uri' : dict.alt 116 | \ } 117 | if s:kind == 'movie' 118 | let cast = ' ★ '.join(map(dict.casts, 'v:val.name'), ',') 119 | let dirc = '🎥 '.join(map(dict.directors, 'v:val.name'), ',') 120 | let middle = dirc.cast 121 | let tail = dict.year 122 | elseif s:kind == 'book' 123 | let middle = join(dict.author, ',') 124 | let tail = dict.pubdate.' '.dict.publisher 125 | else 126 | let middle = join(map(get(dict, 'author', [])[0:2], 'v:val.name'), ',') 127 | let tail = get(dict.attrs, 'pubdate', ['unknown'])[0] 128 | endif 129 | let result.word = '☆ '.substitute(string(dict.rating.average), "'", '', 'g'). 130 | \ ' '.dict.title.' -- 【'.middle.'】-- '.tail 131 | return result 132 | endfunction 133 | 134 | function! s:refresh(input) 135 | call unite#print_source_message('Fetching '.s:kind.' info from douban ...', 136 | \ 'douban/'.s:kind) 137 | let s:candidates = s:http_get(a:input) 138 | call unite#clear_message() 139 | endfunction 140 | 141 | let &cpo = s:save_cpo 142 | unlet s:save_cpo 143 | -------------------------------------------------------------------------------- /autoload/unite/sources/dropbox.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:direct = { 6 | \ 'name' : 'dropbox/files', 7 | \ 'description' : 'dropbox access.', 8 | \ 'hooks' : { 9 | \ 'on_syntax' : function('unite#sources#dropbox#syntax') 10 | \ }, 11 | \ 'gather_candidates' : function('unite#sources#dropbox#gc'), 12 | \ 'syntax' : 'uniteSource__dropbox' 13 | \ } 14 | 15 | let s:search = deepcopy(s:direct) 16 | let s:search.name = 'dropbox/search' 17 | let s:search.description = 'dropbox search.' 18 | 19 | function! s:search.hooks.on_init(args, context) 20 | let keywords = get(a:args, 0, '') 21 | call unite#print_source_message('Searching for files ...', 22 | \ s:search.name) 23 | if keywords == '' 24 | let keywords = unite#util#input('Search keywords:', '') 25 | let s:candidates = unite#kinds#dropbox#search(keywords) 26 | endif 27 | call unite#clear_message() 28 | endfunction 29 | 30 | function! s:direct.hooks.on_init(args, context) 31 | let path = get(a:args, 0, '') 32 | call unite#print_source_message('Getting files ...', 33 | \ s:direct.name) 34 | let s:candidates = unite#kinds#dropbox#list_path(path) 35 | call unite#clear_message() 36 | endfunction 37 | 38 | function! unite#sources#dropbox#syntax(args, context) 39 | syntax match uniteSource__dropbox_type /【.\{-}】/ 40 | \ contained containedin=uniteSource__dropbox 41 | \ contains=uniteCandidateInputKeyword 42 | highlight default link uniteSource__dropbox_type Constant 43 | endfunction 44 | 45 | function! unite#sources#dropbox#gc(args, context) 46 | return s:candidates 47 | endfunction 48 | 49 | function! unite#sources#dropbox#define() 50 | return [s:direct, s:search] 51 | endfunction 52 | 53 | let &cpo = s:save_cpo 54 | unlet s:save_cpo 55 | -------------------------------------------------------------------------------- /autoload/unite/sources/emoji.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:dict = simplify(expand(':p:h').'/../libs/emoji.dict') 5 | let s:source = { 6 | \ 'name': 'emoji', 7 | \ 'description' : 'Search for emoji by description.', 8 | \ "default_action" : "insert", 9 | \ 'hooks' : {}, 10 | \ 'action_table': {}, 11 | \ 'syntax' : 'uniteSource__emoji' 12 | \ } 13 | 14 | let s:source.action_table.insert = { 15 | \ 'description' : 'insert emoji', 16 | \ 'is_quit' : 1 17 | \ } 18 | 19 | function! s:source.action_table.insert.func(candidate) 20 | let word = matchstr(a:candidate.word, '^.\{-}\ze\s') 21 | let col = getcurpos()[2] 22 | let line = getline('.') 23 | if col < 0 | let col = len(line)| endif 24 | let pre = matchstr(line, '^.*\%' . col . 'c.') 25 | let after = line[col :] 26 | call setline(line('.'), pre . word . after) 27 | endfunction 28 | 29 | function! s:source.hooks.on_init(args, context) abort 30 | let a:context.source__data = readfile(s:dict) 31 | endfunction 32 | 33 | function! s:source.hooks.on_close(args, context) 34 | let a:context.source__data = '' 35 | endfunction 36 | 37 | function! s:source.hooks.on_syntax(args, context) 38 | syntax match uniteSource__emoji_desc /\s\+\zs[A-Z0-9 -]\+/ 39 | \ contained containedin=uniteSource__emoji 40 | \ contains=uniteCandidateInputKeyword 41 | highlight default link uniteSource__emoji_desc Normal 42 | endfunction 43 | 44 | function! s:source.gather_candidates(args, context) 45 | return map( 46 | \ a:context.source__data, 47 | \ '{"word": v:val, 48 | \ "kind": "word", 49 | \ "abbr": v:val, 50 | \ "source": "emoji", 51 | \ }') 52 | endfunction 53 | 54 | function! unite#sources#emoji#define() 55 | return s:source 56 | endfunction 57 | 58 | let &cpo = s:save_cpo 59 | unlet s:save_cpo 60 | -------------------------------------------------------------------------------- /autoload/unite/sources/gist_search.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'gist/search', 7 | \ 'description' : 'Search for gists.', 8 | \ 'hooks' : { 9 | \ 'on_syntax' : function('unite#kinds#gist#on_syntax') 10 | \ }, 11 | \ 'syntax' : 'uniteSource__gist' 12 | \ } 13 | 14 | function! s:unite_source.hooks.on_init(args, context) 15 | let input = get(a:args, 0, '') 16 | let input = input != '' ? input : 17 | \ unite#util#input('Please input search words: ', '') 18 | call s:refresh(input) 19 | endfunction 20 | 21 | function! s:unite_source.gather_candidates(args, context) 22 | if a:context.is_redraw 23 | if a:context.input != '' 24 | let input = a:context.input 25 | call s:refresh(input) 26 | endif 27 | endif 28 | return s:candidates 29 | endfunction 30 | 31 | function! s:http_get(input) 32 | let param = {"q": a:input} 33 | let res = webapi#http#get('https://gist.github.com/search', param) 34 | if res.status != '200' 35 | echom 'http error code:'.res.status 36 | return [] 37 | endif 38 | let lines = split(res.content, '\n') 39 | let gists = filter(lines, 'v:val =~ "css-truncate-target"') 40 | return map(gists, 's:extract_entry(v:val)') 41 | endfunction 42 | 43 | function! s:extract_entry(line) 44 | let uri = matchstr(a:line, 'a href="/\zs[^>]\+\ze">') 45 | let id = split(uri, '/')[1] 46 | let filename = matchstr(a:line, 'class="css-truncate-target">\zs[^<]\+\ze<') 47 | return { 48 | \ 'action__id' : id, 49 | \ 'action__uri' : 'https://gist.github.com/'.uri, 50 | \ 'fname' : filename, 51 | \ 'word' : uri.' '.filename, 52 | \ 'kind' : 'gist', 53 | \ 'source' : 'gist/search'} 54 | endfunction 55 | 56 | function! s:refresh(input) 57 | call unite#print_source_message('Fetching gists info from the server ...', 58 | \ 'gist/search') 59 | let s:candidates = s:http_get(a:input) 60 | call unite#clear_message() 61 | endfunction 62 | 63 | function! unite#sources#gist_search#define() 64 | if !exists(':Gist') 65 | return [] 66 | endif 67 | return s:unite_source 68 | endfunction 69 | 70 | let &cpo = s:save_cpo 71 | unlet s:save_cpo 72 | -------------------------------------------------------------------------------- /autoload/unite/sources/gist_user.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'gist/user', 7 | \ 'description' : 'List public gists created by a certain user.', 8 | \ 'hooks' : { 9 | \ 'on_syntax' : function('unite#kinds#gist#on_syntax') 10 | \ }, 11 | \ 'syntax' : 'uniteSource__gist' 12 | \ } 13 | 14 | function! s:unite_source.hooks.on_init(args, context) 15 | let s:username = get(a:args, 0, g:github_user) 16 | call unite#print_source_message('Fetching gists of user '. 17 | \ s:username.' ...', 'gist/user') 18 | let gists = gist#list(s:username) 19 | let s:candidates = map(gists, 's:extract_entry(v:val)') 20 | call unite#clear_message() 21 | endfunction 22 | 23 | function! s:unite_source.gather_candidates(args, context) 24 | return s:candidates 25 | endfunction 26 | 27 | function! s:extract_entry(dict) 28 | let fname = keys(a:dict.files)[0] 29 | let id = a:dict.id 30 | return { 31 | \ 'action__id' : id, 32 | \ 'action__uri' : a:dict.html_url, 33 | \ 'word' : s:username.'/'.id.' '.fname, 34 | \ 'kind' : 'gist', 35 | \ 'source' : 'gist/user' 36 | \ } 37 | endfunction 38 | 39 | function! unite#sources#gist_user#define() 40 | if !exists(':Gist') 41 | return [] 42 | endif 43 | return s:unite_source 44 | endfunction 45 | 46 | let &cpo = s:save_cpo 47 | unlet s:save_cpo 48 | -------------------------------------------------------------------------------- /autoload/unite/sources/github_activity.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | 6 | function! unite#sources#github_activity#define() 7 | let sources = [] 8 | for source in ['feed', 'event'] 9 | let so = { 10 | \ 'name' : 'github/'.source, 11 | \ 'description' : 'Github '.source.'s of a certain user.', 12 | \ 'hooks' : { 13 | \ 'on_syntax' : function('unite#libs#gh_event#on_syntax') 14 | \ }, 15 | \ 'action_table' : {}, 16 | \ 'syntax' : 'uniteSource__github_event' 17 | \ } 18 | 19 | let so.action_table.edit = { 20 | \ 'description' : 'Edit with :Giedit.', 21 | \ 'is_quit' : 1, 22 | \ 'func' : function('unite#kinds#issue#edit') 23 | \ } 24 | 25 | function! so.hooks.on_init(args, context) 26 | let s:kind = split(a:context.source.name, '/')[1] 27 | call s:refresh(a:args) 28 | endfunction 29 | 30 | function! so.hooks.on_close(args, context) 31 | call unite#libs#uri#clear_sign() 32 | endfunction 33 | 34 | function! so.hooks.on_post_filter(args, context) 35 | let s:context = a:context 36 | augroup workflow_icon 37 | autocmd! TextChanged,TextChangedI 38 | \ call unite#libs#uri#show_icon(0, s:context, s:context.candidates) 39 | augroup END 40 | endfunction 41 | 42 | function! so.gather_candidates(args, context) 43 | if a:context.is_redraw 44 | let s:kind = split(a:context.source.name, '/')[1] 45 | call s:refresh(a:args) 46 | let a:context.is_async = 1 47 | endif 48 | return s:candidates 49 | endfunction 50 | 51 | function! so.async_gather_candidates(args, context) 52 | if unite#libs#uri#show_icon(1, a:context, s:candidates) 53 | let a:context.is_async = 0 54 | endif 55 | return [] 56 | endfunction 57 | 58 | call add(sources, so) 59 | endfor 60 | 61 | return sources 62 | endfunction 63 | 64 | function! s:refresh(args) 65 | let target = get(a:args, 0, g:github_user) 66 | call unite#print_source_message('Fetching '.s:kind.'s of user '. 67 | \ target.' ...', 'github/'.s:kind) 68 | let s:candidates = unite#libs#gh_event#get_event(target, s:kind) 69 | call unite#clear_message() 70 | endfunction 71 | 72 | 73 | let &cpo = s:save_cpo 74 | unlet s:save_cpo 75 | -------------------------------------------------------------------------------- /autoload/unite/sources/github_issue.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'github/issue', 7 | \ 'description' : 'List github issues of a certain repository.', 8 | \ 'hooks' : {}, 9 | \ 'syntax' : 'uniteSource__ghissue' 10 | \ } 11 | 12 | function! s:unite_source.hooks.on_init(args, context) 13 | let input = get(a:args, 0, '') 14 | let s:repo = input != '' ? input : 15 | \ s:get_current_repo() 16 | call s:refresh(s:repo) 17 | endfunction 18 | 19 | function! s:unite_source.hooks.on_close(args, context) 20 | call unite#libs#uri#clear_sign() 21 | endfunction 22 | 23 | function! s:unite_source.hooks.on_syntax(args, context) 24 | syntax match uniteSource__ghissue_user /.*\ze\s\+--/ 25 | \ contained containedin=uniteSource__ghissue 26 | syntax match uniteSource__ghissue_label /【.\{-}】/ 27 | \ contained containedin=uniteSource__ghissue 28 | \ contained containedin=uniteSource__ghissue 29 | highlight default link uniteSource__ghissue_user Constant 30 | highlight default link uniteSource__ghissue_label Todo 31 | endfunction 32 | 33 | function! s:unite_source.hooks.on_post_filter(args, context) 34 | let s:context = a:context 35 | augroup workflow_icon 36 | autocmd! TextChanged,TextChangedI 37 | \ call unite#libs#uri#show_icon(0, s:context, s:context.candidates) 38 | augroup END 39 | endfunction 40 | 41 | function! s:unite_source.gather_candidates(args, context) 42 | if a:context.is_redraw 43 | if a:context.input != '' 44 | let s:repo = a:context.input 45 | call s:refresh(s:repo) 46 | let a:context.is_async = 1 47 | endif 48 | endif 49 | return s:candidates 50 | endfunction 51 | 52 | function! s:unite_source.async_gather_candidates(args, context) 53 | if unite#libs#uri#show_icon(1, a:context, s:candidates) 54 | let a:context.is_async = 0 55 | endif 56 | return [] 57 | endfunction 58 | 59 | function! s:http_get(repo) 60 | let res = webapi#http#get("https://api.github.com/repos/".a:repo.'/issues') 61 | if res.status != '200' 62 | echom 'http error code:'.res.status 63 | return [] 64 | endif 65 | let content = webapi#json#decode(res.content) 66 | if type(content) == 4 67 | return [] 68 | endif 69 | return map(content, 's:extract_entry(v:val)') 70 | endfunction 71 | 72 | function! s:extract_entry(dict) 73 | let user = a:dict.user.login 74 | let title = a:dict.title 75 | let labels = join(map(a:dict.labels, 'v:val.name'), ', ') 76 | let labels = labels == '' ? '' : '【'.labels.'】' 77 | return { 78 | \ 'action__id' : a:dict.user.id, 79 | \ 'action__icon' : a:dict.user.avatar_url, 80 | \ 'word' : user.' -- '.title.' '.labels, 81 | \ 'action__uri' : a:dict.html_url, 82 | \ 'action__repo' : s:repo, 83 | \ 'kind' : 'issue', 84 | \ 'source' : 'github/issue' 85 | \ } 86 | 87 | endfunction 88 | 89 | function! s:get_current_repo() 90 | let output = split(system('git remote -v'), '\n') 91 | let output = filter(output, 'v:val =~ "github"') 92 | if output == [] 93 | return 'farseer90718/unite-workflow' 94 | endif 95 | return substitute(matchstr(output[0], 'github.com[/:]\zs[^ ]*'), '\.git$', '', '') 96 | endfunction 97 | 98 | function! s:refresh(repo) 99 | call unite#print_source_message('Getting issues of '.a:repo.' from the server ...', 100 | \ s:unite_source.name) 101 | let s:candidates = s:http_get(a:repo) 102 | call unite#clear_message() 103 | endfunction 104 | 105 | function! unite#sources#github_issue#define() 106 | return s:unite_source 107 | endfunction 108 | 109 | let &cpo = s:save_cpo 110 | unlet s:save_cpo 111 | -------------------------------------------------------------------------------- /autoload/unite/sources/github_search.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'github/search', 7 | \ 'description' : 'Search for github repositories.', 8 | \ 'hooks' : {}, 9 | \ 'action_table': {}, 10 | \ 'syntax' : 'uniteSource__github' 11 | \ } 12 | 13 | let s:unite_source.action_table.clone = { 14 | \ 'description' : 'Clone the repo somewhere', 15 | \ } 16 | 17 | function! s:unite_source.action_table.clone.func(candidate) 18 | if !executable('git') 19 | echoerr 'The executable named git should be in $PATH!' 20 | return 21 | endif 22 | let destdir = unite#util#input('Choose destination directory: ', $PWD, 'file'). 23 | \ '/'.split(a:candidate.word, '/')[1] 24 | let command = 'git clone https://github.com/'.a:candidate.word.' '.destdir 25 | call unite#print_source_message('Cloning the repo to '.destdir.'...', s:unite_source.name) 26 | call system(command) 27 | call unite#clear_message() 28 | execute 'Unite file:'.destdir 29 | endfunction 30 | 31 | function! s:unite_source.hooks.on_init(args, context) 32 | let input = get(a:args, 0, '') 33 | let input = input != '' ? input : 34 | \ unite#util#input('Please input search words: ', '') 35 | call s:refresh(input, a:context.winheight) 36 | endfunction 37 | 38 | function! s:unite_source.hooks.on_close(args, context) 39 | call unite#libs#uri#clear_sign() 40 | endfunction 41 | 42 | function! s:unite_source.hooks.on_syntax(args, context) 43 | syntax match uniteSource__github_user /.*\ze\// 44 | \ contained containedin=uniteSource__github_repo 45 | syntax match uniteSource__github_repo /.*/ 46 | \ contained containedin=uniteSource__github 47 | \ contains=uniteCandidateInputKeyword,uniteSource__github_user 48 | highlight default link uniteSource__github_user Constant 49 | highlight default link uniteSource__github_repo Keyword 50 | endfunction 51 | 52 | function! s:unite_source.hooks.on_post_filter(args, context) 53 | let s:context = a:context 54 | augroup workflow_icon 55 | autocmd! TextChanged,TextChangedI 56 | \ call unite#libs#uri#show_icon(0, s:context, s:context.candidates) 57 | augroup END 58 | endfunction 59 | 60 | function! s:unite_source.gather_candidates(args, context) 61 | if a:context.is_redraw 62 | if a:context.input != '' 63 | let input = a:context.input 64 | call s:refresh(input, a:context.winheight) 65 | let a:context.is_async = 1 66 | endif 67 | endif 68 | return s:candidates 69 | endfunction 70 | 71 | function! s:unite_source.async_gather_candidates(args, context) 72 | if unite#libs#uri#show_icon(1, a:context, s:candidates) 73 | let a:context.is_async = 0 74 | endif 75 | return [] 76 | endfunction 77 | 78 | function! s:http_get(input, number) 79 | let param = { 80 | \ "q": a:input, 81 | \ "per_page": a:number } 82 | let res = webapi#http#get("https://api.github.com/search/repositories", param) 83 | if res.status != '200' 84 | echom 'http error code:'.res.status 85 | return [] 86 | endif 87 | let content = webapi#json#decode(res.content) 88 | if !has_key(content, 'items') 89 | return [] 90 | endif 91 | return map(content.items, 's:extract_entry(v:val)') 92 | endfunction 93 | 94 | function! s:extract_entry(dict) 95 | return { 96 | \ 'action__id' : a:dict.owner.id, 97 | \ 'action__icon' : a:dict.owner.avatar_url, 98 | \ 'word' : a:dict.full_name, 99 | \ 'action__uri' : a:dict.html_url, 100 | \ 'kind' : 'uri', 101 | \ 'source' : 'github/search' 102 | \ } 103 | 104 | endfunction 105 | 106 | function! s:refresh(input, limit) 107 | call unite#print_source_message('Fetching repos info from the server ...', 108 | \ s:unite_source.name) 109 | let s:candidates = s:http_get(a:input, a:limit) 110 | call unite#clear_message() 111 | endfunction 112 | 113 | function! unite#sources#github_search#define() 114 | return s:unite_source 115 | endfunction 116 | 117 | let &cpo = s:save_cpo 118 | unlet s:save_cpo 119 | -------------------------------------------------------------------------------- /autoload/unite/sources/music163.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:url_pre = 'http://music.163.com/' 6 | let s:unite_source = { 7 | \ 'name' : 'music163', 8 | \ 'description' : '网易云音乐搜索', 9 | \ 'hooks' : {}, 10 | \ 'syntax' : 'uniteSource__music163' 11 | \ } 12 | 13 | function! s:unite_source.hooks.on_init(args, context) 14 | let input = get(a:args, 0, '') 15 | let input = input != '' ? input : 16 | \ unite#util#input('Search for songs: ', '') 17 | call s:refresh(input) 18 | endfunction 19 | 20 | function! s:unite_source.hooks.on_syntax(args, context) 21 | syntax match uniteSource__music163_artists /.*\ze\s\+--/ 22 | \ contained containedin=uniteSource__music163 23 | syntax match uniteSource__music163_album /【.\{-}】/ 24 | \ contained containedin=uniteSource__music163 25 | \ contained containedin=uniteSource__music163 26 | highlight default link uniteSource__music163_artists Constant 27 | highlight default link uniteSource__music163_album String 28 | endfunction 29 | 30 | function! s:unite_source.gather_candidates(args, context) 31 | if a:context.is_redraw 32 | if a:context.input != '' 33 | let input = a:context.input 34 | call s:refresh(input) 35 | endif 36 | endif 37 | return s:candidates 38 | endfunction 39 | 40 | function! s:http_get(input) 41 | let param = { 42 | \ 's' : a:input, 43 | \ 'limit' : 20, 44 | \ 'type' : 1, 45 | \ 'offset' : 0 46 | \ } 47 | 48 | let header = { 49 | \ 'Host' : 'music.163.com', 50 | \ 'Referer' : s:url_pre.'search' 51 | \ } 52 | 53 | let res = webapi#http#post(s:url_pre.'api/search/get', param, header) 54 | if res.status != '200' 55 | echom 'http error code:'.res.status 56 | return [] 57 | endif 58 | let content = webapi#json#decode(res.content) 59 | if !has_key(content, 'result') || !has_key(content.result, 'songs') 60 | return [] 61 | endif 62 | return map(content.result.songs, 's:extract_entry(v:val)') 63 | endfunction 64 | 65 | function! s:extract_entry(dict) 66 | let album = a:dict.album.name 67 | let artists = join(map(a:dict.artists, 'v:val.name'), '/') 68 | return { 69 | \ 'word' : artists.' -- 【'.album.'】 '.a:dict.name, 70 | \ 'action__uri' : s:url_pre.'#/song?id='.a:dict.id, 71 | \ 'kind' : 'media', 72 | \ 'source' : 'music163'} 73 | endfunction 74 | 75 | function! s:refresh(input) 76 | call unite#print_source_message('Searching ...', 'music163') 77 | let s:candidates = s:http_get(a:input) 78 | call unite#clear_message() 79 | endfunction 80 | 81 | function! unite#sources#music163#define() 82 | return s:unite_source 83 | endfunction 84 | 85 | let &cpo = s:save_cpo 86 | unlet s:save_cpo 87 | -------------------------------------------------------------------------------- /autoload/unite/sources/reddit.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'reddit', 7 | \ 'description' : 'Latest topics from http://www.reddit.com', 8 | \ 'hooks' : {}, 9 | \ 'syntax' : 'uniteSource__reddit' 10 | \ } 11 | 12 | function! s:unite_source.hooks.on_init(args, context) 13 | call s:refresh(a:args) 14 | endfunction 15 | 16 | function! s:unite_source.hooks.on_syntax(args, context) 17 | syntax match uniteSource__reddit_subreddit /.\{-}\ze----/ 18 | \ contained containedin=uniteSource__reddit_title 19 | syntax match uniteSource__reddit_title /.*/ 20 | \ contained containedin=uniteSource__reddit 21 | \ contains=uniteCandidateInputKeyword,uniteSource__reddit_subreddit 22 | highlight default link uniteSource__reddit_subreddit Constant 23 | highlight default link uniteSource__reddit_title String 24 | endfunction 25 | 26 | function! s:unite_source.gather_candidates(args, context) 27 | if a:context.is_redraw 28 | call s:refresh(a:args) 29 | endif 30 | return s:candidates 31 | endfunction 32 | 33 | function! s:http_get(url) 34 | let res = webapi#http#get(a:url) 35 | if res.status != '200' 36 | echom 'http error code:'.res.status 37 | return [] 38 | endif 39 | let content = webapi#json#decode(res.content) 40 | return map(content.data.children, 's:extract_entry(v:val)') 41 | endfunction 42 | 43 | function! s:refresh(args) 44 | let subreddit = get(a:args, 0, '') 45 | let url_pre = 'http://www.reddit.com' 46 | call unite#print_source_message('Fetching feeds from the server ...', 47 | \ s:unite_source.name) 48 | if subreddit != '' 49 | let url = url_pre.'/r/'.subreddit.'/hot.json' 50 | else 51 | let url = get(g:, 'unite#workflow#reddit#front', url_pre.'/hot.json') 52 | endif 53 | let s:candidates = s:http_get(url) 54 | call unite#clear_message() 55 | endfunction 56 | 57 | function! s:extract_entry(dict) 58 | return { 59 | \ 'word' : a:dict.data.subreddit.' ---- '.a:dict.data.title, 60 | \ 'action__uri' : 'http://www.reddit.com/'.a:dict.data.permalink, 61 | \ 'kind' : 'uri', 62 | \ 'source' : 'reddit' 63 | \ } 64 | 65 | endfunction 66 | 67 | function! unite#sources#reddit#define() 68 | return s:unite_source 69 | endfunction 70 | 71 | let &cpo = s:save_cpo 72 | unlet s:save_cpo 73 | -------------------------------------------------------------------------------- /autoload/unite/sources/toilet.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'toilet', 7 | \ 'description' : 'Ascii art.', 8 | \ 'hooks' : {}, 9 | \ } 10 | 11 | function! s:unite_source.hooks.on_init(args, context) 12 | let input = get(a:args, 0, '') 13 | let input = input != '' ? input : 14 | \ unite#util#input('String to convert: ', '') 15 | call s:get_candidates(input) 16 | endfunction 17 | 18 | function! s:unite_source.gather_candidates(args, context) 19 | if a:context.is_redraw 20 | if a:context.input != '' 21 | let input = a:context.input 22 | call s:get_candidates(input) 23 | endif 24 | endif 25 | return s:candidates 26 | endfunction 27 | 28 | function! s:get_candidates(input) 29 | let candidates = [] 30 | let g:unite#workflow#figlet_fonts#dir = get(g:, 'unite#workflow#figlet_fonts#dir', '/usr/share/figlet') 31 | let fonts = split( 32 | \ unite#util#system( 33 | \ 'find '.g:unite#workflow#figlet_fonts#dir." -name '*.tlf'"), 34 | \ '\n') 35 | let fonts = map(fonts, 'split(v:val, "/")[-1]') 36 | for font in fonts 37 | call add(candidates, { 38 | \ 'word' : unite#util#system(printf(s:command, font, a:input)), 39 | \ 'kind' : 'word', 40 | \ 'is_multiline' : 1, 41 | \ 'source' : 'toilet' 42 | \ }) 43 | endfor 44 | let s:candidates = candidates 45 | endfunction 46 | 47 | function! unite#sources#toilet#define() 48 | if !has('unix') || !executable('find') 49 | return [] 50 | elseif executable('toilet') 51 | let s:command = 'toilet -w 999 -f %s %s' 52 | elseif executable('figlet') 53 | let s:command = 'figlet -w 999 f %s %s' 54 | else 55 | return [] 56 | endif 57 | return s:unite_source 58 | endfunction 59 | 60 | let &cpo = s:save_cpo 61 | unlet s:save_cpo 62 | -------------------------------------------------------------------------------- /autoload/unite/sources/turing.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'turing', 7 | \ 'description' : 'Turing robot', 8 | \ 'action_table' : {}, 9 | \ 'hooks' : {}, 10 | \ } 11 | 12 | let s:unite_source.action_table.insert = { 13 | \ 'description' : 'Reply to the bot.', 14 | \ 'is_quit' : 1 15 | \ } 16 | 17 | function! s:unite_source.action_table.insert.func(candidate) 18 | call unite#start(['turing']) 19 | endfunction 20 | 21 | 22 | function! s:unite_source.hooks.on_init(args, context) 23 | let input = get(a:args, 0, '') 24 | let input = input != '' ? input : 25 | \ unite#util#input('Conversation: ', '') 26 | call s:refresh(input) 27 | endfunction 28 | 29 | function! s:unite_source.gather_candidates(args, context) 30 | return s:candidates 31 | endfunction 32 | 33 | function! s:http_get(input) 34 | let param = { 35 | \ 'key' : '47ab88116e493791a0d4850de55b6ded', 36 | \ 'info' : a:input 37 | \ } 38 | let res = webapi#http#get('http://www.tuling123.com/openapi/api', param) 39 | if res.status != '200' 40 | echom 'http error code:'.res.status 41 | return [] 42 | endif 43 | let content = webapi#json#decode(res.content) 44 | if has_key(content, 'list') 45 | return map(content.list, 's:extract_entry(v:val)') 46 | endif 47 | let result = { 48 | \ 'word' : content.text, 49 | \ 'kind' : 'word', 50 | \ 'is_multiline' : 1, 51 | \ 'source' : 'turing' 52 | \ } 53 | if has_key(content, 'url') 54 | let result.word .= ' 🔗 ' 55 | let result.kind = 'uri' 56 | let result.action__uri = content.url 57 | endif 58 | return [result] 59 | endfunction 60 | 61 | function! s:extract_entry(dict) 62 | return { 63 | \ 'word' : get(a:dict, 'article', get(a:dict, 'name', 'unknown')), 64 | \ 'kind' : 'uri', 65 | \ 'action__uri' : get(a:dict, 'detailurl', 'http://www.tuling123.com'), 66 | \ 'source' : 'turing' 67 | \ } 68 | endfunction 69 | 70 | function! s:refresh(input) 71 | call unite#print_source_message('Getting response ...', 'turing') 72 | let s:candidates = s:http_get(a:input) 73 | call unite#clear_message() 74 | endfunction 75 | 76 | function! unite#sources#turing#define() 77 | return s:unite_source 78 | endfunction 79 | 80 | let &cpo = s:save_cpo 81 | unlet s:save_cpo 82 | 83 | -------------------------------------------------------------------------------- /autoload/unite/sources/twitter.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:dict = expand(':p:h').'/../libs/emoji.dict' 6 | let s:unite_source = { 7 | \ 'name' : 'twitter', 8 | \ 'description' : 'twitter timeline.', 9 | \ 'hooks' : {}, 10 | \ 'action_table': {}, 11 | \ 'syntax' : 'uniteSource__twitter' 12 | \ } 13 | 14 | let s:unite_source.action_table.tweet = { 15 | \ 'description' : 'Create a new tweet.', 16 | \ 'is_quit' : 0 17 | \ } 18 | 19 | function! s:unite_source.action_table.tweet.func(candidate) 20 | call s:http_post('new', a:candidate) 21 | endfunction 22 | 23 | let s:unite_source.action_table.reply = { 24 | \ 'description' : 'Reply to a tweet.', 25 | \ 'is_quit' : 0 26 | \ } 27 | 28 | let s:unite_source.action_table.user = { 29 | \ 'description' : 'Tweets from the same user.' 30 | \ } 31 | 32 | function! s:unite_source.action_table.user.func(candidate) 33 | call unite#start([['twitter', a:candidate.action__user]]) 34 | endfunction 35 | 36 | function! s:unite_source.action_table.reply.func(candidate) 37 | call s:http_post('reply', a:candidate) 38 | endfunction 39 | 40 | let s:unite_source.action_table.retweet = { 41 | \ 'description' : 'Retweet.', 42 | \ 'is_quit' : 0 43 | \ } 44 | 45 | function! s:unite_source.action_table.retweet.func(candidate) 46 | call s:http_post('retweet', a:candidate) 47 | endfunction 48 | 49 | let s:unite_source.action_table.favorite = { 50 | \ 'description' : 'Favorite a tweet.', 51 | \ 'is_quit' : 0 52 | \ } 53 | 54 | function! s:unite_source.action_table.favorite.func(candidate) 55 | call s:http_post('favorite', a:candidate) 56 | endfunction 57 | 58 | function! s:http_post(action, candidate) 59 | if !exists('s:ctx') 60 | return 61 | endif 62 | 63 | let api_url = 'https://api.twitter.com/1.1/' 64 | let url = api_url.'statuses/update.json' 65 | if a:action == 'reply' 66 | let param = { 67 | \ 'status' : unite#util#input('text:', '@'.a:candidate.action__user.' '), 68 | \ 'in_reply_to_status_id' : a:candidate.action__uid, 69 | \ 'trim_user' : 1 70 | \ } 71 | elseif a:action == 'new' 72 | let param = { 73 | \ 'status' : unite#util#input('text:', ''), 74 | \ 'trim_user' : 1 75 | \ } 76 | elseif a:action == 'retweet' 77 | let param = { 78 | \ 'trim_user' : 1 79 | \ } 80 | let url = api_url.'statuses/retweet/'.a:candidate.action__uid.'.json' 81 | elseif a:action == 'favorite' 82 | let param = { 83 | \ 'id' : a:candidate.action__uid, 84 | \ 'include_entities' : 'false' 85 | \ } 86 | let url = api_url.'/favorites/create.json' 87 | endif 88 | 89 | let ret = webapi#oauth#post(url, s:ctx, {}, param) 90 | if ret.status == '200' 91 | redraw 92 | echo 'Done!. Press to refresh.' 93 | else 94 | echom 'http error code:'.ret.status 95 | endif 96 | endfunction 97 | 98 | function! s:unite_source.hooks.on_init(args, context) 99 | let s:input = get(a:args, 0, '') 100 | call s:refresh(a:context.winheight) 101 | endfunction 102 | 103 | function! s:unite_source.hooks.on_close(args, context) 104 | call unite#libs#uri#clear_sign() 105 | endfunction 106 | 107 | function! s:unite_source.hooks.on_syntax(args, context) 108 | syntax match uniteSource__twitter_user /.*\ze::/ 109 | \ contained containedin=uniteSource__twitter 110 | \ contains=uniteSource__twitter_status 111 | syntax match uniteSource__twitter_status /【.\{-}】/ 112 | \ contained containedin=uniteSource__twitter_user 113 | highlight default link uniteSource__twitter_user Constant 114 | highlight default link uniteSource__twitter_status Keyword 115 | endfunction 116 | 117 | function! s:unite_source.hooks.on_post_filter(args, context) 118 | let s:context = a:context 119 | augroup workflow_icon 120 | autocmd! TextChanged,TextChangedI 121 | \ call unite#libs#uri#show_icon(0, s:context, s:context.candidates) 122 | augroup END 123 | endfunction 124 | 125 | function! s:unite_source.gather_candidates(args, context) 126 | if a:context.is_redraw 127 | let s:input = get(a:args, 0, '') 128 | call s:refresh(a:context.winheight) 129 | let a:context.is_async = 1 130 | endif 131 | return s:candidates 132 | endfunction 133 | 134 | function! s:unite_source.async_gather_candidates(args, context) 135 | if unite#libs#uri#show_icon(1, a:context, s:candidates) 136 | let a:context.is_async = 0 137 | endif 138 | return [] 139 | endfunction 140 | 141 | function! s:http_get(number) 142 | let ctx = {} 143 | let config_dir = unite#get_data_directory().'/twitter' 144 | if !isdirectory(config_dir) 145 | call mkdir(config_dir, 'p') 146 | endif 147 | let configfile = config_dir.'/auth.json' 148 | if filereadable(configfile) 149 | let s:ctx = eval(join(readfile(configfile), "")) 150 | else 151 | let ctx.consumer_key = '56CsnzxEQVfnyOZxd2Cl2oPnn' 152 | let ctx.consumer_secret = '5HwtGeeRNP4mPNwjG4fxVNSIL4tFLJxOjRyjVqG3bjZq4H8qq7' 153 | 154 | let request_token_url = 'https://twitter.com/oauth/request_token' 155 | let auth_url = 'https://twitter.com/oauth/authorize' 156 | let access_token_url = 'https://api.twitter.com/oauth/access_token' 157 | 158 | let ctx = webapi#oauth#request_token(request_token_url, ctx) 159 | let redir_url = auth_url.'?oauth_token='.ctx.request_token 160 | if has('win32') || has('win64') 161 | exe '!start rundll32 url.dll,FileProtocolHandler '.redir_url 162 | elseif executable('xdg-open') 163 | call system("xdg-open '".redir_url."'") 164 | elseif executable('open') 165 | call system("open '".redir_url."'") 166 | else 167 | return [] 168 | endif 169 | let pin = input('PIN:') 170 | let s:ctx = webapi#oauth#access_token(access_token_url, ctx, {'oauth_verifier': pin}) 171 | call writefile([string(s:ctx)], configfile) 172 | endif 173 | 174 | let url_pre = 'https://api.twitter.com/1.1/statuses/' 175 | let param = { 176 | \ 'count' : a:number 177 | \ } 178 | if s:input == '' 179 | let url = url_pre.'home_timeline.json' 180 | else 181 | let url = url_pre.'user_timeline.json' 182 | let param.screen_name = s:input 183 | endif 184 | let ret = webapi#oauth#get(url, s:ctx, {}, param) 185 | let content = webapi#json#decode( 186 | \ substitute(ret.content, 187 | \ '\\u\(d\x\{3}\)\\u\(d\x\{3}\)', 188 | \ '\=s:from_surrogates(submatch(1), submatch(2))', 189 | \ 'g') 190 | \ ) 191 | if type(content) != 3 192 | return [] 193 | endif 194 | return map(content, 's:extract_entry(v:val)') 195 | endfunction 196 | 197 | function! s:from_surrogates(high, low) 198 | let high = str2nr(a:high, 16) - 55296 199 | let low = str2nr(a:low, 16) - 56320 200 | let code = printf('&#x%04x;', 65536 + 1024*high + low) 201 | let lines = readfile(s:dict) 202 | call filter(lines, 'v:val =~ "'.code.'"') 203 | return len(lines) > 0 ? lines[0][0:4] : '' 204 | endfunction 205 | 206 | function! s:extract_entry(dict) 207 | let deco = '' 208 | let deco .= a:dict.favorited? '★ ' : '☆ ' 209 | let deco .= a:dict.favorite_count.',' 210 | let deco .= a:dict.retweeted? '♻ ' : '♲ ' 211 | let deco .= a:dict.retweet_count 212 | let url = matchstr(a:dict.text, '[a-z]*:\/\/[^ >,;]*') 213 | let url = url == '' ? 'https://twitter.com' : url 214 | let text = substitute(a:dict.text, '[a-z]*:\/\/[^ >,;]*', '🔗', 'g') 215 | return { 216 | \ 'action__id' : a:dict.user.id, 217 | \ 'action__icon' : a:dict.user.profile_image_url, 218 | \ 'word' : '【'.deco.'】'.a:dict.user.name.'::'.text, 219 | \ 'action__uri' : url, 220 | \ 'action__uid' : a:dict.id_str, 221 | \ 'action__user' : a:dict.user.screen_name, 222 | \ 'kind' : 'uri', 223 | \ 'source' : 'twitter' 224 | \ } 225 | 226 | endfunction 227 | 228 | function! s:refresh(limit) 229 | call unite#print_source_message('Getting tweets ...', 230 | \ s:unite_source.name) 231 | let s:candidates = s:http_get(a:limit) 232 | call unite#clear_message() 233 | endfunction 234 | 235 | function! unite#sources#twitter#define() 236 | return s:unite_source 237 | endfunction 238 | 239 | let &cpo = s:save_cpo 240 | unlet s:save_cpo 241 | -------------------------------------------------------------------------------- /autoload/unite/sources/v2ex.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'v2ex', 7 | \ 'description' : 'Latest topics from http://www.v2ex.com', 8 | \ 'hooks' : {}, 9 | \ 'syntax' : 'uniteSource__v2ex' 10 | \ } 11 | 12 | function! unite#sources#v2ex#define() 13 | return s:unite_source 14 | endfunction 15 | 16 | function! s:unite_source.hooks.on_init(args, context) 17 | call s:refresh() 18 | endfunction 19 | 20 | function! s:unite_source.hooks.on_close(args, context) 21 | call unite#libs#uri#clear_sign() 22 | endfunction 23 | 24 | function! s:unite_source.hooks.on_syntax(args, context) 25 | syntax match uniteSource__v2ex_node /.\{-}\ze----/ 26 | \ contained containedin=uniteSource__v2ex_title 27 | syntax match uniteSource__v2ex_title /.*/ 28 | \ contained containedin=uniteSource__v2ex 29 | \ contains=uniteCandidateInputKeyword,uniteSource__v2ex_node 30 | highlight default link uniteSource__v2ex_node Constant 31 | highlight default link uniteSource__v2ex_title String 32 | endfunction 33 | 34 | function! s:unite_source.hooks.on_post_filter(args, context) 35 | let s:context = a:context 36 | augroup workflow_icon 37 | autocmd! TextChanged,TextChangedI 38 | \ call unite#libs#uri#show_icon(0, s:context, s:context.candidates) 39 | augroup END 40 | endfunction 41 | 42 | function! s:unite_source.gather_candidates(args, context) 43 | if a:context.is_redraw 44 | call s:refresh() 45 | let a:context.is_async = 1 46 | endif 47 | return s:candidates 48 | endfunction 49 | 50 | function! s:unite_source.async_gather_candidates(args, context) 51 | if unite#libs#uri#show_icon(1, a:context, s:candidates) 52 | let a:context.is_async = 0 53 | endif 54 | return [] 55 | endfunction 56 | 57 | function! s:refresh() 58 | call unite#print_source_message('Fetching latest feeds from the server ...', 'v2ex') 59 | let s:candidates = s:http_get() 60 | call unite#clear_message() 61 | endfunction 62 | 63 | function! s:http_get() 64 | let res = webapi#http#get('http://v2ex.com/api/topics/latest.json') 65 | if res.status != '200' 66 | echom 'http error code:'.res.status 67 | return [] 68 | endif 69 | let content = webapi#json#decode(res.content) 70 | return map(content, 's:extract_entry(v:val)') 71 | endfunction 72 | 73 | function! s:extract_entry(dict) 74 | let icon_raw = a:dict.member.avatar_mini 75 | let icon_url = icon_raw =~ '^\/\/' ? '"http:'.icon_raw.'"' : '"'.icon_raw.'"' 76 | return { 77 | \ 'action__id' : a:dict.member.id, 78 | \ 'action__icon' : icon_url, 79 | \ 'action__uri' : a:dict.url, 80 | \ 'node' : a:dict.node.id, 81 | \ 'word' : a:dict.node.title.' ---- '.a:dict.title, 82 | \ 'kind' : 'uri', 83 | \ 'source' : 'v2ex'} 84 | endfunction 85 | 86 | let &cpo = s:save_cpo 87 | unlet s:save_cpo 88 | -------------------------------------------------------------------------------- /autoload/unite/sources/wikipedia.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'wikipedia', 7 | \ 'description' : 'wikipedia search.', 8 | \ 'hooks' : {}, 9 | \ } 10 | 11 | function! s:unite_source.hooks.on_init(args, context) 12 | let input = get(a:args, 0, '') 13 | let input = input != '' ? input : 14 | \ unite#util#input('Searching keyword: ', '') 15 | call unite#print_source_message('Searching ...', 'wikipedia') 16 | let s:candidates = s:http_get(input) 17 | call unite#clear_message() 18 | endfunction 19 | 20 | function! s:unite_source.gather_candidates(args, context) 21 | if a:context.is_redraw 22 | let s:candidates = s:http_get(a:context.input) 23 | endif 24 | return s:candidates 25 | endfunction 26 | 27 | function! s:http_get(input) 28 | let param = { 29 | \ 'format' : 'json', 30 | \ 'action' : 'opensearch', 31 | \ 'search' : a:input 32 | \ } 33 | let res = webapi#http#get('http://en.wikipedia.org/w/api.php', param) 34 | if res.status != '200' 35 | echom 'http error code:'.res.status 36 | return [] 37 | endif 38 | let content = webapi#json#decode(res.content) 39 | return map(content[1], 's:extract_entry(v:val)') 40 | endfunction 41 | 42 | function! s:extract_entry(word) 43 | return { 44 | \ 'word' : a:word, 45 | \ 'kind' : 'uri', 46 | \ 'action__uri' : 'http://en.wikipedia.com/wiki/'.substitute(a:word, '\s', '_', 'g'), 47 | \ 'source' : 'wikipedia'} 48 | endfunction 49 | 50 | function! unite#sources#wikipedia#define() 51 | return s:unite_source 52 | endfunction 53 | 54 | let &cpo = s:save_cpo 55 | unlet s:save_cpo 56 | -------------------------------------------------------------------------------- /autoload/unite/sources/youdao.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'youdao', 7 | \ 'description' : '有道词典', 8 | \ 'hooks' : {}, 9 | \ 'syntax' : 'uniteSource__youdao' 10 | \ } 11 | 12 | function! s:unite_source.hooks.on_init(args, context) 13 | let input = get(a:args, 0, '') 14 | let input = input != '' ? input : 15 | \ unite#util#input('Phrase to translate: ', '') 16 | let s:input = input == '' ? 'Invalid input' : input 17 | call s:refresh() 18 | endfunction 19 | 20 | function! s:unite_source.hooks.on_syntax(args, context) 21 | syntax match uniteSource__youdao_kw /Translation:\|Explanation:\|Phonetic:\|Query:/ 22 | \ contained containedin=uniteSource__youdao 23 | syntax match uniteSource__youdao_ph /\[.*\]/ 24 | \ contained containedin=uniteSource__youdao 25 | syntax match uniteSource__youdao_pos /*\s\zs\w\+\./ 26 | \ contained containedin=uniteSource__youdao 27 | highlight default link uniteSource__youdao_kw Keyword 28 | highlight default link uniteSource__youdao_ph Todo 29 | highlight default link uniteSource__youdao_pos Constant 30 | endfunction 31 | 32 | function! s:unite_source.gather_candidates(args, context) 33 | if a:context.is_redraw 34 | if a:context.input != '' 35 | let s:input = a:context.input 36 | call s:refresh() 37 | endif 38 | endif 39 | return s:candidates 40 | endfunction 41 | 42 | function! s:http_get(input) 43 | let param = { 44 | \ 'q' : a:input, 45 | \ 'keyfrom' : 'vim-workflow', 46 | \ 'key' : '1290268654', 47 | \ 'type' : 'data', 48 | \ 'doctype' : 'json', 49 | \ 'version' : '1.1' 50 | \ } 51 | let res = webapi#http#get('http://fanyi.youdao.com/openapi.do', param) 52 | if res.status != '200' 53 | echom 'http error code:'.res.status 54 | return [] 55 | endif 56 | let content = webapi#json#decode(res.content) 57 | return [s:extract_entry(content)] 58 | endfunction 59 | 60 | function! s:extract_entry(dict) 61 | let basic = get(a:dict, 'basic', {}) 62 | let translation = ' '.get(a:dict, 'translation', [''])[0] 63 | let phonetic = ' ['.get(basic, 'phonetic', '').']' 64 | let explanation = join(map(get(basic, 'explains', []), '" * ".v:val'), "\n") 65 | return { 66 | \ 'word' : join([ 67 | \ 'Query:', ' '.s:input, 68 | \ 'Translation:', translation, 69 | \ 'Phonetic:', phonetic, 70 | \ 'Explanation:', explanation], 71 | \ "\n"), 72 | \ 'kind' : 'word', 73 | \ 'is_multiline' : 1, 74 | \ 'source' : 'youdao'} 75 | endfunction 76 | 77 | function! s:refresh() 78 | call unite#print_source_message('Translating ...', 'youdao') 79 | let s:candidates = s:http_get(s:input) 80 | call unite#clear_message() 81 | endfunction 82 | 83 | function! unite#sources#youdao#define() 84 | return s:unite_source 85 | endfunction 86 | 87 | let &cpo = s:save_cpo 88 | unlet s:save_cpo 89 | -------------------------------------------------------------------------------- /autoload/unite/sources/youtube.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'youtube', 7 | \ 'description' : 'youtube search.', 8 | \ 'hooks' : {}, 9 | \ 'syntax' : 'uniteSource__youtube' 10 | \ } 11 | 12 | function! s:unite_source.hooks.on_init(args, context) 13 | let input = get(a:args, 0, '') 14 | let input = input != '' ? input : 15 | \ unite#util#input('Searching keyword: ', '') 16 | call s:refresh(input) 17 | endfunction 18 | 19 | function! s:unite_source.hooks.on_syntax(args, context) 20 | syntax match uniteSource__youtube_kind /video\|channel\|playlist/ 21 | \ contained containedin=uniteSource__youtube 22 | syntax match uniteSource__youtube_channel /【.*】/ 23 | \ contained containedin=uniteSource__youtube 24 | highlight default link uniteSource__youtube_kind Constant 25 | highlight default link uniteSource__youtube_channel Keyword 26 | endfunction 27 | 28 | function! s:unite_source.gather_candidates(args, context) 29 | if a:context.is_redraw 30 | if a:context.input != '' 31 | let input = a:context.input 32 | call s:refresh(input) 33 | endif 34 | endif 35 | return s:candidates 36 | endfunction 37 | 38 | function! s:http_get(input) 39 | let param = { 40 | \ 'key' : 'AIzaSyAATDG2sY41TYQyH_tN5S-styaWT9kouDM', 41 | \ 'part' : 'snippet', 42 | \ 'maxResults' : 15, 43 | \ 'q' : a:input 44 | \ } 45 | let res = webapi#http#get('https://www.googleapis.com/youtube/v3/search', param) 46 | if res.status != '200' 47 | echom 'http error code:'.res.status 48 | return [] 49 | endif 50 | let content = webapi#json#decode(res.content) 51 | if !has_key(content, 'items') 52 | return [] 53 | endif 54 | return map(content.items, 's:extract_entry(v:val)') 55 | endfunction 56 | 57 | function! s:extract_entry(dict) 58 | let html_pre = 'https://www.youtube.com/' 59 | let title = a:dict.snippet.title 60 | let channel = a:dict.snippet.channelTitle 61 | let channel = channel == '' ? 'Unknown' : channel 62 | let kind = split(a:dict.id.kind, '#')[1] 63 | 64 | if kind == 'video' 65 | let uri = html_pre.'watch?v='.a:dict.id.videoId 66 | elseif kind == 'channel' 67 | let uri = html_pre.'channel/'.a:dict.id.channelId 68 | elseif kind == 'playlist' 69 | let uri = html_pre.'/playlist?list='.a:dict.id.playlistId 70 | else 71 | let uri = html_pre 72 | endif 73 | 74 | return { 75 | \ 'word' : kind.' -- 【'.channel.'】 -- '.title, 76 | \ 'kind' : 'media', 77 | \ 'action__uri' : uri, 78 | \ 'source' : 'youtube'} 79 | endfunction 80 | 81 | function! s:refresh(input) 82 | call unite#print_source_message('Searching ...', 'youtube') 83 | let s:candidates = s:http_get(a:input) 84 | call unite#clear_message() 85 | endfunction 86 | 87 | function! unite#sources#youtube#define() 88 | return s:unite_source 89 | endfunction 90 | 91 | let &cpo = s:save_cpo 92 | unlet s:save_cpo 93 | -------------------------------------------------------------------------------- /autoload/unite/sources/zhihu.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:candidates = [] 5 | let s:unite_source = { 6 | \ 'name' : 'zhihu', 7 | \ 'description' : '知乎日报', 8 | \ 'hooks' : {}, 9 | \ } 10 | 11 | function! s:unite_source.hooks.on_init(args, context) 12 | call s:refresh(a:args) 13 | endfunction 14 | 15 | function! s:unite_source.gather_candidates(args, context) 16 | if a:context.is_redraw 17 | call s:refresh(a:args) 18 | endif 19 | return s:candidates 20 | endfunction 21 | 22 | function! s:http_get(url) 23 | let res = webapi#http#get(a:url) 24 | if res.status != '200' 25 | echom 'http error code:'.res.status 26 | return [] 27 | endif 28 | let content = webapi#json#decode(res.content) 29 | return map(content.stories, 's:extract_entry(v:val)') 30 | endfunction 31 | 32 | function! s:refresh(args) 33 | call unite#print_source_message('获取日报 ...', 34 | \ s:unite_source.name) 35 | let s:candidates = s:http_get('http://news-at.zhihu.com/api/3/news/latest') 36 | call unite#clear_message() 37 | endfunction 38 | 39 | function! s:extract_entry(dict) 40 | return { 41 | \ 'word' : a:dict.title, 42 | \ 'action__uri' : 'http://daily.zhihu.com/story/'.a:dict.id, 43 | \ 'kind' : 'uri', 44 | \ 'source' : 'zhihu' 45 | \ } 46 | 47 | endfunction 48 | 49 | function! unite#sources#zhihu#define() 50 | return s:unite_source 51 | endfunction 52 | 53 | let &cpo = s:save_cpo 54 | unlet s:save_cpo 55 | -------------------------------------------------------------------------------- /plugin/workflow.vim: -------------------------------------------------------------------------------- 1 | let g:unite#workflow#show_icon = get(g:, 'unite#workflow#show_icon', 1) 2 | let g:github_user = get(g:, 'github_user', system('git config --get github.user')[:-2]) 3 | if strlen(g:github_user) == 0 4 | let g:github_user = $GITHUB_USER 5 | endif 6 | -------------------------------------------------------------------------------- /screenshots/apropos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/apropos.png -------------------------------------------------------------------------------- /screenshots/douban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/douban.png -------------------------------------------------------------------------------- /screenshots/dropbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/dropbox.png -------------------------------------------------------------------------------- /screenshots/emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/emoji.png -------------------------------------------------------------------------------- /screenshots/gist_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/gist_user.png -------------------------------------------------------------------------------- /screenshots/github_event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/github_event.png -------------------------------------------------------------------------------- /screenshots/github_issue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/github_issue.png -------------------------------------------------------------------------------- /screenshots/music163.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/music163.png -------------------------------------------------------------------------------- /screenshots/reddit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/reddit.png -------------------------------------------------------------------------------- /screenshots/toilet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/toilet.png -------------------------------------------------------------------------------- /screenshots/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/twitter.png -------------------------------------------------------------------------------- /screenshots/v2ex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/v2ex.png -------------------------------------------------------------------------------- /screenshots/youdao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blindFS/unite-workflow/bba13ee82dccf106631171cbda35eb405455e930/screenshots/youdao.png -------------------------------------------------------------------------------- /t/douban_book.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'douban book' 4 | it 'douban book' 5 | Unite douban/book:gintama 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/douban_movie.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'douban movie' 4 | it 'douban movie' 5 | Unite douban/movie:gintama 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/douban_music.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'douban music' 4 | it 'douban music' 5 | Unite douban/music:gintama 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/github_search.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'github test' 4 | it 'github search' 5 | Unite github/search:unite.vim 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/music163.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'music163' 4 | it 'music163' 5 | Unite music163:rock 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/pre.vim: -------------------------------------------------------------------------------- 1 | runtime plugin/unite.vim 2 | -------------------------------------------------------------------------------- /t/reddit.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'reddit' 4 | it 'subreddit' 5 | Unite reddit:vim 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/turing.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'turing' 4 | it 'turing robot' 5 | Unite turing:来点新闻 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/v2ex.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'v2ex' 4 | it 'v2ex' 5 | Unite v2ex 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/wikipedia.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'wikipedia' 4 | it 'wikipedia search' 5 | Unite youtube:vim 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/youdao.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'youdao' 4 | it 'youdao dictionary' 5 | Unite youdao:vim 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/youtube.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'youtube' 4 | it 'youtube search' 5 | Unite youtube:vim 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /t/zhihu.vim: -------------------------------------------------------------------------------- 1 | source t/pre.vim 2 | 3 | describe 'zhihu' 4 | it 'zhihu daily' 5 | Unite zhihu 6 | Expect line('$') > 1 7 | normal q 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /vimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | set rtp+=./ 3 | set rtp+=./.vim-flavor/deps/blindFS_unite.vim/ 4 | set rtp+=./.vim-flavor/deps/mattn_webapi-vim/ 5 | --------------------------------------------------------------------------------