OmniAICreator/Qiita-1.07M huggingface dataset:
新しい Bingで「日本語プログラミング言語」「説明する」を選んだら‘日本語プログラミング言語 Mind’ を検索し始めた

# はじめに

Edgeで[日本語プログラミング言語「Mind」最新版をリリースしました](https://qiita.com/killy/items/ccec1fbb81c4432757f5)という記事のタイトルから「日本語プログラミング言語」を選択しておき、右側に表示されている「新しい Bing」のチャットで「日本語プログラミング言語」が「選択したテキストをチャットに送信しますか?」に表示されている状態で「送信する」を選択して、「説明する」を実行してみました。

## この記事内容の作業環境
Windows11
Microsoft Edge 111.0.1661.41

## この記事内容の保証
※この記事にはAIが自動生成した意見的な情報が含まれます。AIが自動生成して書かれた内容の妥当性は保証されません。（今回生成された記事の妥当性はけっこう高いと思われました。）

# 実行結果

ページから貼り付け済み
日本語プログラミング言語

テキストに対する処理を選択してください。
説明する

‘日本語プログラミング言語 Mind’ を検索しています


回答を生成しています…

日本語プログラミング言語 Mindは、Forthの影響を受けた、日本語っぽい自然な見掛けが特徴であるプログラミング言語で、いわゆる日本語プログラミング言語のひとつです [1](https://ja.wikipedia.org/wiki/Mind_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E))。1985年に開発され、自然な日本語に近い表記でソースコードを書けるもので、コンパイラにより中間コードを生成し、それをランタイムが実行します。出来上がったオブジェクトコードは高速で動作し小さく配布も容易です [2](https://www.scripts-lab.co.jp/mind/ver8/doc/00-Introduction.html)。

視線が左から右に流れるように読めることと、たとえプログラマでなくても誰が見ても何をしようとしているのかが分かるのが一番の利点です2。オンラインマニュアルもありますので、マニュアルだけでもぜひご覧ください 1。


詳細情報:
1. [ja.wikipedia.org](https://ja.wikipedia.org/wiki/Mind_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E))
2. [scripts-lab.co.jp](https://www.scripts-lab.co.jp/mind/ver8/doc/00-Introduction.html)
3. bing.com
4. [qiita.com](https://qiita.com/mylifewithviolin/items/c4f9c1250f11d20284ed)
5. [scripts-lab.co.jp](http://www.scripts-lab.co.jp/mind/whatsmind.html)
— 表示を減らす


# 考察
[前回の記事](https://qiita.com/mylifewithviolin/items/867abdb7aa00bdbfd6d0)では、急にアピールされて使ってみたという感じだったので、冷静にどのような操作をしたのか思い出せませんでしたが、今回はなんどか使ってみて動きの傾向を把握してからの再記事化です。

[日本語プログラミング言語「Mind」最新版をリリースしました](https://qiita.com/killy/items/ccec1fbb81c4432757f5)という記事を開いていると「日本語プログラミング言語」を選択しただけで、今回は「Mind」を検索ワードに自動付加しました。このあたりはChatGPTをBingに特化して組み込んだマイクロソフトのアレンジのようですね。ユーザーがいま見ているページの内容をある程度認識して、検索実行するような動きでした。

そして、検索結果のリンクを列挙するだけでなく、ある程度それらの情報を総合してまとめた文章を提示というのが、この「チャット」の機能のようです。


ただし、「チャット」ではなく、「作成」の場合は見ているページは関係なく、「執筆分野」にコピペまたは入力した文字で、説明文章を自動生成するようでした。

こちらはChatGPTに近い雰囲気で、情報量の少ない分野については、けっこうまとはずれなことを創作して書いてきます。こちらも後で記事にしておきたいと思います。

「チャット」に戻りますが、[日本語トランスコンパイラ言語 Re:Mind という自作言語の企画趣旨](https://qiita.com/mylifewithviolin/items/9d58db8a101807c19bde)という記事を開いて、新規チャットしますと、回答のトーンを設定するオプションが中央値の「その他バランス」という状態で、下記のようなページの要約を提示してくれました。

>お帰りなさい! このページからの重要なポイントをいくつか紹介します。
>
>Re:Mindは日本語トランスコンパイラ言語で、日本語で書かれたロジックを他のプログラミング言語に変換する。
Re:Mindは日本語プログラミング言語の採用障壁を低減することを目指している。
Re:MindはMindという最古の日本語コンパイラ言語のユーザー会の会員が作成している。
Re:Mindはまだ仕様や実装が未定で、Qiitaでスキルや知見の共有を求めている。


これはこのページの要約だけなので、実際は仕様はドラフト確定していますが、そこはリンク先などもみないとわからないので致し方ありませんが、なかなか要点をついていると思いました。

>Re:Mindは日本語プログラミング言語の採用障壁を低減することを目指している。

この直接的な表現は本文で使っていませんが、うまくまとめているな感はありますね。

上記のセンテンスを選択状態にして、「選択したテキストをチャットに送信しますか?」してみましたところ、下記のような回答でした(笑)
>すみませんが、それについては回答を出すことができません。何か他のことでお手伝いできることはありますか？


# 参考リンク

https://qiita.com/killy/items/ccec1fbb81c4432757f5

https://qiita.com/mylifewithviolin/items/9d58db8a101807c19bde
Rocky Linux 9.0 (Alma Linux) にRedis7.0を入れる

Misskeyのv13.11.0から必須という噂があるので

```
sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo dnf module enable -y redis:remi-7.0

# 既にインストールされてても問題なくアップグレードされます
sudo dnf install redis

# アップグレードの場合
sudo systemctl restart redis 

# 初回インストールの場合
sudo systemctl enable --now redis
```
MAMPで複数のローカルホストを作成、ポート番号を設定する

# MAMPで複数のローカルホストを作成、ポート番号を設定する

　MAMPのapacheでは、複数のローカルホストを作成してポート番号を設定することができる。
***
### 複数の作業用のフォルダを用意する
　/Applications/MAMP/htdocs/の中に、作業用フォルダを複数用意する。
　　　![htdocs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246427/51315752-3000-ab8e-5a6e-a26220b8577c.png)

### 設定ファイルを変更する
　httpd.confの設定に、各作業用フォルダのポート番号とパスを追加する。
~~~
#Listen 12.34.56.78:80
Listen 8888
~~~
　Listenの項目の下に記入。
~~~
Listen 8001
<VirtualHost *:8001>
DocumentRoot "/Applications/MAMP/htdocs/8001_htdocs"
<Directory "/Applications/MAMP/htdocs/8001_htdocs">
  AllowOverride All
</Directory>
</VirtualHost>

Listen 8002
〜〜VirtualHost *:8005まで続ける〜〜

~~~


:::note info
Virtual hostsの設定ファイルを使用するのは、複数のネットワーク インターフェイスを使用していない場合らしい。
~~~
# Virtual hosts
#Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf
~~~
httpd.confでVirtual hostsを有効にして、httpd-vhosts.confにポート番号を書き込んでいたらエラーになっていた。
:::
Cで文字列を反転させるときにハマった話

C言語のチュートリアルをやっていて、文字列の反転を行う際にハマったのでその備忘録です。

### 何が起こったか
文字列を反転させるコードを書いたのですが、反転させた文字列をprintfしても何も出力されませんでした。

### 原因
馬鹿正直にヌル文字まで含めて反転させていたのが原因でした・・・。

### 解決方法
ヌル文字を考慮してコードを書き直したら解決しました。
CMAKE の find_package() で参照される環境変数

CMake のドキュメントからの抜粋です。

https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure


# 参照される環境変数

CMake の `find_package(MyLib)` で参照される環境変数には、検索順の早い順に

* `MyLib_ROOT`
* `MyLib_DIR`
* `CMAKE_PREFIX_PATH`
* `PATH`

があります。

`MyLib_ROOT` は古くから広く使われているパッケージ用のものです。新しく作るライブラリにはふさわしくありません。

`MyLib_DIR` はライブラリ毎の管理になります。登録するライブラリの数が増えてくると邪魔に感じるかもしれません。

`CMAKE_PREFIX_PATH` には同名の CMAKE キャッシュ変数も定義されていて、キャシュ変数の方が先に検索されます。

`PATH` 内で \bin で終わるディレクトリはその一つ上が対象になります。例えば`c:\dev\bin` にパスを通すことで `c:\dev` が指定されます。

`PATH` と同様に `CMAKE_PREFIX_PATH` では、セミコロンで区切ることで複数のディレクトリを指定できます。

find_package() で  `NO_CMAKE_ENVIRONMENT_PATH` を指定すると `CMAKE_PREFIX_PATH` の値は無視されます。 `NO_SYSTEM_ENVIRONMENT_PATH` を指定すると `PATH` が無視されます。 

# 検索されるディレクトリ

`find_package(MyLib)` によって、環境変数で指定されたディレクトリとその下にある特定のサブディレクトリから `MyLibConfig.cmake` および `mylib-config.cmake` が検索されます。

Windows 環境では、指定されたディレクトリからの相対指定で

* cmake
* MyLib*
* MyLib*/cmake
* MyLib*/lib/cmake/MyLib*
* MyLib*/share/cmake/MyLib*
* MyLib*/lib/MyLib*
* MyLib*/share/MyLib*
* MyLib*/lib/MyLib*/cmake
* MyLib*/share/MyLib*/cmake

に対しても検索が行われます。（検索対象は他にもあります。）MyLib* は MyLib もしくは MyLib で始まる任意の文字列です。MyLib-1.0.0 のようにライブラリ名にバージョン名を続ければ、バージョン違いを同じディレクトリの下に並べてインストールできます。

なお、Windows のファイルシステムでは大文字と小文字は区別されません。検索名と比較して大文字と小文字が違っていてもヒットします。

# 追記

https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html

によると

> Paths to packages may also be specified by setting variables matching <PackageName>_DIR, such as SomePackage_DIR. Note that this is not a prefix, but should be a full path to a directory containing a config-style package file, such as /opt/somepackage/lib/cmake/SomePackage in the above example.

ということで、`MyLib_DIR` は `MyLibConfig.cmake` があるディレクトリ(例えば `c:\dev\MyLib\lib\cmake\MyLib`)を設定するのが正しい使い方のようです。ただし、CMake 3.25 においては `c:\dev` を設定しても動作します。
ストワで始めるLua第三回のコード

https://www.nicovideo.jp/watch/sm42051928

https://www.nicovideo.jp/watch/sm42051942

```lua:lua3
data={}
maxh=property.getNumber("max")
minh=property.getNumber("min")
w,h=0,0

function onTick()
    local i
    if w~=0 then
    	table.insert(data,input.getNumber(1))
    	if #data>w then
    		table.remove(data,1)
    	end
    end
end

function onDraw()
	local i,number2pixel
	w=screen.getWidth()
	h=screen.getHeight()
	
	number2pixel=h/(maxh-minh)
	
	if #data>0 then 
		screen.drawText(0,0,data[#data])
	end
	
	if #data>=2 then
		for i=2,#data do
			screen.drawLine(i-1,h-(data[i-1]-minh)*number2pixel,i,h-(data[i]-minh)*number2pixel)
		end
	end
end
```
【メモ】.vimrcの設定

個人的なメモなので詳しくはリンクの先へお願いします。



#便利機能
##マウスの有効化
'set mouse=a'

#ラズパイのキーボード対策
##移動キーの有効化
'set nocompatible'
##バッグスペースの有効化
set backspace=indent,eol,start
LocalStackでAWSリソースを構築してみる (DynamoDB編)

## 概要

**LocalStackって何？**
Dockerコンテナ上で動作する仮想のAWS動作環境
いちいちAWSアカウントやIAMユーザー等を用意せず、無料で検証用のリソースを構築できる。

**今回の記事で実践すること**
LocalStackを使用して、DynamoDBのテーブルを作成する


## 必要なもの
- Docker動作環境
- AWS CLI

## LocalStack用環境の構築
[LocalStack用環境リポジトリ](https://github.com/localstack/localstack)をcloneする
`git clone https://github.com/localstack/localstack`

cloneしたリポジトリに移動し、コンテナをたてる
`cd localstack`
`docker-compose up -d`

LocalStack用の認証情報（ダミー）を追加する

```~/.aws/credentials
[localstack]
aws_access_key_id = dummy
aws_secret_access_key = dummy
```

**※注意事項**
コンテナを落とすと作成したテーブルなどが消える。
あらかじめテーブル作成・初期データ投入用スクリプトを用意しておくと良いかも。

## テーブルを作成する
今回は例として以下のテーブルを作成する

- テーブル名
    - Items
- PK
    - itemName
        - String
        - HASH型
 
```bash
aws dynamodb create-table \
    --table-name Items \
    --attribute-definitions \
        AttributeName=itemName,AttributeType=S \
    --key-schema \
        AttributeName=itemName,KeyType=HASH \
    --provisioned-throughput \
        ReadCapacityUnits=10,WriteCapacityUnits=5 \
    --endpoint-url=http://localhost:4566 \
    --profile localstack
```

## テーブルに項目を追加する
```bash
aws --endpoint-url=http://localhost:4566 dynamodb put-item \
    --table-name Items  \
    --profile localstack \
    --item \
        '{"itemName": {"S": "hoge"}}'
```

## テーブルをスキャンする

Scan = テーブル内のすべての情報を参照する

```
aws dynamodb scan \
--table-name Items \
--endpoint-url=http://localhost:4566 \
--profile localstack
```

## テーブルを削除する
```
aws dynamodb delete-table \
--table-name Items \
--endpoint-url=http://localhost:4566 \
--profile localstack
```

## 番外編: Terraformで作成

テーブルの作成・削除はTerraformでも実行可能
```tf
terraform {
  backend "local" {}
}

provider "aws" {
  region = "ap-northeast-1"

  access_key = "dummy"
  secret_key = "dummy"

  # localstack用の設定
  s3_use_path_style           = true
  skip_credentials_validation = true
  skip_metadata_api_check     = true
  skip_requesting_account_id  = true


  endpoints {
    dynamodb = "http://localhost:4566"
  }
}

resource "aws_dynamodb_table" "this" {
  name           = "Items"
  billing_mode   = "PROVISIONED"
  read_capacity  = 10
  write_capacity = 5
  hash_key       = "itemName"

  attribute {
    name = "itemName"
    type = "S"
  }
}

```

## 参考

DynamoDBとはなんぞや
https://qiita.com/hshimo/items/e5ad98b21786d796f1da

AWS CLI DynamoDB操作コマンドのリファレンス
https://docs.aws.amazon.com/cli/latest/reference/dynamodb/index.html
【electron】アーキテクチャ図解

はじめに、electronプロジェクトの作成手順は[electron getting started](https://www.electronjs.org/ja/docs/latest/tutorial/quick-start)を参照。
簡単にまとめる。
```bash
npm init
npm install --save-dev electron
touch index.js
vim package.json # scriptsに"start": "electron ."を追加
npm start
```


さて、本題。
**※この記事の目的は概念の整理であり、具体的なプログラムの書き方を示すものでありません。**

# electronアーキテクチャ

![electron.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113802/bb5c22ca-4cfb-0e9b-8a14-ee299f5f38f4.jpeg)

electronはchromiumのアーキテクチャをベースとしている。なので、chromiumに詳しい方はelectronの理解もしやすいと思う。

electronには2つのプロセスが存在する。

- メインプロセス
- レンダラープロセス

## メインプロセス

**メインプロセス**はWebでいうバックエンド、サーバサイドにあたる。`npm start`を行うとデフォルトでは`index.js`が実行されるが、そのプロセスがメインプロセスになる。メインプロセスはOS機能にアクセスできる。`index.js`はメインプロセスで実行されることは大切なので意識したい。

メインプロセスの役割は下記の通り。

- アプリケーションウィンドウの作成
- アプリのライフサイクルの管理・ネイティブインターフェースの表示
- レンダラープロセスとイベントの管理
- プリロードスクリプトのアタッチ
- MessagePortの設定・割り当て
    - レンダラープロセス間通信の際に有用
    - 別途、レンダラープロセスからMessagePortを利用可能にするためのAPIを公開するコードをプリロードスクリプトに記載する必要がある

MessagePortの設定・割り当ては少し難しい（私のあまり把握していない）ので、必要なときに勉強すればいいと思う。
個人的によく使うのは、上4つの機能。

## レンダラープロセス

レンダラープロセスの役割は下記の通り。

- 1ウィンドウに1プロセス
- 典型的なフロントエンド機能と同等
- OS、Node.js、electronAPIへのアクセスはできない

レンダラープロセスはchromium（Webでいうブラウザ）上で動作するので、OS機能やNode.js、elctronAPIにはアクセスできない。
つまり、レンダラープロセスでできること = Webブラウザの実行環境でできること、ということである。

## プリロードスクリプトについて

基本的に、メインプロセスとレンダラープロセス間の通信はできない。これはつまり、アプリ画面のとあるボタンをクリックしたら、ファイルへ保存したい（もしくはファイルからデータを取得したい）、といったことができないことを意味する。これでは困る。

そこで、プリロードスクリプトというものを利用して、メインプロセスとレンダラープロセス間で通信できるようにする。

プリロードスクリプトで記述することは、レンダラープロセスからアクセスでき、かつメインプロセスへ信号を送るAPI（関数）を定義することである。プリロードスクリプトの実行環境は、一部のelctronAPIを利用できるため、そこで定義するAPIはelectronAPIを拝借してメインプロセスへの通信機能をもつことができる。

つまり、プリロードスクリプトで定義したメインプロセスへの通信機能をもつAPIをレンダラープロセスから呼び出すことで、メインプロセスとレンダラープロセス間で通信（片方向通信、双方向通信）ができるようになる。レンダラープロセスを起点にした通信、メインプロセスを起点にした通信の両方に対応している。

プリロードスクリプトのアタッチはメインプロセス側のスクリプトで行う。

## まとめ

1. `npm start`を実行する
1. メインプロセスで`index.js`が実行され、アプリケーション（ウィンドウ）が立ち上がる。
1. このとき、プリロードスクリプトも実行される
1. その後、ウィンドウ（chromium）上でレンダラープロセスが走り、HTML・CSS・JSから画面が描画される。
1. 必要に応じて（例えばボタンをクリックすると）、プリロードスクリプトで公開したAPIを利用してレンダラープロセスがメインプロセスへ通信を行いデータをやりとりする

以上。

# 参考

https://www.electronjs.org/ja/docs/latest/
【競プロ/Swift】AtCoder Beginner Contest 296

# 注意事項
本記事は復習のための日記的なものであり、丁寧な解説を求めている方には不十分かと思われますので、ご了承のほどお願いいたします。

# 正解済み問題
## A - Alternately
**問題文**
[こちら問題ページ](https://atcoder.jp/contests/abc296/tasks/abc296_a)

**解答**
一つ前の値と比較し続け、値が交互に配置されているかを判定する。

```swift
let n = Int(readLine()!)!
let s = Array(readLine()!)

var isCorrect = true
var preS = s[0]
for index in 1..<n {
    if preS == s[index] {
        isCorrect = false
        break
    }
    preS = s[index]
}

print(isCorrect ? "Yes" : "No")
```

## B - Chessboard
**問題文**
[こちら問題ページ](https://atcoder.jp/contests/abc296/tasks/abc296_b)

**解答**
座標の指標となる配列を用意し、あとはループ処理を回して＊が回ってきた時の座標を出力する。

```swift
let positonMark = [["a","b","c","d","e","f","g","h"],["8","7","6","5","4","3","2","1"]]
var field = [[String]]()

for _ in 0..<8 {
    field.append(Array(readLine()!).map{String($0)})
}

var position = ""

for row in 0..<field.count {
    for column in 0..<field[row].count {
        if field[row][column] == "*" {
            position = positonMark[0][column] + positonMark[1][row]
            break
        }
    }
}

print(position)
```

# 誤答及び、未解答問題
## C - Gap Existence
**問題文**
[こちら問題ページ](https://atcoder.jp/contests/abc296/tasks/abc296_c)

**未解答**
解き方がわからなかったため、未解答。

**正答**
順番に目標との差分を配列に加えていき、その配列の中に該当の値があれば　X=Ai - Aii のパターンがあるということになる。


```swift
let nx = readLine()!.split(separator: " ").map{Int($0)!}
let a = readLine()!.split(separator: " ").map{Int($0)!}
var values: Set<Int> = []
var ans = false
for aij in a {
  let comp1 = nx[1] + aij
  let comp2 = -(nx[1] - aij)
  values.insert(aij)
  if values.contains(comp1) || values.contains(comp2) {
    ans = true
    break
  }
}
print(ans ? "Yes" : "No")
```
# 参考
https://atcoder.jp/contests/abc296
Hyperを開いたら自動でNeovimを開くようにした

シェルの操作は全部Neovim内のターミナルで行なっているので、ターミナルエミュレータはNeovimの起動（とキーショートカットを使った入力切り替え）ができればいい、ということでHyperの設定をいじりました。

これはその備忘録です。

### 変更内容
```diff_javascript:~/.hyper.js
"use strict";
// Future versions of Hyper may add additional config options,
// which will not automatically be merged into this file.
// See https://hyper.is#cfg for all currently supported options.
module.exports = {
    config: {
        (...中略...)
-       shell: '',
-       shellArgs: ['--login'],
+       shell: '/opt/homebrew/bin/nvim',
+       shellArgs: [],
        (...中略...)
    },
};
```

単純に起動時のシェルにNeovimを指定しているだけです。
注意点として、`shellArgs: [''],`とすると空文字のファイルが指定された、と解釈されてしまうので`shellArgs: [],`とする必要があります。
C言語おべんきょ備忘録1

勉強したことを自分の言葉でまとめていく〜
恐縮ですが、この記事見られた方でこれ間違ってるよ〜
と気が付かれた方いらっしゃいましたら、ご指摘いただけると幸甚です

よし、と言うことで
初めてのc言語、めっちゃ難しいですね
まずソース冒頭の【#include】
これはあらかじめ用意されたファイル(既存のものでも自作でも)、をソース内にコピペしてくることができる。
もはやヘッダファイル(拡張子が.hのもの)でなくても可能
.cのようなc言語のソースでも.txtのようなメモとかでも
ほんとにそれをそのままソースの中にコピペしたことになるのがinclude..らしい

そしてこれらのような#のついた予約語のことをpre-processor directive(プリプロセッサー指令)と言うらしい
一生この名前を使うことはなさそうなので、一旦忘れます🤗

そして例えば、一番見かけるのが　stdio.h　ってやつ
こいつは標準の入力、出力のためのライブラリです
キーボードでの入力やディスプレイへの出力とかとか
standard input/outpu　で std io

それではなぜこんなものを冒頭に記述するのか〜
それはより楽をするためっぽいですね
ソース内で関数を使いたい時、定義されている順番が大事
関数は呼ばれる前に定義されてないといけない

そこでプリプリなんとか指令の登場ですと言うことですね？
色々と使いたい関数が増えていくと全部いちいち定義するのって
めんどくさいので、ライブラリとして全部まとめてあげましたと

だけどだるいのが、ライブラリを読み込むときにライブラリ内の関数というのは
外部関数になってしまうので、それらを使用するのにexterm宣言が必要になる...らしい...

えーextern宣言ってなに〜!?!?!?!、えーっとちょっと調べた感じだとこれだけでまた長くなりそうなので、
次回にでも持ち越します。

一旦話を戻すと、ライブラリの関数全てのextern宣言を記述するのはクソめんどいくね？
って話で、ライブラリ内の関数のextern宣言全てを、まとめて記述してあるヘッダファイルが存在する
という話でした。それが
プリプリなんたらかんたらっていう予約語達なんですね

なのでこれからそのファイルで何を記述するかによって、
使うライブラリが変わってくると思うのですが、
それに合わせて、どんなプリプリプリズナーが必要かを考えながら、
ヘッダファイルを記述していきたいと思うます　うい

こんな感じで今日のびぼーろく終わりたいと思います
１日１びぼーろく目指して勉強していきま〜す

以下が参考にさせていただいた記事です。
ありがとうございますたー🤗

https://webkaru.net/clang/header-hello-world/

https://xtech.nikkei.com/it/article/COLUMN/20100219/344843/

https://monozukuri-c.com/langc-funclist-extern/#toc2
Node.js: ChatGPT API の使い方 (https)

こちらのプログラムを　Node.js の https モジュールを使って書きました。
[Curl: ChatGPT API の使い方](https://qiita.com/ekzemplaro/items/6660260e287a9ee9ecf4)

## プログラム

```bash:node_fuji.sh
export OPENAI_API_KEY="sk-****************'
./node_fuji.js > out01.json
#
jq .choices[0].message out01.json
```

```js:node_fuji.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	node_fuji.js
//
//					Apr/08/2023
//
// ---------------------------------------------------------------
console.error ("*** 開始 ***")

const https = require('https')

const options = {
	hostname: 'api.openai.com',
	path: '/v1/chat/completions',
	method: 'POST',
	headers: {
		'Content-Type': 'application/json',
		'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
	}
}

const data = JSON.stringify({
	"model": "gpt-3.5-turbo",
	"messages": [{"role": "user", "content": "富士山の高さは"}]
})

const req = https.request(options, res => {
	let responseBody = ''

	res.on('data', chunk => {
		responseBody += chunk
	})

	res.on('end', () => {
		console.log(responseBody)
		console.error ("*** 終了 ***")
	})
})

req.on('error', error => {
	console.error(error)
})

req.write(data)
req.end()

// ---------------------------------------------------------------
```

## 実行結果

```text
$ ./node_fuji.sh
*** 開始 ***
*** 終了 ***
{
  "role": "assistant",
  "content": "3776メートルです。"
}
```
初任給を親に渡した。その時の、「親の顔を見てみたい。」

# 初任給を親に渡した。その時の、「親の顔を見てみたい。」
でしょうか。勘違い男より。

(参考)

https://www.google.com/search?q=%E8%A6%AA%E3%81%AE%E9%A1%94%E3%82%92%E8%A6%8B%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%84%E3%80%82&rlz=1CAUHAM_enJP1038JP1038&oq=%E8%A6%AA%E3%81%AE%E9%A1%94%E3%82%92%E8%A6%8B%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%84%E3%80%82&aqs=chrome..69i57j69i61l2.7272j0j1&sourceid=chrome&ie=UTF-8

＞悪意のある言葉。でした。

翻訳
https://www.deepl.com/ja/translator-mobile#ja/en/親の顔を見てみたい。

# リンク

また、この季節になりましたね。
@ishida330様が投稿時は、すでにコロナでした。
以前コメントしたページのリンクです。top50に,はいっていました。(2023/04/08現在)
**「ブスの25箇条」** もリンクしていました。
昔、私はいいコメントをしていましたね。
オット、ishida330様より。
歳とってやっちゃいけないことは「説教」と「昔話」と「自慢話」

https://qiita.com/ishida330/items/149d93b9690eb61d0e05#comment-c292ed0e8ac30e653149

# 初任給を、も？有効にお使い下さい。
時代時代がありますから。

今までは、また昔話?
・給与が手渡し。現金封筒の時代。
・初任給だけは現金封筒。翌月から銀行振込の時代。
　(会社の手続き上、会社都合。又は会社の気持ち?会社の配慮)
・最初から、給与が銀行振込の時代。

(コロナに直接関係ありませんが？)アフターコロナで、
今後、「デジタル初任給」はどうなるんでしょうね。

「デジタル初任給」で、google検索しましたが、ヒットしませんでした。(2023/04/09現在)

https://www.google.com/search?q=%E2%80%9D%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E5%88%9D%E4%BB%BB%E7%B5%A6%E2%80%9D&client=ms-android-huawei&ei=aG4yZM2RHNCr-Qbht7HgCQ&ved=0ahUKEwjN5cWpqJz-AhXQVd4KHeFbDJwQ4dUDCA8&uact=5&oq=%E2%80%9D%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E5%88%9D%E4%BB%BB%E7%B5%A6%E2%80%9D&gs_lcp=Cgxnd3Mtd2l6LXNlcnAQAzIFCAAQogQyBQgAEKIEMgUIABCiBDoKCAAQRxDWBBCwAzoNCAAQigUQsQMQgwEQQzoICAAQgAQQsQM6BQgAEIAEOgcIABCKBRBDOgoIABAEEIAEELEDOgcIABAEEIAEOgYIABAEEAM6DQgAEAQQgAQQsQMQgwE6CAgAEIkFEKIEOgYIABAHEB5KBAhBGABQ2RZYpP0BYKGFAmgacAF4AIAB8QGIAbQikgEGMC4zNi4xmAEAoAEByAEKwAEB&sclient=gws-wiz-serp

私は専門家でないので、不正確です。
**賃金支払の五原則**がありました。労働基準法第24条（賃金の支払）

https://ja.wikibooks.org/wiki/%E5%8A%B4%E5%83%8D%E5%9F%BA%E6%BA%96%E6%B3%95%E7%AC%AC24%E6%9D%A1

https://www.google.com/search?q=%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E7%B5%A6%E4%B8%8E&oq=%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E7%B5%A6%E4%B8%8E&aqs=chrome..69i57j69i59l2j69i61j0i131i433i650j0i512l5.8958j0j4&client=ms-android-huawei&sourceid=chrome-mobile&ie=UTF-8

2023年4月より、支払形態が分割できるようになりました？
B to C、それから C  to 親　
B to C　現金とデジタル給与の混合?

デジタル初任給に、さらにポイントがつく時代がきたら、
現金は、どうなるのかな。

# おじいちゃん、おばあちゃん子なら
親と相談してね。
孫がおじいちゃん、おばあちゃんにプレゼント?
したらどうなるのかな？4等分?6等分?兄弟は減るからやめておきます。
おじいちゃん、おばあちゃんが、
あなたの親から初任給をもらっていない、見たこともないとなると
さらに、ポイントゲット!!
ポイント?の3重取り以上ありかも。

2023/04/09
昔から？
 **(訂正です）今は、おじいちゃん、おばあちゃんが、孫に就職祝い金を渡す。でした。**

https://www.google.com/search?rlz=1CAUHAM_enJP1038JP1038&q=%E5%B0%B1%E8%81%B7%E7%A5%9D%E3%81%84%E9%87%91+%E8%A6%AA%E6%88%9A&sa=X&ved=2ahUKEwjw0-vStZz-AhUS82EKHcDkAsQQ1QJ6BAhTEAE&biw=1366&bih=645&dpr=1

https://www.google.com/search?q=%E5%B0%B1%E8%81%B7+%E7%A5%9D%E3%81%84%E9%87%91&rlz=1CAUHAM_enJP1038JP1038&oq=%E5%B0%B1%E8%81%B7%E3%80%80%E7%A5%9D%E3%81%84%E9%87%91&aqs=chrome..69i57.2762j0j1&sourceid=chrome&ie=UTF-8
Githubに改行コードありのファイル（今回はCSV)をアップロードするときに気をつけること

# Githubに改行コードありのファイルをアップロードすると、改行コードが変換される

GitHubは、アップロードされたファイルをUTF-8エンコーディングで保存します。
このため、例えばCSVファイルに改行が含まれている場合、改行コードは **「\n」** に変換されます。

つまり、ローカル環境でCSVファイルを作成する際に使用される改行コードが、GitHub上での改行コードとは異なる場合、ファイルの内容が変更される可能性があります。

例えば、Windowsの場合は改行に **「\r\n」** が使用されますが、GitHub上では **「\n」** に変換されます。

したがって、CSVファイルに改行が含まれる場合は、ローカル環境での改行コードとGitHub上での改行コードが一致するように注意する必要があります。

## なんでこんなこと気にするのか
Streamlit CloudというWebアプリを超絶簡単に作れるサービスを見つけたので、お試しでやってみたが、どうやらgithub上のCSVを想定通り（ローカルと同じように）読み込めてないらしいことが判明。

色々調べた結果、ローカルはWindowsだから、改行コードが　**「\r\n」** 。
だけど、GithubはUnix/Linux系なので、改行コードが **「\n」** 　になる。。

Windows歴が長すぎて改行コードといえば、「\r\n」という思い込みがあったのが良くなかった。。。

## 追記（2023年4月10日）
投稿後、早速コメントいただいたので、追記いたします。
git には、「core.autocrlf」という設定値があり、これがデフォルトで「true」となっていました（少なくとも、Windows環境では）。

「true」の場合、commit時に「\r\n」を「\n」に変換してくれるという素敵な仕様のようです。
今回は、使用したStreamlit CloudがLinuxサーバなので、「\n」に変換されたままでGithubにおいておこうと思います。

~~やっぱり、環境構成って一番めんどくさい・・・~~


## Streamlit いいね！

サクサクっと、国土地理院からいただいた日本の山岳情報について、表示するアプリを作ってみた。
見た目の設定とか全然気にしなくても、それっぽいレイアウトで作ってくれるから、結構楽しかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407942/57c484db-f286-219d-b96d-e00552244c86.png)
Maven（Apache Maven）概要

Maven（Apache Maven）
※読み：メイブン

【Mavenとは】
Mavenは、プログラムをビルドすることを目的として利用する「ビルドツール」のひとつで、主にJavaで書かれたプロジェクトをビルドするために利用する。
ざっくり言うと、「Mavenを使うことでJavaプロジェクトの開発が楽になる」。
Eclipseと連携して利用することが多い。


【Gradleとの違い】
同じく、Javaで使えるビルドツールとして「Gradle」が存在する。
実は、MavenもGradleもできることに大きな違いはない。 ただし、Gradleの方が後発であることもあり、Mavenの面倒な部分をより細かいカスタマイズができるようになっている。そのため、やりたいことによってMavenかGradleかを選ぶとよい。

【Mavenを使ってできること】
①ライブラリの管理
Mavenの最大のメリットが、「プロジェクトで利用するライブラリを管理できる」という点。 Javaには多くのライブラリが存在しており、それらのライブラリを使うことで高速に開発を進めることが可能。

Mavenでは、XMLに必要なライブラリの情報を記述することで、「そのプロジェクトに必要なライブラリ」を一元管理してくれる。 また、Mavenは依存性を管理する機能も備わっている。
例えば、あるライブラリAを使いたい場合、ライブラリAは、他のライブラリであるBを利用している場合、JavaのプロジェクトにはライブラリAとライブラリBを含める必要がある。 しかし、Mavenを利用した場合には、「ライブラリA」の情報のみを記述するだけで良くなる。
Maven上に存在するライブラリAには、「ライブラリBを利用するよ（依存関係がある）」ということが明記されており、Mavenはこの依存関係を自動で吸収してくれる。 プロジェクトには「ライブラリAを利用する」と記述するだけで、ライブラリBも自動で依存関係に含めてくれる。
 このように、ライブラリの管理が非常に楽になるのがMavenの大きなメリットと言える。

②ライブラリの自動インストール
Mavenは利用するライブラリを管理するだけでなく、それらのライブラリを自動でインストールしてくれる。 先ほど紹介した「依存関係」を自動で検出し、必要なライブラリを一括でダウンロードしてくれる。 手動でライブラリをインストールする必要がないので、複数人で開発するときにありがちな「ライブラリのバージョンが違ったので挙動が異なってしまう」というような問題も発生しなくなる。

③ビルド
もうひとつのメリットが「プロジェクトのビルド」。
コマンドを実行するだけで、
 ・必要なライブラリのインストール
・Javaファイルのコンパイル
・自動テスト
・パッケージ(JarやWar)の作成 
上記の処理を一括で実行できる。
 ビルドからテストまでを一括で実施してくれることで、人の手による作業を減らす役割を担っている。
そのため、複数人で開発をするような現場であればこのようなビルドツールは必須の存在と言える。


【よく使うMavenコマンド】
・依存関係のライブラリをインストールする際には「install」コマンドを利用する。
「mvn install」

・作成したJUnitの単体テストを実行する場合には「test」コマンドを利用する。
「mvn test」

・javaファイルをコンパイルし.classファイルを作成する場合には、compileコマンドを実行。
「mvn compile」

・成果物としてjarやwarといったファイルを作成する際に実行するのが「package」コマンド。
「mvn package」

・ビルドの成果物をサーバー等へ公開する際に利用するのが「deploy」コマンド。
「mvn deploy」

・プロジェクトをクリーンし、ビルド結果を削除する場合には「clean」コマンドを利用する。　ビルドに失敗した場合や、うまく動かない場合にはこのコマンドを利用する。
「mvn clean」




【引用サイト】
・https://qiita.com/tarosa0001/items/e5667cfa857529900216
・https://camp.trainocate.co.jp/magazine/about-maven/
ffmpeg で変換結果を標準出力に出力するとエラーになることがある

# 1. 【概要】

ffmpeg で変換結果を標準出力に出力するためには、`-f mp4 -` のように`-f`オプションで出力フォーマットを明示的に指定した上で、出力先として `-`を指定しなければなりません。
でも、そのような指定をしても変換中にエラーになることがあります。

推測混じりですが原因がつかめたので、せっかくなので投稿することにしました。

# 2. 【発生する問題について】

まず、以下のようなコマンドを実行してみます。

```
ffmpeg -i sample.mp4 -c:v copy -c:a copy -map 0 -f matroska - | ffplay -i -
```
このコマンドでは、mp4形式の動画ファイルを mkv形式に変換して ffplay で再生しています。

**「え？普通に `ffplay -i sample.mp4` でいいんでないの？」** というツッコミはごもっともですが、わかりやすい例として挙げただけなのでご容赦ください。

これを実行すると、普通に ffplay が起動して動画の再生が始まります。まぁ、普通に当たり前です。

次に、出力フォーマットを mp4 にしてみます。

```
ffmpeg -i sample.mp4 -c:v copy -c:a copy -map 0 -f mp4 - | ffplay -i -
```

すると、ffmpeg から以下のようなエラーメッセージが表示され、変換ができません。

```
[mp4 @ 0000016b2121a200] muxer does not support non seekable output
[out#0/mp4 @ 0000016b21214840] Could not write header (incorrect codec parameters ?): Invalid argument
[aost#0:1/copy @ 0000016b212622c0] Error initializing output stream:
S
```

また、出力フォーマットは mkv のままで、映像を `libaom-av1` でエンコードしてみます。

```
ffmpeg -i sample.mp4 -c:v libaom-av1 -crf 23 -c:a copy -map 0 -f matroska - | ffplay -i -
```

すると、ffmpeg から以下のようなエラーメッセージが表示されて、同じく変換に失敗します。

```
av_interleaved_write_frame(): Invalid data found when processing input
```

# 3.【原因について】
エラーメッセージからピンときた方もおられると思いますが、原因は出力先がランダムアクセス不可であったことでした。つまり、出力先を標準出力にしたことによる問題です。

この問題は必ず発生するわけではなく、例えば出力フォーマットに mkv を指定した場合 (つまり `-f matroska`を指定した場合) は問題なく動作しましたし、映像のエンコーダに `copy` / `libx264` / `libx265` を指定した場合も問題ありませんでした。

# 4. 【これってバグ？】

ここから先は私の推測になります。

結論から言うと、**バグではなく仕様** と言えると思います。何故かというと ffmpeg や 各コーデックのプログラム側ではおそらく対処のしようがないからです。

<details>
<summary>※この部分はかなり込み入った話になります。読み飛ばしても結構です。</summary>

話は変わりますが、以前に zip ファイルのフォーマットを調べたことがあるのですが、その中には以下のようなデータ構造がよく使われています。

<----ファイルの先頭方向　　　　　　　　　　　　　　　　ファイルの末尾方向---->
| block の長さ<br/> (2または4バイト整数) | block (圧縮されたデータのバイト列)・・・・・・・・・・・・・・・・・・・・・|
|-------------|----------|

こういったデータ構造をデコードする場合には、まず zip ファイルから「blockの長さ」を読み込んで、次にその長さの分だけ「block」部分を読み込みます。

逆にエンコードの場合には、まず「blockの長さ」を zip ファイルに書き込んで、次に block 部分を書き込み・・・たくなります。ところがそうすることが難しいことがよくあります。その代表的なケースは「block の部分が圧縮されたデータであり、**実際に圧縮をしてみないと圧縮後の長さがわからない**」というものです。

もちろん、実際に圧縮をしてみてその結果の長さを先に書き込んで、圧縮されたデータをその後に書き込む、ということも可能ではあります。しかし、その場合は、圧縮した結果をどこかに保存しておいて、その長さを調べて先に書き込み、その後に圧縮結果を書き込む必要があります。その場合の問題は、圧縮後のデータを格納するためのメモリ(大抵はヒープメモリ)が余分に必要なことです。また、ヒープ領域の管理にはそれなりにCPUやディスクI/Oコストもかかります。

そういった問題を 大抵の zip エンコーダの開発者は以下のように解決しています。
1. まず、「block の長さ」部分をすべて 0 で書き込む。
1. 次に、入力されたデータを逐次圧縮して「block」部分に書き込む。
1. 圧縮されたデータの長さが判明しているので、**「blockの長さ」部分まで戻って** 改めて圧縮されたデータの長さを書き込む。

これなら余分なメモリを消費せず、メモリ管理の手間も減ります。

要するに、消費メモリの削減や圧縮速度を低下させないためには **出力先はランダムアクセス可能でなければならない** わけです。[^1]
</details>

話は ffmpeg 関連に戻りますが、おそらく ffmpeg のいくつかのエンコーダは前述の例と同様の理由でコーデックのファイルフォーマットの都合により出力先がランダムアクセス可能でなくてはならないのではないでしょうか。

# 5. 【まとめ】
+ ffmpeg での変換結果を標準出力やパイプへ出力しようとすると、出力フォーマットや変換コーデックの指定によってはエラーとなることがある。
+ おそらくはファイルフォーマットに由来する仕様であり、回避方法としては出力先をファイルにするしかないと思われる。

[^1]: 余談ですが、実際の zip ファイルフォーマットの規定には、出力先がランダムアクセス不可である場合の救済のためのとある特殊なフォーマットが存在します。しかし、そのフォーマットでのエンコードに対応していない zip エンコーダは多く存在します。
Databricksクラスターポリシーの正式提供

[Announcing General Availability of Cluster Policies \- The Databricks Blog](https://www.databricks.com/blog/2023/04/07/announcing-general-availability-cluster-policies.html)の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

クラスターポリシーの正式提供(GA)を発表できることを嬉しく思っています。

# どうしてDatabricksクラスターポリシー？

Databricksクラスターポリシーを用いることで、管理者は:

- エンドユーザーのクラスター設定を制御することでコストを抑えることができます。
- エンドユーザーがクラスターを作成しやすくなります。
- コスト管理のためにワークスペース横断でタグを強制できます。

また、3つの主要なユースケース向けに事前定義されたクラスターポリシーを提供します: パーソナルユース、共有利用、ジョブです。

また、管理者は自分のポリシーをカスタマイズしたり、事前定義済みのポリシーを編集することができます。

# クラスターポリシーの使い方

## 1. クラスターポリシーへのアクセスを許可

使い始めるには、管理者はポリシーUIでワークスペースごとのDatabricks(あるいはカスタム)クラスターポリシーへのアクセスをユーザーに許可します。
![](https://cms.databricks.com/sites/default/files/inline-images/db-520-blog-img-1.png)

## 2. ポリシーを用いたクラスターの作成

管理者が1人以上のユーザーにポリシーを割り当ると、当該ユーザーはComputeページでポリシーを参照できるようになります。
![](https://cms.databricks.com/sites/default/files/inline-images/db-520-blog-img-2.png)

ユーザーは管理者のガイドラインに準拠していることを理解して、自身のクラスターを作成することができます。

# ポリシーを使い始める

管理者が定義したクラスターポリシーを使用するには、プレミアムプランのDatabricksをし湯押している必要があります。Databricks定義のポリシーファミリーは、向こう数ヶ月ですべてのプランで利用できるようになります。

Databricks管理者として、「クラスター」ページにアクセスし、ポリシーのJSONエディターで自身のポリシーを作成するために「クラスターポリシー」タブにアクセスします。あるいは、API経由でポリシーを作成することができます。詳細はDatabricksドキュメントのクラスターポリシーをご覧ください([AWS](https://docs.databricks.com/administration-guide/clusters/policies.html)、[Azure](https://learn.microsoft.com/ja-jp/azure/databricks/administration-guide/clusters/policies))。

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
エクセルて、何ですか?

2023/04/15追加

**?copilot、副操縦士、データの分離だそうです。
youtubeより**
qiita内にも、copilotのタグが、75記事ありました。
https://qiita.com/tags/copilot
新人の方が、?copilotについてくわしくいらして、
教えていただく際には、よろしくお願いします。
**以上、「新人プログラマ様に応援してもらう_記事投稿キャンペーン」になってしまいました。**

# ①2年前「エクセルて、何ですか?」2021-03-18
詳細は以下のコメントで。古すぎますか？

https://qiita.com/shinkai_/items/f1961705c8d5184a97af#comment-f0ab0501c155b23f35aa

今回、大学の推奨パソコンを調べたら、
大学の新入生は、包括契約でエクセルを使っている。使う予定とわかりました。
エクセルの復活？BYODでしょうか。

https://qiita.com/mrrclb48z/items/09e63a5dcd0e47f56044

私は、GASを使っています。

# ②もしかしたら、「マウスって何ですか?」の時代も来るのかな。
昔の笑い話が復活するかも？「パソコンで、ねずみが飼えるのか？」
検索して、見つかりませんでした。
表現が違いますか？探し方を教えて下さい？

チョト前までは、「6ボタンマウスほしいなあ。」
(ファンクションマウスの) ボタンの割り当てどうしようかな？
お金がないから、マウスジェスチャーのフリーソフトでいいか。
と思っていたのに。
タッチパネル。スマホ、タブレットを使うので、マウスを使いませんね。

参考
＞「ミッキー」2014年12月20日現在の情報
＞今のように広く利用されるようになったのは...
https://flets-w.com/chienetta/pc_mobile/cb_pc-equipment32.html
i＊honeを作った方が、他社の機械を見学してから、m＊cに採用したと読んだ事があります。
マウスのボタンは,1つでなくちゃ。イヤだ。
今は、ピンチイン・ピンチアウト、タッチペンですか？
興味のある方は、正式な文献で。

# ③もしかしたら、「利息って何ですか?」の時代も来るのかな。
利息の代わりに、ポイント。
https://www.deepl.com/ja/translator#ja/en/利息って何ですか?

# 結論?
　
https://www.deepl.com/ja/translator-mobile#ja/en/長い目で見てください。

https://www.google.com/search?q=%E9%95%B7%E3%81%84%E7%9B%AE%E3%81%A7%E8%A6%8B%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84+%E8%8B%B1%E8%AA%9E&rlz=1CAUHAM_enJP1038JP1038&oq=&aqs=chrome.1.35i39i362l8.26480j0j7&sourceid=chrome&ie=UTF-8
URLSessionの処理を関数化する

SwiftUIでCombineを使用してAPIを叩くとき
`URLSession.shared.dataTaskPublisher`を使用する場合は多々あると思います。

とあるアプリを作成中(MVVCを導入)ViewModel内でdataTaskPublisherの処理を書くとどうしてもコードが長くなってしまうので共通化できるところを共通化したお話です。

私の場合はURLRequestを生成する部分はNetworkというClassを作成しそこにある程度処理を持たせています。

下記のコードのようにdecodingTypeとURLRequestを引数に持たせることによって今のところ問題なく使えています。
`func sinkCompletion`の方もSubscrivers.Completionを引数に渡すことによってswitch文をviewmodelの関数に書く必要がなくなります。


```　swift:sample.swift
func urlSession<T: Decodable>(with request: URLRequest, decodingType: T.Type) -> AnyPublisher<T, Error> {
        URLSession.shared.dataTaskPublisher(for: request)
            .tryMap{(data, response) -> Data in
                guard let response = response as? HTTPURLResponse,
                      // 処理
                else {
                    throw URLError(.badServerResponse)
                }
                return data
            }
            .decode(type: T.self, decoder: JSONDecoder())
            .receive(on: DispatchQueue.main)
            .eraseToAnyPublisher()
    }
```

``` swift:sample2.swift
    func sinkCompletion(res: Subscribers.Completion<Error>) {
        switch res {
        case .finished:
            print("Completion:\(res)")
            break
        case .failure:
            print("Completion:\(res)")
            break
        }
    }
```
Httpie: ChatGPT API の使い方

こちらのページを Httpie で書いてみました。
[Curl: ChatGPT API の使い方](https://qiita.com/ekzemplaro/items/6660260e287a9ee9ecf4)

## スクリプト

```bash:http_fuji_a.sh
API_KEY="sk-****************'
http https://api.openai.com/v1/chat/completions \
  'Authorization: Bearer '$API_KEY \
	model="gpt-3.5-turbo" \
    messages:='[{"role": "user", "content": "富士山の高さは"}]' > out01.json
#
jq .choices[0].message out01.json
```

入力ファイルを使った場合

```bash:http_fuji_b.sh
API_KEY="sk-****************'
http https://api.openai.com/v1/chat/completions \
  'Authorization: Bearer '$API_KEY \
  @in01.json > out01.json
#
jq .choices[0].message out01.json
```

```json:in01.json
{
  "model": "gpt-3.5-turbo",
  "messages": [{"role": "user", "content": "富士山の高さは"}]
}
```

## 実行結果

```text
./http_fuji_a.sh
{
  "role": "assistant",
  "content": "富士山の高さは3,776.24メートルです。"
}
```

```text
./http_fuji_b.sh
{
  "role": "assistant",
  "content": "3,776.24メートルです。"
}
```

何度も同じ質問を繰り返すとこんな答えが返ってきます。

```text
{
  "role": "assistant",
  "content": "3776メートルです。ただし、気象庁が公表する高度は、富士山の標高基準面からの高さである3,776.24メートルになります。"
}
```

## 確認したバージョン

```text
$ http --version
3.2.1
```
SwiftにFirebase Crashlyticsを導入した話

基本的には公式のページ見ればOK、問題なく導入できます。

https://firebase.google.com/docs/crashlytics/test-implementation?hl=ja&platform=ios

個人的にあれ？ってなったのは、実装してClashを起こしたあとコンソールには「アプリが検出されクラッシュを待機しています」しか表示されない。

### ちゃんとドキュメント読んでなかった
Buildして立ち上がったシミュレーター上でClashさせていたのですが、正確にはRunでアプリを立ち上げたあと、停止させます。
その後Buildせずにシミュレーターからアプリを起動してClashを起こすだけです。すぐにコンソールに表示されました。

ドキュメントは正確に読みとこう。というお話
テスト92

```vb
'ACCESS
Sub T_UPDATEJoinSet()
'参照設定
'Microsoft ActiveX Data Objects x.x Library
Dim str_SQL1 As String

'AccessのUPDATE文＋結合はちょっと勝手が違うらしい...φ(´･ω･｀*)
'例えば以下のようなSQL文はエラーになる
'str_SQL1 = "UPDATE 商品表1 " & _
'           "SET 商品表1.商品コード = 商品表2.商品コード;"
'           "FROM 商品表 1 " & _
'           "INNER JOIN 商品表2 " & _
'           "ON 商品表1.商品名 = 商品表2.商品名" & _

'以下のSQL文は実行できる(先に内部結合して、結合したデータの指定の列を更新する)
str_SQL1 = "UPDATE (商品表1 " & _
                   "INNER JOIN 商品表2 " & _
                   "ON 商品表1.商品名 = 商品表2.商品名)" & _
           "SET 商品表1.商品コード = 商品表2.商品コード;"

'SQLを実行
DoCmd.RunSQL str_SQL1

End Sub

'メモ
'SELECT *
'FROM TestA AS A
'LEFT JOIN TestB AS B
'ON m_A.id = B.id
'WHERE b.ID Is Null
'
'
'
'SELECT a.ID
'FROM (SELECT a.ID, b.ID
'      FROM 販売履歴A a
'      LEFT OUTER JOIN 販売履歴B b
'      on a.ID=b.ID)
'WHERE b.ID Is Null

'1 ､シートを追加
'2 ､新しいシートに指定の項目を入力
'　（インポート先のテーブルにある項目をそのまま入力）
'3 ､元シートにあるデータを追加したシートへ入力
'　（日付をどう入力する必要があるか確認する）
'4 ､追加シートのデータをAccessの指定のテーブルへ取り込む
'　（SQLにSELECTを入れない）
'※高速化も必要(Application.Echo False(True))
【自作アプリ 第一期】

### 自作アプリ
1月上旬から作成中の収支アプリの経過報告

#### 【アプリ概要】
・株式投資を集計
・集計された収支をグラフとして表示
・固定費計算

#### 【テーブル】
・株式テーブル(INVEST)
・ユーザーテーブル(USERS)

実行したSQL文
INVESTテーブル
```sql
CREATE TABLE INVEST(ID INT PRIMARY KEY AUTO_INCREMENT,
USER_ID INT NOT NULL,
COMPANY VARCHAR(100) NOT NULL,
NUMBER_SHARE INT NOT NULL,
MARKET_PRICE INT NOT NULL,
MEMO VARCHAR(100),
INVEST_DATE DATE);
```

USERSテーブル
```sql
CREATE TABLE USERS(ID INT PRIMARY KEY AUTO_INCREMENT,
ACCOUNT  VARCHAR(20) NOT NULL,
PASS VARCHAR(256) NOT NULL;
```
（メモ）
テーブルを作成する際にAUTO_INCREMENTを指定していないと連続してINSERTした場合に一意制約エラーが起きてしまっていた。初歩的なミスだが割と時間が掛かってしまったのでここの場を借りてメモをしておく。

#### 【機能】
##### --ログイン画面--
⇨ログイン機能
存在しているユーザーのアカウント名とパスワードと照合してログインの判定を行う。
空文字はエラーメッセージを表示
⇨アクション
ログイン
新規登録
固定費計算

##### --ユーザー新規登録画面--
⇨ユーザー新規登録機能
空文字はエラーメッセージを表示
⇨アクション
登録
戻る
##### --トップ画面--
⇨株式集計機能
ログインしているユーザー毎に集計する事が可能（セッションにてユーザー情報を取得）
⇨アクション
追加
戻る
ログアウト

##### --固定費計算画面--
⇨固定費計算機能
固定費が計算できる
⇨アクション
追加
削除
戻る
ログアウト

（改善点）
遷移元がトップ画面なのでユーザー情報をセッションで飛ばしていない為
全てのデータを集計してしまっている。トップ画面からの遷移にしてログインしているユーザー別に
集計するべき。

#### 【画面レイアウト】
ログイン画面
![ログイン画面　第一期.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918178/680e4787-efee-b829-8313-003992f69d2c.png)


ユーザー新規登録画面
![ユーザー新規登録画面　第一期.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918178/ced53b71-85f2-6a04-335f-051ec2e894f9.png)


トップ画面
![トップ画面　第一期➀.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918178/025ec469-f825-c54a-3f8e-d28f5399fc5f.png)

![トップ画面　第一期➁.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918178/1b593bfa-5877-4a43-3aca-e86533536d9a.png)


固定費計算画面
![固定費計算画面　第一期➀.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918178/478e1f48-8f6a-5186-d2b0-ca07fc441fce.png)

![トップ画面　第一期➁.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918178/eeb88597-7027-52ad-464b-6b27cde43f0c.png)
rails お気に入り機能エラー

# railsお気に入りマーク押すとエラー

自分用のメモになりますが、こんなミスをしていたよーというのを書き残したいので投稿させてもらいます。

下記のハートを押してお気に入り一覧に表示させたい！
と思って押すと…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111780/75e3c4c2-215f-e435-d2cd-fd991c3c2268.png)

こんなエラーが…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111780/d424d9a1-46a9-6a05-a9d7-ca6ba5422f69.png)

ルーティングエラー…
　
$ rails routesで確認してみると…


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111780/c916852b-2f8a-927c-aecf-41cbf5bc0ec2.png)
ルートパスが`user_spot_favorites`となっている

ビューで入力したパスを見てみると…

```php
<div>
  <%= link_to user_favorites_path(spot), method: :delete do %>
   <div class="heart">
    <i class="fas fa-heart fa-2x" style="color: red;"></i>
     </div>
  <% end %>
    </div>
  <% else %>
    <div>
      <%= link_to user_favorites_path(spot), method: :post do %>
        <div class="heart">
          <i class="far fa-heart like-btn fa-2x" style="color: black;" ></i>
```




`user_favorites_path(spot)`となっていて
パスが間違えていました


ここを`user_spot_favorite(spot)直せば大丈夫でした。
```php
<div>
  <%= link_to user_spot_favorites_path(spot), method: :delete do %>
   <div class="heart">
    <i class="fas fa-heart fa-2x" style="color: red;"></i>
     </div>
  <% end %>
    </div>
  <% else %>
    <div>
      <%= link_to user_spot_favorites_path(spot), method: :post do %>
        <div class="heart">
          <i class="far fa-heart like-btn fa-2x" style="color: black;" ></i>
```




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111780/d5e511c9-96eb-e2ee-b91c-c80517f09f93.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111780/86d8aa88-b42c-39af-d0c6-b95761d97c63.png)


よかった…
構文木と結合

# 結合の仕方は構文木の深さだけではわからなかった...
左結合、右結合について、四則演算なら左側に「(」が連続していれば左結合、逆が右結合だと思っていました。
左結合: (((1 + 2) + 3) + 4)
右結合: (1 + (2 + (3 + 4)))

同じように木構造も左結合は左側が深い、といったルールだとずっと考えていたのですが、文法のつくりかたによってそうではない場合もあるのですね。

これは足し算引き算の文法で左再帰を除去するときに気づきました。
Powershellでファイルの中身を出力する

# ファイルの中身を確認したい

ファイルの中身を表示したい時に使うコマンドを調べました。
それがGet-content コマンドになります。

それでは実行して結果を確認してみましょう。

コマンドの書き方としては以下の通りになります。

Get-Content ファイルパス/ファイル名

今回はmoji.txtというファイルの中身を表示したい場合です。

例
```moji.txt

a
dd
ooo
j
```

```
Get-Content フォルダパス/moji.txt

a
dd
ooo
j
```

moji.txtの内容である「a　dd　ooo　j」が表示されました。


# 結果をファイルに出力して記録したい場合

では実行した結果をコンソールではなく、何かのファイルに記録したい場合を考えてみます。
その場合ですが場合、set-contentコマンドを使用します。

| （パイプライン）を使用することでコマンドの結果を別ファイルに出力できます。

```
Get-Content 出力元のファイル|Set-content -Path 出力先のファイル
```


moji.txtの内容をmoji.logというファイルに出力したい場合は以下の通りです。
```
Get-Content フォルダパス/moji.txt|Set-content -Path フォルダパス/moji.log  
```

これでmoji.logに中身が出力されました。

パイプラインの便利さを改めて感じました。もっと応用していきたいですね。
WindowsとGitHubのファイル並び順の違いを、ASCII文字の範囲で具体的に確認した

# そのリポジトリがこちら

https://github.com/Phroneris/ASCII-Filename-Order

という感じ。

リポジトリの README は英語っぽい何かで書いたが、せっかくなのでそれと同じことをここ Qiita に日本語っぽい何かで書いておく。


# ASCII 文字のファイル並び順調査

Windows と GitHub のファイル名における ASCII 文字の取り扱いを見てみる。

## Windows

画像が縦長すぎるので縮小表示している。
クリックすれば別タブで原寸閲覧できるはず。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/9e88af7d-2fdf-7e2f-0ad6-dd948d3387cf.png" width="250" height="470" title="Windows 10（クリックで原寸閲覧）">

### 並び順

- 数字部分は数値として並び替えられる。
- 大文字・小文字は区別されない。

### 制約

- 頭と尻のスペースは削除される。
- 一部の記号が使えない。 `"` `*` `/` `:` `<` `>` `?` `\` `|`

Windows 10 Home 64-bit 22H2 にて確認。

実は他にも色々と制約があるが、ASCII 文字の並び順というテーマからは遠のくのでカットしている。
その辺は公式ドキュメントを見た方がずっと正確だろう。

https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions

## GitHub

画像は [`invalid-on-Windows`](https://github.com/Phroneris/ASCII-Filename-Order/tree/invalid-on-Windows) ブランチのもの。
やはり縦長すぎるので縮小表示している。クリックで原寸閲覧。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225134/752ffc8b-12ac-4239-983b-0d9df6a705ec.png" width="230" height="880" title="GitHub（クリックで原寸閲覧）">

### 並び順

- 数字も含め、全てが ASCII 順に並ぶ。

### 制約

GitHub の "Create new file" で新規ファイル名を入力する際、

- 頭と尻のスペースは削除される。
- スラッシュ `/` が使えない。
- `/` 以外の Windows で使えない記号、つまり `"` `*` `:` `<` `>` `?` `\` `|` は、こちらでは**使える**。
  しかし、リポジトリを Windows でクローンした場合に深刻なエラーを引き起こす恐れがある。
  ```
  error: invalid path ':a'
  error: invalid path '\a'
  error: unable to create file "a: Invalid argument
  error: unable to create file *a: Invalid argument
  error: unable to create file <a: Invalid argument
  error: unable to create file >a: Invalid argument
  error: unable to create file ?a: Invalid argument
  error: unable to create file |a: Invalid argument
  ```

Google Chrome 111.0 にて、2023 年 4 月 8 日確認。

なお、上記エラーはクローン時に `--config core.protectNTFS=true` とか `--sparse` とかのオプションで回避できる可能性が無くもない。
ただ、回避といっても「とりあえず他のファイルはチェックアウトできるようになる」程度のものであり、エラーの原因となったファイル自体は依然としてローカルに存在を許されないので、およそ根本解決と言えるものではなかろう。

https://scrapbox.io/Mijinko/Windows%E7%89%88Git%E3%81%AEerror:_invalid_path%E3%82%92%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B

https://qiita.com/yokra9/items/90503b25f4cfe8de2242

## 他の OS

募集中。

聞きかじった限りだと、
- Mac では `/` と `:` が使えないらしい。
- Unix では**改行 `\n` すら使える**らしい。

https://qiita.com/uasi/items/996b24185dffb003105a

https://zenn.dev/hankei6km/articles/lf-in-filenames-is-confusing

# おまけ

## ASCII コード一覧

まぁ、一応。

- 0x00～0x1F、0x7F (DEL)
  - 制御文字
- 0x20～0x2F
  - スペース、`!`、`"`、`#`、`$`、`%`、`&`、`'`、`(`、`)`、`*`、`+`、`,`、`-`、`.`、`/`
- 0x30～0x3F
  - 0～9、`:`、`;`、`<`、`=`、`>`、`?`
- 0x40～0x4F
  - `@`、A～O
- 0x50～0x5F
  - P～Z、`[`、`\`、`]`、`^`、`_`
- 0x60～0x6F
  - `` ` ``、a～o
- 0x70～0x7E
  - p～z、`{`、`|`、`}`、`~`


# ツイートはこちら

https://twitter.com/Phroneris/status/1644496774172930048


&ZeroWidthSpace;

おわり
apacheでサクッとベーシック認証

# はじめに
Apacheを使ってベーシック認証を実装する機会があったので、まとめてみます。

## 認証ユーザーとパスワードを設定する
```linux
$ sudo htpasswd -c /etc/httpd/htpasswd ユーザー名
New password: パスワード
Re-type new password: パスワード
```

-c コマンドは、ユーザーとパスワードが書かれたファイルを新規作成or上書きします。

cat コマンドで確認すると、ユーザーとパスワードが見れます！
```
$ cat .htpasswd
ユーザー名：暗号化されたパスワード
```

## パスワードファイルのアクセス権を変更する
apacheのみがアクセスできるようにしておきます。
```
$ sudo chown apache:apache /etc/httpd/htpasswd
$ sudo chmod 600 /etc/httpd/htpasswd
```

## Apacheの設定

### confファイルを編集
confファイルを開きます。
```
$ sudo vim /etc/httpd/conf/httpd.conf
```

Directoryタグを追加します。
```
<Directory "/var/www/html">
  AuthType Basic
  AuthName "auth"
  AuthUserFile /etc/httpd/htpasswd
  Require valid-user
</Directory>
```

※例では アクセス制限をかける場所を、/var/www/html としていて、Apacheの公開ディレクトリ全部にアクセス制限を行なっています。

### リロードして設定ファイルを反映させる
```
$ sudo systemctl reload httpd.service
```

## 該当ページへアクセス
ベーシック認証画面が表示されていれば成功です！
【♪】TechTune #0004「Web application programming paradigm shift」

<iframe width="560" height="425" src="https://www.youtube.com/embed/RlVLSt6EB-I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

このドキュメントは毎週土曜日に配信しているポッドキャスト「テックチューン」からピックアップしたトピックスです。

時代の傍観者、宴会部長、マカ―の生き残り、生きた化石のいしたんがお届けする、人生の吹き溜まりのラジオ番組「テックチューン」の時間です。テックチューンは最近話題のテクノロジーや私の身の回りで起こったこと、興味があることなどをお話する番組です。特に目標もなく無気力に続けていきたいと思いますので、お付き合いいただけますと幸いです。

## はじめに
今回はウェブアプリケーションの開発手法について検討してみました。
ウェブアプリケーションというのはブラウザで閲覧できるアプリケーションのことになります。
今回はPCとiOS、Androidの３デバイスで使用できるフレームワークや開発手法について検討しました。
![スクリーンショット 2023-04-08 9.49.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514807/dfd3f558-e12c-cf52-0f83-1e172ba585b7.png)

Webアプリケーションの開発スタイルを現状(Current)と将来(Future)に分けてみました。
![スクリーンショット 2023-04-08 9.49.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514807/dcfcfa20-3135-b9d2-cbcb-0937113d6376.png)

プラットフォーム観点での現状と将来について検討してみました。単体サーバーだったものがサーバーレスなどのクラウド環境を前提としたアーキテクチャとなっています。
![スクリーンショット 2023-04-08 9.49.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514807/98f584d6-f055-8406-010a-bdd9add935c1.png)

実際にフロントエンドフレームワークを使用して開発を進める場合に、どういった観点で選定を行えばよいかをまとめました。
![スクリーンショット 2023-04-08 9.50.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514807/34ad48d3-02eb-017d-84ae-a4649d91a362.png)

Google Trends を使用して直近５年間のフレームワークの人気度をグラフ化してみました。
![スクリーンショット 2023-04-08 9.50.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514807/1bcf86ac-cb48-4145-a1bc-92db3868701e.png)


## おわりに
それぞれのフレームワークを使用して実際にプログラムを開発してみたいと思います。また、バックエンド側も開発してそれぞれの使い勝手を考えてみます。
EC2にアタッチしたIAMロール vs ECS タスク起動ロール

AWSのサービス諸々ありますが、IAMが一番難しいです…。
それぞれのサービス特有の権限とIAMロールの権限が競合するときや、複数のIAMロールが付与された環境にて優先される権限等、枚挙にいとまがありません。
今回は特にECS on EC2 環境での
- EC2にアタッチしたIAMロール
- ECS タスク起動ロール

が競合した際、どちらが優先されるのか実験したいと思います。
（ECSタスク起動ロールとタスクロールの違いはここでは解説しません💦）


## 実験
両者が競合する状況として、EC2で起動しているコンテナの**CloudWatchへの書き込み**を想定しました。
図のような状況です。

![名称未設定ファイル.drawio (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759541/73b5fb11-2066-44fe-20d2-5777e2b7adae.png)


この場合、EC2にアタッチしたIAMロール、ECS タスク起動ロールのどちらが優先されるのでしょうか？

ChatGPTさんによると、どちらかに権限があれば書き込みが出来るそうですが...。


### 手順

#### ECRにイメージのpush
`hello-world`するDockerfileを用意し、ECRにpushします

```Dockerfile:Dockerfile
FROM hello-world
```

![スクリーンショット 2023-04-08 9.39.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759541/7eb6c9b5-f1dd-ae6e-1b5d-f50de61067ae.png)

OK

#### タスクの追加&ECSクラスタの作成

まずはタスクの作成、イメージURlは先ほどpushしたhello-worldイメージのURlをします。
![スクリーンショット 2023-04-08 9.42.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759541/cad522c6-a22f-61e0-faa4-061f454dcae5.png)

続いてクラスタの作成。
![スクリーンショット 2023-04-08 9.53.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759541/f08d75cf-d1cd-6a7b-f08c-f282ddc19acd.png)

ここまではデフォルトの権限（ecsTaskExecutionRole）を用いています。
この権限にはAmazonECSTaskExecutionRolePolicyのポリシーがついているため、CloudWatchへの書き込みができるはずです！

早速hello-worldしてみましょう！٩( ᐛ )و
![スクリーンショット 2023-04-08 9.58.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759541/1a204ca9-02c0-0ca7-9d33-38938498563f.png)

大丈夫そうですね！
ではそれぞれのパターンで調査してみます。

## 結果

|EC2|ECS|ログ|
|:----|:----|:----|
|あり|あり|○|
|なし|あり|○|
|あり|なし|○|
|なし|なし|x|

ChatGPTさんの言う通りになりました！

なしなしの場合はログ出力がなく、以下のようなエラーメッセージが出てました。
![スクリーンショット 2023-04-08 10.23.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759541/fbddfde1-2771-ea73-e30a-c20ea6e18512.png)

詳細
状況の理由	CannotStartContainerError: Error response from daemon: failed to initialize logging driver: failed to create Cloudwatch log stream: NoCredentialProviders: no valid providers in chain. Deprecated. For verbose messaging see aws.Config.CredentialsChainVerbo

## まとめ
IAMにはAllow、Denyの概念もあり、さらにややこしいです。


https://www.guri2o1667.work/entry/2022/08/23/%E3%80%90AWS%E3%80%91IAM%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%81%AEAllow/Deny%E3%81%AE%E5%84%AA%E5%85%88%E5%BA%A6%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_evaluation-logic.html
fzf でターミナルのコマンド入力を便利にする

# この記事は何？
最近 fzf という便利なコマンドラインツールを知ったので、簡単に紹介してみます。

# fzfとは?

fzf は高速で拡張性のあるコマンドラインインタラクティブフィルタリングツールです。
https://github.com/junegunn/fzf

# インストール
ubuntuの場合aptで一発です。
```
sudo apt install fzf
```

# 具体的にどんなことができる？
以下に使用例の一部を紹介します。

## ファイルやディレクトリの検索
例えば以下のようにfindコマンドと組み合わせて、特定のディレクトリ以下のファイルをfzfでフィルタリングしながら選択することができます。

```bash
find /path/to/directory -type f | fzf
```

動いているところのイメージは公式レポジトリのyoutube動画が分かりやすいです。
https://youtu.be/qgG5Jhi_Els?t=69

## コマンド履歴の検索
コマンド履歴をフィルタリングして検索することができます。例えば、以下のようにhistoryコマンドと組み合わせて、コマンド履歴をfzfでフィルタリングしながら選択することができます。

```bash
history | fzf
```

## プレビューモードの利用
例えばlsコマンドと組み合わせて、選択したファイルの内容をプレビューすることができます。
```bash
ls | fzf --preview "cat {}"
```

# 使用例
## 過去に実行したコマンドを選択して実行
上記のhistory 検索を少しだけ拡張した例です。過去の実行履歴からコマンドを選択して、実行します。
```bash
	history | awk '{$1=""; print $0}' | fzf
```

## docker-composeファイルを選択してコマンドを実行
開発環境で複数のdocker-composeファイルを使い分けているような場合に、ファイルを選択してコマンドを実行できます。以下はdocker-compose up を実行する例です。preview オプションを使用して、compseファイルの中身を確認しつつファイルを選択できます。
```bash
find docker-compose*.yml -type f | fzf --preview "head -100 {}"| xargs -I @ docker-compose -f @ up -d
```
以下の様に.bashrcに関数として定義しておけば、更に簡単に使えます。
* .bashrc
```bash
# functions
hf(){
	history | awk '{$1=""; print $0}' | fzf
}


# dkc (docker-compose) up down
dkc(){
    case $1 in
            "up")  find docker-compose*.yml -type f | fzf --preview "head -100 {}"| xargs -I @ docker-compose -f @ up -d ;;
            "down") find docker-compose*.yml -type f | fzf --preview "head -100 {}" | xargs -I @ docker-compose -f @ down  ;;
            *) echo "plese give the params up, down" ;;
    esac
}
```

```bash
# history選択して実行
hf

# カレントディレクトリの docker-compose*.ymlファイルを選択してupする
dkc up
```

# まとめ
以上、簡単なfzfの紹介と使用例でした。
アイデア次第でいろいろな便利な使い方ができそうですね。

fzfには他にもキーバインディングのカスタマイズなど色々な便利機能があるようです。気になった方はぜひ公式レポジトリをチェックしてみてください。

# 参考
aliasについて以下の記事を参考にさせていただきました。
* https://qiita.com/belion_freee/items/caa274cd6f642ea464bf
<button>などの要素が持つ属性をpropsの型に指定するには

# そんな時にはReact.ComponentProps型が使える

このように使うことが出来ます。
```react
type Props = {
  text: string
} & ComponentPropsWithoutRef<'button'>

const Button: FC<Props> = ({ text, ...otherProps }) => {
  return (
    <button {...otherProps}>
      {text}
    </button>
  )
}
```

コンポーネントを使う側はbutton要素に存在する属性を書く事が出来ます。
```react
<Button
  text='hello'
  name='world'
  disabled={false}
  onClick={handleClick}
/>
```

嬉しい事として、Buttonコンポーネントに使いたい属性が増えるたびにその属性を書く手間が不要という事があるかと思います。コンポーネントを使う側で属性を追加するだけで済むので個人的に使いやすいなと思っています。
下記のように`name`、`disabled`、`onClick`を追加したいとなった時に下記のように追加せず、

```diff_jsx
type Props = {
  text: string
+ name: string
+ disabled: boolean
+ handleClick: () => void
}

- const Button: FC<Props> = ({ text }) => {
+ const Button: FC<Props> = ({ text, name, disabled, handleClick }) => {
  return (
-    <button>
+    <button name={name} disabled={disabled} onClick={() => handleClick()}>
      {text}
    </button>
  )
}
```

コンポーネントを使う側だけ属性を追加すれば良いようになります。
```diff_jsx
<Button
   text='Hello'
+  name='button'
+  disabled={false}
+  onClick={handleClick}
/>
```

## 余談
`ComponentPropsWithoutRef`は`ref`を受け取らない型なので、`ref`を指定したい場合は、`ComponentPropsWithRef`があるのでこちらを使う事になります。

## まとめ

`button`などの要素が持つ属性をpropsで使うにはと思った時の参考の一つになれば嬉しいです。