text: <template>
      <div class="search-result-item">
        <div
          class="search-result"
          :title="searchResult.filePath"
        >
          <svg
            class="icon icon-arrow"
            :class="{'fold': !showSearchMatches}"
            aria-hidden="true"
            @click.stop="toggleSearchMatches()"
          >
            <use xlink:href="#icon-arrow"></use>
          </svg>
          <div
            class="file-info"
            @click.stop="toggleSearchMatches()"
          >
            <div class="title">
              <span class="filename">
                <span class="name">{{ filename }}</span><span class="extension">{{extension}}</span>
              </span>
              <span class="match-count">{{ matchCount }}</span>
            </div>
            <!-- <div class="folder-path">
              <span>{{ dirname }}</span>
            </div> -->
          </div>
        </div>
        <div
          class="matches"
          v-if="showSearchMatches"
        >
          <ul>
            <li
              class="text-overflow"
              v-for="(searchMatch, index) of getMatches"
              :key="index"
              :searchMatch="searchMatch"
              :title="searchMatch.lineText"
              @click="handleSearchResultClick(searchMatch)"
            >
              <!-- <span class="line-number">{{ searchMatch.range[0][0] }}</span> -->
              <span>{{ ellipsisText(searchMatch.lineText.substring(0, searchMatch.range[0][1])) }}</span>
              <span class="highlight">{{ searchMatch.lineText.substring(searchMatch.range[0][1], searchMatch.range[1][1]) }}</span>
              <span>{{ searchMatch.lineText.substring(searchMatch.range[1][1]) }}</span>
            </li>
          </ul>
          <div v-if="!allMatchesShown">
            <div
              class="button tiny"
              @click="handleShowMoreMatches"
            >
              Show more matches
            </div>
          </div>
        </div>
      </div>
  </template>
  
  <script>
  import path from 'path'
  import { mapState } from 'vuex'
  import { fileMixins } from '../../mixins'
  import { PATH_SEPARATOR } from '../../config'
  
  export default {
    mixins: [fileMixins],
    data () {
      return {
        showSearchMatches: this.searchResult.matches.length <= 20,
        allMatchesShown: this.searchResult.matches.length <= 10,
        shownMatches: 10
      }
    },
    props: {
      searchResult: {
        type: Object,
        required: true
      }
    },
    computed: {
      ...mapState({
        tabs: state => state.editor.tabs,
        currentFile: state => state.editor.currentFile
      }),
  
      getMatches () {
        if (this.searchResult.matches.length === 0 || this.allMatchesShown) {
          return this.searchResult.matches
        }
        return this.searchResult.matches.slice(0, this.shownMatches)
      },
  
      // Return filename without extension.
      filename () {
        return path.basename(this.searchResult.filePath, path.extname(this.searchResult.filePath))
      },
  
      matchCount () {
        return this.searchResult.matches.length
      },
  
      // Return the filename extension or null.
      extension () {
        return path.extname(this.searchResult.filePath)
      },
  
      // Return the parent directory with trailing path separator.
      dirname () {
        return path.join(path.dirname(this.searchResult.filePath), PATH_SEPARATOR)
      }
    },
    methods: {
      toggleSearchMatches () {
        this.showSearchMatches = !this.showSearchMatches
      },
  
      handleShowMoreMatches (event) {
        this.shownMatches += 15
        if (event.ctrlKey || event.metaKey ||
            this.shownMatches >= this.searchResult.matches.length) {
          this.allMatchesShown = true
        }
      },
  
      ellipsisText (text) {
        const len = text.length
        const MAX_PRETEXT_LEN = 6
        return len > MAX_PRETEXT_LEN ? `...${text.substring(len - MAX_PRETEXT_LEN)}` : text
      }
    }
  }
  </script>
  
  <style scoped>
    .search-result-item {
      position: relative;
      user-select: none;
      padding: 0 10px 8px 10px;
      color: var(--sideBarColor);
      font-size: 14px;
      & > .search-result {
        display: flex;
        align-items: center;
        & > svg:first-child {
          margin-right: 3px;
        }
        & > .file-info {
          flex: 1;
          overflow: hidden;
        }
      }
      & .title .filename {
        font-size: 14px;
        text-overflow: ellipsis;
        overflow: hidden;
        white-space: nowrap;
        padding-right: 8px;
      }
      & .matches {
        & ul {
          padding-left: 0;
          list-style-type: none;
          & li {
            display: block;
            padding: 2px 16px;
            padding-right: 0;
            cursor: pointer;
            /* Hide space between inline spans */
            font-size: 0;
            & .highlight {
              background: var(--highlightColor);
              line-height: 16px;
              height: 16px;
              display: inline-block;
              color: var(--sideBarTextColor);
              border-radius: 1px;
            }
            &:hover {
              background: var(--sideBarItemHoverBgColor);
            }
            & span {
              font-size: 13px;
              white-space: pre;
            }
          }
        }
        & .button {
          width: 130px;
          margin: 0 auto;
          text-align: center;
        }
      }
    }
    .search-result-item.active {
      font-weight: 600;
      .title {
        color: var(--themeColor);
      }
    }
    .search-result-item.active::before {
      height: 100%;
    }
    .title {
      display: flex;
      color: var(--sideBarTextColor);
      & .filename {
        flex: 1;
        & .name {
          font-weight: 600;
        }
        & .extension {
          color: var(--sideBarTextColor);
          font-size: 12px;
        }
      }
      & .match-count {
        display: inline-block;
        font-size: 12px;
        line-height: 18px;
        text-align: center;
        min-width: 18px;
        height: 18px;
        border-radius: 9px;
        flex-shrink: 0;
        background: var(--itemBgColor);
        color: var(--sideBarTextColor);
      }
    }
  
    .folder-path {
      font-size: 12px;
    }
  
    .folder-path > span,
    .matches {
      width: 100%;
      margin-top: 5px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      color: var(--sideBarTextColor);
    }
  
    .icon-arrow {
      transition: all .25s ease-out;
      transform: rotate(90deg);
      fill: var(--sideBarTextColor);
    }
    .icon-arrow.fold {
      transform: rotate(0);
    }
  </style>
  