원하는 URL을 조합해 웹브라우저로 여는 대화형 함수 만들기 - elixir 문서 편하게 검색

2 minute read

elixir 문서를 보고 싶은 모듈이 있다. https://hexdocs.pm/elixir/ 사이트를 방문한다. 검색 필드에 모듈이나 함수 이름으로 찾는다. 번거롭다고 말하려고 했는데, 과정을 써보니 간단하다. 하지만 이 간단한 작업도 반복되니 번거롭다. elixir 프로그래밍을 emacs에서 주로 하니깐 emacs에서 바로 검색 결과 페이지를 열 수 있었으면 좋겠다.

웹브라우저로 여는 주소는 간단하다.

https://hexdocs.pm/elixir/search.html?q=enum%20take

enum take 문자열로 검색하면 https://hexdocs.pm/elixir/search.html 페이지에 쿼리 스트링(query string) 파라미터 필드(field)로 q 를 값으로는 검색할 문자열을 퍼센트 인코딩을 해서 enum%20take 를 넘기면 된다.

필요한 건 다음과 같다.

  1. 검색할 문자열을 받는 대화형(interactive) 함수를 emacs lisp로 만든다.
  2. 쿼리 스트링 파라미터값을 퍼센트 인코딩을 해서 보내야 한다. emacs lisp 라이브러리가 있겠지. 없다면 빈 공백만 %20 으로 대체해서 아쉬운 대로 사용한다.
  3. 조합한 URL을 웹브라우저로 여는 emacs lisp 함수를 호출해야 한다.

1. 대화형 함수 추가

(defun search-elixir-doc (search-terms)
  (interactive "sEnter your search terms: ")
  (message "search terms - %s" search-terms))

interactive 함수를 사용해 대화형 함수로 만들었다. 임의의 문자열을 입력받게 하려고 앞에 s 문자를 붙였다. 함수 실행 후 입력받은 검색어를 *Messages* 버퍼에 출력하게 했다.

커서를 함수 위치에 대고 M-x eval-defun 함수를 실행한다. 그럼 바로 사용할 수 있다.

M-x search-elixir-doc

함수를 실행하면 미니 버퍼에 Enter your search terms: 문자열이 출력된다. enum take 를 입력하면 *Message* 버퍼에 search terms - enum take 문자열이 출력되는 걸 볼 수 있다.

이제 알맹이를 채워 넣으면 된다.

2. 검색어를 퍼센트 인코딩을 한 다음 웹브라우저로 열 URL 조합

그래 없을 리가 없지. 조금이라도 의심해서 미안해요. url-encode-url 함수를 사용하면 된다.

(defun search-elixir-doc (search-terms)
  (interactive "sEnter your search terms: ")
  (let ((search-terms (url-encode-url search-terms)))
    (message "search terms - %s" search-terms)))

url-encode-url 함수 결과를 search-terms 심볼에 바인딩했다.

다시 커서를 함수 위치에 대고 M-x eval-defun 함수를 실행해서 갱신한 다음 search-elixir-doc 함수를 실행한다.

search terms - enum%20take

enum take 문자열을 입력하면 퍼센트 인코딩이 된 걸 확인할 수 있다.

이제 쿼리 스트링을 포함한 전체 url을 만들어야 한다.

(format "https://hexdocs.pm/elixir/search.html?q=%s" search-terms) 표현식으로 url을 조합할 수 있지만 emacs lisp 표준 라이브러리에 있는 쿼리 스트링 관련 함수를 찾아서 써보고 싶다.

웹서핑으로는 찾기 힘들어서 M-x find-function 함수를 실행해서 url-build-query-string 함수를 찾았다.

(url-build-query-string '(("q" "enum take")))
"q=enum%20take"

따로 퍼센트 인코딩을 안 해줘도 되겠다. 함수 내부에서 인코딩한다. 리스트 자체로 넘기려고 ’ 문자를 붙였다. ’ 문자를 안 붙이면 첫 번째 요소인 “q” 를 함수로 두 번째 요소인 “enum take” 를 인자로 계산한다. 이런 계산을 막고 리스트 자체를 넘기려면 ’ 문자를 붙여준다. 이름하여 quote.

(let ((search-terms "enum take"))
  (url-build-query-string '(("q" search-terms))))
"q=search-terms"

값을 바인딩한 심볼을 쓰면 문제가 생긴다. 심볼 이름이 그대로 들어가기 때문이다.

(let ((search-terms "enum take"))
  (url-build-query-string `(("q" ,search-terms))))
"q=enum%20take"

에이 다 말고 search-terms 는 계산(evaluation) 해주세요. 이럴 때는 backquote를 사용하면 된다. backquote를 사용하고 계산할 심볼 앞에 , 문자를 붙이면 원하는 대로 쿼리 스트링이 만들어진다.

(defun search-elixir-doc (search-terms)
  (interactive "sEnter your search terms: ")
  (let* ((base-url "https://hexdocs.pm/elixir/search.html")
         (query-string (url-build-query-string `(("q" ,search-terms))))
         (url (format "%s?%s" base-url query-string)))
    (message "url - %s" url)))
url - https://hexdocs.pm/elixir/search.html?q=enum%20take

원하는 대로 url이 만들었다. 이제 다음은 웹브라우저로 열 차례다.

3. 웹브라우저로 URL 열기

(browse-url url)

왜 이렇게 단계를 나눴을까? 웹브라우저로 URL을 여는 건 함수 하나 호출로 끝난다. browse-url 함수를 사용하면 OS 기본 브라우저로 선택한 브라우저로 URL을 연다.

마무리

(defun search-elixir-doc (search-terms)
  (interactive "sEnter your search terms: ")
  (let* ((base-url "https://hexdocs.pm/elixir/search.html")
         (query-string (url-build-query-string `(("q" ,search-terms))))
         (url (format "%s?%s" base-url query-string)))
    (browse-url url)))

전체 코드다.

M-x search-elixir-doc
enum take

입력하면 웹브라우저로 nil 페이지를 연다. 이제 이 함수를 만들어 놨다는 것만 잊지 않으면 elixir 문서를 쉽게 검색할 수 있다.

참고

C-x C-s C-x C-c