step1. on Synology DSM, install "docker gitlab"
step2. login "docker gitlab"
step3. create project in "docker gitlab" (e.g. xxxx)
step4. open xcode and "source control > xxxx - master > configure xxxx > Remote (+)":
[your DSM IP]:3000/root/xxxx.git
step5. commit code in xcode: "source control > commit..."
step6. push code in xcode: "source control > push..."
2017年6月2日 星期五
2017年4月17日 星期一
git grep for a pattern
假如想要找某一行 code 這樣的 pattern 在某個 commit 的 log
可以這樣下:
git grep '[pattern]' [sha]
如果想要找全 history 可以這樣下:
git grep '[pattern]' [sha] $(git rev-list --all)
如果還想要檢查前面 20 行 可以這樣下:
git grep -B20 '[pattern]' [sha] $(git rev-list --all)
可以這樣下:
git grep '[pattern]' [sha]
如果想要找全 history 可以這樣下:
git grep '[pattern]' [sha] $(git rev-list --all)
如果還想要檢查前面 20 行 可以這樣下:
git grep -B20 '[pattern]' [sha] $(git rev-list --all)
2017年4月15日 星期六
[C++] Any input type template function
主題 : Any input type template function
引言 : C++ 11 引入了此功能,讓 function 可以吃同類型任何型態的參數進來,並且還保持原來 type 的樣子。
描述 :
這名字我亂取的,我只是想要說明這樣的 pattern 的寫法可以讓你寫出一個 template function 可以吃所有同類型的 TYPE, TYPE&, TYPE&& ...
這真的很強大,不必再 for reference input 寫一個 function,for right value input 再寫一個 function。
已經有文章寫得很好了,請參照
http://thbecker.net/articles/rvalue_references/section_01.html
~
http://thbecker.net/articles/rvalue_references/section_08.html
一句話解釋,"當你想把 type 忠實的傳入到 func 內使用請使用以下的 pattern"
細節請讀 section_01~section_08
以下是 section_01~section_08 給的 factory design pattern 的範例,
這個 factory template function 的 arg 可能吃 1. value 2. reference 3. right value ...
因為 C++ 很在意 type,type 不對就 compile error
那我們要怎麼寫一個任何 type 都能傳入的 function 呢 ? 如下 function,
引言 : C++ 11 引入了此功能,讓 function 可以吃同類型任何型態的參數進來,並且還保持原來 type 的樣子。
描述 :
這名字我亂取的,我只是想要說明這樣的 pattern 的寫法可以讓你寫出一個 template function 可以吃所有同類型的 TYPE, TYPE&, TYPE&& ...
這真的很強大,不必再 for reference input 寫一個 function,for right value input 再寫一個 function。
已經有文章寫得很好了,請參照
http://thbecker.net/articles/rvalue_references/section_01.html
~
http://thbecker.net/articles/rvalue_references/section_08.html
一句話解釋,"當你想把 type 忠實的傳入到 func 內使用請使用以下的 pattern"
細節請讀 section_01~section_08
以下是 section_01~section_08 給的 factory design pattern 的範例,
這個 factory template function 的 arg 可能吃 1. value 2. reference 3. right value ...
因為 C++ 很在意 type,type 不對就 compile error
那我們要怎麼寫一個任何 type 都能傳入的 function 呢 ? 如下 function,
template<typename T, typename Arg> shared_ptr<T> factory(Arg&& arg) { return shared_ptr<T>(new T(std::forward<Arg>(arg))); }
當 Arg 是 X 則 new T(X)當 Arg 是 X& 則 new T(X&)當 Arg 是 X&& 則 new T(X&&)
很神奇吧,我的說明肯定不會比 section_01~section_08 還好。
如果你想知道為什麼,耐著性子看完你就會知道為什麼了。
2017年4月14日 星期五
[App] iTunes Connect Screenshot Sizes for iPhone and iPad
image:
iPhone 6 Plus(5.5 Inch): 1242 x 2208 px
iPad Pro (12.9 Inch): 2732 x 2048 px
video: (in 15 or 30 seconds)
iPhone 6 Plus(5.5 Inch): 1080 x 1920 (Portrait)
https://developer.apple.com/support/app-previews/
iPhone 6 Plus(5.5 Inch): 1242 x 2208 px
iPad Pro (12.9 Inch): 2732 x 2048 px
video: (in 15 or 30 seconds)
iPhone 6 Plus(5.5 Inch): 1080 x 1920 (Portrait)
https://developer.apple.com/support/app-previews/
2017年4月8日 星期六
[App] 如何一鍵刪除 iPhone/iPad 裡面所有的照片 ?
【軟體名稱】Photo Trash Can
【程式開發】Chun-Pai Yang
【軟體類別】工具
【軟體大小】13.5MB
【軟體售價】0.99 鎂
【下載連結】點我
▼ 當點下這個紅色的按鈕後,會要求你輸入你 iPhone/Ipad 裡的 相片:影片 數目,以避免誤操作:
如果您喜歡 Photo Trash Can的話,還請您不吝於給予我們五顆星的評價 (馬上前往)
有任何疑問/功能建議,都歡迎聯絡我們喔!
Photo Trash Can Facebook粉絲團:https://www.facebook.com/Photo-Trash-Can-716543165173369
Photo Trash Can 聯絡Email:phototrashcan@gmail.com
【程式開發】Chun-Pai Yang
【軟體類別】工具
【軟體大小】13.5MB
【軟體售價】0.99 鎂
【下載連結】點我
【Photo Trash Can 介紹】如何一鍵刪除 iPhone/iPad 裡面所有的照片 ?
Photo Trash Can 是一款刪除所有照片/影像的 App。許多用戶在使用完一些備份軟體如: Synology DS Photo 或是 dropbox .. 將 iPhone/iPad 裡面的照片/影片全部備份完後,這些軟體並不會自動地將 iPhone/iPad 裡面的照片/影片刪除。此時就是使用此軟體的時機。
▼ 若沒有此軟體在相片備份完後必須使用 Mac Book 的 Photo App 匯入並且一次刪除所有照片。
相當的麻煩 ...
▼ Photo Trash Can 一開始的畫面,意思就是你真的要想清楚才按下此鍵:
▼ 當做完一些最終的確認後,你所有的照片和影片就全數被刪除了:
▼ 刪除後其實全部的照片都可以從 Apple 的內建 Photos App 的 "最近刪除" (Recently Deleted) 相簿中。
若想要回復可要一張張的救回來了。
所以在使用此軟體前可要先確保你所有的照片都已經備份了喲。
但對於像是作者平時很懶,會有幾千張照片才會用 Synology DS Photo 備份一次並在備份完想要刪除所有照片的人真的是相當的方便。
如果您喜歡 Photo Trash Can的話,還請您不吝於給予我們五顆星的評價 (馬上前往)
有任何疑問/功能建議,都歡迎聯絡我們喔!
Photo Trash Can Facebook粉絲團:https://www.facebook.com/Photo-Trash-Can-716543165173369
Photo Trash Can 聯絡Email:phototrashcan@gmail.com
2017年1月18日 星期三
ssh tunnel
記錄一下。
之前都不知道怎麼建,應該說我知道這東西,但沒實際使用的經驗。
最近有一個 support 要我幫 user 看 router 上的設定,但即使開了 remote beckend,仍然是無法連到 router 網頁的阿。
這時候就是 ssh tunnel 使用的時機:
ssh -L 11111:192.168.1.1:80 -p [port] admin@[public ip]
以上的前提是你有 ssh 的 admin 帳密以及 public ip 在加上你知道 ssh 的 port 是多少並且 ssh port 有被 portforward 出來。
那麼下了以上的指令,你就可以把 [public ip] 內網的 192.168.1.1:80 和 localhost:11111 連在一起了。
以下是示意圖:
[localhost]:11111 <= ssh tunnel => [public ip]:[port] <= connect & redirect => 192.168.1.1:80
也就是下完以上 command,並用網頁瀏覽器開啟 localhost:11111 就可以進到 router 的網頁介面了。
話說開 ssh tunnel 真的很可怕,內網可以說整個全開了,顆顆。
------------------------------- 2017.02.20 reverse tunnel ----------------------------------------
話說以上是 forward tunnel,
建 forward tunnel 是想要 " local 這台 ssh client 機器額外開 port 導到 ssh server 端,然後在由 ssh server 再幫我們導向另外一台的某個 port"。
ssh client (開 port) <================> ssh server =============> forward packet
以下是 reverse tunnel, reverse tunnel 就是幫 ssh server 開後門,
建 reverse tunnel 是想要 "在 remote ssh server 那台機器上額外開 port,然後希望 remote ssh 的那個 port 收到的東西都幫我們導到 local 這台機器的的某個 port"
ssh client <================> ssh server (開 port) <============= receive packet
之前都不知道怎麼建,應該說我知道這東西,但沒實際使用的經驗。
最近有一個 support 要我幫 user 看 router 上的設定,但即使開了 remote beckend,仍然是無法連到 router 網頁的阿。
這時候就是 ssh tunnel 使用的時機:
ssh -L 11111:192.168.1.1:80 -p [port] admin@[public ip]
以上的前提是你有 ssh 的 admin 帳密以及 public ip 在加上你知道 ssh 的 port 是多少並且 ssh port 有被 portforward 出來。
那麼下了以上的指令,你就可以把 [public ip] 內網的 192.168.1.1:80 和 localhost:11111 連在一起了。
以下是示意圖:
[localhost]:11111 <= ssh tunnel => [public ip]:[port] <= connect & redirect => 192.168.1.1:80
也就是下完以上 command,並用網頁瀏覽器開啟 localhost:11111 就可以進到 router 的網頁介面了。
話說開 ssh tunnel 真的很可怕,內網可以說整個全開了,顆顆。
------------------------------- 2017.02.20 reverse tunnel ----------------------------------------
話說以上是 forward tunnel,
建 forward tunnel 是想要 " local 這台 ssh client 機器額外開 port 導到 ssh server 端,然後在由 ssh server 再幫我們導向另外一台的某個 port"。
ssh client (開 port) <================> ssh server =============> forward packet
以下是 reverse tunnel, reverse tunnel 就是幫 ssh server 開後門,
建 reverse tunnel 是想要 "在 remote ssh server 那台機器上額外開 port,然後希望 remote ssh 的那個 port 收到的東西都幫我們導到 local 這台機器的的某個 port"
ssh client <================> ssh server (開 port) <============= receive packet
2016年8月5日 星期五
[gitlab] how to merge request by gitlab
主題:
How to merge request by gitlab
步驟:
1. fork project on gitlab UI, and you will get a git respository location like: git@git.xxxx:[yourname]/[projectname].git
gitlab -> select project -> fork
2. add respository
git remote add upstream git@git.xxxx:[yourname]/[projectname].git
3. check if the repository is added
git remote -v
4. fetch the repository
git fetch upstream
5. push your commit to the repository instead of 'origin' repository
git push upstream master
6. create merge request on gitlab UI
gitlab -> select [merge requests] -> click [New merge request] ....
7. wait project owner to merge the code
8. delete the repository on gitlab UI
2016年5月11日 星期三
use c++ regex parse string enclosed in double quote
主題:
use c++ regex parse string enclosed in double quote難處:
考慮 escaped quote範例:
如果是 std::string s = "\"\\\"aaa\"\"bbb\""; 要 parse 成 \"aaa & bbb以下我直接貼 code, 後面註解是想要 parse 的結果
std::string s = "\"\\\\\"aaa\"\"bbb\""; // \\"aaa & bbb
std::string s = "\"aa\\\"a\" \"bbb\""; // aa\"a & bbb
std::string s = "\"aa\\\\\"a\" \"bbb\""; // aa\\"a & bbb
std::string s = "\"\"\"aaa\"\t \"bbb\""; // empty & aaa & bbb
怎麼寫:
std::regex e ("\"((([^\\\\]*\\\\.)|([^\"]*))*)\"");std::smatch sm;
std::string line = s;
while (std::regex_search (line, sm, e)) {
std::cout << "range with " << sm.size() << " matches\n";
std::cout << "the matches were: ";
for (unsigned i=0; i<sm.size(); ++i) {
std::cout << "[" << sm[i] << "] ";
}
line = sm.suffix().str();
std::cout << std::endl << "line: " << line;
std::cout << std::endl;
}
// 裡面印出的 sm[1] 就是我們想要的結果
參考:
http://stackoverflow.com/questions/21658860/how-to-use-regex-chttp://www.cplusplus.com/reference/regex/match_results/suffix/
http://stackoverflow.com/questions/6863518/regex-match-one-of-two-words
http://stackoverflow.com/questions/249791/regex-for-quoted-string-with-escaping-quotes (Guy BedFord 的寫法再改良)
2015年7月23日 星期四
[vim] display trailing white space
in vim
:highlight ExtraWhitespace ctermbg=red guibg=red
:match ExtraWhitespace /\s\+$/
:highlight ExtraWhitespace ctermbg=red guibg=red
:match ExtraWhitespace /\s\+$/
2015年7月17日 星期五
[data base] mariadb install for python
Env:
Ubuntu 14.10python 2.7
Commands:
import MySQLdb needsapt-get install python2.7-mysqldb
import mysql.connector as mariadb needs
http://dev.mysql.com/downloads/connector/python/
2015年7月15日 星期三
[vimdiff] diffg
在vimdiff下我們可以用好用的diffg來同步
當我們用vimdiff時左右兩邊視窗不一致時,我們可以在左邊視窗用 "大寫V" 選擇要左右sync的區塊,然後再按下 :diffg ,就會把右邊視窗所選的同步到左邊。
如果是按下 :diffget,就會把左邊同步到右邊。
NOTE: 通常不額外設定 git difftool 使用的也是vimdiff。
當我們用vimdiff時左右兩邊視窗不一致時,我們可以在左邊視窗用 "大寫V" 選擇要左右sync的區塊,然後再按下 :diffg ,就會把右邊視窗所選的同步到左邊。
如果是按下 :diffget,就會把左邊同步到右邊。
NOTE: 通常不額外設定 git difftool 使用的也是vimdiff。
2015年7月13日 星期一
[opencv] install
主題: opencv install
很難安裝, 筆記一下
Ubuntu 14.10
- pre install QT4
apt-get install qt4-default libqt4-dev qtchooser qt4-designer
- git clone opencv
git clone https://github.com/Itseez/opencv.git
cd opencv
mkdir release
cd release
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..
sudo make
sudo make install
成功
MAC OS Yosemite 10.10.4
直接brew install opencv會有問題
- 一樣要先裝QT, 但要brew要多下"build-from-source"的option
brew install qt --build-from-source- git clone opencv(這邊就和上面一樣)
失敗...
2015年7月9日 星期四
[Python] hook function for self.x, self.x = 3, delete self.x
主題: hook function for self.x, self.x = 3, delete self.x
說明:
我們有一個class A,假設我們想要在"讀取"self.x或在"設定"self.x時或在"刪除"self.x時可以多做一些"額外的事情(某個function)",那麼該怎麼把我們的function插入呢?
實作:
實作一個descriptor, 並安裝到A中成為class member data。#!/usr/bin/python
class Integer(object):
def __init__(self, name):
self.name = name
def __get__(self, instance, cls):
if instance is None:
return self
else:
return instance.__dict__[self.name]
def __set__(self, instance, value):
if not isinstance(value, int):
raise TypeError('Expected an int')
instance.__dict__[self.name] = value
def __delete__(self, instance):
del instance.__dict__[self.name]
class A(object):
x = Integer('x')
def __init__(self, x, y):
self.x = x
self.y = y
a = A(1.0, 2)
結果:
Traceback (most recent call last): File "./descriptor.py", line 27, ina = A(1.0, 2) File "./descriptor.py", line 24, in __init__ self.x = x File "./descriptor.py", line 15, in __set__ raise TypeError('Expected an int') TypeError: Expected an int
無效:
因為這件事情很重要,再重複一次,"實作一個descriptor, 並安裝到A中成為class member data。"
如果你實作了一個descriptor,但安裝到class中不是成為class member data而是instance data, 這樣是不起作用的。
class A(object):
def __init__(self, x, y):
self.x = Integer('x')
self.y = y
繼承還是有效:
class B(A):
def __init__(self, x, y):
self.x = x
self.y = y
b = B(1.0, 2)
繼承還是有效,因為child class繼承了class member data Traceback (most recent call last): File "./descriptor.py", line 32, inb = B(1.0, 2) File "./descriptor.py", line 29, in __init__ self.x = x File "./descriptor.py", line 15, in __set__ raise TypeError('Expected an int') TypeError: Expected an int
順帶一題:
property, classmethod, staticmethod, __slots__都是相同概念:安裝一個descriptor到class上
2015年7月8日 星期三
2015年7月6日 星期一
[Python] @staticmethod 和 @classmethod
主題: @staticmethod和@classmethod的差別
說明:
這兩個都是decorator,一言以蔽之 classmethod的input function第一個參數必須是class,
而staticmethod則第一個參數就是真的參數。
可以參考這邊(staticmethod/classmethod)
另外一提,這兩個的實作方式和@property的做法很像。
[Python] __slots__ 記憶體優化工具
主題: __slots__
範例:
不使用__slots__優化記憶體(內部為一個hash table)
#!/usr/bin/python
from pympler import asizeof
class A(object):
#__slots__ = ['year', 'month', 'day']
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
a = A(1,2,3)
print asizeof.asized(a, detail=1).format()
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7f15e50e9cd0="" data-blogger-escaped-at="" data-blogger-escaped-object=""> size=552 flat=64
__dict__ size=488 flat=280
__class__ size=0 flat=0
使用__slots__優化記憶體(不存table, 分開以更節省記憶體的方式存)
#!/usr/bin/python
from pympler import asizeof
class A(object):
__slots__ = ['year', 'month', 'day']
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
a = A(1,2,3)
print asizeof.asized(a, detail=1).format()
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x191f6c8="" data-blogger-escaped-at="" data-blogger-escaped-object=""> size=224 flat=72
__slots__ size=80 flat=80
month size=24 flat=24
day size=24 flat=24
year size=24 flat=24
__class__ size=0 flat=0
結論:
使用__slots__優化記憶體 552->224缺點就是因為內部不存hash table, 所以你也只能使用__slots__指定的那些屬性名稱
2015年7月5日 星期日
[Python] property繼承的寫法
主題: property繼承的寫法
假設我們有一個擁有name property的class A:
class A(object):
def __init__(self):
print ("A init")
@property
def name(self):
print ("A name getter")
@name.setter
def name(self, x):
print ("A name setter")
我們想要對A的name property繼承,並且改寫。
改寫的方式想要繼承A原本的一些code再附加新的class的一些code,可以這樣寫:
class B(A):
def __init__(self):
print ("B init")
@property
def name(self):
super(B, B).name.fget(self)
print ("B name getter")
@name.setter
def name(self, x):
super(B, B).name.fset(self, x)
print ("B name setter")
或者把fget和fset換成__get__和__set__
class B(A):
def __init__(self):
print ("B init")
@property
def name(self):
super(B, B).name.__get__(self)
print ("B name getter")
@name.setter
def name(self, x):
super(B, B).name.__set__(self, x)
print ("B name setter")
為什麼可以這樣? 有興趣的人可以去研究一下 property這個class
還有一點要注意, 其實這樣的寫法是"定義B的自己版本name property", 換句話說,
B.name和A.name是兩個不同的版本。
也就是如果B只有定義getter或是setter,那麼這個property也只會剩下getter或是setter的能力:
#!/usr/bin/python
class A(object):
def __init__(self):
print ("A init")
@property
def name(self):
print ("A name getter")
@name.setter
def name(self, x):
print ("A name setter")
class B(A):
def __init__(self):
print ("B init")
@property
def name(self):
super(B, B).name.__get__(self)
print ("B name getter")
b = B()
b.name
b.name = 3
結果:
B init A name getter B name getter Traceback (most recent call last): File "./property.py", line 25, inb.name = 3 AttributeError: can't set attribute Shell 已返回1
結論:
1. child class要改寫parent class的property最好全部都改寫,除非你知道你在做什麼,你真的想閹割parent class的setter or getter or deleter ?
2. child class若要呼叫parent class的class method(memer data), 那就要用 super(B, B).name的寫法
3. property class有實作"descriptor protocol"(__get__, __set__, __delete__這三個function),
property class的__get__會去呼叫 property class的instance method: fget
property class的__set__會去呼叫 property class的instance method: fset
property class的__delete__會去呼叫 property class的instance method: fdel
2015年7月4日 星期六
[Python] decorator的等價寫法
主題: decorator的等價寫法
class A(object):
@property
def func(self):
...
同
class A(object):
def func(self):
...
func = property(func)
換句話說這時候 func經過property之後
1. 從單純的func變成為property
2. func則變為 class variable (不是intance variable)
[Python] property and descriptor protocol
主題: 了解property的概念
簡介:
假設今天我們有一個需求,我們有一個A class:
a = A()
當寫 a.m 我們希望呼叫到 A.f
當寫 a.m = 3我們希望呼叫到 A.g
當寫 del a.m我們希望呼叫到A.p
那我們該如何實作 ?
答案在這邊 (直接參考property這個class的實作方式)
個人理解:
先說一下規則好了,如果一個有實作 "descriptor protocol"的class,假設叫D好了:
當寫
d = D()
d
d = 5
del d
則會觸發
__get__
__set__
__del__
據此,我們可以讓 __get__ 去呼叫A.f
__set__去呼叫A.g
__del__去呼叫A.p
就可以達到題目需求....
但這樣很不彈性,
因此我們再多寫三個function以便有機會可以替換掉
A.f
A.g
A.p
其實以上就是property的概念:
"
Property是一個class擁有fget, fset, fdel這三個function,
我們可以用 getter, setter, deleter去註冊這三個function,
且getter, setter, deleter回傳都是Proptery object。
"
"
Property是一個class擁有fget, fset, fdel這三個function,
我們可以用 getter, setter, deleter去註冊這三個function,
且getter, setter, deleter回傳都是Proptery object。
"
2015年7月2日 星期四
[Python] 雙底線的用處
目的: 了解雙底線的用處
1. 不可繼承
2. public
3. 不管是class member或method都遵循這個規則
以下用class method舉例:
#!/usr/bin/python
class A(object):
def __init__(self):
pass
def test1(self):
print "test1"
def __test2(self):
print "test2"
class B(A):
def __init__(self):
pass
b = B()
b.test1()
b.__test2()
結果:(注意test1有印出來但呼叫__test2時發生AttributeError的Exception)
test1 Traceback (most recent call last): File "./private.py", line 18, inb.__test2() AttributeError: 'B' object has no attribute '__test2'
訂閱:
文章 (Atom)