Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

코드 읽기 모험:굉장한 인쇄 보석

멋진 인쇄는 출력 형식을 irb로 지정하는 멋진 보석입니다. &pry 가독성을 높일 수 있습니다.

예를 들어...

이것은 awesome_print로 해시를 표시하는 것입니다. 다음과 같이 보입니다:

코드 읽기 모험:굉장한 인쇄 보석

하지만 어떻게 작동합니까?

<블록 인용>

"진실은 오직 한 곳, 즉 코드에서만 찾을 수 있습니다." ― 로버트 C. 마틴

소스 코드를 살펴보고 알아봅시다!

멋진 인쇄

저는 프로젝트 구조(파일 및 폴더)에 대한 간략한 개요와 함께 코드 읽기 세션을 시작한 다음 앞으로의 탐색에 집중할 수 있는 질문을 하고 싶습니다.

그래서 제가 생각해낸 첫 번째 질문은 :

awesome_print는 어떻게 pry의 출력을 변경하시겠습니까?

이제 탐정 ​​모자를 쓰고 가설을 세웁니다. :

"이 보석은 $stdout을 대체할 수 있습니다. pry의 출력을 캡처한 다음 예쁘게 만들 수 있도록."

그러나 이 구현에서는 pretty_print와 같은 출력을 사용자 정의할 수 없습니다. (Ruby의 표준 라이브러리에서) 그렇습니다.

또한 코드를 구문 분석하거나 평가해야 할 수도 있습니다. 좋은 생각은 아닙니다!

다음 :

이 보석이 어떻게 로드되는지 살펴보았습니다.

이것은 우리에게 코드에 대한 진입점을 제공할 것입니다.

멋진 인쇄물 로드 중

awesome_print를 로드하려면 이 작업을 수행해야 합니다.

require 'awesome_print'
AwesomePrint.pry!

이제 pry! 위치를 찾고 싶습니다. 정의됩니다.

Atom의 "디렉토리에서 검색" 기능을 사용하여 찾았습니다.

코드는 다음과 같습니다. :

def pry!
  Pry.print = proc { |output, value| output.puts value.ai } if defined?(Pry)
end

Pry에서 print 값을 설정하여 출력을 수정할 수 있는 것 같습니다. .

이것은 "시작할 위치" 질문에 대한 답변입니다. 🙂

<블록 인용>

이 "proc"에 대해 더 알고 싶으십니까? "블록, 프로세서 및 람다에 대한 궁극적인 가이드"를 읽으십시오. 이것은 내 Ruby Deep Dive 책의 샘플 챕터입니다.

이 프로시저는 두 개의 인수를 사용합니다. :

  • 출력
  • 가치

그리고 해당 개체에 대해 두 가지 메서드를 호출합니다.

다음 질문 :

ai는 무엇인가요? 방법?

Kernel에 정의된 메소드입니다. 모듈:

def ai(options = {})
  ap      = AwesomePrint::Inspector.new(options)
  awesome = ap.awesome(self)

  if options[:html]
    awesome = "</pre>#{awesome}</pre>"
    awesome = awesome.html_safe if defined? ActiveSupport
  end

  awesome
end

alias :awesome_inspect :ai
#{awesome}" Awesome =Awesome.html_safe(정의된 경우)? ActiveSupport 종료 Awesomeendalias :awesome_inspect :ai

모든 개체에는 Kernel이 포함되어 있기 때문에 기본적으로 이 ai가 있습니다. 방법을 사용할 수 있습니다.

이제 이 Inspector 수업이 진행됩니다.

인스펙터 클래스

inspector.rb를 연 직후 initialize 내부에서 거대한 옵션 해시를 찾습니다. 방법.

여기에 일부가 있습니다 :

@options = {
  indent:        4,      # Number of spaces for indenting.
  index:         true,   # Display array indices.
  html:          false,  # Use ANSI color codes rather than HTML.
  multiline:     true,   # Display in multiple lines.
  # ...
}

그 후에 이 코드를 찾을 수 있습니다. :

@formatter  = AwesomePrint::Formatter.new(self)
@indentator = AwesomePrint::Indentator.new(@options[:indent].abs)

Thread.current[AP] ||= []

따라서 서식 자체와 코드 들여쓰기를 처리하는 것처럼 보이는 두 개의 개체가 더 설정됩니다.

하지만 이 Thread.current 뭐?

글쎄, 이것은 현재 스레드에 대한 액세스를 제공합니다. 애플리케이션에서 스레드를 사용하지 않더라도 "메인" 스레드가 있습니다.

AP 상수는 inspector.rb 상단에 정의된 상수일 뿐입니다. :

AP = :__awesome_print__

여기에서 무슨 일이 일어나고 있습니까?

멋진 인쇄는 Thread.current를 사용하고 있습니다. &__awesome_print__ 현재 스레드에서만 사용할 수 있는 일부 데이터를 저장하는 키입니다.

이것은 멀티 스레딩 문제를 방지하는 데 사용됩니다.

멋진 서식

AwesomePrint::Formatter 내부에서 발생하는 출력 형식 지정 코드를 살펴보겠습니다. 수업.

이것이 작동하는 방식은 검사기(ai 메서드)는 format을 호출합니다. 방법.

def unnested(object)
  @formatter.format(object, printable(object))
end

그런 다음 이 format Formatter의 메소드 클래스는 이러한 유형의 개체를 처리하는 가장 좋은 방법을 찾고 약간의 메타프로그래밍을 사용하여 다른 메서드를 호출합니다.

방법은 다음과 같습니다. :

def format(object, type = nil)
  core_class = cast(object, type)

  awesome = if core_class != :self
    send(:"awesome_#{core_class}", object) # Core formatters.
  else
    awesome_self(object, type) # Catch all that falls back to object.inspect.
  end

  awesome
end

Formatter를 이해하려면 우리는 또한 cast 방법:

def cast(object, type)
  CORE.grep(type)[0] || :self
end

CORE 상수는 핵심 Ruby 클래스 및 :self를 나타내는 기호 배열입니다. "찾을 수 없음"을 의미하는 데 사용되는 기호입니다(이 예에서는 일반적으로 Ruby가 아님).

CORE = [:array, :bigdecimal, :class, :dir, :file, :hash, :method, :rational, :set, :struct, :unboundmethod]

무슨 일이야 :

서식이 지정되는 개체가 "핵심 클래스" 목록에 있으면 특수 형식을 갖게 됩니다.

그렇지 않으면 일반적인 것이 됩니다.

특수 포맷터는 lib/awesome_print/formatters/ 아래에 정의되어 있습니다. 디렉토리 및 Array와 같은 항목 포함 , Hash &Class .

예를 들어, 다음은 클래스에 대한 포맷터 메서드입니다.

def format
  superclass = klass.superclass
  if superclass
    colorize("#{klass.inspect} < #{superclass}", :class)
  else
    colorize(klass.inspect, :class)
  end
end

원하는 경우 자신만의 포맷터를 작성할 수 있습니다.

요약

배열 및 해시와 같은 개체를 멋지게 표시할 수 있는 Awesome Print gem에 대해 배웠습니다.

이 시간을 즐기고 새로운 것을 배웠기를 바랍니다!

더 많은 사람들이 배울 수 있도록 지금 이 게시물을 즐겨찾는 소셜 네트워크에 공유하세요 🙂