OmniAICreator/Qiita-1.07M huggingface dataset:
DockerとSELinux

# はじめに
Dockerなどのコンテナを使っていると「SELinuxを有効にしておけ」と言われますが、
実際に起動していないとどうなのか検証してみたことと、
色々なところでも紹介されているものですが、自身のメモとして投稿しました。

#### 今回の検証環境

- VirtualBox 6.0
- CentOS 7.3
- Docker 19.03.05

# SELinuxが無効な場合
まず、SELinuxを無効にします。

```
# vi /etc/selinux/config
(以下にパラメータを変更)
SELINUX=disabled  # enforcingからdisabledに変更
# reboot
```
※ SELinuxの状態

 - Enforcing　:　SELinuxが有効
 - Permissive ： SELinuxのラベリングはしているけど、無効な状態
 - Disabled　 ： SELinuxが無効 

再起動後、SELinuxの状態確認

```
# getenforce
Disabled
```

これでコンテナを作成してみて、dmesgコマンドを実行すると、

```
$ docker run -it --rm  centos:7 bash
[root@27726ede260a /]# dmesg
(実行結果は省略)
```

と色々出てきてしまいます。
これはなんでかと調べると、コンテナはホストOSのカーネルを共有しているため、
dmesgなどのコマンド実行するとすべて中身が見えてしまいます。

コンテナを安全に設計していたとしてもホストOS側が雑に作られていると、
ホストOSが攻撃対象になってしまうことが想定されています。
それとコンテナの脆弱性に関しては少しずつ発表されてきていますが、
コンテナは最悪作り直しがすぐにできますが、
ホスト側の作り直しはかなり手間なので、SELinuxを有効にしておく必要があります。

# SELinuxが有効な場合
まず、SELinuxを有効にします。

```
# vi /etc/selinux/config
(以下にパラメータを変更)
SELINUX=enforcing  # disabledからenforcingに変更
# reboot

(再起動後確認)
# getenforce 
Enforcing
```

ではコンテナを作成し、dmesgコマンドを入力すると以下の結果になりました。

```
$ docker run -it --rm centos:7 bash
[root@c282a2fe3617 /]# dmesg
dmesg: read kernel buffer failed: Operation not permitted
```

エラーになり、dmesgコマンドが失敗しました。
このようにホスト側の情報を隠すといううえでも、SELinuxを有効にする必要があります。

いったんコンテナを抜けてラベルを確認します。

```
[root@c282a2fe3617 /]# (Ctrl +P→Q)
$
$ ps -efZ
(一部省略)
system_u:system_r:spc_t:s0      root      3084  3068  0 15:06 pts/0    00:00:00 bash
$ ls -Z
-rw-r--r--. root root system_u:object_r:var_log_t:s0   /var/log/dmesg
```

### 補足
DockerのSELinuxに関しては、別パッケージが必要です。
最新版はcontainer-selinuxパッケージにSELinuxの必要なラベルが入っており、インストール時もdocker-ceなどのパッケージと依存関係にあるのでセットでインストールします。
古いDockerのバージョンですと、docker-selinuxパッケージが別途必要なようです。
新しくDockerをインストールするなら、最新バージョンのほうが良さそうですね。
脆弱性も発表されていますし。。
参考:
[Dockerの脆弱性](http://www.security-next.com/110066)
[Dockerの探索](http://www.security-next.com/111159)

## (参考)dmesgのアクセス制限
コンテナ上でdmesgコマンドを実行してもエラーになるように、専用の個別設定も可能ですが、
一つ一つ設定していくのは手間なので、SELinuxでまとめて制限かけたほうが無難な印象です。

```
# echo "kernel.dmesg_restrict=1" >> /etc/sysctl.d/dmesg.conf
# sysctl --system
$ 
$ docker run -it --rm centos:7 bash
/# dmesg
dmesg: read kernel buffer failed: Operation not permitted
```

# さいごに
このように、コンテナやクラウド、さらにはIoTなど、LinuxをホストOSとして利用されていることが増えてきましたが、
リソースが乏しく、ソフトのバージョンアップなどが難しいものなどで使用される場合は万が一侵入されても大丈夫な対策として、SELinuxの導入がされ始めています。

先述していますが、個別設定でも抜けがでたりするので、まとめて設定できるSELinuxに慣れないといけないのだな…と私は感じました。

参考になれば幸いです。
CodePen - HTML+JavaScriptで色サンプル(RGBカラーのパレット)作ってみた

クリックした座標のカラーコードを#RRGGBB形式で表示します。

<p class="codepen" data-height="690" data-theme-id="default" data-default-tab="result" data-user="kob58im" data-slug-hash="yLyRpzL" style="height: 690px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="ColorTest">
  <span>See the Pen <a href="https://codepen.io/kob58im/pen/yLyRpzL">
  ColorTest</a> by kob58im (<a href="https://codepen.io/kob58im">@kob58im</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

※~~step 51/255選んだときに右端クリックしてもFFにならないのでバグってるっぽい・・というかstepの割り振りの設計ミスってます。~~
⇒直せたはず。

# 参考サイト

+ [getPixel from HTML Canvas? - stackoverflow](https://stackoverflow.com/questions/667045/getpixel-from-html-canvas)
+ [HTML5 スライダーで数値を入力するサンプル(range) - ITSakura](https://itsakura.com/html5-range)
+ [Canvasイベント操作まとめ - Qiita](https://qiita.com/nekoneko-wanwan/items/9af7fb34d0fb7f9fc870)
Facebookのシェア用URLでテキストを入れる方法

#始めに
URLにアクセスするだけでシェア画面を表示することができるのですが、色々調べてもFacebookではテキストを入れる方法が見つかりませんでした。

```text:Facebookのシェアリンク
https://www.facebook.com/sharer/sharer.php?u=<URL>
```

+ https://qiita.com/Ancient_Scapes/items/d27a3e2b247fa43e39f9
+ https://11-30am.com/38/?utm_source=qiita&utm_content=article

ただ色々試していたら、引用テキストとして表示する方法が見つかりましたので記事に残しました。

# テキストを入れる方法
結論から言うと以下のように`quote`パラメータが引用文の役割を果たしているようです。

```text:引用文を含めたシェアリンク
https://www.facebook.com/sharer.php?quote=<引用文>&u=<URL>
```

```text:サンプル
https://www.facebook.com/sharer.php?quote=引用文&u=http://127.0.0.1
```

サンプルのURLを開くと以下の画像のようになります（ユーザー名や入力テキスト部分は除外しています）。

![スクリーンショット 2020-01-24 15.53.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/4f5d338d-cc9e-8283-6cec-35d38766b696.png)


## 注意点
この`quote`プロパティはFacebook SDKの仕様を参考にしました。
ただこのプロパティの説明で以下のようなことが書かれており、もしかしたら使えない仕様かもしれない音でご注意くださいm(_ _)m
（FacebookのURLをシェアする時には使えませんと言う意味なら問題ないですが）

>リンクでシェアする引用。記事のプルクオートと同様に、利用者によりハイライトされるか、開発者により事前定義されています。
<b>このパラメーターはFacebook URLには利用できません。</b>

# 終わりに
Facebookのシェア用URLでテキストを入れる方法について紹介しました。
ただ公式のドキュメントから見つけたものではないので、ご注意ください。
PDF to Excel、あなたにおすすめの超実用的な方法

PDF形式の利点は、編集が完了すると、オペレーティングシステム、ディスプレイ画面のサイズや解像度、印刷方法に関係なく、レイアウト形式が乱雑にならないため、ドキュメントをPDF形式。 Excelフォームにもこの要求があり、セキュリティ上の考慮事項と変更の考慮事項を防ぐために、PDF形式に変換されて送信されます。

しかし、文書を受け取った人はPDFフォームを持って心配していました。どうすれば分析を進めることができますか？さまざまなリソースWebサイトからダウンロードされたデータを含め、それらの多くはPDF形式であるため、PDFフォームをExcelに変換する方法は多くの人々にとって大きな問題です。

オンライン変換にsanpdfを使用しているこのWebサイトは、間違いなくアーティファクトです。 PDF、PPT、WORD、およびEXCEL形式の間で変換でき、PDFファイルを結合、分割、および反転することもできます。この記事では、PDFからExcelについてのみ説明していますが、他の機能は自分で調査して使用することができます。

この記事では、さまざまなニーズを満たすためにチートを変換する方法を紹介します。
1. anSanPDFの公式ウェブサイトを開きます。
2. 目的の機能-PDF to Excelを選択します。
3. 変換するExcelスプレッドシートを選択します。
4. 最後にクリックして変換を開始します。
5. クリックしてダウンロードします。

Sanpdfは、効率を高め、時間を節約し、効率的に作業し、プライバシーを尊重するのに役立ちます。ファイルは、24時間の変換後にサーバーから自動的に削除されます。
ポモドーロ・テクニックを導入したことで解決できた課題とやり方について

# ポモドーロ・テクニックを導入したことで解決できた課題とやり方について

## チーム内で課題として上がっていたこと

メンバー間の雑談だったり、一週間の振り返りの場でこういう意見があった。

**「仕様確認の質問が色んな人から度々来るから、作業に集中する時間が取れない」**
**「サボっているわけでもないのに、今日やろうと思っていた仕事が全然進んでいない」**

結局のところ、仕事に向かってはいるけど集中する時間が取れないために、なかなか進捗が出ないという状態だった。

せっかく集中できていても話しかけられることで途切れ、再度集中しようと思っても時間がかかってしまう…

話し合いをすることは大事だからなくすことはできないけど、集中する時間もほしいということで、[ポモドーロ・テクニック](https://next.rikunabi.com/journal/20161026_m1/)を使って、時間の使い方にメリハリを付けることにした。

## ポモドーロをやる上での決め事

基本的なサイクルとしては

- 集中タイム：２５分
- Slack確認、メンバー間での質問：約５分（伸びすぎない程度に適宜変更）
- 休憩：５分

エンジニアチーム内で **共通のタイマー** を使って、このサイクルをまわしている。

**周りの人** にお願いしたことは

- 集中タイムの間は、緊急時以外は話しかけないようにしてもらう
- 質問がある際は、社内SNSのSlackでメンションをつけて内容を送っておいてもらう

**作業者** のルールとして設けたのは

- 集中タイムの時は目の前のタスクに専念するため、社内SNSを開かないようにする
- 集中タイムが終わったら必ずSlackを確認し、質問に回答する
- 休憩中は作業をしないでリフレッシュに専念する

今が集中タイムかどうかを周りの人がすぐわかるように、うちのチームでは目立つところに **小さな旗を立てている** 。

こういった目印は結構重要で、周りの人は席から立たずに状況を確認できるし、あのチームは何か面白そうなことしているというアピールにもなる。

## 実際にやってみて

２５分間も待てないレベルの急な用事というのはほとんどなく（周りの人が気を使ってくれているのもあると思う）、集中タイム中は目の前の仕事に専念することができ、それに伴って以前よりも進捗がはっきりと出てくるようになった。

作業者側が高評価だったのはもちろんのこと、意外にも周りの人からの評価も高く、今までは「今、質問していいのか？集中を妨げてしまうのではないか？」と気になっていたようでこういったストレスがなくなったらしい。

## サイクルの使い分け

ちなみに、出社している時は **集中：２５分・休憩５分** のサイクル 、リモートワークの時は **集中：５０分・休憩１０分**のサイクル でまわしている。

使い分けのポイントは休憩時間にあって
５分休憩であればトイレに行ったり軽い談笑で終わってしまうけど、１０分休憩となると、思ったより長くやることがなくなってしまう。

ただリモートワークとなると話は別で、１０分休憩があれば家事をこなすことができる。休日にすべてやらなくてもリモートワークの日と分割すると負担が減るし、体を動かすとリフレッシュ効果もあるのでオススメ！

## まとめ
ポモドーロ・テクニックを使えば、手軽に効率化ができるので同じような課題を感じているチームは導入してみたらいいと思う。
人によっては外出や会議などで自分がコントロールできない時間があるかもしれない。でも３０分以上のコントロールできる時間があるのであれば、そこだけでもやってみると効果が出るかも？
anyenvを使うためのfishの設定ファイルの例

各envが、バージョン毎にディレクトリを分割して管理するようになったので
今までは固定でも大丈夫だったものの、PATHを動的に変更する必要が出てきた。
なので一例として設定ファイルを公開（自分がfishを使っているのでfish用）。

```:各envのバージョン
$ goenv -v
goenv 2.0.0beta11
$ nodenv -v
nodenv 1.3.1+11.5024679
$ pyenv -v
pyenv 1.2.16-5-g7097f820
```

```:config.fish
# anyenvの設定
set -x PATH "$HOME/.anyenv/bin" $PATH

# pyenvの設定
set -x PYENV_ROOT "$HOME/.anyenv/envs/pyenv"
set -x PATH "$PYENV_ROOT/bin" $PATH
set -x PATH (pyenv prefix)/bin $PATH
eval (pyenv init - | source)

# goenvの設定
set -x GOENV_ROOT "$HOME/.anyenv/envs/goenv"
set -x PATH "$GOENV_ROOT/bin" $PATH
set -x GOROOT (goenv prefix)
set -x GOPATH $HOME/go/(goenv versions --bare)
set -x PATH "$GOPATH/bin" $PATH
eval (goenv init - | source)

# novenvの設定
set -x NODENV_ROOT "$HOME/.anyenv/envs/nodenv"
set -x PATH "$NODENV_ROOT/bin" $PATH
set -x PATH (nodenv prefix)/bin $PATH
eval (nodenv init - | source)
```

## 補足
- `(xxxenv prefix)` で、各バージョンのパスが取得できる。こうしておくことで、言語のバージョンを切り替えた時に参照するライブラリのパスを動的に変更することができる。
- `(goenv versions --bare)` は、goのバージョンのみを取得することができる。
artisanコマンドの引数にハイフン始まりの値を渡したい

この記事は移行しました！[最新の内容はこちら](https://naoqoo2.github.io/blog/artisan%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E5%BC%95%E6%95%B0%E3%81%AB%E3%83%8F%E3%82%A4%E3%83%95%E3%83%B3%E5%A7%8B%E3%81%BE%E3%82%8A%E3%81%AE%E5%80%A4%E3%82%92%E6%B8%A1%E3%81%97%E3%81%9F%E3%81%84/)をご覧ください😀

引数にハッシュ値を指定するartisanコマンドを作っていたのですが、
ハッシュ値がハイフン始まりのときにオプション扱いされてエラーになりました。。

## 現象
例）ハッシュ値が`-LA12_ed`

```
php artisan hoge:fuga -LA12_ed
```

エラーになる。`The "-L" option does not exist.  `

## 対策

そんなときはエスケープすればいいよね。
エスケープ文字は `-- ` でした。ハイフンハイフン半角スペース！

```
php artisan hoge:fuga -- -LA12_ed
```

これで無事引数を受け取れます。

## 参考
https://stackoverflow.com/questions/35493936/laravel-custom-command-argument-with-dash
THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF CAPISTRANO. Please join the conversation here if this affects you. https://github.com/capistrano/capistrano/issues/1686のエラー解決例

#1.エラーの様子

まず、自動デプロイを設定し、実行コマンドを行いました。すると下記のようになりました。


```ruby
Neverland:chat-space-kai kontatomoya$ bundle exec cap production deploy
#自動deployのコマンドを打ちました
#ここまでまでエラーなし（省略）

00:51 unicorn:start
      unicorn is running...
      unicorn restarting...
      01 kill -s USR2 `cat /var/www/chat-space-kai/shared/tmp/pids/unicorn.pid`
    ✔ 01 ec2-user@13.112.68.204 0.609s
Skipping task `unicorn:restart'.
Capistrano tasks may only be invoked once. Since task `unicorn:restart' was previously invoked, invoke("unicorn:restart") at config/deploy.rb:43 will be skipped.
If you really meant to run this task again, use invoke!("unicorn:restart")
THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF CAPISTRANO. Please join the conversation here if this affects you.
https://github.com/capistrano/capistrano/issues/1686
#↑エラーの全文

#以下エラーなし（省略）

```

黄色い文章（筆者の環境では赤文字でした）を読むとバージョン違うんじゃない？と書いてあって心当たりがなかったので`THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF CAPISTRANO. Please join the conversation here if this affects you.
https://github.com/capistrano/capistrano/issues/1686`の部分で検索をかけたところ下記の記事を見つけました。
https://obel.hatenablog.jp/entry/20181030/1540880580
この中ではunicornのrestartができないのをどうにかすれば良い。とありましたが、restartコマンドは挿入した記憶があるため分からない。そしてgithubの更新を反映できないという状況になってました。


#2.原因と解決策
結論から言いますと下記のファイルにrestartの実行を2回重複して記載していたためエラーを起こしており、その部分を取り除けば解決しました。

```ruby:app/config/deploy.rb
lock '3.11.2'
set :application, 'chat-space-kai'
set :repo_url,  'git@github.com:KONTA2019/chat-space-kai.git'
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')
set :rbenv_type, :user
set :rbenv_ruby, '2.5.1'
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['~/.ssh/ChatSpace.pem'] 
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end
#↑この部分が不要です

set :linked_files, %w{ config/secrets.yml }
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
  desc 'upload secrets.yml'
  task :upload do
    on roles(:app) do |host|
      if test "[ ! -d #{shared_path}/config ]"
        execute "mkdir -p #{shared_path}/config"
      end
      upload!('config/secrets.yml', "#{shared_path}/config/secrets.yml")
    end
  end
  before :starting, 'deploy:upload'
  after :finishing, 'deploy:cleanup'
end
```


#3.この記事で伝えたかったこと
題名のエラーが目立つため、バージョンの間違いによる「互換性の問題に違いない」とドツボにはまってしまうことがあるかもしれませんが、もしかしたら筆者のように簡単なことで止まってるかもしれないので、'app/config/deploy.rb'を見直してみるとエラーが発見できるかもしれませんよ！ということを伝えたいと思ってこの記事を書きました。

何かのご参考になればと思います。
IE11でbackground-imageのJQueryが反映されない

問題となったコード。

```html:html
<div id="image_area"></div>
```

```js:JQuery
$("#image_area").css("background-image","url(画像パス)");
```

このコードでは、Chrome、FireFoxでは動作するが、IE11では動かず。
いろいろ原因を探って、たどり着いた答えがコレ。


```js:修正後
$("#image_area").css({
    "background-image": 'url("画像パス")',
});
```
IE11で`background-image`プロパティを指定するときは

**1. `{ "background-image": 値 }` の形式で書く**
**2. 画像パスはダブルクオーテーションで囲む**

必要があるようです。なんでこうしないといけないのかはわからないですが...

参考にしたところ
[jQueryで背景画像を変える時にIEでの対処法【JS】](http://blog.e-riverstyle.com/2011/11/jqueryiejs.html)
[背景画像をJavaScriptで書き換える](http://cly7796.net/wp/javascript/rewrite-the-background-image-in-the-javascript/)
kintone のドロップダウンフィールドの項目をCSVとして取り出す方法

ドロップダウンの項目がだんだんと増えてきて、いっそのことマスタアプリにした方がいいんじゃない？と感じた時に試してみましょう。

# 方法

* フォーム情報取得系の kintone REST API を叩いて JSON で保存します。
* 保存したJSONを jq コマンドで成形して、ファイルに出力します。
* エクセルで読み込んでkintoneに読み込むレコードに成形します。
* アプリを作成してCSV読み込みします。

# 手順

やってみます。

# form.json を使う場合

[フォーム設計情報取得](https://developer.cybozu.io/hc/ja/articles/201941834)APIを使う例です。

## アプリの詳細画面を開いて form.json API を実行

1. アプリの詳細画面を開きます。
2. ChromeのDevToolsを開きます。
3. Consoleにform.json API を入力してEnterします。
4. 結果のJSONをコピーしてファイルに保存します。

3.の実行例

```javascript
var body = {
    "app": kintone.app.getId()
};
kintone.api(kintone.api.url('/k/v1/form', true), 'GET', body, function(resp) {
    // success
    console.log(JSON.stringify(resp, null, 2));
}, function(error) {
    // error
    console.log(error);
});
```

## JSONを jqコマンドで成形

1. OSのコマンドラインで JSONファイルを読み込みます。
2. jqコマンドで必要なフィールドに絞り込みます。
3. さらにドロップダウンの"options"だけを取り出します。


```bash
$ cat form.json | jq '.["properties"] | map(select(.["label"] == "取り出したいフィールド名")) | .[].options | .[]'
"sample1"
"sample2"
```

## jqコマンド cheat sheet

フォームのラベルの取り出し
`cat form.json | jq '.["properties"] | .[].label'`

上と同じことをパイプで
`cat form.json | jq '.["properties"] | .[] | .label'`

配列に入れて
`cat form.json | jq '.["properties"] | .[] | [.type, .label]'`

CSVにするとか
`cat form.json | jq '.["properties"] | .[] | [.type, .label] | @csv'`

-r つけて
`cat form.json | jq -r '.["properties"] | .[] | [.type, .label] | @csv'`

nkf で文字コードを変換
`cat form.json | jq -r '.["properties"] | .[] | [.type, .label] | @csv' | nkf -Ws`

ドロップダウンフィールドだけ抽出するとか
`cat form.json | jq -r '.["properties"] | map(select(.["type"] == "DROP_DOWN")) | .[] | [ .label, .options ]`

labelとoptionsを並べて
`cat form.json | jq -r '.["properties"] | map(select(.["type"] == "DROP_DOWN")) | .[] | [ .label, .options[] ]'`

csvで出力する
`cat form-anken.json | jq -r '.["properties"] | map(select(.["type"] == "DROP_DOWN")) | .[] | [ .label, .options[] ] | @csv'`


---
# form/fields.json を使う場合

[フォームの設定の取得](https://developer.cybozu.io/hc/ja/articles/204783170)APIを使う例です。

## アプリの詳細画面を開いて form/fields.json API を実行

API実行例

```javascript
var body = {
    "app": kintone.app.getId()
};
kintone.api(kintone.api.url('/k/v1/app/form/fields', true), 'GET', body, function(resp) {
    // success
    console.log(JSON.stringify(resp, null, 2));
}, function(error) {
    // error
    console.log(error);
});
```

## JSONを jqコマンドで成形


```bash
$ $ cat form-fields.json | jq '[.["properties"]["<フィールドコード>"]["options"][]] | sort_by(.index) | .[]["label"]'
```

indexのソートが上手くいってないですが、ひとまずこちらで取り出すことはできました。

# 参考

* [jq](https://stedolan.github.io/jq/)
* [jq コマンドを使う日常のご紹介](https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af)
* [【 nkf 】コマンド――文字コードと改行コードを変換する](https://www.atmarkit.co.jp/ait/articles/1609/29/news016.html)
GitHub Actions の使用制限

## GitHub Actions の使用制限
~~[GitHub Actionsについて
](https://web.archive.org/web/20200118040607/https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/about-github-actions)~~
このページにあるように、以下の目的で使用することはできません。

> また、次の目的ではGitHub Actionsを使用しないでください。
> 
> - 法律違反、またはそれ以外で当社の利用規約またはコミュニティガイドラインに反しているコンテンツまたは行為
> - クリプトマイニング
> - サーバーレスコンピューティング
> - GitHub ユーザまたは GitHub サービスを危険にさらす行為
> - GitHub Actionsが使用されるリポジトリに関連するソフトウェアプロジェクトの製造、テスト、デプロイ、公開に関連

### 2020/10/23 追記
以下のページが最新です。
[GitHub追加製品の利用規約](https://docs.github.com/ja/free-pro-team@latest/github/site-policy/github-additional-product-terms#5-%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8)

## 違反が見つかった場合
[GitHub Actions Advent Calendar 2019](https://qiita.com/advent-calendar/2019/github-actions) の記事で違反と認められたと思われる例があります。
そのユーザのいくつかのリポジトリを見たところ、記事で紹介されていない複数のリポジトリで GitHub Actions の使用が制限されていることを確認しました。

```
Actions jobs for this repository have been disabled by GitHub staff. If you are the repository owner, you can contact support via https://github.com/contact for more information.
```

リポジトリだけでなく<strong>ユーザ単位で GitHub Actions の使用ができなくなる</strong>ようです。

そのユーザは現在別の無料アカウントを作成しそちらで GitHub Actions を実行しているようですが、複数の無料アカウントの作成も規約違反になるので注意が必要です。

https://help.github.com/ja/github/site-policy/github-terms-of-service#3-account-requirements

## 2020/8/27追記
2020/8/14〜8/23の間に利用規約が変更され、サーバレス用途に関するルールが変わったようです。
8/14
https://web.archive.org/web/20200814142929/https://docs.github.com/en/github/site-policy/github-additional-product-terms
8/23
https://web.archive.org/web/20200823163646/https://docs.github.com/en/github/site-policy/github-additional-product-terms

「serverless computing」が禁止用途から削除され、負荷とユーザに提供される利益が不釣り合いでないものや負荷の小さいものは許されるようです。
（もちろんリポジトリに関連しないものや他の規約等に反するものは引き続き許可されません）
【JS】フッターのコピーライトとかで自動的に今の年を表示する方法

フッター等によく書いてあるコピーライト。
`Copyright © hoge.exmaple.com 2010-2020 All Rights Reserved.`
こういうやつです。

この2020という年数を年が変わるたびに手動で変更するのは面倒ですよね。今回はJavaScriptで自動で今の年を表示する方法を紹介します。ものすごい小ネタです。

## フッターのコピーライトとかで自動的に今の年を表示する方法

```html
<footer>
  <p class="copyright">Copyright © <span class="thisYear"></span> hoge.example.com All Rights Reserved.</p>
</footer>
```

JavaScriptで今の年を表示しているだけです。

```js
  const yearElm =  document.querySelector('.thisYear'); // <span class="thisYear"></span>を取得
  const thisYear = new Date().getFullYear(); // 今の年を取得
  yearElm.innerHTML = thisYear; // <span class="thisYear"></span>の中に年を表示
```

## コピーライトの書き方
ちなみに、最初に例示したコピーライトは間違ってはいませんがいろいろ不要なものが多いです。というかそもそもコピーライトの表記自体なくても問題ないのです。でも慣習的に書いておいた方が無難。

正しくは
`© 2010 hoge.exmaple.com`　←年数はそのサイトが開設された年（著作物が発行された年）
で十分。今の年を表示させる必要は実はないんです。

**参考**
[年号と©マークと何が必要？Copyright（コピーライト）表記の正しい書き方](https://liginc.co.jp/designer/archives/11313)
[Wikipedia: 著作権表示](https://ja.wikipedia.org/wiki/%E8%91%97%E4%BD%9C%E6%A8%A9%E8%A1%A8%E7%A4%BA#All_rights_reserved)
Swift4 の String.count を Go でやる

## やりたいこと

`家族👨‍👩‍👦‍👦` を3文字として数えたい。

## Swift4 の `String.count` はすごい

内部で`Grapheme Cluster`なるアルゴリズムを使っていて、それによってUnicode文字列の文字数を正確に計算できているらしい（[参考](https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#ID297)）。

```swift
print("家族👨‍👩‍👧‍👦".count) // -> 3
```

## Go の `utf8.RuneCountInString` では対応できない

`👨‍👩‍👧‍👦`が7文字として数えられてしまう。

```go
import "unicode/utf8"

func main() {
    print(utf8.RuneCountInString("家族👨‍👩‍👧‍👦")) // -> 9
}
```

## Go でも Swift4 の `String.count` がやりたい

[github.com/rivo/uniseg](https://github.com/rivo/uniseg)を使うと`Grapheme Cluster`を利用して文字列を処理できる。
Playgroundでやると[こんな感じ](https://play.golang.org/p/dgL9vtBj81d)になる。

```go
import "github.com/rivo/uniseg"

func main() {
    print(uniseg.GraphemeClusterCount("家族👨‍👩‍👧‍👦")) // -> 3
}
```
numpyをストレスなく使う！（エラー「AttributeError: 'float' object has no attribute 'sin'」の解釈(対処？）)

#目的
　**numpyをストレスなく使う！**
Pythonで計算などをする場合には、**numpy**が頻繁に使われる。そのため、numpy関連のエラーに出会うことも少なくない。
エラーを早めに解決するためには、少しでも、理解のレベルを上げる必要あり。
なんでも、こだわって、、、、理解を深める。

ここで、取り上げるエラーは、以下。

```
AttributeError: 'float' object has no attribute 'sin'
```

どのような場面で出るかというと、例えば、以下。

```
>>>
>>> import numpy as np
>>> a = np.array([1.1, 2.2],dtype=object)
>>> np.sin(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'float' object has no attribute 'sin'
>>>
```

このエラーをとりあげる理由は、
**エラーの意味がわからない**
だろうと思うため。
'float'オブジェクトが、sinを持たない
と言われているが、そんな処理は、依頼してないし。。。。

##検討環境
Name: numpy
Version: 1.16.4

#エラーの説明
このエラーに対しては、以下の記事が参考になる。

https://github.com/numpy/numpy/issues/13666

ここでの報告者の方は、

>Many NumPy methods fail if an array has dtype object, and produce a misleading error message.

他力で、日本語にすると（Google翻訳（ママ）　）
>**配列にdtypeオブジェクトがある場合、多くのNumPyメソッドは失敗し、誤解を招くエラーメッセージが生成されます。**

と主張されている。
**⇒そのとおりだと思う。**

このサイトでのやり取りの結論は、よくわからないのですが、、、
とにかく、
numpy側も
**エラーメッセージがあまり適切でない**
ことは、認めているよう。
治しているようにも読めるが。。。。治ってない気がします。


#エラーの対処方法

エラーの対処方法は、そもそも、何がやりたいのかにもよるが、
経緯上、dtype=objectである必要があるのであれば、
**sinの計算の前に、astypeでキャストする**
などがいいと思う。

```
>>> a = np.array([1.1, 2.2],dtype=object)
>>> np.sin(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'float' object has no attribute 'sin'
>>> np.sin(a.astype(np.float64))
array([0.89120736, 0.8084964 ])
>>>
```


#まとめ

わずかに、numpyに詳しくなった。
numpyは、深いので、まだ、誤差の範囲だと思うが。


#関連（本人）
[英語と日本語、両方使ってPythonを丁寧に学ぶ。](https://qiita.com/enoughspacefor/items/d4b49747773e2d0285f9)

#今後
numpy、学ぶぞーーーー。
コメントなどあれば、お願いします。:candy:
Java備忘 LocalDateを使ってみた

##はじめに
Javaで○日以上古いファイルを検出するというプログラムを書く機会があったので、備忘として残しておく。
あくまで一つの例として。

##LocalDateを使う
Dateでも可能だが、より新しいLocalDateを使ってみる。

```java
Long lastModified = targetFile.lastModified();
    LocalDate lastDate = Instant.ofEpochMilli(lastModified).atZone(ZoneId.systemDefault()).toLocalDate();
```
これでファイルクラスで宣言した対象のファイルから最終更新日を取得する。
エポック時間をLocalDate型に変換しているイメージ。

```java
LocalDate daysBefore = LocalDate.now().minusDays(5); 
```
LocalDateクラスのnow()で本日の日付を取得する。
今回は5日前の日付を対象にするとして、minusDays(5)で取得することができる。

```java
if (lastModified.isBefore(base) || lastModified.isEqual(base))

if (lastModified.compareTo(base) <= 0)

if (lastModified.until(LocalDate.now(), ChronoUnit.DAYS) >= 5)
```
あとはこんな感じのif文を書いてあげれば指定した日付以前のファイルを炙り出せるはず。
注意したいのはisBefore()だけでは5日より前しか取れないこと。
isEqual()で5日前も取れるようにしてあげる。

追記
@swordoneさんからコメントをいただき、
if文の条件式を追加しました。

##まとめ
ここにFileクラスをピピーっとぶっ込んでやるといい感じなる。
ご指摘等ございましたらコメントお願いします。
Eclipse JavaからSQLファイルに飛ぶ(ジャンプ)方法

# Eclipse java DomaSQLでJavaからSQLファイルに飛ぶ方法
SQLファイルとリンクしている関数を右クリック > Doma > Jump To Sqlファイル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384142/41cfb2c7-905e-9a50-d256-724b37223928.png)

メニューに出ない場合はDomaToolがインストールされていない可能性あり。
以下に手順を示す。

# DomaToolのインストール
1. ヘルプ > 新規ソフトウェアのインストール
2. `http://eclipse.seasar.org/updates/3.5/` > 追加
3. `Doma`にチェックし、次へ
4. インストールを完了する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384142/222fe2b4-d376-2ec3-1615-c3398f0008e6.png)

### 参考：
Doma - セットアップ
http://doma.seasar.org/setup.html#Eclipse%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB
JavaScriptでgetUserMediaでマイク・カメラ（ビデオ）を使うときの注意点とデバイスへのアクセス権限について


# マイクのみ使用するのにaudioのみの指定では動かないブラウザがある

とあるサンプルがEdgeで動作したがChromeで動作しなかったので調べてみた。

<b>Chromeは`audio`だけでなく`video`も指定しないと音声入力が取得ができない。</b>
https://www.html5rocks.com/ja/tutorials/getusermedia/intro/  より引用：
> 注: Chrome にはバグがあり、「audio」のみを渡しても無効です（crbug.com/112367）。Opera でも <audio> を動作させることはできませんでした。 

自分でも確認しましたが、
　Chromeのバージョン: 79.0.3945.130（Official Build） （64 ビット）
で再現しました。`audio`指定のみでは動作せず、`video`を`audio`と一緒に指定すると動作する。

# navigator.mediaDevices.getUserMediaが推奨らしい

`navigator.getUserMedia`ではなく`navigator.mediaDevices.getUserMedia`が推奨らしい

https://qiita.com/Futo23/items/bff1ce1d2e1b219b243d

# アクセス権限について

ブラウザが管理しているようである。
<b>サイト（ドメイン）単位で管理される</b>っぽい？
意識していないと結構危険かもしれない。

例：CodePenのある１作品で許可してたら、ほかの作品からアタックされる恐れがある。
（マイクやカメラを許可済みにすると、許可したときのページのみではなく、ドメイン上の任意のページからのアクセスを許可したことになってしまうので、知らない間にCodePenの作品を埋め込んだページを含んで情報が吸い上げられることも考えられる。）[^1]

[^1]: CodePenが悪いわけではなく、レンタルサーバ上のブログなどでも同様。CodePenを例にしたのはたまたま自分が使ってたから。

## アクセス権を削除するには - Microsoft Edge

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/db1d40ef-4c2b-0246-25d3-53c5695fcd28.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/15f4c459-7692-4298-48b7-d740f6b44c28.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/4f45a983-00ae-2ff8-2747-fb03e7eeade5.png)
アクセス権を設定したドメインの名前が一覧表示されるので、変更したいものを選んで処置してください。

## アクセス権を削除するには - Chrome (PC版)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/1db8d62f-8f76-872d-c937-af645df5a528.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/2b474538-9a86-81f4-9247-4647db3c1080.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/d7bce00b-72c0-dc53-e6d9-01ad46990069.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/26fd32d4-0f44-b6b6-a5b8-8720202e12a6.png)
あとはお好みで。
【AWS】~/.ssh/configを使って、簡単にssh接続する

# 概要
AWSのサーバーにssh接続する際は、ご自身のディレクトリの配下に隠しファイル「.ssh」を作成し、その中にAWSの設定を書いておくと、毎回以下のようなものを書かなくて済みます。

```bash:Terminal
ssh -i /path/my-key-pair.pem ec2-user@ec2-198-51-100-1.compute-1.amazonaws.com
```

# .sshディレクトリの作成と下準備
```bash:Terminal
# 作業したいディレクトリかどうかを確認してください
[~@~ your_dir]$ pwd

# ディレクトリを作成します
[~@~ your_dir]$ mkdir .ssh

# cd .ssh と同義。「!$」は、直前行った引数を指すので、今回は「.ssh」を指す
[~@~ .ssh]$ cd !$

# aws.key, configファイルを作成します
[~@~ .ssh]$ touch aws.key && touch config
```

# aws.keyとconfigファイルの作成と設定

①ディレクトリ構成を確認します
②aws.keyに、ご自身がssh接続で使用しているpemファイルをコピペします
③configファイルに設定を書き込みます

## ①ディレクトリ構成を確認します

現状以下のようなファイル構成になっていると思います。

```bash:Terminal
[~@~ .ssh]$ ls -la
-rw-------  1 ~ ~ ~ ~月 ~ ~:~ aws.key
-rwxr-xr-x  1 ~ ~ ~ ~月 ~ ~:~ config
```

## ②aws.keyに、ご自身がssh接続で使用しているpemファイルをコピペします

ご自身がssh接続で使用しているpemファイルをコピーして、aws.keyに貼ってください。
「-----BEGIN RSA PRIVATE KEY-----」から「-----END RSA PRIVATE KEY-----」まで、すべて貼ってください。

```bash:.ssh/aws.key
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAhioJPY7kJGHQ1m5dR+
~~~~~~(中略)~~~~~~
-----END RSA PRIVATE KEY-----
```

## ③configファイルに設定を書き込みます

```bash:.ssh/config
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
IdentityFile .ssh/aws.key
User ec2-user
Host <HOST名>
  Hostname <IPアドレス>
```

以下、記述例を記載してます。
・Host名を使用して、ssh接続します。なので、ご自分の好きな名前を設定してください。
・複数ある場合は、同じように設定していきます。

```bash:.ssh/config
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
IdentityFile .ssh/aws.key
User ec2-user
Host live-web01
  Hostname 192.168.xxx.xx
Host live-web02
  Hostname 127.0.xxx.xx
Host live-batch
  Hostname 52.168.xxx.xx
```

# ssh接続する

設定したので、ssh接続しましょう。

```bash:Terminal
# 作業ディレクトリにいることを確認してください。
[~@~ your_dir]$ pwd
your_dir

# ssh -F .ssh/config <Host名> で接続できます。上記で設定したlivew-web01に接続したい場合は、
[~@~ your_dir]$ ssh -F .ssh/config live-web01
```

これで、ssh接続が簡単になりました！
HTML, CSSの基礎

#今回はProgateを使ったHTML,CSSの学習をしました。
　実は前に２、３回くらいやったことがあったので、スラスラと進めることができました。
　具体的にやったこととしては見出しの書き方やHTMLへのCSSのリンクの書き込み、ヘッダーやフッターやメインの基礎です。HTML、CSSの復習としてはかなりいいものでした。
##HTMLとCSSの要約
  HTMLでサイトに文字や画像などを書き込み、CSSでその文字やCSSを装飾します。基本的にはこの二つを使うことでサイトの見た目を作ることができます。
Zoho Connectで独自アプリをカスタマイズする時に見たいページ 

Zoho Connectで独自アプリをカスタマイズしたい時に参照するページが何処へいったかわからなくなるので、自分の作業用にリンクをまとめています。

##Zoho Creatorフィールドのデータ型

https://www.zoho.com/deluge/help/creator-field-datatype.html

##組込み関数

https://www.zoho.com/deluge/help/built-in-functions.html

##Client Functions
###hide | show
https://www.zoho.com/deluge/help/client-functions/hide-show.html
・フィールドで見えなくしてるだけなのでmustにしてるとバリテーションかかった時にエラーになります。

###Clear items
https://www.zoho.com/deluge/help/client-functions/clear.html
これが利用できるのは以下のフィールドタイプの時だけ
・Radio
・Drop Down
・Multi Select
・Checkbox
・Lookup
自作機器(例えば、UARTを吐く）をUSBゲームコントローラに見せる(windows)

デモアプリを Unity で作るとする。Ardity というアセットを使うと UART の読み書きができます。（ほかにもあります）

でも、既存のアセット類を使いたい。Unity ちゃんを（いろいろなチュートリアルで使われているように） standard-assets-characters で楽して歩かせたい、歩かせることに時間を割きたくない、少しくらい気に入らないところがあっても、歩いてジャンプすればいいのだ、ということはよくある。

となると、自作の機器が Unity からUSBゲームパッドに見えると嬉しい。

あります！

仮想ジョイパッドドライバ　http://vjoystick.sourceforge.net/site/index.php/77-vjoy/84-homepage-v200

UART に限らず、何でも joypad に見せることができます。



最近は direct input は古くて、 xinput だよね（xinputしか対応してないんだよね）
何とかなります！

XOutput https://github.com/csutorasa/XOutput

direct input を xinput にリダイレクト？してくれます



本物のUSBで作りたい？

あります！

・Arduino micro など ATmega32u4 とか、USBを持っているものを使う

・digispark という、Arduino 環境で開発できる、ソフトウェアで USB 実装しているマイコンが容易に入手可能。
　※（ゲームコントローラを作りたいという話をしてますが、）環境によっては、CDC(仮想シリアルポート）のライブラリは BSoD で Windows が死ぬ
GASをChrome拡張を使って手軽にGithub管理する

気軽にGithub連携できそうだったので導入してみました。
それほど難しくないけどメモ。

[2020/02/04 追記]
末尾でも書いてますが、複数プロジェクトのコードを管理するなら圧倒的にclaspの方が楽です。
詳細は末尾の見てください。

## 使うもの
これを使います。
[Google Apps Script GitHub アシスタント](https://chrome.google.com/webstore/detail/google-apps-script-github/lfjcgcmkmjjlieihflfhjopckgpelofo)

## 手順
特に解説する程の工程はありませんが、一応。

1. 上記Chrome拡張を入れる
2. GASを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430401/601dd4ed-40ca-76d2-53e1-24abb009f98d.png)
追加されてます。
3. LoginSCMを押してログイン

これでPullとかPushとかできるようになるはずです。
あとは良い感じに使いましょう。

## 分かった事
- ファイル名と関数名が一致しているとエラーになる
- 新規追加されたファイルをGAS側でPullしようとすると読み込みエラーになる事がある（詳細な原因は不明）
- GAS側から新しいブランチ作ってもGAS画面に表示されるまでに時間がかかる
- 複数のプロジェクトを管理するならclaspを使った方が全然楽  
Chrome拡張だと1プロジェクト1リポジトリみたいな管理になっちゃいそうです。  
これに対して、claspならプロジェクトをディレクトリで分けるだけって感じで1リポジトリ管理が簡単にできます。  
⇒[【GAS】claspでソース管理できるようにする](https://qiita.com/wau/items/0b4ad172b01cdb4ec621)
【javascript】文字列の配列をArrayに変換する方法

# jsで文字列の配列をArrayに変換する方法はいくつかの方法があります
evalは使い所を間違えるとユーザーに任意のjsを実行させてしまうことになるので注意しましょう。

## カンマ区切りの文字列を配列にする方法

### 元データがこれの場合
```js
'Shiro,Ai,Kaguya,Tokino'
```

```js
'Shiro,Ai,Kaguya,Tokino'.split(',');
```


## json parseで実装する方法

### 元データが文字列の配列の場合
```js
'["BoraOne", "RacingZero", "Zonda"]'
```

```js
JSON.parse('["BoraOne", "RacingZero", "Zonda"]')
```

## evalで実装する方法

### 元データが文字列の配列の場合
```js
'["BoraOne", "RacingZero", "Zonda"]'
```

```js
eval('["BoraOne", "RacingZero", "Zonda"]')
```
Python-peewee使用连接方式

# 方法1
To connect to a MySQL database, we will use MySQLDatabase. After the database name, you can specify arbitrary connection parameters that will be passed back to the driver (either MySQLdb or pymysql).

```
# http://docs.peewee-orm.com/en/latest/peewee/database.html#using-mysql
from peewee import (
    MySQLDatabase,
    Model,
    DateTimeField,
)
# MySQL连接
db = MySQLDatabase('my_database')

class BaseModel(Model):
    """
    DB-Base
    """
    class Meta:
        database = db

    created_at = DateTimeField(default=datetime.datetime.now)
    updated_at = DateTimeField(default=datetime.datetime.now)

    def save(self, *args, **kwargs):
        self.updated_at = datetime.datetime.now()
        return super(BaseModel, self).save(*args, **kwargs)
```
## 参照
http://docs.peewee-orm.com/en/latest/index.html

# 方法2
Connection pooling is provided by the pool module, included in the playhouse extensions library. 

The pool supports:
- Timeout after which connections will be recycled.
- Upper bound on the number of open connections.

```
#http://docs.peewee-orm.com/en/latest/peewee/database.html#connection-pooling

from playhouse.pool import PooledMySQLDatabase
from peewee import (
    Model,
    UUIDField,
    CharField,
)
# MySQL连接
db = PooledMySQLDatabase('my_database', max_connections=my['max_connections'])
```

##参照
https://stackoverflow.com/questions/34764266/peewee-pooledmysqldatabase-has-cache-or-buffer
Q：peewee PooledMySQLDatabase has cache or buffer?
A：
No cache, no buffer. It has to do with transaction management. Just be sure that you're running your statements in transactions and you should be fine.

Multi-threaded apps DO NOT REQUIRE A POOL with peewee. Peewee correctly manages per-thread connections even without a pool.

# 方法3
peewee-async is a library providing asynchronous interface powered by asyncio for peewee ORM.

```
#https://peewee-async.readthedocs.io/en/latest/
import peewee_async

from peewee import (
    Model,
    UUIDField,
    CharField,
)

# 自定义连接类
class AsyncMySQLConnection(peewee_async.AsyncMySQLConnection):
    """
    Asynchronous database connection pool.
    """

    def __init__(self, *, database=None, loop=None, timeout=None, **kwargs):
        self.pool = None
        self.loop = loop
        self.database = database
        self.timeout = timeout
        kwargs.setdefault('pool_recycle', 3600)
        self.connect_params = kwargs

# MySQL连接
db = peewee_async.PooledMySQLDatabase('my_database'
    max_connections=my['max_connections'],
    async_conn=AsyncMySQLConnection)
```
##参照
https://www.w3cschool.cn/hack_tutorial/hack_tutorial-qay32dz7.html
他のブログサイトのコード貼り付けを調べてみる

<B>はてなブログ

https://hatenablog.com


<B>ソースコード貼り付け機能もあり、コピペ可能

以下抜粋 ruby言語例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/b8736bb7-7129-72b7-7f54-8ca7c21b1b5b.png)






情報源
https://hatenadiary.g.hatena.ne.jp/keyword/ソースコードを色付けして記述する（シンタックス・ハイライト）



追記予定あり
JSのグローバル変数について備忘録

JSを勉強している中で**「グローバル変数」**なるものを知りました。
なにに使うの？他には何があるの？どういうところを気を付ければいいの？と調べた内容を備忘録的に記載します。

※参考サイトは一番下に記載してます。
もはやそれらサイトの中身をちょいちょいかいつまんだ内容になっております。。あくまで備忘録

###グローバル変数とは
グローバル変数とは、プログラムのどこからでもアクセスできる変数。

グローバル変数の対義語として、**「ローカル変数」**というものがあり、ローカル変数は関数内で宣言して関数内で使用できる変数、とのことです。

###グローバル変数を定義するには
**①関数の外で変数の宣言をする**
**②varなしで変数宣言(JSでは「var」を使わずに宣言した変数はすべてグローバル変数とみなされる)**
このどちらかで宣言された変数はグローバル変数となります。

###グローバル変数の懸念点
`var`を使わずに関数の内外どこでも宣言でき便利なようで、どこでも取り出せてどこでも再代入できてしまうため、同じ変数名が複数存在したときにバグになりやすい　という懸念点があります。

###varの懸念点
じゃあ関数内で`var`で宣言すればいいか？というとそうでもない。
同じ関数内であれば再代入も再宣言も可能なので、気が付いたら自分が思っていたのと違う中身になっていたそれがどこで発生している事象なのかおっかけるの大変・・・などという状況になり、予期せぬバグになりやすい。

###JSで変数を使用するときは
基本的には `const` を使用し、再代入が必要な変数には `let` を使用する のが良いとのこと。

###`const`とは
`const`とは値書き換えを禁止した変数を宣言する方法で、定数として一度宣言したら再代入・再宣言は不可となる。（書き換えようとするとエラーが発生するため、予期せぬバグになりにくい）

###`let`とは
再代入可能だが再宣言は不可。ブロックスコープ。
同じ関数内でもブロックごと分けることで再代入の影響を受けなくなる。
多少書き換えがあっても影響範囲がブロックに留まるため、どこでなにしてるかわかりやすくなる。

###まとめ
指定せずグローバル変数にするのは辞めましょう。
`var` は自由度が高すぎるので予期せぬエラーが発生しやすい。

そのため、予期せぬエラーを防ぐ・可読性を上げるためにも変数は基本 `const`  再代入を行いたい場合 `let` を使用する。

参考サイト
[JavaScriptのグローバル変数を解説！ローカル変数と違いとは](https://techplay.jp/column/636)
[JavaScriptでのグローバル変数の宣言方法](https://uxmilk.jp/11598)
[JavaScript初心者必見！constとは？基礎の基礎を解説！](https://www.sejuku.net/blog/58868)
jQueryで年月のプルダウンを生成する

こんなかんじのプルダウンを作成します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482507/0f3b1b0d-435b-82bf-20b5-32056c135204.png" width=50%>

```
<select>
    <option value="">選択する</option>
</select>
```

```
<!--jQueryはCDNを使用-->
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script>
$(function(){
//英語の月を配列にする
var m_eng = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

var today=new Date();
//現在の年月を文字列の状態で取得する(例：20201)
var now_date = String(today.getFullYear()) + String((today.getMonth() +1));
//現在の年月が5文字(例：20201~20209)の場合、月を01表記に整形
	if(now_date.length == 5){
	var now_date = now_date.slice(0, 4) + "0" + now_date.slice(-1);
	}
var num_date = Number(now_date);

//スタート年月を設定(今回は2019年1月)
var onset = 201901;

//スタート年月(onset)～現在(num_date)のプルダウンを繰り返しで生成する
while (onset <= num_date) {
	//onsetの月部分が13になった時、年に+1年、月を1月にする
	//例）201913→202001
	var set_cnv = String(onset);
		if(set_cnv.slice(-2) == 13){
		var onset = onset + 100 -12;
		var set_cnv = String(onset);
		}
        //年と月
	var set1 = set_cnv.slice(0, 4);
	var set2 = Number(set_cnv.slice(-2)) -1;

//selectにoptionタグを追加する
$('select').append(
'<option value="' + set_cnv + '">' + set1 + '[' + m_eng[set2] + ']' + '</option>');

onset++;
}

});
</script>
```

以下、jQueryで生成されたタグです。

```
<select>
    <option value="">選択する</option>
	<option value="201901">2019[Jan]</option>
	<option value="201902">2019[Feb]</option>
	<option value="201903">2019[Mar]</option>
	<option value="201904">2019[Apr]</option>
	<option value="201905">2019[May]</option>
	<option value="201906">2019[Jun]</option>
	<option value="201907">2019[Jul]</option>
	<option value="201908">2019[Aug]</option>
	<option value="201909">2019[Sep]</option>
	<option value="201910">2019[Oct]</option>
	<option value="201911">2019[Nov]</option>
	<option value="201912">2019[Dec]</option>
	<option value="202001">2020[Jan]</option>
</select>
```
Railsのテンプレファイル(html.erb)でのコメント方法

一度うまくいった記述を、きれいなコードにする際にコメントアウトして残す癖があるが、html.erbファイルでのコメント方法が分からず調べたため備忘録として。

1. `<%#= %>`もしくは`<%#  %>`で囲む

```
<%# ココはコメントアウトされる %>
<%#= ココはコメントアウトされる %>
```
複数行の場合は

```
<%#
ココは
コメントアウト
される
%>
```
　
2. `<% if false %>`  `<% end %>`で囲む
できるっちゃできますが、コメントアウトというより正しくはデッドロジック作っているので、やはり無理やり感ありますね。

```
<% if false %>
ココはコメントアウトされる
<% end %>
```

### その他
なお、他にも、複数行コメントとして、`<% begin %>`と`<% end >%`で囲むという方法も見つかりましたが、上記1.ほどシンプルでなく改行によってはうまく機能しなかったりするので、通常使うにはイマイチということで、記載していません。

##　参考
- https://stackoverflow.com/questions/2774841/best-way-to-add-comments-in-erb
なんとなくtmuxを使ってる人が、ひとつ上の男になるためにセッションを使いだしたお話

tmuxはコピーモードが便利で、いってしまえばそれだけの理由でtmuxを使ってたんですけど、
色々な理由から、
「ちゃんと使おう・・・」
と思ったため備忘録として残しておきます。

## とりあえず今まで開いてきたセッションをすべてクリア（削除）しよう

その前に、ちゃんと使おうと思った理由として、
僕はitermを使っているんですけど
itermとかのアップデートタイミングでそのときに開いてたタブもそのまま一気に消されちゃうんですよね。

でもファイルをvimで開いてるのがあったりしたらswp残って面倒だし、
djangoでrunserverしてるのがあったりしたらそれも落としておかないとだし。
要はヘタレなんですけど、とりあえずそういう作業が面倒だったんです。

また、そういった窓はtmuxの機能ではなく、itermのタブを使ってるんです。

で、itermのアップデートボタンをポチっとするとそのタブごとitermは落とされるんですけど、再起動のタイミングではそいつらは復活しないんですよね。

もちろんそういうときこそtmuxの出番で、セッションとして残っているはずなのでアタッチすればいいんですけど、最初はそんなこと全く意識してなかったので先程、

```
tmux ls
```

ってうったらすごい量のセッションが残ってたんですよね。アハアハ。
で、そのセッションがいつ何をしてたときのわからないし面倒なのでいったん全部消してしまおうと。俺の伝説はこれから始まるんだと。

前置きが長くなりましたがやることは、

```
tmux ls
```
で過去の愚行を確認し、


```
tmux kill-server
```

で過去をリセット。


## よく行う作業ごとにセッションを作ろう

上記の、`tmux kill-server` をした直後はtmuxから抜けていると思うので、

```
tmux
```

とうち、新たにtmuxのセッションを作成します。

僕は、BQに投げたりするSQLをvim上で書くので、このセッション名に【SQL】と名前をつけることにしました。


`Prefix + $`
でセッション名の変更ができます。（Prefixは人それぞれなのでググってください。ちなみに僕は「コントロールキーを素早く2回押す」のをPrefixとしています。）

セッション名を変更したら

`Prefix + d`
でデタッチします（セッションから抜ける）

抜けたらまた、

```
tmux ls
```
と打つと、先程作ったセッション名の、
SQL
というのがいるはずなので、

```
tmux a -t SQL
```

でそのセッションにアタッチします。
すると、デタッチしたときの状態から作業を開始することができるっぽいです。幸せいっぱいですね。

そんな感じで、
・クエリを書く窓（セッション）
・djangoをいじる窓

などなど、役割ごとにセッションを作って置くことで幸せになれるんじゃないかと思ってます。


tmuxにはウィンドウという概念（というか機能）もあるんですけど、ここらへん正直itermの昨日で個人的には事足りているのでノータッチです。
ただ、サーバにSSHしてどうこうするって時には必要になってくるかも知れないのでその時がきたら本格的に触ってみようかなと。

## ※5分後に追記したこと

ペイン使い出しました。
`Prefix + %` で縦、
`Prefix + "` で横に画面を分割。

`Prefix + o` でアクティブペインの移動。

マウスクリックで移動できないのがちょっとつらい。


## 以上です。


ちゃんと使おう
って言っておきながら結局なんも大したことしてないということに気づいたけど許してください。
Reactメモ

# はじめに
Reactを書いているときに、簡単だけど「どうやるんだっけ？」ってなることをまとめていきます。 
自分用のメモといった感じです。
# 画像表示

```javascript
import Image from './images/image.png'
const Component = () =>{
  return <img src={Icon}  alt="アイコン" />
}
export default Component
```
【mysql】UPDATEで連番を振り直す

### はじめに
- テストとかしてカラムごにゃった時に番号がずれてしまったりしたので、連番をきれいに振り直したいと思ったしだい。
- 忘れがちなので、書いておくことにした

### mysql のバージョン
```sql
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.28    |
+-----------+
```

### やってみる
- 例えば、この↓ `select`文の`no`が１から始まって欲しいのに2から始まってる。

```sql
mysql> select id, no from tests; 
+----+----+
| id | no |
+----+----+
|  1 |  2 |
|  2 |  3 |
|  3 |  4 |
|  4 |  5 |
+----+----+
4 rows in set (0.00 sec)
```

- 振り直す！！

```sql
mysql> set @cnt_i:=0; update tests set no = (@cnt_i := @cnt_i + 1 );

Query OK, 0 rows affected (0.00 sec)
Query OK, 4 rows affected (0.00 sec)
Rows matched: 4  Changed: 4  Warnings: 0
```

- 確認してみる。無事に `no` が 1 からの連番になっている。やったー

```sql
mysql> select id, no from tests; 
+----+----+
| id | no |
+----+----+
|  1 |  1 |
|  2 |  2 |
|  3 |  3 |
|  4 |  4 |
+----+----+
4 rows in set (0.01 sec)
```
MVCモデル（CakePHP）の基礎知識整理

なんぞやについて
CakePHPベースで調べたもの

# MVCモデルについて
プログラムの中身（処理）を機能ごとに分けて記述することで、プログラムを整理しやすくする考え方

- モデル(Model)：表示や入力に関連しない処理を担当
- ビュー(View)：表示や入力に関する処理を担当
- コントローラ(Controller)：ビューとモデルの橋渡し役を担当

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430585/5669785b-eee1-13c8-0848-5d70fdf0050e.png)
1. ブラウザからコントローラーとアクションを指名され、アクションが実行される。
2. アクション内でモデルが指定されていればモデルが実行される。
3. アクションの処理が終了したら、Templateフォルダ¥コントローラーと同名のフォルダ¥アクション名と同名のctpファイルを表示対象として生成する。
4. ブラウザに返す。
(https://qiita.com/tsuyuri104/items/72797ba4c8b3fe79149a)


## それぞれの役割について

### Model
**ビジネスロジック**[^1]を担当する
ControllerからDB関連の仕事をもらって処理する人
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430585/722f122b-4bca-67f9-0eec-d760435d6ce4.png)
(https://umaroidblog.com/what_mvcmodel)

■ フォルダ構成

```terminal
Model
|-Entity（Table内のソースを動かす）
|-Table（CRUD処理や入力チェックを実装する）
|-Validation（カスタマイズしたかったらここにいれる。自分で作る）
```

### View
実際に入力や設定を行う画面を表示する
コントローラーから渡されたDBのデータをHTMLで表示したり

拡張子が「.ctp」だけど、中身はHTML with PHP
→ 普通にHTMLファイルとして編集すればOK

■ フォルダ構成
フォルダ名注意（別用途でViewフォルダがある）

```terminal
Template
|-Element（HTMLファイルをパーツごとに書き出すことができる）
|-Error（エラーの時に表示する画面）
|-Layout（全画面共通で表示したいことを設定するdefault.ctp）
（他省略）
```

### Controller
Viewからリクエストを受け取り、Modelへのメッセージに変換
そして、レスポンスとして処理後の画面をViewに返す
普通にPHPを書くところ


## 命名規則
ファイル名やソース内での扱いも含め

### Modelの名前
【Table】
（例）**UsersTable.php**

・`DB名`+`Table`.php[^2]
・先頭とTableの"T"は**大文字**
・ファイル内のクラス名はファイル名同様に`DB名+Table`だが、ControllerでTableを呼ぶときは**DB名のみ**
　→ `TableRegistry::get('Users');`
・Table内のメソッドは**キャメル式**🐪

【Entity】
（例）**User.php**

・`DB名`.php（単数形）
・**大文字**スタート

【Validation】
規定は特になし

### Viewの名前
（例）**index.ctp**

・**小文字**スタート
・Template配下の命名規則は同じ
・対象のController.phpのアクション名[^3]と同じものを指す ↓

```php:UserController.php
class UserController extends Controller
{
    public function index() {
        ・・・・・・
    }

    private function showList() {
        ・・・・・・
    }
}
```
この場合、`src/Template/User/`[^4]配下に
・**`index.ctp`**
・**`show_list.ctp`**（ここではスネーク式🐍になる）
が必要となる

※`private`のアクションだった場合はファイルなし
　→ ブラウザからリクエストされたときのアクションのみ必要なため
　（そもそも`private`だったらクラス外からアクセスできない）


### Controllerの名前
（例）**UserController.php**

・`コントローラ名`+`Controller`.php
・先頭とControllerの"C"は**大文字**
・アクション名は**キャメル式**🐫





# 参考
1. [MVCモデルとは | 「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word11584.html)
2. [初めてCakePHPで開発するときに気をつけたいMVC〜 | Qiita](https://qiita.com/tsuyuri104/items/72797ba4c8b3fe79149a)
3. [MVCモデルについてわかりやすく解説します！【初心者向け】 | ウマロのゲームブログ](https://umaroidblog.com/what_mvcmodel)


[^1]: 処理した結果をデータベースへ反映させること
[^2]: DB名自体、基本は複数形だが単数形でも動作する
[^3]: ～Controller.php内のメソッドのこと（多分）
[^4]: Template/Userフォルダ：Controllerごとにフォルダが必要
【Python】特定の文字列で始まる要素のみを配列に残す

# はじめに
備忘録。
特定の文字列から始まる要素のみを配列に残したい。
``['hogehoge.form', 'hugahuga.form', 'hogehoge.form2']``という配列があり、``hogehoge``から始まる要素のみを残し、他の要素は削除したい。

## 解決方法
### 文字列メソッド``startswith()``を使う
文字列の先頭を判別できるメソッド

```py
moji = 'hogehoge'

# trueを返す
moji.startswith('hoge')

# falseを返す
moji.startswith('huga')
```

### サンプルコード
```py
# 元の配列
moji_ary = ['hogehoge.form', 'hugahuga.form', 'hogehoge.form2']

# 新しい配列new_aryに、元の配列moji_aryの要素のうち`ho`から始まる要素のみを入れる
new_ary = [hoge for hoge in moji_ary if hoge.startswith('ho')]

# 出力結果['hogehoge.form', 'hogehoge.form2']
print(new_ary)

```

## さいごに
文字列の後尾（？）を判定するメソッド``endswith()``もある。
「python 文字列操作」でググると他にも便利なものが見つかる。

## 参考サイト
- https://note.nkmk.me/python-list-str-select-replace/
- https://qiita.com/Amtkxa/items/a03dabe050d8c648f098#startswith%E3%81%AB%E3%82%88%E3%82%8B%E5%85%88%E9%A0%AD%E6%96%87%E5%AD%97%E5%88%A4%E5%AE%9A
あっさり読むrails　番外(image)

#はじめに
[以前の記事](https://qiita.com/Moon1126Snow/items/a4aaae5f290c3e223684)の応用で、画像アドレスをフォームに入力すると、自動的に画像が表示されるようにします。
#前提
前記事をそのまま修正します。
#実行
ビューファイルを次の様に修正します。

```haml:sample.haml.html
= form_with model:@sample, local: true do |f|
  = f.text_area :name, placeholder: "サンプル", class: "sample-form"

.add-image
```
`add-text`を`add-image`に変えただけです。

JSファイルを次の様に書きます。

```javascript:sample.js
$(function(){
 $(".sample-form").on("change" functon(){
   var image = $(this).val();
   let html = `
     <div class = "add-image__sample">
       <img src = "$(image)" height = "500" //heightはなんでもいい
     </div>
   `
   ;
   $(".add-image").append(html);
 })
});
```

大雑把な流れとしては、
1.`フォーム(.sample-form)の中身が変わった("change")時＝画像アドレスを貼り付けた時`
2.`その値をimageに代入し`
3.`それを表示させるhtmlデータを変数に代入し`
4.`.add-imageに追加(append)する`

となります。

本当は、別の画像アドレスを貼り付ける時に元の画像を削除する必要がありますが、
ひとまずはこれで非同期の画像表示ができます。
【小ネタ】VSCodeの拡張機能で tab を強調表示してみた

## 概要
インデント tab 嫌いマンなので拡張機能を使って赤く強調表示してみました。

## 拡張機能のインストール
拡張機能から ```Whitespace+``` で検索してください。
![Whitespace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503672/e4d8367d-667c-f85a-e64e-f1c43a21ae08.png)

## 設定ファイルを変更
```Ctr+Shift+P``` でファイル検索モードに切り替え、```Whitespace+ Config``` と入力してEnter。

以下の記述が tab についてです。

~~~
"name": "tab",
"enabled": true,
"pattern": "\\t",
"style": {
    "borderWidth": "1px",
    "borderRadius": "2px",
    "borderStyle": "solid",
    "light": {
        "backgroundColor": "rgba(170, 53, 53, 0.3)",
        "borderColor": "rgba(170, 53, 53, 0.4)"
    },
    "dark": {
        "backgroundColor": "rgba(223, 20, 20, 0.3)",
        "borderColor": "rgba(255, 97, 97, 0.4)"
    }
}
~~~

コピペで使えるように全文載せておきます。

~~~
{
    "mode": "all",
    "autoStart": true,
    "refreshRate": 100,
    "elements":
    [{
        "name": "space",
        "enabled": true,
        "pattern": "\\s",
        "style": {
            "borderWidth": "1px",
            "borderRadius": "2px",
            "borderStyle": "solid",
            "light": {
                "backgroundColor": "rgba(1, 1, 1, 0.3)",
                "borderColor": "rgba(58, 70, 101, 0.4)"
            },
            "dark": {
                "backgroundColor": "rgba(30, 30, 30, 0.3)",
                "borderColor": "rgba(30, 30, 30, 0.4)"
            }
        }
    },{
        "name": "tab",
        "enabled": true,
        "pattern": "\\t",
        "style": {
            "borderWidth": "1px",
            "borderRadius": "2px",
            "borderStyle": "solid",
            "light": {
                "backgroundColor": "rgba(170, 53, 53, 0.3)",
                "borderColor": "rgba(170, 53, 53, 0.4)"
            },
            "dark": {
                "backgroundColor": "rgba(223, 20, 20, 0.3)",
                "borderColor": "rgba(255, 97, 97, 0.4)"
            }
        }
    },{
        "name": "newline",
        "enabled": true,
        "pattern": "\\n",
        "style": {
            "borderWidth": "1px",
            "borderRadius": "2px",
            "borderStyle": "solid",
            "light": {
                "borderColor": "rgba(40, 40, 40, 0.4)"
            },
            "dark": {
                "borderColor": "rgba(40, 40, 40, 0.4)"
            }
        }
    },{
        "name": "trailing",
        "enabled": "unlessCursorAtEndOfPattern",
        "pattern": "[^\\S\\r\\n]+$",
        "style": {
            "borderWidth": "1px",
            "borderRadius": "2px",
            "borderStyle": "solid",
            "light": {
                "backgroundColor": "rgba(40, 40, 40, 0.3)",
                "borderColor": "rgba(40, 40, 40, 0.4)"
            },
            "dark": {
                "backgroundColor": "rgba(40, 40, 40, 0.3)",
                "borderColor": "rgba(40, 40, 40, 0.4)"
            }
        }
    }]
}
~~~

## 結果
tab を赤く強調表示できました。2度とtabを書くことはなくなります。
![tab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503672/8e7c8bcc-73ae-5660-eae8-7d4f7b3fc043.png)





## 補足
半角スペースの表示は下記のファイルに追記
C:\Users\{user}\AppData\Roaming\Code\User\settings.json

~~~css
{
    "editor.renderWhitespace": "all"
}
~~~
多国語対応の Text::VisualPrintf をアップデートした

# 日本語と printf の相性

Perl に限らないが、プログラムの中で printf 系の関数を使って日本語を出力しようとすると、大概の場合思ったような結果を得られない。今時は GUI や HTML で表示したりすることが多いので、それほど問題にならないのかもしれないが、やはり必要になることはある。printf を使わずに済ませることも工夫次第で可能だが、やはりあれば便利だ。

# Text::VisualPrintf

`Text::VisualPrintf` は、マルチバイト文字を処理するための Perl モジュールだ。最初に作ったのは2011年で `MBprintf` という名前だったが、2017年に `Text::VisualWidth::PP` を使うように修正した際に、今の名前に変更した。なぜそうしたかというと、やってる処理がほとんど同じで、より優れた部分があったからだ。ただ、足りない部分もあったので、それを提案して採り入れてもらえたので乗り換えた。

```perl:
use Text::VisualPrintf qw(vprintf vsprintf);
```

のように読み込むと `vprintf` と `vsprintf` という2つの関数が使えるようになる。

使い方については、解説するまでもあるまい。実際のコードの一部を載せておこう。

```perl:subst.pm
vprintf("%3d: %${from_max}s => %-${to_max}s",
        $i + 1, $from_re // '', $to // '');
```
出力例はこんな感じだ。揃っていないと大変読みにくい。

<img width="970" alt="スクリーンショット 2020-01-24 13.19.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/59d4e131-9a43-440e-9151-a09ce8593b16.png">

ちなみに、内部で利用している `Text::VisualWidth::PP` には Unicode の結合文字に対応する修正を入れてもらってあるので、日本語に限らず大方の言語は正しく処理できるはずだ。

# 実装

実装はかなり手抜きだ。Perl の sprintf は、文字幅を考慮しないので、マルチバイト文字を含むパラメータは、含まない文字列に置き換えてしまう。そして、sprintf で出力した結果を変換して元の文字列を復活させる。

アルゴリズムは次の通り。

1. まず、制御文字を含めてフォーマット文字列で使われていない文字2つ選ぶ。普通は`^A` と `^B` が選ばれるはずだ。これを `$a`, `$b` とする。
2. 置換の対象となる引数を `$a` で始まってそれに `$b` の繰り返しが続く文字列に返還する。
3. `sprintf` の結果の `/$a$b*/` に対応する部分を、順番にセーブしておいた文字列に変換する。

こうすることで、変換結果が最悪1カラムになってしまったとしても間違いなく変換することが可能だ。

# Text::VisualPrintf::IO

今回、このモジュールを作ってみた。やっていることは単純で、重要なのはこの1行だけだ。

```perl:
*IO::Handle::printf  = \&Text::VisualPrintf::printf;
```
IO::Handle の `printf` メソッドを置き換えているので、次のように使えるようになる。

```perl:
use Test::More;
use Text::VisualPrintf::IO qw(printf);

open OUT, ">", \(my $out) or die;
OUT->printf("%10s\n", "あいうえお");
close OUT;
is( decode('utf8', $out),  "あいうえお\n", 'FH->printf' );
```

`IO::Handle` の実装を変えると `IO::File` 等でも使える。残念ながら

```perl:
printf OUT "%10s\n", "あいうえお";
```
のような使い方はできない。`vprintf` というメソッドも設定してあるので、次のように使うことはできる。

```perl:
vprintf OUT "%10s\n", "あいうえお";
```
いい考えがあればおしえてほしい。

ただ、どちらかと言うと `vsprintf` を使って普通に出力する方がお勧めだ。

# インストール

## Text::VisualPrintf

Perl プログラマなら cpanm はインストールしてあるだろうから、これで。

```sh:
$ cpanm Text::VisualPrintf
```

いないと思うけど、ない人はこれでどうぞ。

```sh:
$ curl -sL http://cpanmin.us | perl - Text::VisualPrintf
```

# SEE ALSO

https://github.com/kaz-utashiro/Text-VisualPrintf

# 2020.02.06 追記

## Truncation

この記事を書いた時には、与えた文字列が短くなるような操作には対応していなかったのだが、最新バージョンでは対応するようになっている。ただし、最低でも2バイトは残ってくれないと駄目だ。

短縮するために `Text::ANSI::Fold` モジュールを使用したので、perl v5.14 以上の対応となった。

## Text::VisualPrintf::IO

`Text::VisualPrintf::IO` は、import パラメータを受け取るように変更した。`printf` と `vprintf` を指定することができる。

# 2020.10 追記

その後のアップデートで、1バイトの短縮に対応し、2020年9月にリリースした 3.06 からは、0バイトへの短縮、つまり対応する要素が消滅してしまう場合にも対応している。