Blessed
GitHub概要
chjj/blessed
A high-level terminal interface library for node.js.
スター11,566
ウォッチ117
フォーク553
作成日:2013年1月27日
言語:JavaScript
ライセンス:Other
トピックス
なし
スター履歴
データ取得日時: 2025/7/25 11:10
Blessed
Blessedは、Node.js向けの高レベルなターミナル・インターフェース・ライブラリです。ncursesライブラリの機能を再実装し、ウィジェットベースのAPIでターミナルアプリケーションを構築できます。DOM風のAPIを提供し、親子関係を持つ要素の階層構造でUIを組み立てる特徴があります。
特徴
包括的なウィジェットシステム
- 豊富なウィジェット: Box、Text、List、Form、Button、Table、Terminalなどの構成要素
- 階層構造: 親子関係によるUI構成
- イベント駆動: DOM風のイベントバブリング機能
- フォーカス管理: ウィジェット間のフォーカス移動
効率的なレンダリング
- 最適化レンダリング: ダメージバッファによる変更追跡
- CSR対応: 効率的なスクロール処理
- BCE対応: 背景色の効率的な管理
- スマートカーソル: 最適化されたカーソル移動
クロスターミナル対応
- terminfo/termcap: 様々なターミナルタイプに対応
- Tputシステム: 自動的な制御シーケンス生成
- 互換性: 幅広いターミナルエミュレータで動作
- 色対応: 16色、256色、フルカラー対応
高度な機能
- マウスサポート: クリック、ホイール、ホバーイベント
- キーボードハンドリング: 詳細なキー入力処理
- スタイリング: タグベースの書式設定
- フォーカス管理: Tab/Shift+Tabナビゲーション
基本的な使用方法
インストール
npm install blessed
# or
yarn add blessed
Hello World
const blessed = require('blessed');
// スクリーンオブジェクトを作成
const screen = blessed.screen({
smartCSR: true
});
// ボックスウィジェットを作成
const box = blessed.box({
top: 'center',
left: 'center',
width: '50%',
height: '50%',
content: 'Hello {bold}World{/bold}!',
tags: true,
border: {
type: 'line'
},
style: {
fg: 'white',
bg: 'magenta',
border: {
fg: '#f0f0f0'
},
hover: {
bg: 'green'
}
}
});
// スクリーンにボックスを追加
screen.append(box);
// ESCまたはq、Ctrl-Cで終了
screen.key(['escape', 'q', 'C-c'], (ch, key) => {
return process.exit(0);
});
// フォーカス設定とレンダリング
box.focus();
screen.render();
リストウィジェット
const blessed = require('blessed');
const screen = blessed.screen();
const list = blessed.list({
parent: screen,
label: ' {bold}{cyan-fg}File Manager{/cyan-fg}{/bold} ',
tags: true,
top: 'center',
left: 'center',
width: '50%',
height: '50%',
border: 'line',
selectedBg: 'blue',
items: [
'file1.txt',
'file2.js',
'directory/',
'image.png',
'document.pdf'
]
});
// アイテム選択時の処理
list.on('select', (item) => {
const msg = blessed.message({
parent: screen,
top: 'center',
left: 'center',
height: 'shrink',
width: 'half',
label: ' {blue-fg}選択{/blue-fg} ',
tags: true,
keys: true,
hidden: true,
border: 'line'
});
msg.display(`選択されました: ${item.getText()}`, 3, () => {
screen.render();
});
});
screen.key(['escape', 'q', 'C-c'], () => process.exit(0));
list.focus();
screen.render();
フォームウィジェット
const blessed = require('blessed');
const screen = blessed.screen();
// フォームコンテナ
const form = blessed.form({
parent: screen,
keys: true,
left: 'center',
top: 'center',
width: 30,
height: 10,
border: {
type: 'line'
},
label: ' Login Form '
});
// テキスト入力フィールド
const username = blessed.textbox({
parent: form,
mouse: true,
keys: true,
top: 1,
left: 2,
height: 1,
width: 20,
name: 'username',
border: {
type: 'line'
},
label: ' Username '
});
const password = blessed.textbox({
parent: form,
mouse: true,
keys: true,
top: 4,
left: 2,
height: 1,
width: 20,
name: 'password',
censor: true,
border: {
type: 'line'
},
label: ' Password '
});
// 送信ボタン
const submit = blessed.button({
parent: form,
mouse: true,
keys: true,
shrink: true,
top: 7,
left: 2,
name: 'submit',
content: 'Submit',
style: {
bg: 'blue',
focus: {
bg: 'red'
}
}
});
// フォーム送信処理
submit.on('press', () => {
form.submit();
});
form.on('submit', (data) => {
console.log('Form data:', data);
process.exit(0);
});
screen.key(['escape', 'q', 'C-c'], () => process.exit(0));
username.focus();
screen.render();
主要ウィジェット
Box
基本的なコンテナ要素
const box = blessed.box({
parent: screen,
top: 10,
left: 10,
width: '50%',
height: '50%',
content: 'Box content',
border: 'line'
});
Text
テキスト表示用ウィジェット
const text = blessed.text({
parent: screen,
content: '{bold}Bold{/bold} and {underline}underlined{/underline} text',
tags: true,
left: 'center',
top: 'center'
});
List
スクロール可能なリスト
const list = blessed.list({
parent: screen,
label: 'Items',
items: ['Item 1', 'Item 2', 'Item 3'],
keys: true,
mouse: true,
style: {
selected: {
bg: 'blue'
}
}
});
Table
テーブル表示
const table = blessed.table({
parent: screen,
data: [
['Name', 'Age', 'City'],
['John', '30', 'New York'],
['Jane', '25', 'London']
],
border: 'line',
align: 'center'
});
高度な機能
プログレスバー
const blessed = require('blessed');
const screen = blessed.screen();
const progressBar = blessed.progressbar({
parent: screen,
border: 'line',
style: {
bg: 'blue'
},
ch: ' ',
width: '50%',
height: 3,
top: 'center',
left: 'center',
label: 'Progress',
percent: 0
});
// プログレス更新
let progress = 0;
const timer = setInterval(() => {
progress += 10;
progressBar.setProgress(progress);
screen.render();
if (progress >= 100) {
clearInterval(timer);
setTimeout(() => process.exit(0), 1000);
}
}, 200);
screen.key(['escape', 'q', 'C-c'], () => process.exit(0));
screen.render();
ファイルマネージャー
const fs = require('fs');
const path = require('path');
const blessed = require('blessed');
const screen = blessed.screen();
class FileManager {
constructor() {
this.currentPath = process.cwd();
this.createUI();
}
createUI() {
this.fileList = blessed.list({
parent: screen,
label: ` Current: ${this.currentPath} `,
top: 0,
left: 0,
width: '100%',
height: '100%',
keys: true,
mouse: true,
border: 'line',
style: {
selected: {
bg: 'blue'
}
}
});
this.loadDirectory();
this.setupEvents();
}
loadDirectory() {
try {
const files = fs.readdirSync(this.currentPath);
const items = ['../'].concat(files.map(file => {
const fullPath = path.join(this.currentPath, file);
const stat = fs.statSync(fullPath);
return stat.isDirectory() ? `${file}/` : file;
}));
this.fileList.setItems(items);
this.fileList.setLabel(` Current: ${this.currentPath} `);
screen.render();
} catch (err) {
console.error('Error reading directory:', err);
}
}
setupEvents() {
this.fileList.on('select', (item) => {
const fileName = item.getText();
if (fileName === '../') {
this.currentPath = path.dirname(this.currentPath);
this.loadDirectory();
} else if (fileName.endsWith('/')) {
this.currentPath = path.join(this.currentPath, fileName.slice(0, -1));
this.loadDirectory();
}
});
screen.key(['escape', 'q', 'C-c'], () => process.exit(0));
this.fileList.focus();
}
}
new FileManager();
screen.render();
エコシステム
関連パッケージ
- blessed-contrib: ダッシュボード作成用のチャートウィジェット
- neo-blessed: モダン化されたBlessedフォーク
- blessed-xterm: Xtermターミナルエミュレータ統合
- blessed-terminal: ターミナルエミュレータウィジェット
実用例
- vtop: システムモニタリングツール
- blessed-contrib-demo: ダッシュボードデモ
- slap: ターミナルベースエディタ
- ranger.js: ファイルマネージャー
利点
- 豊富な機能: 包括的なウィジェットセット
- 高性能: 最適化されたレンダリング
- クロスプラットフォーム: 様々なターミナルで動作
- 成熟したライブラリ: 長期間の開発と実績
- DOM風API: Web開発者にとって理解しやすい
制約事項
- 学習コスト: 独自のAPIを習得する必要
- メンテナンス: 開発活動が停滞気味
- モダンJS: ES6+機能の部分的サポート
- 文書化: ドキュメントが不完全な部分がある
他のライブラリとの比較
項目 | Blessed | Ink | Terminal Kit |
---|---|---|---|
アプローチ | Widget風 | React風 | 関数風 |
学習コスト | 中 | 低(React経験者) | 中 |
パフォーマンス | 高 | 高 | 中 |
ウィジェット | 豊富 | 中 | 基本的 |
開発状況 | 停滞気味 | 活発 | 活発 |
まとめ
Blessedは、包括的な機能セットを持つ成熟したTUIライブラリです。豊富なウィジェットと高性能なレンダリングにより、複雑なターミナルアプリケーションを構築できます。開発活動が停滞気味ですが、安定性と機能の豊富さから、今でも多くのプロジェクトで使用されています。特に、ダッシュボードやファイルマネージャーなど、複雑なUIを必要とするアプリケーションに適しています。