New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

input()で何も入力なしで<CR>叩いた場合と<Esc>した場合を区別したい #467

Open
LeafCage opened this Issue Sep 3, 2013 · 21 comments

Comments

Projects
None yet
6 participants
@LeafCage

LeafCage commented Sep 3, 2013

どちらも空文字列になり、通常では区別が出来ません。
(cmapでやのマッピングを変えるという荒業がありますが、副作用があります。)

未入力でだとデフォルトの動作、
だとキャンセルというように、動作を区別させることが出来ません。

どうにかしてどちらなのかを知る方法が提供されてほしいです。
(外部変数や専用関数など)

@koron

This comment has been minimized.

Show comment
Hide comment
@koron

koron Sep 4, 2013

Member

もともと区別ができるという仕様が定義されているわけではないので
「~できない」というタイトル&内容は不適切だと感じます。
「~したい」という風に修正できないでしょうか?

あと eval.txt の該当箇所を修正する形でパッチを作ってくれると
どうして欲しいかのイメージが伝わりやすく今後の議論の助けになるでしょう。

Member

koron commented Sep 4, 2013

もともと区別ができるという仕様が定義されているわけではないので
「~できない」というタイトル&内容は不適切だと感じます。
「~したい」という風に修正できないでしょうか?

あと eval.txt の該当箇所を修正する形でパッチを作ってくれると
どうして欲しいかのイメージが伝わりやすく今後の議論の助けになるでしょう。

@koron

This comment has been minimized.

Show comment
Hide comment
@koron

koron Sep 4, 2013

Member

eval.txt の該当箇所を修正する形でパッチを作って

想定している関数を使ったスクリプトの断片でも良いかも。

Member

koron commented Sep 4, 2013

eval.txt の該当箇所を修正する形でパッチを作って

想定している関数を使ったスクリプトの断片でも良いかも。

@mattn

This comment has been minimized.

Show comment
Hide comment
@mattn

mattn Sep 4, 2013

Member

例えばこんなのどうでしょう?

scriptencoding utf-8

function! s:input(...) abort
  new
  cmap <buffer> <esc> __CANCELED__<cr>
  let ret = call('input', a:000)
  bw!
  redraw
  if ret =~ '__CANCELED__$'
    throw "キャンセルされました"
  endif
  return ret
endfunction

echo s:input("foo:")
Member

mattn commented Sep 4, 2013

例えばこんなのどうでしょう?

scriptencoding utf-8

function! s:input(...) abort
  new
  cmap <buffer> <esc> __CANCELED__<cr>
  let ret = call('input', a:000)
  bw!
  redraw
  if ret =~ '__CANCELED__$'
    throw "キャンセルされました"
  endif
  return ret
endfunction

echo s:input("foo:")
@mattn

This comment has been minimized.

Show comment
Hide comment
@mattn

mattn Sep 4, 2013

Member

<c-w> はさすがにまずいかw

Member

mattn commented Sep 4, 2013

<c-w> はさすがにまずいかw

@koron

This comment has been minimized.

Show comment
Hide comment
@koron

koron Sep 4, 2013

Member

普通にesc文字が出てくるのでも良いかなと思った。

Member

koron commented Sep 4, 2013

普通にesc文字が出てくるのでも良いかなと思った。

@Shougo

This comment has been minimized.

Show comment
Hide comment
@Shougo

Shougo Sep 4, 2013

Member

普通にesc文字が出てくるのでも良いかなと思った。

挙動が変わったほうが、使う方としては綺麗ですが後方互換性が失われるのがちょっと……。
input()は多数のスクリプトで使用されています。引数を追加して、それによって動作を変えるという手はあるかもしれません。

Member

Shougo commented Sep 4, 2013

普通にesc文字が出てくるのでも良いかなと思った。

挙動が変わったほうが、使う方としては綺麗ですが後方互換性が失われるのがちょっと……。
input()は多数のスクリプトで使用されています。引数を追加して、それによって動作を変えるという手はあるかもしれません。

@LeafCage

This comment has been minimized.

Show comment
Hide comment
@LeafCage

LeafCage Sep 4, 2013

第4引数にキャンセルされたかどうかを判定する変数をセットできるようにする。

function! s:input_example()
  let canceled = 0
  let input = input('> ', '', '', canceled)
  if canceled
    return
  elseif input == ''
    echo 'default'
  else
    echo input
  endif
endfunction

あるいは直前のinputがキャンセルされたか否かを知る、v:inputcanceledまたはinputcanceled()を用意する。
という案を提示します。

LeafCage commented Sep 4, 2013

第4引数にキャンセルされたかどうかを判定する変数をセットできるようにする。

function! s:input_example()
  let canceled = 0
  let input = input('> ', '', '', canceled)
  if canceled
    return
  elseif input == ''
    echo 'default'
  else
    echo input
  endif
endfunction

あるいは直前のinputがキャンセルされたか否かを知る、v:inputcanceledまたはinputcanceled()を用意する。
という案を提示します。

@Shougo

This comment has been minimized.

Show comment
Hide comment
@Shougo

Shougo Sep 4, 2013

Member

私としては、引数の追加に+1

Member

Shougo commented Sep 4, 2013

私としては、引数の追加に+1

@LeafCage

This comment has been minimized.

Show comment
Hide comment
@LeafCage

LeafCage Sep 4, 2013

私としましては、引数の追加は汚く見えるので後者のv:inputcanceledまたはinputcanceled()の追加を推したいのです。

LeafCage commented Sep 4, 2013

私としましては、引数の追加は汚く見えるので後者のv:inputcanceledまたはinputcanceled()の追加を推したいのです。

@thinca

This comment has been minimized.

Show comment
Hide comment
@thinca

thinca Sep 4, 2013

Member

引数を追加するにしても、その方法は無理です。参照渡しではないので。

Member

thinca commented Sep 4, 2013

引数を追加するにしても、その方法は無理です。参照渡しではないので。

@mattn

This comment has been minimized.

Show comment
Hide comment
@mattn

mattn Sep 4, 2013

Member

throw するかどうかのフラグ、なら実現性ある

Member

mattn commented Sep 4, 2013

throw するかどうかのフラグ、なら実現性ある

@mattn

This comment has been minimized.

Show comment
Hide comment
@mattn

mattn Sep 4, 2013

Member

もしくはesc時は0を返すとか。type()で判断してもらう形。

Member

mattn commented Sep 4, 2013

もしくはesc時は0を返すとか。type()で判断してもらう形。

@Shougo

This comment has been minimized.

Show comment
Hide comment
@Shougo

Shougo Sep 4, 2013

Member

throw するかどうかのフラグ、なら実現性ある

throwはありだと思います。Vim scriptでは他にそういう挙動をする関数が見当たらないのがネックとなるでしょうか。

もしくはesc時は0を返すとか。type()で判断してもらう形。

それでも良いと思います。文字列を返す時とは違い、誤動作はなくなるはずなので。

私としましては、引数の追加は汚く見えるので後者のv:inputcanceledまたはinputcanceled()の追加を推したいのです。

引数の追加はたしかに汚いですが、v:変数の追加や関数の追加のほうが影響範囲が大きく余計に汚く見えます。
ユーザーの入力がキャンセルかどうか判断するためだけに、グローバル変数を追加するやり方は私は好みでないです。
使う方も余計な手間がかかるかと。

Member

Shougo commented Sep 4, 2013

throw するかどうかのフラグ、なら実現性ある

throwはありだと思います。Vim scriptでは他にそういう挙動をする関数が見当たらないのがネックとなるでしょうか。

もしくはesc時は0を返すとか。type()で判断してもらう形。

それでも良いと思います。文字列を返す時とは違い、誤動作はなくなるはずなので。

私としましては、引数の追加は汚く見えるので後者のv:inputcanceledまたはinputcanceled()の追加を推したいのです。

引数の追加はたしかに汚いですが、v:変数の追加や関数の追加のほうが影響範囲が大きく余計に汚く見えます。
ユーザーの入力がキャンセルかどうか判断するためだけに、グローバル変数を追加するやり方は私は好みでないです。
使う方も余計な手間がかかるかと。

@koron

This comment has been minimized.

Show comment
Hide comment
@koron

koron Sep 4, 2013

Member

throw exception when cancelled みたいなフラグ引数追加か、関数自体を追加かね。

Member

koron commented Sep 4, 2013

throw exception when cancelled みたいなフラグ引数追加か、関数自体を追加かね。

@LeafCage

This comment has been minimized.

Show comment
Hide comment
@LeafCage

LeafCage Sep 4, 2013

0を返すという案はなかなか魅力的に見えます.

LeafCage commented Sep 4, 2013

0を返すという案はなかなか魅力的に見えます.

@koron

This comment has been minimized.

Show comment
Hide comment
@koron

koron Sep 4, 2013

Member

もしくはesc時は0を返すとか。type()で判断してもらう形。

既存の input() の動作を引数などの変更なしに変えるのは、やはり好ましくないのでは?
文字列しか返ってこないものとして作られているモノはあるでしょう。
(だいたいのケースで問題にならないってのはわかりますが)

  • 引数増やして動作を制御する
  • 別関数を用意する

のどちらかで、パッチの提案が速いほうってことで決まりそう。

Member

koron commented Sep 4, 2013

もしくはesc時は0を返すとか。type()で判断してもらう形。

既存の input() の動作を引数などの変更なしに変えるのは、やはり好ましくないのでは?
文字列しか返ってこないものとして作られているモノはあるでしょう。
(だいたいのケースで問題にならないってのはわかりますが)

  • 引数増やして動作を制御する
  • 別関数を用意する

のどちらかで、パッチの提案が速いほうってことで決まりそう。

@Shougo

This comment has been minimized.

Show comment
Hide comment
@Shougo

Shougo Sep 4, 2013

Member

既存の input() の動作を引数などの変更なしに変えるのは、やはり好ましくないのでは?
文字列しか返ってこないものとして作られているモノはあるでしょう。
(だいたいのケースで問題にならないってのはわかりますが)

はい。0を返す場合は、引数の追加が必要になるでしょう。
じゃないと、既存のコードが壊れることになります。

Member

Shougo commented Sep 4, 2013

既存の input() の動作を引数などの変更なしに変えるのは、やはり好ましくないのでは?
文字列しか返ってこないものとして作られているモノはあるでしょう。
(だいたいのケースで問題にならないってのはわかりますが)

はい。0を返す場合は、引数の追加が必要になるでしょう。
じゃないと、既存のコードが壊れることになります。

@mattn

This comment has been minimized.

Show comment
Hide comment
@mattn

mattn Sep 4, 2013

Member

get みたく default 値(キャンセル値)を設けるのがいいのかな。文字列しか入れないだろうから、明確に分けたい人は数値とかdictを入れるみたいな使い方。Bramが嫌うかどうかは知らない。

Member

mattn commented Sep 4, 2013

get みたく default 値(キャンセル値)を設けるのがいいのかな。文字列しか入れないだろうから、明確に分けたい人は数値とかdictを入れるみたいな使い方。Bramが嫌うかどうかは知らない。

@Shougo

This comment has been minimized.

Show comment
Hide comment
@Shougo

Shougo Sep 4, 2013

Member

たしかにその手はありますね。フラグ引数追加よりはインタフェースとしてマシになりそうな気がします。

Member

Shougo commented Sep 4, 2013

たしかにその手はありますね。フラグ引数追加よりはインタフェースとしてマシになりそうな気がします。

@koron

This comment has been minimized.

Show comment
Hide comment
@koron

koron Sep 4, 2013

Member

それだと結局そこにどんな値を入れるべきかで悩む&バッドノウハウ化するんじゃない?

<ESC> を入れるのを提案しようと思ったけど <C-V><ESC> で普通に入力できてショボーンだった。

だから基本は 0 を返す案を支持。

Member

koron commented Sep 4, 2013

それだと結局そこにどんな値を入れるべきかで悩む&バッドノウハウ化するんじゃない?

<ESC> を入れるのを提案しようと思ったけど <C-V><ESC> で普通に入力できてショボーンだった。

だから基本は 0 を返す案を支持。

@ichizok

This comment has been minimized.

Show comment
Hide comment
@ichizok

ichizok Dec 2, 2013

Member

https://gist.github.com/ichizok/7755887
結果を格納するリストを渡すようにしてみました。

function! s:input_example()
  let result = []
  let input = input('> ', '', '', result)
  " canceled => add(result, 0)
  " otherwise => add(result, input)
  if (type(result[-1]) == type(0))
    " canceled
    return
  elseif input ==# ''
    echo 'default'
  else
    echo input
  endif
endfunction
Member

ichizok commented Dec 2, 2013

https://gist.github.com/ichizok/7755887
結果を格納するリストを渡すようにしてみました。

function! s:input_example()
  let result = []
  let input = input('> ', '', '', result)
  " canceled => add(result, 0)
  " otherwise => add(result, input)
  if (type(result[-1]) == type(0))
    " canceled
    return
  elseif input ==# ''
    echo 'default'
  else
    echo input
  endif
endfunction
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment