-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
1312 lines (799 loc) · 78.4 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
<!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
<head>
<meta charset="utf-8">
<title>尹良灿得闲</title>
<meta name="author" content="wenLiangcan">
<meta name="description" content="原文:ArcadeRS 1.1: A simple window 本系列文章的目是通过开发一个简单的老式射击游戏来一探 Rust 这门语言,这是其中的第一部分。除去介绍,本系列共有 16 个部分组成: 一个简单的窗口,我们在此安装 SDL2
事件处理,我们在此讨论生存期限
处理更多的事件, …">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="http://wenLiangcan.github.io">
<link href="/favicon.png" rel="icon">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
<link href="http://feeds.feedburner.com/wenLiangcan" rel="alternate" title="尹良灿得闲" type="application/atom+xml">
<script src="/javascripts/modernizr-2.0.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="./javascripts/lib/jquery.min.js"%3E%3C/script%3E'))</script>
<script src="/javascripts/octopress.js" type="text/javascript"></script>
<!--Fonts from Google"s Web font directory at http://google.com/webfonts -->
<link href="http://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
<link href="http://fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-40394985-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body >
<header role="banner"><hgroup>
<h1><a href="/">尹良灿得闲</a></h1>
<h2>巴甫洛夫很忙……巴甫洛夫正在死亡</h2>
</hgroup>
</header>
<nav role="navigation"><ul class="subscription" data-subscription="rss">
<li><a href="http://feeds.feedburner.com/wenLiangcan" rel="subscribe-rss" title="subscribe via RSS">RSS</a></li>
</ul>
<form action="http://google.com/search" method="get">
<fieldset role="search">
<input type="hidden" name="q" value="site:wenLiangcan.github.io" />
<input class="search" type="text" name="q" results="0" placeholder="Search"/>
</fieldset>
</form>
<ul class="main-navigation">
<li><a href="/">Blog</a></li>
<li><a href="/blog/archives">Archives</a></li>
</ul>
</nav>
<div id="main">
<div id="content">
<div class="blog-index">
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/08/11/arcaders-1-01/">【译】ArcadeRs 1.1: 一个简单的窗口</a></h1>
<p class="meta">
<time datetime="2015-08-11T20:32:00+08:00" pubdate data-updated="true">Aug 11<span>th</span>, 2015</time>
| <a href="/blog/2015/08/11/arcaders-1-01/#disqus_thread"
data-disqus-identifier="http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-01/">Comments</a>
</p>
</header>
<div class="entry-content"><blockquote><p>原文:<a href="https://jadpole.github.io/arcaders/arcaders-1-1/">ArcadeRS 1.1: A simple window</a></p></blockquote>
<p>本系列文章的目是通过开发一个简单的老式射击游戏来一探 <code>Rust</code> 这门语言,这是其中的第一部分。除去介绍,本系列共有 16 个部分组成:</p>
<ol>
<li><a href="/blog/2015/08/11/arcaders-1-01/">一个简单的窗口</a>,我们在此安装 SDL2</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-2/">事件处理</a>,我们在此讨论生存期限</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-3/">处理更多的事件</a>,我们在此讨论宏</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-4/">视图</a>,我们在此学习装箱,模式匹配,trait 对象,还有动态分发</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-5/">视图的切换</a>,我们在此使用装箱,模式匹配,trait 对象,还有动态分发</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-6/">移动的矩形</a>,我们在此绘制图像</li>
<li><a href="#">Main menu</a>, where we play with textures and Rust’s vectors</li>
<li><a href="#">Sprites</a>, where we create shareable images</li>
<li><a href="#">Backgrounds</a>, where we handle resizing, scale and translate through time</li>
<li><a href="#">The player’s ship</a>, where we control a multi-sprite object</li>
<li><a href="#">Shooting bullets</a>, where we handle resource pooling</li>
<li><a href="#">Animated sprites</a>, where we render animated asteroids</li>
<li><a href="#">Asteroid attack!</a>, where we make multiple objects interact</li>
<li><a href="#">Explosions</a>, where we see things do boom.</li>
<li><a href="#">Music</a>, where we hear things go boom.</li>
<li><a href="#">High score & wrap-up</a>, where we play with the filesystem</li>
</ol>
<h2>一个华丽的新项目</h2>
<p>作为开始,让我们亲切地请求 Cargo 为我们创建一个新项目。在你的项目目录下执行:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nv">$ </span>cargo new arcade-rs --bin
</span><span class='line'><span class="nv">$ </span><span class="nb">cd </span>arcade-rs
</span></code></pre></td></tr></table></div></figure>
<p>如果你打开生成的 <code>Cargo.toml</code>,你可以看到类似如下的内容:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="o">[</span>package<span class="o">]</span>
</span><span class='line'><span class="nv">name</span> <span class="o">=</span> <span class="s2">"arcade-rs"</span>
</span><span class='line'><span class="nv">version</span> <span class="o">=</span> <span class="s2">"0.1.0"</span>
</span><span class='line'><span class="nv">authors</span> <span class="o">=</span> <span class="o">[</span><span class="s2">"John Doe <[email protected]>"</span><span class="o">]</span>
</span></code></pre></td></tr></table></div></figure>
<p>你可以通过 <code>cargo run</code> 命令运行生成的 <code>hello world</code> 程序,然而现在来说这并没有什么卵用。我们要做的是,稍微更改一下这个配置文件以加入所需的依赖。请把以下几行添加到该文件的底部:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="o">[</span>dependencies<span class="o">]</span>
</span><span class='line'><span class="nv">sdl2</span> <span class="o">=</span> <span class="s2">"0.6"</span>
</span></code></pre></td></tr></table></div></figure>
<p>结束的时候,我们的项目会依赖于更多的外部 <code>crate</code> (<code>Rust</code> 概念中的 库),不过眼下我们只需要这些。<code>sdl2</code> <em>crate</em> 使我们可以创建程序窗口,在上面渲染画面和处理各种事件,而这些也正好是我们在接下来的几章将要做的事情。</p>
<blockquote><p>很可能你的电脑上尚未安装有 SDL2 的开发库,那样的话将无法编译 SDL2 的 Rust 绑定。
我建议你参照 <a href="https://github.com/AngryLawyer/rust-sdl2#sdl20--development-libraries">rust-sdl2 的 README 文件</a> 中的步骤,在你的系统中安装所需的开发库。
等你完成后我们接着继续。</p></blockquote>
<p>现在,SDL2 已经(希望是)安装在你的系统中了,你可以执行:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nv">$ </span>cargo build
</span><span class='line'> Updating registry <span class="sb">`</span>https://github.com/rust-lang/crates.io-index<span class="sb">`</span>
</span><span class='line'> Downloading sdl2 v0.6.0
</span><span class='line'> Downloading sdl2-sys v0.6.0
</span><span class='line'> Compiling sdl2-sys v0.6.0
</span><span class='line'> Compiling bitflags v0.2.1
</span><span class='line'> Compiling rustc-serialize v0.3.15
</span><span class='line'> Compiling libc v0.1.8
</span><span class='line'> Compiling rand v0.3.8
</span><span class='line'> Compiling num v0.1.25
</span><span class='line'> Compiling sdl2 v0.6.0
</span><span class='line'> Compiling arcade-rs v0.1.0 <span class="o">(</span>file:///home/johndoe/projects/arcade-rs<span class="o">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>如果一切顺利,各类绑定和它们的依赖就已经编译好而我们也可以开启一个窗口了。否则,很可能你并没有正确安装 SDL2 而你只有解决了这一问题才能进行接下来的步骤。</p>
<h2>激动人心的三秒钟</h2>
<p>好了,让我们来创建一个窗口。用你最喜欢的文本编辑器打开 <code>src/main.rs</code> 然后修改为以下内容:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span><span class="w"> </span><span class="n">crate</span><span class="w"> </span><span class="n">sdl2</span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="kn">use</span><span class="w"> </span><span class="n">sdl2</span><span class="o">::</span><span class="n">pixels</span><span class="o">::</span><span class="n">Color</span><span class="p">;</span><span class="w"></span>
</span><span class='line'><span class="kn">use</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">thread</span><span class="p">;</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="k">fn</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="c1">// 初始化 SDL2</span>
</span><span class='line'><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">sdl_context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdl2</span><span class="o">::</span><span class="n">init</span><span class="p">().</span><span class="n">video</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="w"> </span><span class="c1">// 创建窗口</span>
</span><span class='line'><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">window</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdl_context</span><span class="p">.</span><span class="n">window</span><span class="p">(</span><span class="s">"ArcadeRS Shooter"</span><span class="p">,</span><span class="w"> </span><span class="mi">800</span><span class="p">,</span><span class="w"> </span><span class="mi">600</span><span class="p">)</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">position_centered</span><span class="p">().</span><span class="n">opengl</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">renderer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">window</span><span class="p">.</span><span class="n">renderer</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">accelerated</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="w"> </span><span class="n">renderer</span><span class="p">.</span><span class="n">set_draw_color</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">RGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">));</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="n">renderer</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="n">renderer</span><span class="p">.</span><span class="n">present</span><span class="p">();</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="w"> </span><span class="n">thread</span><span class="o">::</span><span class="n">sleep_ms</span><span class="p">(</span><span class="mi">3000</span><span class="p">);</span><span class="w"></span>
</span><span class='line'><span class="p">}</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>现在,如果你运行这个程序的话…</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nv">$ </span>cargo run
</span><span class='line'> Compiling arcade-rs v0.1.0 <span class="o">(</span>file:///home/johndoe/projects/arcade-rs<span class="o">)</span>
</span><span class='line'> Running <span class="sb">`</span>target/debug/arcade-rs<span class="sb">`</span>
</span></code></pre></td></tr></table></div></figure>
<p><img src="https://jadpole.github.io/images/arcade-1.png" alt="three_sec" /></p>
<p>… 你可以看到一个窗口在屏幕上停留了 3 秒钟,然后消失了。就是这样!有趣的部分来了:弄明白刚刚我们所写的究竟是什么意思。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span><span class="w"> </span><span class="n">crate</span><span class="w"> </span><span class="n">sdl2</span><span class="p">;</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>一开始我们先包含了作为依赖添加进来的 <code>sdl2</code> <em>crate</em>。如果需要,我们可以像 Python 那样,给它另起一个名字。比如这样:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">extern</span><span class="w"> </span><span class="n">crate</span><span class="w"> </span><span class="n">sdl2</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">pineapple</span><span class="p">;</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>之后我们把代码中出现的所有 <code>sdl2</code> 都换成 <code>pineapple</code>(菠萝) 得到的结果是不变的。虽然我挺喜欢菠萝,接下来的文章里我还是继续使用 <code>sdl2</code> 算了(当然,没人强求 你 也这么做)。有一个类似的语法可以用于重命名被使用(use)的类型(type)和函数(function),我将在<a href="https://jadpole.github.io/arcaders/arcaders-1-6/">第 6 章</a>用到它。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kn">use</span><span class="w"> </span><span class="n">sdl2</span><span class="o">::</span><span class="n">pixels</span><span class="o">::</span><span class="n">Color</span><span class="p">;</span><span class="w"></span>
</span><span class='line'><span class="kn">use</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">thread</span><span class="p">;</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>第一行很简单:因为 <code>sdl2::pixels::Color</code> 敲起来太长了,所以我们只使用(use)这一路径下的最后一个标识符 <code>Color</code> 来代表同一事物。<code>use</code> 语句不仅可以用于类型和函数,对 模块(module)同样有效。这就是第二行的用意,现在我们只需要写 <code>thread::某标函数</code> 而不用写 <code>std::thread::某函数</code>。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">fn</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>在此,我们声明了作为我们程序的入口的 <code>main</code> 函数。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span><span class="w"> </span><span class="n">sdl_context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdl2</span><span class="o">::</span><span class="n">init</span><span class="p">().</span><span class="n">video</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>现在,开始触及有趣的部分了!<code>init</code> 函数返回一个我们用来初始化 SDL2 的上下文(context)的对象。厉害之处是这里用到了 <code>Rust</code> 版的<a href="https://aturon.github.io/ownership/builders.html">生成器模式(builder pattern)</a>。就是说,<code>init</code> 返回如下类型的对象:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="k">pub</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="n">InitBuilder</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="n">flags</span><span class="o">:</span><span class="w"> </span><span class="kt">u32</span><span class="w"></span>
</span><span class='line'><span class="p">}</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>这一类型提供了一个便于使用 SDL2 API 的接口。通过调用比如像 <code>timer()</code>,<code>joystick()</code> 和 <code>video()</code> 这些方法,我们可以选择性的初始化 SDL2 的某些部分,以最小化这个库的占用空间。一旦准备就绪,我们调用 <code>build()</code> 方法,获得 <code>Result<Sdl, String></code>。</p>
<p>使用 <code>Result</code> 类型的对象是 <code>Rust</code> 中进行错误处理(error handling)的方式。得到错误值的可能性被集成到了类型系统中,开发者被强制要求去处理这一情况,从而获取函数的结果。这一次,我们只是简单的通过 <code>unwrap()</code> “解封”其中的值,这意味着我们断定(assert)我们得到的是被封装在 <code>Ok</code> 类型中的正确值,否则的话就不再执行后续的代码。我们之所以这么做,是因为如果我们创建不了上下文,我们就无法渲染我们的游戏,我们的程序就失去了它的意义了。</p>
<p>解封(unwrapping)<code>Err</code> 中的值会把错误信息打印出来并引发恐慌(panic),使得程序安全地崩溃掉。如果被解封的值是 <code>Ok(Sdl)</code> 类型的话,解封出来的值会被直接返回并赋值给 <code>sdl_context</code>。</p>
<p>把上下文绑定(binding)到一个标识符的好处是,一旦它脱离了自己的作用域(在 <code>main</code> 函数结束处),它所持有的所有资源都会被自动释放。其实,就算我们的程序运行至某处 panic 了,析构器(destructor)也会被如常调用,以防止内存泄漏。这就是我所指的安全地崩溃掉。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span><span class="w"> </span><span class="n">window</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdl_context</span><span class="p">.</span><span class="n">window</span><span class="p">(</span><span class="s">"ArcadeRS Shooter"</span><span class="p">,</span><span class="w"> </span><span class="mi">800</span><span class="p">,</span><span class="w"> </span><span class="mi">600</span><span class="p">)</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">position_centered</span><span class="p">().</span><span class="n">opengl</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>我们在此处打开了窗口。它有一个名为“ArcadeRS Shooter”的标题,800 象素的宽度 和 600 象素的高度。像前面一样,这里使用了生成器模式,我们可以方便地使窗口居中和激活 OpenGL 模式(更高效)的渲染。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">renderer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">window</span><span class="p">.</span><span class="n">renderer</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">accelerated</span><span class="p">()</span><span class="w"></span>
</span><span class='line'><span class="w"> </span><span class="p">.</span><span class="n">build</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>这一步你懂的!我们在创建一个与窗口关联的渲染器(renderer),把它设置成可以使用 OpenGL 来辅助渲染,之后我们会用它来“作画”。如果创建失败,程序就会伴随着错误信息 panic 掉。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">renderer</span><span class="p">.</span><span class="n">set_draw_color</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">RGB</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">));</span><span class="w"></span>
</span><span class='line'><span class="n">renderer</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
</span><span class='line'><span class="n">renderer</span><span class="p">.</span><span class="n">present</span><span class="p">();</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>在第一行,我们把笔刷设置为黑色(red=0,green=0,blue=0)。第二行处,我们先清空缓冲区再填入刚刚选择的笔刷颜色。第三行交换缓冲区正式向用户展现我们绘制的画面。</p>
<p>如果我们去掉最后一行,奇怪的事情就发生了。比如在 Gnome 下,窗口的内容被设置成了它背后的画面。虽然可能听起来怪怪的,按照 <code>Rust</code> 世界的传统,<code>renderer</code> 所提供的接口让我们无法轻易地使程序挂掉。</p>
<p><img src="https://jadpole.github.io/images/arcade-2.png" alt="blank_win" /></p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rust'><span class='line'><span class="n">thread</span><span class="o">::</span><span class="n">sleep_ms</span><span class="p">(</span><span class="mi">3000</span><span class="p">);</span><span class="w"></span>
</span></code></pre></td></tr></table></div></figure>
<p>继续执行程序前,我们在这里先等待 3000 毫秒,即 3 秒钟。也可以看出,此后 <code>main</code> 函数就结束了,在其中分配的所有资源都会被释放掉。在用户看来,就是程序窗口被关掉。对我们来说,也没有太大的不同。美妙的是,即使此处发生了再多的事情,我们也无需为之操心!</p>
<p>你也许注意到了,我们从头到尾都无需写明任何数据类型。当然,我们使用了诸如 <code>sdl2::init</code> 和 <code>Color::new</code> 这些模块函数(module function)和关联函数(associated function)(也许你会对静态方法这个名字更熟悉些),可是我们从来没有告诉 <code>Rust</code> 我们的上下文的类型是 <code>sdl2::Sdl</code>。这被称为 类型推导(type inference),它是使得 <code>Rust</code> 让人愉快地使用的众多特性之一,虽然它们看起来像是无关紧要的附加品。</p>
<p>这就是本系列的第一部分。<a href="https://jadpole.github.io/arcaders/arcaders-1-2/">下一次</a>,我们将提出一种更好的关闭窗口的方式:通过点击那个叉叉(x)。</p>
<p>在那之前,保持 rusting!</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2015/08/11/arcaders-1-00/">【译】ArcadeRs 1.0: 介绍</a></h1>
<p class="meta">
<time datetime="2015-08-11T20:14:00+08:00" pubdate data-updated="true">Aug 11<span>th</span>, 2015</time>
| <a href="/blog/2015/08/11/arcaders-1-00/#disqus_thread"
data-disqus-identifier="http://wenLiangcan.github.io/blog/2015/08/11/arcaders-1-00/">Comments</a>
</p>
</header>
<div class="entry-content"><blockquote><p>原文:<a href="https://jadpole.github.io/arcaders/arcaders-1-0/">ArcadeRS 1.0: The project</a></p></blockquote>
<p>本系列文章的目是通过开发一个简单的老式射击游戏来一探 <code>Rust</code> 这门语言,这是其中的介绍部分。除去介绍,本系列共有 16 个部分组成:</p>
<ol>
<li><a href="/blog/2015/08/11/arcaders-1-01/">一个简单的窗口</a>,我们在此安装 SDL2</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-2/">事件处理</a>,我们在此讨论生存期限</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-3/">处理更多的事件</a>,我们在此讨论宏</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-4/">视图</a>,我们在此学习装箱,模式匹配,trait 对象,还有动态分发</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-5/">视图的切换</a>,我们在此使用装箱,模式匹配,trait 对象,还有动态分发</li>
<li><a href="https://jadpole.github.io/arcaders/arcaders-1-6/">移动的矩形</a>,我们在此绘制图像</li>
<li><a href="#">Main menu</a>, where we play with textures and Rust’s vectors</li>
<li><a href="#">Sprites</a>, where we create shareable images</li>
<li><a href="#">Backgrounds</a>, where we handle resizing, scale and translate through time</li>
<li><a href="#">The player’s ship</a>, where we control a multi-sprite object</li>
<li><a href="#">Shooting bullets</a>, where we handle resource pooling</li>
<li><a href="#">Animated sprites</a>, where we render animated asteroids</li>
<li><a href="#">Asteroid attack!</a>, where we make multiple objects interact</li>
<li><a href="#">Explosions</a>, where we see things do boom.</li>
<li><a href="#">Music</a>, where we hear things go boom.</li>
<li><a href="#">High score & wrap-up</a>, where we play with the filesystem</li>
</ol>
<p>这是一篇写给那些哪怕仅仅是通过某个脚本语言,已经对软件开发这门技艺有所了解的人的教程,他们刚刚发现了这头名为 <code>Rust</code> 的怪兽。他们过了一遍<a href="https://doc.rust-lang.org/book/">官方教程</a>,阅读了大量关于这门看起来熟悉,据说向原有的软件安全概念发起了挑战的语言的博文,然后 excited,想要发掘如何真正地在实践中运用 <code>Rust</code>。</p>
<p>我对读者的要求是,他或她(或者它?)应该理解诸如接口,方法,条件结构,和(基础的)静态类型这些概念。多数情况下,这些术语的含义在其上下文中是不言自明的。然而,如果理解它们对你来说很成问题,提醒一下我不会对其作长篇大论的解释。</p>
<p>我还期望你阅读这篇教程前已经学习过一点 <code>Rust</code>,即使只是浅显的部分。比如你得明白 <code>Rust</code> 的 <code>use</code> 语句,哪怕仅限于在 <code>main.rs</code> 文件里,是用来干什么的。当然,你不需要成为一名专家才能探索其中的微妙。</p>
<p>在接下来的几周里,我们将会基于 Mike Geig 的棒棒哒 <a href="http://fixbyproximity.com/2d-game-development-course/">2D 游戏开发教程</a> 来制作一个太空射击游戏。我们还会编写一个叫做 <code>phi</code> 的库,它会为我们提供诸如视图(在 LibGDX 中称为 screens),内置碰撞检测(虽然很基础)的矩形,和动态精灵等 2D 游戏所需的组件。</p>
<p>我们将要用到的库是 AngryLawyer 的 SDL2 的绑定,版本为 6.0,你可以在<a href="https://github.com/AngryLawyer/rust-sdl2">这里</a>找到,以及相关的一些插件。</p>
<p>继续讲述前,我要强调的是你无需精通 <code>Rust</code> 再阅读这篇教程。相反,本教程的目的之一就是探索 <code>Rust</code> 的微妙之处,哪怕不是主要的,基于此,老实说,我不推荐在生产中使用 <code>phi</code>。可是,你至少得浏览过<a href="https://doc.rust-lang.org/book/">官方教程</a>或者 <a href="http://rustbyexample.com/">Rust by Example</a>。</p>
<p>基本上,我会直接展示如何<em>使用</em>而不会解释语法。</p>
<p>所以,不多说,我们<a href="/blog/2015/08/11/arcaders-1-01/">开始吧</a>。</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2014/08/02/processing-pattern-matches-while-performing-string-substitutions-in-python/">如何在 Python 中操作正则替换的匹配结果</a></h1>
<p class="meta">
<time datetime="2014-08-02T21:39:00+08:00" pubdate data-updated="true">Aug 2<span>nd</span>, 2014</time>
| <a href="/blog/2014/08/02/processing-pattern-matches-while-performing-string-substitutions-in-python/#disqus_thread"
data-disqus-identifier="http://wenLiangcan.github.io/blog/2014/08/02/processing-pattern-matches-while-performing-string-substitutions-in-python/">Comments</a>
</p>
</header>
<div class="entry-content"><p>在进行字符串的正则替换时,我们可能会希望替换的结果是基于匹配结果的,就是说把匹配的字符串提取出来进行一定的修改再应用回原文。</p>
<p>以 <code>sed</code> 为例:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">echo</span> <span class="s1">'cat dog mouse'</span> | sed <span class="s1">'s/dog/\*&\*/'</span>
</span><span class='line'>cat *dog* mouse
</span></code></pre></td></tr></table></div></figure>
<p>用 <code>&</code> 符号可以把匹配的字符串 <code>"dog"</code> 提取出来,然后在它的前后加上了 <code>*</code>。</p>
<p>在 <code>Python</code> 使用 <code>re</code> 模块时可以这么写:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">re</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">repl</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
</span><span class='line'> <span class="k">return</span> <span class="s">'*'</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">()</span> <span class="o">+</span> <span class="s">'*'</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">'dog'</span><span class="p">,</span> <span class="n">repl</span><span class="p">,</span> <span class="s">'cat dog mouse'</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># 输出:cat *dog* mouse</span>
</span></code></pre></td></tr></table></div></figure>
<p>当传给 <code>re.sub()</code> 方法的第二个参数是一个函数时,<code>re.sub()</code> 会给这个函数传入一个 <code>Match Object</code> 然后以这个函数的返回值作为替换结果。</p>
<p>我们可以通过这个 <code>Match Object</code> 的 <code>grou()</code> 方法获取每次执行替换前的匹配结果。这个方法之所以叫做 <code>group</code> ,是因为我们有时会使用多个匹配模板,同时获取多个(一组)匹配结果,再以 <code>sed</code> 为例:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">echo</span> <span class="s1">'cat dog mouse'</span> | sed <span class="s1">'s/\(dog\) \(mouse\)/\*\1\* _\2_/'</span>
</span><span class='line'>cat *dog* _mouse_
</span></code></pre></td></tr></table></div></figure>
<p>符号 <code>\1</code> 和 <code>\2</code> 对应于第一和第二个括号里我们要提取的字符串。</p>
<p>Python 则如下:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">re</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">repl</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
</span><span class='line'> <span class="k">return</span> <span class="s">'*'</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="s">'*'</span> <span class="o">+</span> \
</span><span class='line'> <span class="s">'_'</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="s">'_'</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">'(dog) (mouse)'</span><span class="p">,</span> <span class="n">repl</span><span class="p">,</span> <span class="s">'cat dog mouse'</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># 输出:cat *dog* _mouse_</span>
</span></code></pre></td></tr></table></div></figure>
<p>上一例中的 <code>m.group()</code> 也可以写为 <code>m.goup(0)</code>,意为把所有结果作为一个字符串取出。</p>
<p>还有一种跟传统正则表达式比较相似的写法:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">re</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">repl</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
</span><span class='line'> <span class="k">return</span> <span class="s">'*'</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="n">expand</span><span class="p">(</span><span class="s">r'\1'</span><span class="p">)</span> <span class="o">+</span> <span class="s">'*'</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">'(dog)'</span><span class="p">,</span> <span class="n">repl</span><span class="p">,</span> <span class="s">'cat dog mouse'</span><span class="p">))</span>
</span></code></pre></td></tr></table></div></figure>
<p>用 <code>expand()</code> 方法展开表达式,不过似乎不支持符号 <code>&</code>。</p>
<h2>参考资料</h2>
<ul>
<li><a href="https://docs.python.org/3.4/howto/regex.html">Regular Expression HOWTO</a></li>
<li><a href="https://stackoverflow.com/questions/9134964/regex-in-python-is-it-possible-to-get-the-match-replacement-and-final-string">Regex in python: is it possible to get the match, replacement, and final string?</a></li>
<li><em><a href="http://shop.oreilly.com/product/0636920027072.do">Python Cookbook (3rd Edition)</a></em>: <strong>2.6. Searching and Rplacing Case-Insensitive Text</strong></li>
</ul>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2014/07/26/fix-gvim-empty-border-on-fullscreen/">去除全屏下 GVim 出现的白边</a></h1>
<p class="meta">
<time datetime="2014-07-26T14:08:00+08:00" pubdate data-updated="true">Jul 26<span>th</span>, 2014</time>
| <a href="/blog/2014/07/26/fix-gvim-empty-border-on-fullscreen/#disqus_thread"
data-disqus-identifier="http://wenLiangcan.github.io/blog/2014/07/26/fix-gvim-empty-border-on-fullscreen/">Comments</a>
</p>
</header>
<div class="entry-content"><p>全屏下 GVim 的左侧和底部会出现白边,可以在 <code>~/.gtkrc-2.0</code> 文件中加入一下设置:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>style "vimfix" {
</span><span class='line'> bg[NORMAL] = "#002B36"
</span><span class='line'>}
</span><span class='line'>widget "vim-main-window.*GtkForm" style "vimfix"</span></code></pre></td></tr></table></div></figure>
<p> <br/>
<code>#002B36</code> 这个颜色对应于我使用的 <code>Solarized Dark</code> <code>Vim</code> 配色的背景色,可以根据个人情况修改。</p>
<h2>参考资料</h2>
<ul>
<li><a href="https://bbs.archlinux.org/viewtopic.php?pid=786106#p786106">howto fix gvim border width ?</a></li>
</ul>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2014/05/18/ipv6-to-ipv4-proxy/">IPv6 到 IPv4 的代理</a></h1>
<p class="meta">
<time datetime="2014-05-18T01:30:00+08:00" pubdate data-updated="true">May 18<span>th</span>, 2014</time>
| <a href="/blog/2014/05/18/ipv6-to-ipv4-proxy/#disqus_thread"
data-disqus-identifier="http://wenLiangcan.github.io/blog/2014/05/18/ipv6-to-ipv4-proxy/">Comments</a>
</p>
</header>
<div class="entry-content"><p>为了安装 <a href="http://johnmacfarlane.net/pandoc/">Pandoc</a> 添加了 <a href="https://wiki.archlinux.org/index.php/Unofficial_user_repositories#haskell-core">haskell-core</a> 这个仓库(<code>AUR</code> 里的包要自己编译太麻烦了),不过要用 Goagent 代理才能访问,本来以为是墙了。</p>
<p>可是问题来了,更新/安装一般的官方仓库的包时我是不希望通过代理的,所以会先注释掉 <code>pacman.conf</code> 里的 <code>haskell-core</code> 再 <code>pacman -Syu</code>,这样一来已安装的 <code>haskell</code> 包会引起依赖问题导致更新无法继续。</p>
<p>无意中想起用 <a href="http://cloudmonitor.ca.com/en/ping.php">http://cloudmonitor.ca.com/en/ping.php</a>(以前叫 just-ping.com)ping 一下这个仓库的地址(xsounds.org)看看,结果发现这货只支持通过 <code>IPv6</code> 访问!!!而我学校的网络只支持 <code>IPv4</code>。。。</p>
<p>Google 了一番后让我找到了 <a href="https://www.sixxs.net/tools/gateway/">SixXs</a> 这个服务,提供了 <code>IPv6</code> 到 <code>IPv4</code> 的代理,只要在想要访问的网址后加上 “.ipv4.sixxs.org” 这个后缀就可以了,就像这样:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>xsounds.org.ipv4.sixxs.org/~haskell/core/$arch</span></code></pre></td></tr></table></div></figure>
<p>抱着尝试的心态添加到了 <code>pacman.conf</code> 里,结果真的可用!</p>
<p>ps: 通过这样的地址下载时就看不到进度条了,原因不明。 <br/>
pps: 其实 <code>SixXs</code> 也提供了 <code>IPv4</code> 到 <code>IPv6</code> 的代理服务的,把上面的后缀换成 “.sixxs.org” 或者 “.ipv6.sixxs.org” 就可以了。</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2014/04/20/keepass-cjk-fonts-displaying/">解决 Linux 下 KeePass 中文显示的问题</a></h1>
<p class="meta">
<time datetime="2014-04-20T23:05:00+08:00" pubdate data-updated="true">Apr 20<span>th</span>, 2014</time>
| <a href="/blog/2014/04/20/keepass-cjk-fonts-displaying/#disqus_thread"
data-disqus-identifier="http://wenLiangcan.github.io/blog/2014/04/20/keepass-cjk-fonts-displaying/">Comments</a>
</p>
</header>
<div class="entry-content"><p>Linux 下用 KeePass 中文一直以来都显示为方块,准确的说是点开编辑条目的时候,外面的列表显示倒没有问题,弄得我一直不敢在 Linux 下编辑我的数据文件,每次想要添加新帐号都得开个虚拟机。。。</p>
<p>突然发现原来是 Local 设置的问题,因为我习惯使用英文作为系统语言,所以只要让 KeePass 使用中文 Local 运行就好了。比如 Arch 下安装的官方源里的包的话,在 <code>/usr/bin/keepass</code> 里加入:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nb">export </span><span class="nv">LANG</span><span class="o">=</span>zh_CN.utf8
</span></code></pre></td></tr></table></div></figure>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2014/04/01/pkgbuild-for-rjsupplicant/">Linux 版锐捷客户端的 PKGBUILD</a></h1>
<p class="meta">
<time datetime="2014-04-01T19:58:00+08:00" pubdate data-updated="true">Apr 1<span>st</span>, 2014</time>
| <a href="/blog/2014/04/01/pkgbuild-for-rjsupplicant/#disqus_thread"
data-disqus-identifier="http://wenLiangcan.github.io/blog/2014/04/01/pkgbuild-for-rjsupplicant/">Comments</a>
</p>
</header>
<div class="entry-content"><p>在愚人节的今天,学校全面强制使用 4.99 版本的锐捷客户端作为上网认证,之前一直在 Arch 下默默辛勤工作的 <a href="https://code.google.com/p/mentohust/">MentoHUST</a> 就这样挂掉了。。。</p>
<p>锐捷其实也有 Linux 版的,叫做 rjsupplicant,试了一下居然能用,不用离开 Linux 回到 Windows 算是万幸,不过不出所料的无法开多网卡建 WiFi 热点了,也只好如此。</p>
<p>自从学了一下下 PKGBUILD 怎么写,无论多小的程序或脚本,不用 <code>Pacman</code> 管理就不舒服,所以这次也打了个包,文件都在<a href="https://github.com/wenLiangcan/PKGBUILD/tree/master/rjsupplicant">这里</a>。</p>
<p>安装好后输入 <code>rjsupplicant --help</code> 查看帮助,我的认证格式如下:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo rjsupplicant -a1 -d0 -nenp2s0 -u<用户名> -p<密码></span></code></pre></td></tr></table></div></figure>
<ul>
<li>-a: 1 的话表示有线连接,0 就是无线</li>
<li>-d: 1 使用 dhcp,0 不使用</li>
<li>-n: 网卡名</li>
</ul>
<p>退出可以按 <code>q</code>。</p>
<p>打包里还有个 <code>Systemd</code> 的 service 文件,从 <code>AUR</code> 上的 <a href="https://aur.archlinux.org/packages/mentohust-bin/">mentohust-bin</a> 里修改而来。安装好后如果要启用,先打开 <code>/usr/lib/systemd/system/rjsupplicant.service</code>,在<a href="https://github.com/wenLiangcan/PKGBUILD/blob/master/rjsupplicant/rjsupplicant.service#L10">第 10 行</a>添加上上述的认证参数,想在 <code>makepkg</code> 前添加的话请记得更新 <code>PKGBUILD</code> 里对应的 <code>md5sum</code> 值。</p>
</div>
</article>
<article>
<header>
<h1 class="entry-title"><a href="/blog/2013/12/14/zip-function-and-dict-comprehension-in-python/">Zip 函数和 Dict Comprehension</a></h1>
<p class="meta">
<time datetime="2013-12-14T16:43:00+08:00" pubdate data-updated="true">Dec 14<span>th</span>, 2013</time>
| <a href="/blog/2013/12/14/zip-function-and-dict-comprehension-in-python/#disqus_thread"
data-disqus-identifier="http://wenLiangcan.github.io/blog/2013/12/14/zip-function-and-dict-comprehension-in-python/">Comments</a>
</p>
</header>
<div class="entry-content"><p>要下载某个会反盗图的网站上的图片,想到了这篇 <a href="http://qixinglu.com/post/google_image_proxy.html">Google 的图片代理</a>。</p>
<p>通过 Google 来抓取想要的图片就可以逃过反盗图了,主要的工作就是为一系列原图的 url 生成特定的请求链接,所以要做的就是拼凑字符串,机械的任务当然交给机器去做了,<code>Python</code> 实现之。</p>
<p>虽然听起来挺简单,可是以我原有的知识实现起来还是有些繁琐。 需要处理的数据是存储在一个列表里的原图链接,最终想要获得的数据是一系列的文件名和与之一一对应的下载链接,第一反应当然是用字典组织它们了。 请求地址是从原链接拼凑生成的,文件名也是由原链接获得,使用 <code>os.path.basename()</code> 方法。</p>
<p>开始的想法是用两次 <code>List Comprehension</code>,遍历存储原链接的列表,获得两个分别含有文件名和下载地址的新列表,可是怎么把它们分别作为 <code>Key</code> 和 <code>Value</code> 合成为一个字典呢?我可不要循环操作下标。。。。Google 之,知道了 <code>zip</code> 函数,用法如下:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="o">>>></span> <span class="n">keys</span> <span class="o">=</span> <span class="p">[</span><span class="s">'a'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">,</span> <span class="s">'c'</span><span class="p">]</span>
</span><span class='line'><span class="o">>>></span> <span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</span><span class='line'><span class="o">>>></span> <span class="n">dictionary</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">values</span><span class="p">))</span>
</span><span class='line'><span class="o">>>></span> <span class="k">print</span> <span class="n">dictionary</span>
</span><span class='line'><span class="p">{</span><span class="s">'a'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s">'b'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s">'c'</span><span class="p">:</span> <span class="mi">3</span><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p> <br/>
<code>zip()</code> 会返回一系列的元组,然后通过 <code>dct()</code> 生成一个字典。</p>
<p>可是两次遍历的都是同一个列表,难道就不能在同一次遍历中完成上面的任务吗 (“▔□▔),好吧,原来还有 <a href="http://www.python.org/dev/peps/pep-0274/"><code>Dict Comprehension</code></a> 这个东西:</p>
<ul>
<li>如果需要遍历的 <code>sequence</code> 是一个列表,那么</li>
</ul>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="n">l</span> <span class="p">:</span> <span class="n">l</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<ul>
<li>如果 <code>sequence</code> 是一个字典</li>
</ul>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="n">key</span> <span class="p">:</span> <span class="n">value</span> <span class="k">for</span> <span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="ow">in</span> <span class="n">dictionary</span><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<ul>
<li>另外,在 2.6 及以下的 <code>Python</code> 中,需要使用 <code>dict</code> 构造函数</li>
</ul>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">d</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="o">...</span> <span class="k">for</span> <span class="o">...</span> <span class="ow">in</span> <span class="n">sequence</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p></p>
<p>再复习一下如何用 <code>for in</code> 迭代一个字典分别获取其中的键和值:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">d</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
</span><span class='line'> <span class="o">...</span>
</span></code></pre></td></tr></table></div></figure>
<p>在 <code>Python 3.x</code> 中使用的是 <code>items()</code>, <code>Python 2.x</code> 中也有这个方法,不过返回的是包含一对键、值的元组。</p>
<p>最后,贴一下代码:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="c">#!/usr/bin/python</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">urllib2</span><span class="o">,</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">os</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">inputlinks</span><span class="p">():</span>
</span><span class='line'> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span><span class='line'> <span class="n">links</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">"Enter links :</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
</span><span class='line'> <span class="k">else</span><span class="p">:</span>
</span><span class='line'> <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">"-i"</span><span class="p">:</span>
</span><span class='line'> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span><span class='line'> <span class="n">links</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()</span>
</span><span class='line'> <span class="k">else</span><span class="p">:</span>
</span><span class='line'> <span class="n">links</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
</span><span class='line'> <span class="k">return</span> <span class="n">links</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">generate</span><span class="p">(</span><span class="n">links</span><span class="p">):</span>
</span><span class='line'> <span class="n">prefix</span> <span class="o">=</span> <span class="s">r"https://images2-focus-opensocial.googleusercontent.com/gadgets/proxy?url="</span>
</span><span class='line'> <span class="n">suffix</span> <span class="o">=</span> <span class="s">r"&container=focus&gadget=a&no_expand=1&resize_h=0&rewriteMime=image</span><span class="si">%2F</span><span class="s">*"</span>
</span><span class='line'> <span class="n">images</span> <span class="o">=</span> <span class="p">{</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="p">:</span> <span class="n">prefix</span> <span class="o">+</span> <span class="n">i</span> <span class="o">+</span> <span class="n">suffix</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">links</span><span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="n">images</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">download</span><span class="p">(</span><span class="n">images</span><span class="p">):</span>
</span><span class='line'> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">image</span> <span class="ow">in</span> <span class="n">images</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
</span><span class='line'> <span class="k">try</span><span class="p">:</span>
</span><span class='line'> <span class="n">imgdata</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">image</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">output</span><span class="p">:</span>
</span><span class='line'> <span class="n">output</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">imgdata</span><span class="p">)</span>
</span><span class='line'> <span class="k">except</span><span class="p">:</span>
</span><span class='line'> <span class="k">print</span> <span class="s">"Er..."</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
</span><span class='line'> <span class="n">download</span><span class="p">(</span><span class="n">generate</span><span class="p">(</span><span class="n">inputlinks</span><span class="p">()))</span>
</span></code></pre></td></tr></table></div></figure>
<h2>参考资料</h2>
<ul>