Yuruhuwa Develop

keyboard_silencing_mod


キーボード静音化への道

デスクトップPCで使うキーボードがうるさいという問題があるので
今回はキーボードの静音化に挑戦しました。
主に底打ち音(低音) とキーがカチャカチャ響く音(高音) を改善したいのです。

静音化するには

まずはじめに、静音化にはどのようなことをすればよいのかを紹介します。
静音化に関する方法は複数ありますが、今回は、有名どころの以下3つを試してみようと思います。

  • lube mod
    所要時間: 2時間30分
    → 潤滑剤をキースイッチ内部に塗布することによって、キーの押下時と解放時の打鍵音を軽減させる。
    また、打鍵感もしっとりとした手触りになり、キータッチが楽しくなる。
  • tape mod
    所要時間: 15分
    → キーボード内部のPCBの裏面にマスキングテープを貼り付けることによって、キーの押下時の底打ち音を低減させる。比較的簡単なmod。
  • clay mod
    所要時間: 30分
    → キーボード内部に粘土を敷き詰めることによって、キー押下時の打鍵音の響きを低減させる。
    高音が響く場合に効果が見られる。

使うもの

  • キーボード本体
  • 分解工具
    • キープラー
    • キースイッチプラー
    • キースイッチオープナー
    • 精密ドライバー
    • パーツオープナー
  • 静音化用品
    • エアコン配管用パテ
    • マスキングテープ
    • 潤滑剤

作業開始

キーボード紹介

僕のキーボードは Drunkdeer a75 というキーボードです。

キーボード全体像

静電容量無接点方式 と呼ばれるメカニカルキースイッチを採用しており、Webドライバからキーコンフィグの設定が可能な点が特徴です。
そして、いわゆる、Rapid Triggerと呼ばれる機能もあるので、FPSのゲームで活躍するところも魅力的です。
キーキャップは、アリエクで買ったハングル印字のABS樹脂のものを使っています。
おもちゃチックな見た目ですが、こだわりの一品という感じで気に入っています。
韓国語でチャットをするので、韓国語の印字は必須です。

キーキャップを外す

キーキャップをキープラーを使って外していきます。
メカニカルキーボードを購入すると大抵は付属していることが多いです。
金属のワイヤータイプから、プラスチックのものまでさまざまですが、ワイヤータイプの方が、キーキャップを傷つけずに外せるのでおすすめです。
外したキーキャップは食器用洗剤で洗って干しておきます。
キースイッチが接する箇所は水気が溜まりやすいので、エアダスターで吹き込むか、衝撃を与えて、水気を切るといいです。

キーキャップ

キーキャップなしのキーボード


取り出したメカニカルキースイッチ

購入してから2年間掃除していなかったので、汚かったです…

汚れが目立つ


汚れが目立つ2

Read more ⟶

article_script2


メディアやコールアウトの挿入を楽にしよう!!

このブログで使用しているテーマでは、各種メディアとコールアウトをサポートしています。

  • 画像
  • Github Gist
  • Youtube
  • X Post(Tweet)
  • Vimeo
  • Instagram
  • コールアウト

嬉しい機能ですが、マークダウンで記述する性質上、ショートコードを覚えている必要があり、めんどくさいのです。 そこで、またスクリプトを用意しました。


import argparse
import shutil
import re
from pathlib import Path


def main():
    parser = argparse.ArgumentParser(
        description="Insert media into article"
    )

    parser.add_argument("article_name", help="Target article name")

    subparsers = parser.add_subparsers(
        dest="mode",
        required=True
    )

    # picture
    pic = subparsers.add_parser("picture", help="Insert picture")
    pic.add_argument("picture_name", help="Picture file name")
    pic.add_argument("-l", "--line", type=int, required=True)

    # callout
    callout = subparsers.add_parser("callout", help="Insert callout")
    callout.add_argument(
        "callout_type",
        choices=["alert", "warning", "tip"],
        help="Callout type"
    )
    callout.add_argument("-l", "--line", type=int, required=True)

    # youtube
    yt = subparsers.add_parser("youtube", help="Insert YouTube embed")
    yt.add_argument("url", help="YouTube URL")
    yt.add_argument("-l", "--line", type=int, required=True)

    # tweet
    tw = subparsers.add_parser("tweet", help="Insert tweet embed")
    tw.add_argument("url", help="Tweet URL")
    tw.add_argument("-l", "--line", type=int, required=True)

    args = parser.parse_args()
    handle(args)


def handle(args):
    article_path = resolve_article(args.article_name)

    insert_text = build_insert_text(args)
    new_content = insert_at_line(article_path, insert_text, args.line)

    safe_write(article_path, new_content)

    print(f"Inserted {args.mode} into {article_path} at line {args.line}")


# --------------- #
# Core functions  #
# --------------- #

def resolve_article(article_name: str) -> Path:
    candidates = [
        Path(f"/yout/path/content/posts/{article_name}/index.md")
    ]
    for p in candidates:
        if p.exists():
            return p
    raise FileNotFoundError("Article not found")


def insert_at_line(path: Path, insert_text: str, line_no: int) -> str:
    lines = path.read_text(encoding="utf-8").splitlines(keepends=True)

    if line_no < 1 or line_no > len(lines) + 1:
        raise ValueError("line number out of range")

    lines.insert(line_no - 1, insert_text + "\n")
    return "".join(lines)


def safe_write(path: Path, new_content: str):
    backup = path.with_suffix(path.suffix + ".bak")
    tmp = path.with_suffix(path.suffix + ".tmp")

    shutil.copy2(path, backup)
    tmp.write_text(new_content, encoding="utf-8")
    tmp.replace(path)


def build_insert_text(args) -> str:
    if args.mode == "picture":
        return f'{{{{< figure src="{args.picture_name}" title="" >}}}}'

    if args.mode == "callout":
        return f'{{{{< callout type="{args.callout_type}" text="" >}}}}\n' # {{< callout type="alert" text="" >}}


    if args.mode == "youtube":
        video_id = extract_youtube_id(args.url)
        return f'{{{{< youtube {video_id} >}}}}' # https://www.youtube.com/watch?v=w7Ft2ymGmfc → w7Ft2ymGmfc

    if args.mode == "tweet":
        tweet_id = extract_tweet_id(args.url)
        return f'{{{{< tweet {tweet_id} >}}}}' # https://x.com/GoHugoIO/status/877500564405444608 → user="GoHugoIO" id="877500564405444608"

    raise ValueError("Unknown mode")


def extract_youtube_id(url: str) -> str:

    m = re.search(r"v=([^&]+)", url)
    if m:
        return m.group(1)
    raise ValueError("Invalid YouTube URL")

def extract_tweet_id(url: str) -> str:
    m = re.search(r"https://x\.com/([^/]+)/status/([0-9]+)", url)
    if m:
        user = f'user="{m.group(1)}"'
        tweet_id = f'id="{m.group(2)}"'
        tweet = f"{user} {tweet_id}"
        return tweet

    raise ValueError("Invalid tweet URL")




if __name__ == "__main__":
    main()

主に使う機能として

Read more ⟶

vimrc_mac


Macでyy + pが使えない!!

Macでvimで作業するときの基礎コマンドであるヤンクペーストですが、 Macでは.vimrcに設定をしないとペーストができないようです。 以下のように設定をしたら解決しました。

set clipboard=unnamed,unnamedplus
⚠️ Warning
以下の設定では、システムクリップボードレジスタが使えないので機能しなかったです。
set clipboard=unnamedplus

念の為、unnamedunnamedplusを指定しました。 どうやら、unnamedplusというのはunix系のレジスタで扱うシステムクリップボードのレジスタのようです。
なので、Macはunnamedを指定するとうまくいくみたいです。
vimでのヤンクとOSでのクリップボードでは格納されるレジスタや参照されるレジスタが違うので、うまく機能しなかったのかなと思います。
参考にした記事: .vimrcの設定

参考にした記事: レジスタ一覧

参考にした記事: レジスタ一覧(英語ソース)

Read more ⟶