아래 명령을 이용해서 빈 줄을 삭제할 수 있다.
:g/^$/d
make 에는 -j 옵션이 있고, 이 옵션은 한번에 수행할 수 있는 job 을 지정하는 옵션이다.
이 job의 수는 총 core 개수 + core 개수의 20% 를 추가하는 것이 가장 효율이 좋다고 알려져 있다. 즉
job 수 = core 개수 + round(core 개수 * 0.2)
가 된다.
즉 Q6600 같이 core가 4개라면 4 + round(4 * 0.2) = 5가 된다.
시스템 마다 이것을 계산하는 shell script를 짜면 아래와 같다.
#~/bin/sh
cores=`cat /proc/cpuinfo | grep cores | wc -l`
jobs=`echo "$cores + $cores*0.2"|bc`
echo $jobs|awk '{print int($1+0.5)}'
아래 명령을 통해서 빌드를 위한 패키지를 설치한다.
$ sudo apt-get build-dep wine-unstable
이 상태에서는 실제로 빌드가 되지 않는다. 아래 명령으로 추가 패키지를 설치해야 한다.
$ sudo apt-get install ia32-libs-dev
설치가 끝나면 wine 소스를 받는다(wine 홈페이지에서 소스를 받아도 된다).
$ sudo apt-get source wine-unstable
받은 소스를 풀고 원하는 패치를 한 후에 빌드하면 된다.
$ ./configure $ make
이 문서는 Debian Linux에서 Local Deb Repository를 만드는 방법을 기술한다.
Debian Linux를 사용하다보면 인터넷의 Repository를 사용하지 않고
Local Repository를 만드는 순서는 아래와 같다.
$ sudo mkdir -p /var/local/deb
$ sudo cp filename.deb /var/local/deb
$ cd /var/local $ su # dpkg-scanpackages deb | gzip -9c > deb/Packages.gz
아래 명령으로 source list 파일을 생성한다.
$ sudo vi /etc/apt/sources.list.d/local.list
파일 내용은 아래와 같다
# local package deb file:/var/local deb/
$ sudo apt-get update
이 문서는 Debian Linux에서 Mastroska(.mkv) 파일의 트랙을 추출하고 합치는 방법에 대해서 기술한다. 간혹 재생이 잘 안되는 Mastroska 파일은 트랙을 추출/합치는 것 만으로 재생이 잘될 때가 있다.
아래 명령으로 필요한 패키지를 설치한다.
$ sudo apt-get install mkvtoolnix
mkvinfo를 이용해서 추출할 트랙 정보를 얻는다.
$ mkvinfo -s filename.mkv | head -3
아래와 같은 정보를 얻을 수 있다.
Track 1: video, codec ID: V_MPEG4/ISO/AVC, default duration: 33.367ms (29.970 fps for a video track), language: und, pixel width: 640, pixel height: 480, display width: 640, display height: 480
Track 2: audio, codec ID: A_MPEG/L3, default duration: 24.000ms (41.667 fps for a video track), language: und, sampling freq: 48000, channels: 2
I frame, track 1, timecode 0 (00:00:00.000000000), size 36297, adler 0x5bfac6c8
여기서 추출할 track을 결정한다(위 예제에서는 video 1개 audio 1개가 있지만, audo track 이 여러 개인 경우가 있다).
mkvextract를 통해서 트랙을 추출한다.
$ mkvextract tracks filename.mkv 1:video1 2:audio1
트랙번호:파일이름 형식을 사용하면 된다. 만일 1번과 3번 트랙을 추출하려면
$ mkvextract tracks filename.mkv 1:video1 3:audio3
mkvmerge를 통해서 추출한 트랙을 합친다.
$ mkvmerge --default-duration 0:29.970fps vidio1 audio1 -o output_filename.mkv
이 때 fps 값은 추출한 video track의 fps를 사용한다.
VirtualBox에서는 VBoxManage 라는 command 도구를 제공하는데, 특정 가상머신을 바로 실행 시킬 수 있다.
Apple script를 이용해서 내가 원하는 가상 머신을 바로 실행 시키는 코드를 작성해보았다.
tell me
activate
do shell script "VBoxManage startvm \"Debian Linux\""
end tell
Safari 5.0 부터 확장 프로그램(Extention)이 기능으로 추가되었다. 개발자용 메뉴에서 확장 프로그램 활성화 기능을 켜주면 사용할 수 있다.
기능을 활성화 시킨 후 환경설정을 보면 확장 프로그램탭이 추가되어 있는 것을 확인할 수 있다.
이름 | 설명 |
AdBlock | AdBlock의 Extension 버전. |
Gentle Status Bar | Chrome과 비슷한 상태표시줄을 만들어준다. |
ClickToFlash | ClickToFlash의 Extention 버전. |
Better Google Reader | 구글 리더에 몇 가지 기능을 추가해준다. |
greader-bgtabs | 구글 리더에서 v키로 현재 글을 새 tab으로 열 때 배경 탭으로 열리게 해준다. |
SafariRestore | Safari를 종료할 때 열려있던 탭 정보를 기억했다가 복구해준다. 비슷한 기능이 SafariStand에도 들어있지만 Extention 쪽이 좀 더 자연스럽게 동작하는 것 같다. |
MiddleButtonScroll | 마우스 가운데 버튼을 클릭하고 마우스를 이동하면 그대로 스크롤이 된다. |
SIMBL의 플러그인 형태로 기능을 확장할 수 있다
이름 | 설명 |
GreaseKit | Safari에서 User Script를 사용할 수 있게 해준다. |
Safari Stand | Safari에서 Quick Search등의 기능을 추가해준다 |
SafariGestures | Safari에서 마우스 제스쳐를 지원해준다. |
megazoomer | Cocoa Application을 전체 화면으로 실행시켜 준다 |
이 문서는 Snow Leopard에서 PyQt를 설치하는 방법을 기술한다.
아래 경로에서 Cocoa 버전의 QT 를 다운 받는다.
http://qt.nokia.com/downloads/qt-for-open-source-cpp-development-on-mac-os-x
아래 경로에서 PyQt를 다운 받는다.
http://www.riverbankcomputing.co.uk/software/pyqt/download
아래 경로에서 sip를 다운 받는다.
http://www.riverbankcomputing.co.uk/software/sip/download
우선 터미널에서 아래와 같이 sip를 빌드하고 설치한다.
$ export MACOSX_DEPLOYMENT_TARGET=10.6 $ python configure.py --universal --arch=i386 --arch=x86_64 -s MacOSX10.6.sdk $ make $ sudo make install
$ export QTDIR=/Developer/Applications/Qt $ python configure.py --confirm-license --use-arch=i386 --use-arch=x86_64 $ make $ sudo make install
아래와 같은 python 코드를 저장하고 실행해본다
import sys
from PyQt4 import QtCore, QtGui
def translate(widgetname, defstr):
return QtGui.QApplication.translate(widgetname, defstr)
class Sample(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Sample, self).__init__(parent)
self.setWindowTitle(translate(u'mainwindow', u'Sample'))
self.resize(250, 150)
self.setCenter()
self.statusBar().showMessage(translate(u'mainwindow', u'Ready'))
workarea = QtGui.QWidget(self)
quit = QtGui.QPushButton(translate(u'mainwindow', u'Close'), workarea)
workarea.connect(quit, QtCore.SIGNAL('clicked()'), self, QtCore.SLOT('close()'))
quit.setToolTip(translate(u'mainwindow', u'This is a close button.'))
QtGui.QToolTip.setFont(QtGui.QFont(u'Tahoma', 10))
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(quit)
vbox = QtGui.QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
workarea.setLayout(vbox)
self.setCentralWidget(workarea)
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(
self,
translate(u'messagebox', u'Question'),
translate(u'messagebox', u'Are you sure to quit?'),
QtGui.QMessageBox.Yes,
QtGui.QMessageBox.No)
if QtGui.QMessageBox.Yes == reply:
event.accept()
else:
event.ignore()
def setCenter(self):
screen = QtGui.QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = Sample()
main.show()
sys.exit(app.exec_())
실행하면 아래와 같은 화면이 표시된다.
Debian에서 Opera를 사용하는 경우 flash 안에 있는 버튼이 클릭되지 않을 때가 있다. 이때 아래와 같은 방법으로 해결할 수 있다.
compiz을 사용하지 않으면 3D 화면 효과를 사용할 수 없고, 페이지 전체를 선택하는 방법은 매번 귀찮게 키보드를 누르기 때문에 GDK_NATIVE_WINDOWS환경 변수를 설정하는 것이 편리하다.
아래 명령으로 /usr/lib/opera/operapluginwrapper파일을 편집한다.
$ sudo vi operapluginwrapper
파일을 열고 맨 아래 부분을 아래처럼 고쳐서 operapluginwrapper 가 실행하기 전 환경 변수를 설정한다.
export GDK_NATIVE_WINDOWS=1
exec "$wrapper" "$@"
Opera 10.5x 버전부터 UserScript에서 아래와 같이 load 이벤트에 대해서 함수 연결이 되지 않는다.
document.addEventListener('load', function() {
alert(1);
}, false);
아래와 같이 그냥 실행하도록 수정한다.
(function () {
alert(1);
})();
출처 : http://www.google.com/support/forum/p/youtube/thread?tid=46dd241356fbad51&hl=en
최신 flash player를 설치했음에도 불구하고 Opera로 Youtube를 접속하면 flash를 업데이트하라는 메시지가 표시된다. 이때는 user script 폴더에 YoutubeProtectionRemover.js파일을 만들어 주면 된다.
// ==UserScript==
// @name YoutubeProtectionRemover
// @include http://www.youtube.com/*
// @description Removes lame protection on YouTube
// @copyright 2010, Snap
// ==/UserScript==
window.opera.addEventListener('BeforeScript', function (ev){
ev.element.text = ev.element.text.replace("yt.flash.update(swfConfig, forceUpdate);","");
}, false);
백업용으로 보관. 원문은 http://www.silvermac.com/mac-os-x-keyboard-shortcuts/.
shortcut | description |
X | Force Mac OS X startup |
C | Start up from a bootable CD |
N | Attempt to start up from a compatible network server (NetBoot) |
T | Start up in FireWire Target Disk mode |
Opt-Cmd-Shift-Delete | Seeks a different startup volume |
Shift | Start up in Safe Boot mode |
Cmd-V | Start up in Verbose mode |
Cmd-S | Start up in Single-User mode |
Cmd-Opt-Esc | Force Quit menu |
Cmd-Opt-D | Show/hide the dock |
Ctrl-Eject | Bring up Shutdown/Sleep/Logout Dialog |
Ctrl-Cmd-Eject | Restart immediately |
shortcut | description |
Cmd-C | Copy |
Cmd-V | Paste |
Cmd-X | Cut |
Cmd-A | Select All |
shortcut | description |
Cmd-N | New Finder window |
Cmd-W | Close Window |
Opt-Cmd-W | Close all Windows |
Cmd-Down | Open File/Folder |
Cmd-Up | Navigate to parent |
Cmd-Right | Expand folder (in list view) |
Cmd-Left | Collapse Folder (in list view) |
Opt-Cmd-Right | Expand folder and its subfolders (in list view) |
Opt-Cmd-Up | Open parent folder and close current window |
Cmd-Shift-H | Jump to your Home folder |
Cmd-Shift-A | Jump to your Applications folder |
Cmd-Shift U | Jump to your Utilities folder |
Cmd-Shift K | Jump to the Network browser |
Cmd-Shift G | Goto Folder… |
Cmd-1 | View as Icons |
Cmd-2 | View as List |
Cmd-3 | View as Columns |
Cmd-Space | Open Spotlight (OS X 10.4) |
Cmd-Delete | Move file/folder to trash |
Cmd-Click window title | Display the file path |
shortcut | description |
shortcut | description |
Shift-Cmd-Q | Log out |
Shift-Opt-Cmd-Q | Log out immediately |
Shift-Cmd-Delete | Empty Trash |
Opt-Shift-Cmd-Delete | Empty Trash without dialog |
Cmd-H | Hide window |
Opt-Cmd-H | Hide Others |
Cmd-N | File New window |
Shift-Cmd-N | New Folder |
Cmd-O | Open |
Cmd-S | Save |
Shift-Cmd-S | Save as |
Cmd-P | |
Cmd-W | Close Window |
Opt-Cmd-W | Close all Windows |
Cmd-I | Get Info |
Opt-Cmd-I | Show Attributes Inspector |
Cmd-D | Duplicate |
Cmd-L | Make Alias |
Cmd-R | Show original |
Cmd-T | Add to Favorites |
Cmd-Delete | Move to Trash |
Cmd-E | Eject |
Cmd-F | Find |
Cmd-Z | Undo |
Cmd-B | Hide Toolbar |
Cmd-J | Show View Opts |
Cmd | [ = Go Back |
Cmd | ] = Go Forward |
Shift-Cmd-C | Go to Computer |
Shift-Cmd-H | Go to your Home folder |
Shift-Cmd-I | Go to iDisk |
Shift-Cmd-A | Go to Applications folder |
Shift-Cmd-G | Go to Go-To Folder |
Cmd-K | Connect to Server |
Cmd-M | Minimize Window |
Cmd-? | Open Mac Help |
Cmd-Space | Open Spotlight (OS X 10.4) |
shortcut | description |
Cmd-Shift 3 | Capture the screen to a file |
Cmd Ctrl Shift 3 | Capture the screen to the clipboard |
Cmd-Shift 4 | Select an area to be captured to a file |
Cmd Ctrl Shift 4 | Select an area to be captured to the clipboard |
Cmd-Shift 4, then press Space | Capture entire window |
shortcut | description |
Opt-Cmd-* (asterisk) | Turn on Zoom |
Opt-Cmd-+ (plus) | Zoom in |
Opt-Cmd? (minus) | Zoom out |
Cmd-Opt-Ctrl-8 | Invert Screen colours |
shortcut | description |
Cmd-W | Close window |
Cmd-Opt-W | Close all windows |
Cmd-M | Minimise window |
Cmd-Opt-M | Minimise all windows |
Cmd-H | Hide Application |
Cmd-~ | Cycle through windows for current application |
Ctrl-F4 | Cycle through every open window |
Cmd-Tab | Bring up the Application Switcher. |
Cmd-Tab | Cycle Forwards |
Cmd-~ | Cycle Backwards |
Cmd-Shift-Tab | Cycle Backwards |
Cmd-Q | Quit application |
shortcut | description |
F9 | Show all open windows on the screen at once |
F10 | Show all windows for the current application. |
F11 | Shows Desktop |
F12 | Activates Dashboard |
F12 (hold) | ejects disk |
shortcut | description |
Opt-Cmd-D | Show/Hide Dock |
Ctrl-Up | Move up one page |
Ctrl-Down | Move down one page |
Opt-Drag | Copy to new location |
Opt-Cmd-Drag | Make alias in new location |
Cmd-Drag | Move to new location without copying |
Opt-Cmd-Eject | Sleep |
Cmd-click window toolbar button (upper right corner) | Cycle through toolbar views |
Ctrl-Cmd-D and mouse over word in Cocoa applications | shows Dictionary description for that word |
usb device를 연결했을 때 아래와 같이 동일한 장치에 대해서 두 번 mount 되는 경우가 있다.
$ mount /dev/sdg1 on /media/MARKBOY_IPO type vfat (rw,nosuid,nodev,uhelper=udisks,uid=1000,gid=1000,shortname=mixed,dmask=0077,utf8=1,flush) /dev/sdg1 on /media/MARKBOY_IPO-1 type vfat (rw,nosuid,nodev,sync,uhelper=hal,umask=002)
gnome-volume-manager와
$ sudo apt-get remove halevt
PulseAudio를 audio server로 사용할 때 PulseAudio를 사용하는 다른 응용프로그램(리듬 박스등)이 실행 중일 때 flash가 동작하지 않거나 소리가 들리지 않는 증상이 있다(그 반대의 증상도 나타난다).
아래와 같은 설정을 추가하면 문제가 해결된다.
아래와 같은 내용으로 ~/.asoundrc파일을 만든다.
pcm.pulse { type pulse }
ctl.pulse { type pulse }
pcm.!default { type pulse }
ctl.!default { type pulse }
기상청 홈페이지가 개편되면서 날씨 정보에 대한 xml를 제공하기 시작했습니다. 그러나 기온 변화 그래프에서 필요한 현재 시간 날씨 정보에 대해서는 xml 데이타를 제공하지 않습니다.
기온 변화 그래프를 계속 그리기 위해서 기상청 웹페이지를 해석해서 그래프로 그리는 간단한 python 스크립트를 작성해봤습니다.
이 스크립트는 기상청 페이지를 가져와서 xml로 변환하는 buildwexml.py와 그래프를 그리는 gengraph.py 두 부분으로 나뉘어 있습니다.
이 스크립트는 Debian Linux, python 2.5 환경에서 제작, 테스트 되었습니다.
코드는 아래와 같습니다
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""gengraph.py
buildwexml.py를 이용해 생성한 xml 파일을 가지고 그래프를 그리는 스크립트
"""
__author__ = 'Yun-yong Choi'
__version__ = '0.1'
import time
import xml.etree.ElementTree
import Gnuplot, Gnuplot.funcutils
import buildwexml
# 데이타를 저장할 경로
write_root = '/tmp/'
# 그래프 파일 경로
graph_filename = '/home/markboy/temperature_graph.png'
writeinfo = {
u'서울':[u'seoul.dat', u'Seoul'],
u'부산':[u'busan.dat', u'Busan'],
u'제주':[u'jeju.dat', u'Jeju'],
}
findcities = [ u'서울', u'부산', u'제주' ]
# web에서 xml 정보를 가져온다.
buildwexml.build(write_root + 'current.xml')
#xml을 해석한다.
xmlobj = xml.etree.ElementTree.parse(write_root + 'current.xml')
timestr = time.strftime('%Y/%m/%d %H',
time.strptime(xmlobj.getiterator('datetime')[0].attrib['data'], '%Y.%m.%d.%H:%S') )
# city node를 순회한다.
for city in xmlobj.getiterator('city'):
# 찾는 도시가 있으면
if city.attrib['name'] in findcities :
# 기온값을 저장한다.
f = file(write_root + writeinfo[city.attrib['name']][0], 'at')
f.write("%s %s\n" % (timestr, city.find('temperature').find('now').attrib['data']))
f.close()
# 일주일분만 표시하기 위해서 7일전 날짜를 구한다.
ago = time.time() - 60 * 60 * 24 * 7
ago_str = time.strftime("%Y/%m/%d", time.localtime(ago) )
# plot 파일 저장
f = file(write_root + 'temperature_graph.plot', 'wt')
f.write("""
set term png small
set size 1.0, 0.6
set output '%s'
set grid
set key left bottom
set ylabel \"Temperature(C)\"
set xdata time
set timefmt \"%%Y/%%m/%%d\"
set xrange [\"%s\":]
set timefmt \"%%Y/%%m/%%d %%H\"
set format x \"%%m/%%d\"
plot """ % (graph_filename, ago_str) )
for key in writeinfo.keys() :
f.write("'%s' using 1:3 title \"%s\" with line" % (write_root + writeinfo[key][0], writeinfo[key][1]))
if key <> writeinfo.keys()[-1] :
f.write(', ')
f.close()
# 그래프 그리기
g = Gnuplot.Gnuplot()
g.load(write_root + 'temperature_graph.plot')
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" buildwexml.py
기상청의 현재 날씨 정보 페이지를 가져와서 xml 파일을 만드는 스크립트
"""
__author__ = 'Yun-yong Choi'
__version__ = '0.2'
import os
import sys
import codecs
import urllib2
def getWebpage(url, referer='') :
"""url 파일을 읽어온다"""
debug = 0
if debug :
return file(url.split('/')[-1], 'rt').read()
else :
opener = urllib2.build_opener()
opener.addheaders = [
('User-Agent', 'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)'),
('Referer', referer),
]
return opener.open(url).read()
def getMainPage():
return getWebpage('http://www.kma.go.kr/weather/observation/currentweather.jsp')
def getDataPage():
return getWebpage('http://www.kma.go.kr/weather/observation/currentweather_data.jsp', 'http://www.kma.go.kr/weather/observation/currentweather.jsp' )
def normalize(s):
"""<td> tag와 를 제거한 문자열을 돌려준다.
s - 입력 문자열
"""
return s.replace('<td>', '').replace('</td>', '').replace(' ', '')
def printUsing():
"""사용 방법을 출력한다"""
print sys.argv[0], '<output file name>'
def getDateTime(buffers):
""" html 내용을 해석해서 데아타가 생성된 날짜를 얻는다. 날짜 형식은 yyyy.mm.dd.HH:SS 이다.
buffers - html 파일 내용
"""
return buffers.split('<p class="table_topinfo">')[1].split('</p>')[0].split('/>')[-1]
def getDatablocks(buffers):
"""html 내용을 해석해서 도시별로 묶은 list를 돌려준다
buffers - html 파일 내용
"""
# <table class="table_develop 앞부분을 잘라낸다.
a = buffers.split('<table class="table_develop"')[1]
# 맨 처음 만나는 </table>을 기준으로 뒤를 잘라낸다.
b = a.split('</table>')[0]
# </thread>를 기준으로 앞을 잘라낸다.
c = b.split('</thead>')[1].replace('<tr>', '')
# 빈 줄 제거
r = ''
for line in c.split('\n') :
line = line.decode('cp949').encode('utf-8')
line = line.strip()
if len(line) > 0 :
r = r + line + '\n'
# </tr> 기준으로 잘라내면 데이타 block이 완성된다.
return r.split('</tr>\n')[:-1] # 마지막 block은 버린다.
def writeXMLheader(out):
"""XML header를 기록한다."""
out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
out.write('<xml>\n')
out.write(' <current_weather>\n')
def writeXMLfooter(out):
"""XML footer를 기록한다."""
out.write(' </current_weather>')
out.write('</xml>')
def writeXMLnode(out, datablock):
data = datablock.split('\n') # 0번째 <tr>부분은 버린다.
# 0 - 이름
city = data[0].split('</a>')[0].split('>')[2]
out.write(""" <city name="%s">
<!-- 날씨 -->
<weather>
<!-- 현재일기 -->
<now data="%s" />
<!-- 시정(km) -->
<visibility data="%s" />
<!-- 운량 (1/10) -->
<clouds data="%s" />
<!-- 중하운량 -->
<ml_clouds data="%s" />
</weather>
<!-- 기온 -->
<temperature>
<!-- 현재 기온 -->
<now data="%s" />
<!-- 이슬점온도 -->
<dew_point_c data="%s" />
<!-- 체감 온도 -->
<wind_chill_c data="%s" />
</temperature>
<!-- 강수 -->
<precipitation>
<!-- 일강수(mm) -->
<now data="%s" />
<!-- 적설 (cm) -->
<snow_cover data="%s" />
<!-- 습도 (%%) -->
<humidity data="%s" />
</precipitation>
<!-- 바람 -->
<wind>
<!-- 풍향 -->
<direction data="%s" />
<!-- 풍속(m/sec) -->
<speed data="%s" />
</wind>
<!-- 기압 (hPa) -->
<atmospheric_pressure>
<!-- 해면 기압 -->
<see_level data="%s" />
</atmospheric_pressure>
</city>
""" % (city,
normalize(data[1]),
normalize(data[2]),
normalize(data[3]),
normalize(data[4]),
normalize(data[5]),
normalize(data[6]),
normalize(data[7]),
normalize(data[8]),
normalize(data[9]),
normalize(data[10]),
normalize(data[11]),
normalize(data[12]),
normalize(data[13]) ) )
def build(outputname) :
""" 기상청 사이트에서 현재 날씨 정보를 읽어와서 xml로 저장한다.
outputname - 저장할 파일 이름
"""
out = file(outputname, 'wt')
writeXMLheader(out)
out.write(' <datetime data="%s" />\n' % getDateTime(getMainPage()))
for datablock in getDatablocks(getDataPage()) :
writeXMLnode(out, datablock)
writeXMLfooter(out)
if __name__ == '__main__' :
if len(sys.argv) <> 2 :
printUsing()
sys.exit(1)
build(sys.argv[1])
맥북에서 다음 TV 팟을 보려고 하면 미묘한 화면 길이 때문에 약간의 스크롤을 필요로 한다. 또한 덧글의 수준이 매우 낮은데 기본으로 덧글을 표시해서 귀찮다.
내가 보기 싫은 element를 숨기도록 user script를 작성했다.
// ==UserScript==
// @name tvpot.user.js
// @author Yun-yong, Choi
// @version 0.1
// @include http://tvpot.daum.net/*
// @compatible Opera 9
// @description Macbook 에서 TV pot을 볼때 페이지 길이를 줄이기 위해서 상단의 일부 메뉴와 덧글을 숨기는 script.
// ==/UserScript==
(function () {
function getElementsByClass( searchClass, domNode, tagName) {
if (domNode == null) domNode = document;
if (tagName == null) tagName = '*';
var el = new Array();
var tags = domNode.getElementsByTagName(tagName);
var tcl = " "+searchClass+" ";
for(i=0,j=0; i<tags.length; i++) {
var test = " " + tags[i].className + " ";
if (test.indexOf(tcl) != -1) el[j++] = tags[i];
}
return el;
}
function hideClass(className) {
var els = getElementsByClass(className);
for (var i=0; i < els.length; i++) els[i].style.display = "none";
}
function hideId(id) {
var els = document.getElementById(id);
if (els) els.style.display = "none";
}
///// 화면 상단
// 최상위 메뉴 숨김
hideId("DaumUI__minidaum");
// TV Pot 로고 제거
hideId("gnbLogoNav");
// TV pot 메뉴 제거
//hideId("gnbTabNavNew");
// title, 브랜드팟 이동 메뉴 모두 제거
hideClass("brandPotHeadWrap");
// title 스킨 제거
//hideClass("header");
// 브랜드 팟 이동 메뉴 제거
//hideClass("brandPotNav");
///// 화면 하단
// 통계 제거
hideId("statisticsArea");
// 추천 메뉴 제거
hideClass("etcClipInfor");
// 마이팟 담기, 통계 메뉴 제거
hideClass("clipEtcFucntion");
// 댓글 제거
hideClass("commentArea");
// 브랫드 팟 랭킹 목록 제거
hideClass("brandPotRankingList");
// 동영상을 화면 상단에 표시하기 위해서 화면을 scroll
// @todo 계산을 해서 scroll 하도록 수정해야 한다.
scrollTo(0, 100);
})();
debian에서 eclipse 실행 시 오류가 발생할 때 수정하는 방법을 기술한다.
실행 시 아래와 같이 Integrated browser support not working오류 창이 발생 한다.
라이브러리가 설치되지 않아서 발생한 문제이다. 임시로 icedove 패키지를 설치하고 라이브러리를 링크한다.
$ sudo apt-get install icedove $ $ sudo ln -s /usr/lib/icedove/libgtkembedmoz.so /usr/lib/xulrunner/libgtkembedmoz.so
실행 시 같은 오류 창이 발생한다. 이때는 로그 파일을 읽어서 원인을 찾아야 한다.
로그 내용이 아래와 비슷하면, Welcome screen 표시 못하는 경우이다.
!SESSION 2010-01-22 00:28:09.672 -----------------------------------------------
eclipse.buildId=M20080911-1700
java.version=1.6.0_0
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=ko_KR
Framework arguments:
Command-line arguments: -os linux -ws gtk -arch x86_64
!ENTRY org.eclipse.osgi 4 0 2010-01-22 00:28:14.675
!MESSAGE Application error
!STACK 1
org.eclipse.swt.SWTError: XPCOM error -2147467262
at org.eclipse.swt.browser.Mozilla.error(Mozilla.java:1638)
at org.eclipse.swt.browser.Mozilla.setText(Mozilla.java:1861)
at org.eclipse.swt.browser.Browser.setText(Browser.java:737)
at org.eclipse.ui.internal.intro.impl.presentations.BrowserIntroPartImplementation.generateContentForPage(BrowserIntroPartImplementation.java:252)
at org.eclipse.ui.internal.intro.impl.presentations.BrowserIntroPartImplementation.dynamicStandbyStateChanged(BrowserIntroPartImplementation.java:451)
at org.eclipse.ui.internal.intro.impl.presentations.BrowserIntroPartImplementation.doStandbyStateChanged(BrowserIntroPartImplementation.java:658)
at org.eclipse.ui.internal.intro.impl.model.AbstractIntroPartImplementation.standbyStateChanged(AbstractIntroPartImplementation.java:249)
at org.eclipse.ui.internal.intro.impl.model.IntroPartPresentation.standbyStateChanged(IntroPartPresentation.java:443)
at org.eclipse.ui.intro.config.CustomizableIntroPart.standbyStateChanged(CustomizableIntroPart.java:266)
at org.eclipse.ui.internal.ViewIntroAdapterPart$2.run(ViewIntroAdapterPart.java:74)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.ui.internal.ViewIntroAdapterPart.setStandby(ViewIntroAdapterPart.java:70)
at org.eclipse.ui.internal.ViewIntroAdapterPart$1.propertyChanged(ViewIntroAdapterPart.java:55)
at org.eclipse.ui.internal.WorkbenchPartReference.fireInternalPropertyChange(WorkbenchPartReference.java:374)
at org.eclipse.ui.internal.WorkbenchPartReference.fireZoomChange(WorkbenchPartReference.java:539)
at org.eclipse.ui.internal.PartPane.setZoomed(PartPane.java:349)
at org.eclipse.ui.internal.PartStack.setZoomed(PartStack.java:1526)
at org.eclipse.ui.internal.PartSashContainer.zoomIn(PartSashContainer.java:884)
at org.eclipse.ui.internal.PartSashContainer.childRequestZoomIn(PartSashContainer.java:905)
at org.eclipse.ui.internal.LayoutPart.requestZoomIn(LayoutPart.java:354)
at org.eclipse.ui.internal.PartStack.setState(PartStack.java:1501)
at org.eclipse.ui.internal.WorkbenchPage.setState(WorkbenchPage.java:3872)
at org.eclipse.ui.internal.WorkbenchPage.toggleZoom(WorkbenchPage.java:3944)
at org.eclipse.ui.internal.WorkbenchIntroManager.setIntroStandby(WorkbenchIntroManager.java:201)
at org.eclipse.ui.internal.WorkbenchIntroManager.showIntro(WorkbenchIntroManager.java:136)
at org.eclipse.ui.internal.WorkbenchWindow$20.runWithException(WorkbenchWindow.java:2182)
at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:133)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3378)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3036)
at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
at org.eclipse.ui.internal.Workbench$25.runWithException(Workbench.java:1361)
at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:133)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3378)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3036)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2293)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2198)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:493)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:288)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:488)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:193)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:386)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:549)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:504)
at org.eclipse.equinox.launcher.Main.run(Main.java:1236)
at org.eclipse.equinox.launcher.Main.main(Main.java:1212)
아래와 같이 실행한다.
$ eclipse -vmargs -Dorg.eclipse.swt.browser.XULRunnerPath=/usr/lib/xulrunner/
eclipse가 실행되면 Workbench아이콘을 눌러서 Welcome screen을 끄면 다음 실행부터는 오류가 발생하지 않는다.
사진 파일(jpg)의 시간을 사진을 찍은 시간으로 변경하는 python script. EXIF.py를 사용한다.
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""jpg 파일 변경 시간을 exif 에서 읽어온 시간으로 변경한다."""
__version__ = '0.1'
import os
import sys
import time
import dircache
import EXIF
# 허가할 확장자 목록
EXTENSIONS = ('.jpg', '.jpeg')
# 사진을 찍은 시간을 얻을 필드. 처음 발견하는 필드를 사용한다.
TAGS = ['Image DateTime', 'EXIF DateTimeOriginal', 'DateTime']
def printUsing():
"""사용 방법을 출력한다.
"""
print sys.argv[0], '<file or directory>'
def EXIFDateTime2time(exifdatetime):
"""exif의 시간 문자열을 time 값으로 변경한다.
@param[in] exifdatetime 시간 문자열
@return 변환된 time 값
"""
return time.mktime(time.strptime(exifdatetime, '%Y:%m:%d %H:%M:%S'))
def correctJPGTime(filename):
"""jpg 파일 변경 시간을 수정한다.
@param[in] filename 수정할 파일 이름
"""
fnl = filename.lower()
for ext in EXTENSIONS:
# 파일 확장자 검사
if fnl.endswith(ext):
f = file(filename, 'rb')
# exif tag를 읽는다.
tags = EXIF.process_file(f, details=False)
for key in TAGS:
if key in tags:
# TAGS 중 처음 발견한 tag의 시간 값을 사용한다.
exif_time = EXIFDateTime2time(str(tags[key]))
statinfo = os.stat(filename)
if exif_time != statinfo.st_mtime:
# 시간이 다르면 파일 시간을 변경한다.
os.utime(filename, (statinfo.st_atime, exif_time))
print 'fix:', filename
break
break
def main():
if os.path.isdir(sys.argv[1]):
# 주어진 인자가 디렉토리면
for name in dircache.listdir(sys.argv[1]):
# 디렉토리의 파일들에 대해서 수정 작업을 한다.
# sub directory에 대해서는 아무 작업도 하지 않는다.
fullname = sys.argv[1] + os.path.sep + name
if os.path.isfile(fullname):
correctJPGTime(fullname)
elif os.path.isfile(sys.argv[1]):
# 주어진 인자가 파일이면
correctJPGTime(sys.argv[1])
if __name__ == '__main__':
if len(sys.argv) < 2:
printUsing()
sys.exit(1)
main()
gcc에서 target platform이 64bit 환경인지 확인하기 위해서 아래 매크로들이 정의되었는지 확인하면 된다3.2이상에서 확인할 수 있다검사할 64bit 가 LP64만 존재할 경우 gcc 3.4이상에서는 __LP64__매크로 정의 여부만 확인해도 된다..
__alpha__
__ia64__
__ppc64__
__s390x__
__x86_64__
예제 코드는 아래와 같다
#include <stdio.h>
int main(int argc, char **argv)
{
#if defined(__alpha__) || defined(__ia64__) || defined(__ppc64__) || defined(__s390x__) || defined(__x86_64__)
printf("64\n");
#else
printf("32\n");
#endif
}