파이썬에서 함수의 두 가지 인수를 바꾸는 방법?


11

파이썬 함수 호출에서 두 인수를 어떻게 바꿀 수 있습니까?

point이 두 논쟁 사이에 공백을 두면

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

그런 다음 M-t( transpose-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

함수 transpose-subr를 가져 와서 forward함수로 변환 하는 핵심 함수 가 transpose있습니다. 따라서 만약 우리가 c-forward-arglist(한 함수 arg에서 다음 AFAICT로 이동하는 함수는 존재하지 않는다면) 우리는 가질 것 c-transpose-arglist입니다.
Brendan

답변:


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 수정은 비교적 쉽습니다 (위 참조). 내가 재미있는 대안을 작성하여 Stefan의 조언을 따르려고 시도한 것은 forward-sexp-function쉼표로 인해 너무 성가신 것으로 보입니다. 그런 다음 traspose-sexp똑같은 일을 하기 위해 copycat 을 시도했지만 다시 쉼표를 고려해야하면 이것이 실제로 어려워집니다. 나는 이것이 구분자를 나열 할 때 항상 올바른 일을한다고 주장하지는 않는다. 아마도 절반의 시간 일 뿐이다.
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
질문은 C 코드를 폐지하지만이 답변은 다음에 적용됩니다. f(a=1, b=2)- emacs.stackexchange.com
a

2

SMIE를 사용하는 모드에서는 transpose-sexp해당 경우에 올바르게 작동해야합니다. 접두어 기호 (일명 "분리 자")가 ,(또는 a ;)가 아니라 단어 (예 :) 인 경우에도 여전히 실패합니다 and.

따라서 제 의견은 그 명령 transpose-sexp이 올바르게 작동하지 않을 때 버그로 생각합니다 (그러나 버그가 고칠 수 있고 / 또는 수정하고 우선 순위가 낮은 버그는 고려하지 마십시오) 숨을 참으십시오). 이 문제를 해결하는 방법 forward-sexp-function은 "쉼표를 본 후에 전체 인수를 건너 뛰는 것"이라는 기능을 설정 하는 것입니다.


1
Java 모드 (예 : SMIE)를 사용하지 않는 것 같습니다. 어떻게 고칠 수 있을까요?
Samuel Edwin Ward

1
실제로 C와 같은 언어의 주요 모드는 SMIE를 사용하지 않으며 역사적 이유로 만 사용됩니다. SMIE의 파서는 해당 언어에 비해 너무 약합니다. SMIE의 파서는 쉼표로 구분 된 두 개의 인수를 바꾸고 싶다면 (문법 의이 부분은 간단합니다) SMIE를 구성하고 사용할 forward-sexp-function수 있다고 생각합니다. SMIE를 forward-sexp-function 충분히 사용 하는 경우 에만 코드를 추가하여 잘 작동하는 경우가 많습니다. 다른 경우에는 혼동을 일으킬 수 있습니다.
Stefan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.