Pythonで関数の2つの引数を転置するには?


11

Python関数の呼び出しで2つの引数を交換するにはどうすればよいですか?

pointこれらの2つの引数の間にスペースを置いた場合:

self.assertEqual(json.loads(some.data), json_data)

そしてM-ttranspose-words)、私は得ます:

self.assertEqual(json.loads(some.json), data_data)

一方、CMt(transpose-sexps)では、次のようになります。

self.assertEqual(json.loadsjson_data, (some.data))

私が欲しいのは:

self.assertEqual(json_data, json.loads(some.data))

それを行うコマンドはありますか?


2
私は試していませんが、Anchored Transposeを使用できます。ただし、これは2段階のプロセスです。
Kaushal Modi、2015

関数と呼ばれるコア関数があり、transpose-subrそれをforward関数に変換しtransposeます。したがって、c-forward-arglist(ある関数の引数から次の引数に移動する関数-AFAICTは存在しません)があれば、そうなりますc-transpose-arglist
ブレンダン

回答:


4

これも私が長い間持ちたいと思っていたもので、ここに取り組む動機が見つかりました。おそらくそれほど堅牢ではありませんが、最初の試行では、私が試したケースをカバーしているようです:

(defun my/calculate-stops ()
  (save-excursion
    (let ((start
           (condition-case e
               (while t (backward-sexp))
             (error (point))))
          stops)
      (push start stops)
      (condition-case e
          (while t
            (forward-sexp)
            (when (looking-at "\\s-*,")
              (push (point) stops)))
        (error (push (point) stops)))
      (nreverse stops))))

(defun my/transpose-args ()
  (interactive)
  (when (looking-at "\\s-") (backward-sexp))
  (cl-loop with p = (point)
           with previous = nil
           for stop on (my/calculate-stops)
           for i upfrom 0
           when (<= p (car stop)) do
           (when previous
             (let* ((end (cadr stop))
                    (whole (buffer-substring previous end))
                    middle last)
               (delete-region previous end)
               (goto-char previous)
               (setf middle (if (> i 1) (- (car stop) previous)
                              (string-match "[^, \\t]" whole 
                                            (- (car stop) previous)))
                     last (if (> i 1) (substring whole 0 middle)
                            (concat (substring whole (- (car stop) previous) middle)
                                    (substring whole 0 (- (car stop) previous)))))
               (insert (substring whole middle) last)))
           (cl-return)
           end do (setf previous (car stop))))

ポイントがスペース上にあるときにこれが得られます(コンマ上で機能します):let *:間違ったタイプの引数:integer-or-marker-p、nil
Croad Langshan

@CroadLangshan修正は比較的簡単でした(上記を参照)。ステファンのアドバイスに従って代替案を書いてみましforward-sexp-functionたが、これはカンマのために面倒すぎます。それから私traspose-sexpは同じことをするために模倣を試みました、そして、再び、コンマを説明しなければならないことはこれを本当に難しくします。区切り文字のリストに関しては、これが常に正しいことを主張するわけではありません。おそらく半分の時間です...
wvxvw

これは(aa, bb)、カーソルが最初にあるときに失敗しますa。これはまた、移調のための作業はありません何とかは、移調を台無しに。FOO(aaa *, bbb, ccc)*
ideasman42

また失敗しますFOO(&aaa, bbb)(&はスワップしません)。
ideasman42

4

私は、そのバリエーションを使用して、transpose-sexpsコンマで区切られたものを記述および転置する場合、または単に通常の場合を検索しますtranspose-sexps。また、カーソルを前にドラッグする代わりにそのままにします。これは少し異なりますが、個人的には好きです。

(defun my-transpose-sexps ()
  "If point is after certain chars transpose chunks around that.
Otherwise transpose sexps."
  (interactive "*")
  (if (not (looking-back "[,]\\s-*" (point-at-bol)))
      (progn (transpose-sexps 1) (forward-sexp -1))
    (let ((beg (point)) end rhs lhs)
      (while (and (not (eobp))
                  (not (looking-at "\\s-*\\([,]\\|\\s)\\)")))
        (forward-sexp 1))
      (setq rhs (buffer-substring beg (point)))
      (delete-region beg (point))
      (re-search-backward "[,]\\s-*" nil t)
      (setq beg (point))
      (while (and (not (bobp))
                  (not (looking-back "\\([,]\\|\\s(\\)\\s-*" (point-at-bol))))
        (forward-sexp -1))
      (setq lhs (buffer-substring beg (point)))
      (delete-region beg (point))
      (insert rhs)
      (re-search-forward "[,]\\s-*" nil t)
      (save-excursion
        (insert lhs)))))

私にとってこれは、assertEqual呼び出しの開始時に空白を残します(スペース上のポイントで開始)。
Croad Langshan

1
これは次のようなキーワード引数に対しては機能しません:(f(a=1, b=2)それは転置されます)
Att Righ

1
質問はabount Cコードですが、この答えは、のために働くf(a=1, b=2)- emacs.stackexchange.com/a/47930/2418
ideasman42

2

SMIEを使用するモードでtranspose-sexpは、その場合は正しく動作するはずです。中置記号(別名「セパレーター」)が,(または;)ではなく単語(例:)の場合でも、失敗しandます。

だから、私の意見では、そのためのコマンドがtranspose-sexpあり、これが正しく機能しない場合は、バグと見なします(ただし、バグがあり、修正に時間がかかり、優先度が低い可能性があるため、しないでください) t息を止める)。これを修正する方法はforward-sexp-function、「カンマが表示されたら、引数全体をジャンプする」ことを知っている関数に設定することです。


1
(たとえば)java-modeはSMIEを使用しないと思いますか?それを修正するにはどうすればよいですか?
Samuel Edwin Ward

1
いいえ、確かに、Cのような言語のメジャーモードはSMIEを使用していません。歴史的な理由だけでなく、SMIEのパーサーはこれらの言語に対して弱すぎるだけです。これは、コンマで区切られた2つの引数を交換する場合(文法のこの部分は十分に簡単です)、SMIEのパーサーは問題なく機能するため、SMIEを構成して使用することは可能forward-sexp-functionだと思いますが、いくつかのコードを追加して、SMIEがforward-sexp-function 十分に機能する場合にのみSMIEを使用するようにします。
Stefan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.