ZSH 기본 설정 변경

|

ZSH 기본 설정 변경

ZSH 기본 설정은 ~/.zshrc 파일에서 세팅할 수 있습니다. ~/.zshrc 파일은 터미널을 처음 실행했을 때 실행되는 환경 변수 파일이기도 합니다. (.bashrc 파일과 유사)


기본 테마를 agnoster로 변경

~/.zshrc 파일을 열어서 다음과 같이 변경합니다. 기본 값은 ZSH_THEME="robbyrussell" 입니다.

ZSH_THEME="agnoster"

만약 실행할 때마다 랜덤으로 테마를 변경하고 싶으면 다음과 같이 설정할 수도 있습니다.

ZSH_THEME="random"


테마 색상(팔레트) 변경

가독성이 좋은 Solarize 색상 테마로 변경하는 방법입니다. 저는 Solarize 색상 테마 안의 Dark Theme를 사용하고 있습니다.

sudo apt-get install dconf-cli

git clone git://github.com/sigurdga/gnome-terminal-colors-solarized.git ~/.solarized
cd ~/.solarized
./install.sh

This script will ask you which color scheme you want, and which Gnome Terminal profile to overwrite.

Please note that there is no uninstall option yet. If you do not wish to overwrite any of your profiles, you should create a new profile before you run this script. However, you can reset your colors to the Gnome default, by running:

    Gnome >= 3.8 dconf reset -f /org/gnome/terminal/legacy/profiles:/
    Gnome < 3.8 gconftool-2 --recursive-unset /apps/gnome-terminal

By default, it runs in the interactive mode, but it also can be run non-interactively, just feed it with the necessary options, see 'install.sh --help' for details.

Please select a color scheme:
1) dark
2) dark_alternative
3) light
#? 1

Please select a Gnome Terminal profile:
1) Unnamed
#? 1
~~~

그런 다음 .zshrc 파일 맨 아래에 아래 항목을 추가합니다.

eval `dircolors ~/.dir_colors/dircolors`

그 다음 터미네이터의 Preferences 에서 Profiles > ColorsBuilt-in schemes 항목을 엽니다. Solarized dark 항목이 추가되어 있는 것을 확인할 수 있습니다.

저는 백그라운드 색을 White on Black으로 설정하며, Palette 항목은 Solarized로 설정하고 있습니다. (Ubuntu 20.04 기준으로는 Foreground and Blackground에서 Built-in schemesWhite on Black, PaletteBuilt-in schemesSolarized로 설정했습니다.)


.zshrc 예제

예제

# 터미널 색상 테마 적용
eval `dircolors ~/.dir_colors/dircolors`

# for (i-search)
stty stop undef

# for Java
export JAVA_HOME=/usr/lib/jvm/java-8-oracle

# for Android
export ANDROID_SDK=~/Android/Sdk
export ANDROID_NDK=~/Android/Ndk/android-ndk-r17b
export ANDROID_HOME=$ANDROID_SDK

export PATH=$PATH:$ANDROID_SDK:$ANDROID_TOOLS:$ANDROID_NDK:$ANDROID_HOME/tools:$ANDROID_SDK/platform-tools

# for TERM setting
export TERM=xterm

# for ZSH AutoSuggestion
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=cyan'

# 프롬프트에서 컴퓨터 이름 삭제
prompt_context() { 
  if [[ "$USER" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then 
    prompt_segment black default "%(!.%{%F{yellow}%}.)$USER" 
  fi 
}

ZSH 및 Oh! My ZSH 설치하는 방법

|

ZSH 및 Oh! My ZSH 설치하는 방법


terminator 설치(생략 가능)

테마 적용도 하기 쉬운 편이며, ZSH와 잘 어울리는 조합이기 때문에 가급적 terminator를 설치하는 것을 추천합니다.

sudo apt-get update
sudo apt-get install terminator


zsh 설치

sudo apt-get install zsh


Oh My ZSH 설치

sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"


Powerline 폰트 설치(생략 가능)

저는 개인적으로 D2Coding Regular를 사용하기 때문에 이 과정은 건너뛰는 편입니다.

wget https://github.com/powerline/powerline/raw/develop/font/PowerlineSymbols.otf
wget https://github.com/powerline/powerline/raw/develop/font/10-powerline-symbols.conf

mkdir ~/.fonts/
mv PowerlineSymbols.otf ~/.fonts/
mkdir -p ~/.config/fontconfig/conf.d 

fc-cache -vf ~/.fonts/
mv 10-powerline-symbols.conf ~/.config/fontconfig/conf.d/

어느 날 갑자기 외장 디스크가 Read Only가 된 경우 해결법

|

어느 날 갑자기 외장 디스크가 Read Only가 된 경우 해결법

어느 날 갑자기 외부 저장 매체가 Read Only 상태가 되어버렸을 때의 현상 수정하는 방법입니다. 아마 불필요하거나 손상된 파일이 많이 생긴 바람에 이런 현상이 생긴 것 같습니다.

터미널에서 다음과 같이 명령을 수행합니다.


경로 확인

$ sudo df -Th
Filesystem     Type      Size  Used Avail Use% Mounted on
udev           devtmpfs  7.8G     0  7.8G   0% /dev
tmpfs          tmpfs     1.6G  1.9M  1.6G   1% /run
...
/dev/sdd1      vfat      932G   36G  896G   4% /media/snowdeer/PORTABLESSD

여기에서 외장 디스크의 Filesystem 이름과 Mounted 되어있는 경로 이름을 확인합니다.


Unmout

$ sudo umount /media/snowdeer/PORTABLESSD


불필요한 파일 정리

$ sudo dosfsck -a /dev/sdd1

fsck.fat 4.1 (2017-01-24)
0x41: Dirty bit is set. Fs was not properly unmounted and some data may be corrupt.
 Automatically removing dirty bit.
/.Trash-1000/files/res
 Start does point to root directory. Deleting dir. 
/.Trash-1000/files/java
 Start does point to root directory. Deleting dir. 
Reclaimed 185 unused clusters (6062080 bytes) in 179 chains.
Free cluster summary wrong (29345789 vs. really 29345582)
  Auto-correcting.
Performing changes.
/dev/sdd1: 440012 files, 1170741/30516323 clusters


불필요한 파일 확인

위 명령어를 수행하면 외장 디스크 루트 디렉토리 안에 수 많은 *.REC 파일들이 생겼음을 확인할 수 있습니다. 해당 파일들을 전부 지우고 파일 탐색 브라우저를 종료했다가 다시 실행하면 Read Only 상태가 해제되었음을 확인할 수 있습니다.

PyGame - 이미지 회전하기

|

PyGame에서 이미지 회전하는 방법

pygame에서 이미지를 회전하려면 아래와 같은 코드로 할 수 있습니다.

self.rotated_image = pygame.transform.rotate(self.image, self.head)

하지만 이 때, 회전 후 이미지를 렌더링할 때 그 좌표가 틀어지기 때문에 이미지를 그릴 때 아래와 같은 보정을 해줍니다.

screen.blit(self.rotated_image, (self.x + self.image.get_width() / 2 - self.rotated_image.get_width() / 2, 
                                 self.y + self.image.get_height() / 2 - self.rotated_image.get_height() / 2))


소스 코드

import pygame
import sys
import time
import random

SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
SPAWN_TIME = 1

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

pygame.init()
pygame.display.set_caption("Stars in Space")
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()


class Star(object):
    def __init__(self):
        self.image = pygame.image.load("images/star.png").convert_alpha()
        self.x = random.randint(0, SCREEN_WIDTH - self.image.get_width())
        self.y = random.randint(0, SCREEN_HEIGHT - self.image.get_height())
        self.head = random.randint(0, 359)
        self.rotated_image = pygame.transform.rotate(self.image, self.head)
        self.rotate_speed = random.randint(1, 3)

    def rotate(self):
        self.head += self.rotate_speed
        self.rotated_image = pygame.transform.rotate(self.image, self.head)

    def draw(self):
        screen.blit(self.rotated_image, (self.x + self.image.get_width() / 2 - self.rotated_image.get_width() / 2,
                                         self.y + self.image.get_height() / 2 - self.rotated_image.get_height() / 2))


def main():
    stars = []

    last_spawn_time = time.time()

    while True:
        clock.tick(60)
        screen.fill(BLACK)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        if time.time() - last_spawn_time > SPAWN_TIME:
            stars.append(Star())
            last_spawn_time = time.time()

        for star in stars:
            star.rotate()
            star.draw()

        pygame.display.update()


if __name__ == "__main__":
    main()

PyGame 스페이스 인베이더(Space Invader) - 점수 출력

|

PyGame 스페이스 인베이더(Space Invader) - 점수 출력

import pygame
import sys

SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480

white = (255, 255, 255)
black = (0, 0, 0)

pygame.init()
pygame.display.set_caption("Space Invaders")
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 32)


class Enemy(object):
    def __init__(self):
        self.image = pygame.image.load("images/space_invader_enemy.png").convert_alpha()
        self.x = 40
        self.y = 40
        self.speed = 3
        self.direction = 1

    def move(self):
        self.x += self.speed * self.direction

        if self.x <= 40:
            self.y += 20
            self.direction = 1

        if self.x + 80 >= SCREEN_WIDTH:
            self.y += 20
            self.direction = -1

        if self.y >= 400:
            self.y = 40

    def draw(self):
        screen.blit(self.image, (self.x, self.y))

    def is_hit(self, bullets):
        for b in bullets:
            if pygame.Rect(self.x, self.y, 40, 40).colliderect((b.x, b.y, 0, b.height)):
                self.x = 40
                self.y = 40

                bullets.remove(b)
                return True

        return False


class Player(object):
    def __init__(self):
        self.x = 300
        self.y = 400
        self.speed = 5
        self.image = pygame.image.load("images/space_invader_player.png").convert_alpha()

    def move(self, key_event):
        if key_event[pygame.K_LEFT]:
            self.x -= self.speed

        if key_event[pygame.K_RIGHT]:
            self.x += self.speed

        if self.x <= 40:
            self.x = 40

        if self.x + 80 >= SCREEN_WIDTH:
            self.x = SCREEN_WIDTH - 80

    def draw(self):
        screen.blit(self.image, (self.x, self.y))


class Bullet(object):
    def __init__(self, x, y):
        self.height = 4
        self.speed = 7
        self.x = x
        self.y = y

    def move(self):
        self.y -= self.speed

    def is_screen_out(self):
        return self.y - self.height <= 0

    def draw(self):
        pygame.draw.line(screen, black, (self.x, self.y), (self.x, self.y + self.height), 1)


def main():
    score = 0

    player = Player()
    enemy = Enemy()
    bullets = []

    while True:
        clock.tick(60)
        screen.fill(white)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                bullets.append(Bullet(player.x + 20, player.y - 5))

        key_event = pygame.key.get_pressed()

        enemy.move()
        enemy.draw()
        if enemy.is_hit(bullets):
            score += 100

        player.move(key_event)
        player.draw()

        for b in bullets:
            b.move()
            b.draw()

            if b.y > SCREEN_HEIGHT:
                bullets.remove(b)

        screen.blit(font.render("Score: {0}".format(score), True, black), (10, 10))

        pygame.display.update()


if __name__ == "__main__":
    main()