Compiler Picker UI Improvements (#4849)

Alrighty, round 2!

This PR makes the compiler picker dropdown taller (max height is to the
bottom of the screen)

![image](https://user-images.githubusercontent.com/51220084/224517409-17706ba6-fe85-444a-ad3b-f244f66eea5b.png)

I've added a toolbar button for opening the popout as well as a button
when the dropdown is open:


![image](https://user-images.githubusercontent.com/51220084/224517304-6478fca5-7bc1-4f87-b2ae-e9091d7d48bc.png)

![image](https://user-images.githubusercontent.com/51220084/224517317-83468805-1e9d-4bc6-8a4f-8786325f1e7b.png)

Then the modal interface allows text searching, filtering by compiler
category, and filtering by compiler instruction set. In the future I'd
like to replace the instructionSet property with an architecture
property so the filtering here can be a little better.


![image](https://user-images.githubusercontent.com/51220084/224517348-9cf40866-c5af-4274-84ba-21eb640ab2ea.png)

Demo of the category filtering:


![image](https://user-images.githubusercontent.com/51220084/224517529-5370b3f9-9ad3-4340-838a-b2d0a47c7467.png)

The text filtering highlights results the same as tomselect does:


![image](https://user-images.githubusercontent.com/51220084/224517490-d0dfa6d0-9b61-4be4-8cc7-ca4a4729a532.png)

I moved the favorites permanently to their own column so compilers
aren't jarringly shifted around the screen when favoriting /
unfavoriting.

Also added media queries so the modal looks ok on smaller screens:


![image](https://user-images.githubusercontent.com/51220084/224517563-bdf409c1-7e3a-4c73-812b-f02179b55799.png)


![image](https://user-images.githubusercontent.com/51220084/224517574-07fa2c8b-67d2-496d-9174-b1343e22bd62.png)

I think the only other two changes from the first PR are now the active
compiler is highlighted like it is in the tomselect dropdown and I
figured out how to reliably focus the search bar on modal open. (Oh, and
now clicking a compiler actually does something!)

---------

Co-authored-by: Matt Godbolt <matt@godbolt.org>
This commit is contained in:
Jeremy Rifkin
2023-03-12 17:07:44 -04:00
committed by GitHub
parent d319b25a61
commit 55dc09017e
25 changed files with 764 additions and 48 deletions

View File

@@ -20,6 +20,8 @@ group.gnat.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
group.gnat.licenseName=GNU General Public License
group.gnat.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
group.gnat.supportsBinaryObject=true
group.gnat.instructionSet=amd64
group.gnat.compilerCategories=gcc
compiler.gnat82.exe=/opt/compiler-explorer/gcc-8.2.0/bin/gnatmake
compiler.gnat82.semver=8.2
@@ -54,6 +56,7 @@ group.gnatcross.isSemVer=true
group.gnatcross.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
group.gnatcross.licenseName=GNU General Public License
group.gnatcross.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
group.gnatcross.compilerCategories=gcc
################################
# GNAT for sparc

View File

@@ -12,6 +12,7 @@ group.nasm.options=
group.nasm.isSemVer=true
group.nasm.baseName=NASM
group.nasm.compilerType=nasm
group.nasm.instructionSet=amd64
compiler.nasm21202.semver=2.12.02
compiler.nasm21202.exe=/opt/compiler-explorer/nasm-2.12.02/nasm
compiler.nasm21302.semver=2.13.02
@@ -27,6 +28,7 @@ group.gnuas.versionFlag=--version
group.gnuas.options=-g
group.gnuas.isSemVer=true
group.gnuas.baseName=x86-64 binutils
group.gnuas.instructionSet=amd64
compiler.gnuas72.exe=/opt/compiler-explorer/gcc-7.2.0/bin/as
compiler.gnuas72.semver=2.27
compiler.gnuas73.exe=/opt/compiler-explorer/gcc-7.3.0/bin/as
@@ -51,6 +53,7 @@ group.gnuasarm.isSemVer=true
group.gnuasarm.baseName=ARM binutils
group.gnuasarm.supportsExecute=false
group.gnuasarm.objdumper=/opt/compiler-explorer/arm/gcc-10.2.0/arm-unknown-linux-gnueabihf/bin/arm-unknown-linux-gnueabihf-objdump
group.gnuasarm.instructionSet=arm32
compiler.gnuasarmhfg54.exe=/opt/compiler-explorer/arm/gcc-5.4.0/arm-unknown-linux-gnueabihf/bin/arm-unknown-linux-gnueabihf-as
compiler.gnuasarmhfg54.name=ARMhf binutils 2.28
@@ -79,6 +82,7 @@ group.gnuasarm64.isSemVer=true
group.gnuasarm64.baseName=AArch64 binutils
group.gnuasarm64.supportsExecute=false
group.gnuasarm64.objdumper=/opt/compiler-explorer/arm64/gcc-10.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/bin/objdump
group.gnuasarm64.instructionSet=aarch64
compiler.gnuasarm64g630.exe=/opt/compiler-explorer/arm64/gcc-6.3.0/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-as
compiler.gnuasarm64g630.name=AArch64 binutils 2.28
@@ -100,6 +104,7 @@ group.llvmas.options=-filetype=obj -o example.o
group.llvmas.versionRe=LLVM version .*
group.llvmas.isSemVer=true
group.llvmas.baseName=x86-64 clang
group.llvmas.instructionSet=amd64
compiler.llvmas30.exe=/opt/compiler-explorer/clang+llvm-3.0-x86_64-linux-Ubuntu-11_10/bin/llvm-mc
compiler.llvmas30.semver=3.0.0
compiler.llvmas31.exe=/opt/compiler-explorer/clang+llvm-3.1-x86_64-linux-ubuntu_12.04/bin/llvm-mc
@@ -175,6 +180,7 @@ group.ptxas.compilerType=ptxas
group.ptxas.demangler=
group.ptxas.isSemVer=true
group.ptxas.supportsExecute=false
group.ptxas.instructionSet=ptx
compiler.ptxasnvcc91.objdumper=/opt/compiler-explorer/cuda/9.1.85/bin/nvdisasm
compiler.ptxasnvcc91.semver=9.1.85

View File

@@ -29,6 +29,7 @@ group.gcc86.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
group.gcc86.licenseName=GNU General Public License
group.gcc86.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
group.gcc86.supportsBinaryObject=true
group.gcc86.compilerCategories=gcc
compiler.g412.exe=/opt/compiler-explorer/gcc-4.1.2/bin/g++
compiler.g412.semver=4.1.2
@@ -208,6 +209,7 @@ group.clang.licenseName=LLVM Apache 2
group.clang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.clang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.clang.supportsBinaryObject=true
group.clang.compilerCategories=clang
# Ancient clangs don't support GCC toolchain option
compiler.clang30.exe=/opt/compiler-explorer/clang+llvm-3.0-x86_64-linux-Ubuntu-11_10/bin/clang++
@@ -352,6 +354,7 @@ group.clangx86trunk.unwiseOptions=-march=native
group.clangx86trunk.supportsPVS-Studio=true
group.clangx86trunk.supportsSonar=true
group.clangx86trunk.ldPath=${exePath}/../lib|${exePath}/../lib/x86_64-unknown-linux-gnu
group.clangx86trunk.compilerCategories=clang
compiler.clang_trunk.exe=/opt/compiler-explorer/clang-trunk/bin/clang++
compiler.clang_trunk.semver=(trunk)
@@ -421,6 +424,7 @@ group.clang-rocm.supportsSonar=true
group.clang-rocm.licenseName=LLVM Apache 2 and NCSA
group.clang-rocm.licenseLink=https://github.com/RadeonOpenCompute/llvm-project/blob/amd-stg-open/LICENSE.TXT
# and https://github.com/RadeonOpenCompute/ROCm-Device-Libs/blob/amd-stg-open/LICENSE.TXT
group.clang-rocm.compilerCategories=clang
compiler.clang-rocm-trunk.exe=/opt/compiler-explorer/clang-rocm-trunk/bin/clang++
compiler.clang-rocm-trunk.semver=(amd-stg-open)
@@ -463,6 +467,7 @@ group.armclang32.objdumper=/opt/compiler-explorer/arm/gcc-10.2.0/arm-unknown-lin
group.armclang32.licenseName=LLVM Apache 2
group.armclang32.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.armclang32.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.armclang32.compilerCategories=clang
compiler.armv7-clang1101.exe=/opt/compiler-explorer/clang-11.0.1/bin/clang++
compiler.armv7-clang1101.semver=11.0.1
@@ -508,6 +513,7 @@ group.armclang64.instructionSet=aarch64
group.armclang64.licenseName=LLVM Apache 2
group.armclang64.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.armclang64.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.armclang64.compilerCategories=clang
compiler.armv8-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
compiler.armv8-clang1500.semver=15.0.0
@@ -572,6 +578,7 @@ group.mosclang-trunk.compilerType=llvmmos
group.mosclang-trunk.isSemVer=true
group.mosclang-trunk.objdumper=/opt/compiler-explorer/llvm-mos-trunk/bin/llvm-objdump
group.mosclang-trunk.objdumperType=llvm
group.mosclang-trunk.compilerCategories=clang
compiler.mos-nes-cnrom-trunk.exe=/opt/compiler-explorer/llvm-mos-trunk/bin/mos-nes-cnrom-clang++
compiler.mos-nes-cnrom-trunk.semver=nes-cnrom
@@ -616,6 +623,7 @@ group.rv32clang.options=-target riscv32-unknown-elf -march=rv32gc -mabi=ilp32d -
group.rv32clang.objdumper=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-objdump
group.rv32clang.baseName=RISC-V rv32gc clang
group.rv32clang.groupName=RISC-V 32 Clang
group.rv32clang.compilerCategories=clang
compiler.rv32-clang900.exe=/opt/compiler-explorer/clang-9.0.0/bin/clang++
compiler.rv32-clang900.semver=9.0.0
@@ -658,6 +666,7 @@ group.rv64clang.options=-target riscv64-unknown-linux-gnu -march=rv64gc -mabi=lp
group.rv64clang.objdumper=/opt/compiler-explorer/riscv64/gcc-10.2.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-objdump
group.rv64clang.baseName=RISC-V rv64gc clang
group.rv64clang.groupName=RISC-V 64 Clang
group.rv64clang.compilerCategories=clang
compiler.rv64-clang900.exe=/opt/compiler-explorer/clang-9.0.0/bin/clang++
compiler.rv64-clang900.semver=9.0.0
@@ -703,6 +712,7 @@ group.wasmclang.supportsBinary=false
group.wasmclang.licenseName=LLVM Apache 2
group.wasmclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.wasmclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.wasmclang.compilerCategories=clang
compiler.wasm32clang.exe=/opt/compiler-explorer/clang-trunk/bin/clang++
compiler.wasm32clang.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
@@ -719,6 +729,8 @@ group.icc.groupName=ICC x86-64
group.icc.baseName=x86-64 icc
group.icc.isSemVer=true
group.icc.licensePreamble=Proprietary, with thanks to Intel for the license
group.icc.compilerCategories=icc
group.icc.instructionSet=amd64
compiler.icc1301.exe=/opt/compiler-explorer/intel/bin/icc
compiler.icc1301.alias=/opt/intel/bin/icc
@@ -806,6 +818,8 @@ group.icx.compilerType=clang-intel
group.icx.licenseName=LLVM Apache 2
group.icx.licenseLink=https://github.com/intel/llvm/blob/sycl/LICENSE.TXT
group.icx.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.icx.compilerCategories=icc
group.icx.instructionSet=amd64
compiler.icx202112.exe=/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/bin/icpx
compiler.icx202112.ldPath=/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/compiler/lib/intel64_lin:/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/lib
@@ -877,6 +891,7 @@ group.cross.supportsExecute=false
group.cross.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
group.cross.licenseName=GNU General Public License
group.cross.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
group.cross.compilerCategories=gcc
###############################
# Cross for BPF
@@ -893,6 +908,7 @@ group.clangbpf.isSemVer=true
group.clangbpf.options=-target bpf
group.clangbpf.objdumper=/opt/compiler-explorer/clang-trunk/bin/llvm-objdump
group.clangbpf.objdumperType=llvm
group.clangbpf.compilerCategories=clang
compiler.bpfclangtrunk.exe=/opt/compiler-explorer/clang-trunk/bin/clang++
compiler.bpfclangtrunk.semver=(trunk)
@@ -1536,6 +1552,7 @@ group.mips-clang.supportsBinary=false
group.mips-clang.supportsBinaryObject=false
group.mips-clang.supportsExecute=false
group.mips-clang.options=-target mips-elf
group.mips-clang.compilerCategories=clang
compiler.mips-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
compiler.mips-clang1500.semver=15.0.0
@@ -1554,6 +1571,7 @@ group.mipsel-clang.supportsBinary=false
group.mipsel-clang.supportsBinaryObject=false
group.mipsel-clang.supportsExecute=false
group.mipsel-clang.options=-target mipsel-elf
group.mipsel-clang.compilerCategories=clang
compiler.mipsel-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
compiler.mipsel-clang1500.semver=15.0.0
@@ -1572,6 +1590,7 @@ group.mips64-clang.supportsBinary=false
group.mips64-clang.supportsBinaryObject=false
group.mips64-clang.supportsExecute=false
group.mips64-clang.options=-target mips64-elf
group.mips64-clang.compilerCategories=clang
compiler.mips64-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
compiler.mips64-clang1500.semver=15.0.0
@@ -1590,6 +1609,7 @@ group.mips64el-clang.supportsBinary=false
group.mips64el-clang.supportsBinaryObject=false
group.mips64el-clang.supportsExecute=false
group.mips64el-clang.options=-target mips64el-elf
group.mips64el-clang.compilerCategories=clang
compiler.mips64el-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
compiler.mips64el-clang1500.semver=15.0.0
@@ -1672,6 +1692,7 @@ compiler.mipselg1220.demangler=/opt/compiler-explorer/mipsel/gcc-12.2.0/mipsel-m
group.mips64el.groupName=MIPS64EL GCC
group.mips64el.compilers=mips564el:mips64elg1210:mips64elg1220
group.mips64el.baseName=mips64 (el) gcc
group.mips64el.compilerCategories=gcc
compiler.mips564el.exe=/opt/compiler-explorer/mips64el/gcc-5.4.0/mips64el-unknown-linux-gnu/bin/mips64el-unknown-linux-gnu-g++
compiler.mips564el.semver=5.4
@@ -1882,6 +1903,8 @@ group.cl.demanglerType=win32
group.cl.supportsBinary=false
group.cl.objdumper=
group.cl.isSemVer=true
group.cl.compilerCategories=msvc
group.cl.instructionSet=amd64
group.cl19.groupName=WINE MSVC 2017
group.cl19.compilers=cl19_64:cl19_32:cl19_arm
group.cl19.options=/I/opt/compiler-explorer/windows/10.0.10240.0/ucrt/ /I/opt/compiler-explorer/windows/19.10.25017/lib/native/include/
@@ -1895,7 +1918,7 @@ compiler.cl19_32.semver=19.10.25017
compiler.cl19_arm.exe=/opt/compiler-explorer/windows/19.10.25017/lib/native/bin/amd64_arm/cl.exe
compiler.cl19_arm.name=ARM msvc v19.10 (WINE)
compiler.cl19_arm.semver=19.10.25017
compiler.cl19_arm.instructionSet=arm
compiler.cl19_arm.instructionSet=arm32
group.cl19_2015_u3.groupName=WINE MSVC 2015
group.cl19_2015_u3.compilers=cl19_2015_u3_64:cl19_2015_u3_32:cl19_2015_u3_arm
@@ -1910,7 +1933,7 @@ compiler.cl19_2015_u3_32.semver=19.00.24210
compiler.cl19_2015_u3_arm.exe=/opt/compiler-explorer/windows/19.00.24210/bin/amd64_arm/cl.exe
compiler.cl19_2015_u3_arm.name=ARM msvc v19.0 (WINE)
compiler.cl19_2015_u3_arm.semver=19.00.24210
compiler.cl19_2015_u3_arm.instructionSet=arm
compiler.cl19_2015_u3_arm.instructionSet=arm32
group.cl_new.groupName=WINE MSVC 2017
group.cl_new.compilers=cl_new_64:cl_new_32:cl_new_arm32:cl_new_arm64
@@ -2018,6 +2041,8 @@ group.cxx6502.supportsExecute=false
group.cxx6502.licenseLink=https://github.com/lefticus/6502-cpp/blob/master/LICENSE
group.cxx6502.licenseName=The Unlicense
group.cxx6502.licensePreamble=This is free and unencumbered software released into the public domain.
group.cxx6502.compilerCategories=gcc
group.cxx6502.instructionSet=6502
compiler.gcc6502_1110.exe=/opt/compiler-explorer/6502-c++-trunk/bin/6502-c++
compiler.gcc6502_1110.semver=11.1.0
@@ -2042,6 +2067,7 @@ group.nvcxx_x86_cxx.demanglerType=nvhpc
group.nvcxx_x86_cxx.groupName=nvc++ x86
group.nvcxx_x86_cxx.baseName=x86 nvc++
group.nvcxx_x86_cxx.isSemVer=true
group.nvcxx_x86_cxx.compilerCategories=nvc++
compiler.nvcxx_x86_cxx22_7.demangler=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/22.7/compilers/bin/nvdecode
compiler.nvcxx_x86_cxx22_7.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/22.7/compilers/bin/nvc++
@@ -2069,6 +2095,7 @@ group.nvcxx_arm_cxx.groupName=nvc++ arm
group.nvcxx_arm_cxx.baseName=ARM64 nvc++
group.nvcxx_arm_cxx.isSemVer=true
group.nvcxx_arm_cxx.instructionSet=aarch64
group.nvcxx_arm_cxx.compilerCategories=nvc++
compiler.nvcxx_arm_cxx22_7.demangler=/opt/compiler-explorer/hpc_sdk/Linux_aarch64/22.7/compilers/bin/nvdecode
compiler.nvcxx_arm_cxx22_7.exe=/opt/compiler-explorer/hpc_sdk/Linux_aarch64/22.7/compilers/bin/nvc++

View File

@@ -2,6 +2,7 @@
compilers=&gcc:&clang
group.gcc.compilers=g44:g45:g46:g47:g48:g5:g6x:g7:g8:g9:g10:g11:gdefault
group.gcc.compilerCategories=gcc
compiler.g44.exe=/usr/bin/g++-4.4
compiler.g44.name=g++ 4.4
compiler.g45.exe=/usr/bin/g++-4.5
@@ -33,6 +34,7 @@ compiler.gdefault.name=g++ default
group.clang.compilers=clang7:clang8:clang9:clang10:clang11:clang12:clangdefault
group.clang.intelAsm=-mllvm --x86-asm-syntax=intel
group.clang.compilerType=clang
group.clang.compilerCategories=clang
compiler.clang7.exe=/usr/bin/clang++-7
compiler.clang7.name=clang 7
compiler.clang8.exe=/usr/bin/clang++-8

View File

@@ -23,6 +23,7 @@ group.cgcc86.supportsPVS-Studio=true
group.cgcc86.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
group.cgcc86.licenseName=GNU General Public License
group.cgcc86.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
group.cgcc86.compilerCategories=gcc
compiler.cg412.exe=/opt/compiler-explorer/gcc-4.1.2/bin/gcc
compiler.cg412.semver=4.1.2
@@ -149,6 +150,8 @@ group.cgcc-classic.supportsExecute=false
group.cgcc-classic.supportsBinary=false
group.cgcc-classic.licenseName=GNU CC GENERAL PUBLIC LICENSE (Clarified 11 Feb 1988)
group.cgcc-classic.supportsBinaryObject=true
group.cgcc-classic.compilerCategories=gcc
group.cgcc-classic.instructionSet=amd64
compiler.cg127.exe=/opt/compiler-explorer/gcc-1.27/bin/gcc
compiler.cg127.semver=1.27
@@ -165,6 +168,7 @@ group.cclang.supportsPVS-Studio=true
group.cclang.licenseName=LLVM Apache 2
group.cclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.cclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.cclang.compilerCategories=clang
compiler.cclang30.exe=/opt/compiler-explorer/clang+llvm-3.0-x86_64-linux-Ubuntu-11_10/bin/clang
compiler.cclang30.semver=3.0.0
@@ -297,6 +301,7 @@ group.armcclang32.instructionSet=arm32
group.armcclang32.licenseName=LLVM Apache 2
group.armcclang32.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.armcclang32.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.armcclang32.compilerCategories=clang
group.armcclang64.groupName=Arm 64-bit clang
group.armcclang64.compilers=armv8-cclang900:armv8-cclang901:armv8-cclang1000:armv8-cclang1001:armv8-cclang1100:armv8-cclang1101:armv8-cclang1200:armv8-cclang1201:armv8-cclang1300:armv8-cclang1301:armv8-cclang1400:armv8-cclang1500:armv8-cclang-trunk:armv8-full-cclang-trunk
@@ -307,7 +312,7 @@ group.armcclang64.instructionSet=aarch64
group.armcclang64.licenseName=LLVM Apache 2
group.armcclang64.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.armcclang64.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.armcclang64.compilerCategories=clang
compiler.armv7-cclang1500.name=armv7-a clang 15.0.0
compiler.armv7-cclang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang
@@ -512,6 +517,7 @@ group.cmosclang-trunk.compilerType=llvmmos
group.cmosclang-trunk.isSemVer=true
group.cmosclang-trunk.objdumper=/opt/compiler-explorer/llvm-mos-trunk/bin/llvm-objdump
group.cmosclang-trunk.objdumperType=llvm
group.cmosclang-trunk.compilerCategories=clang
compiler.cmos-nes-cnrom-trunk.exe=/opt/compiler-explorer/llvm-mos-trunk/bin/mos-nes-cnrom-clang
compiler.cmos-nes-cnrom-trunk.semver=nes-cnrom
@@ -551,6 +557,7 @@ group.rvcclang.isSemVer=true
group.rvcclang.licenseName=LLVM Apache 2
group.rvcclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.rvcclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.rvcclang.compilerCategories=clang
group.rv32cclang.compilers=rv32-cclang:rv32-cclang1500:rv32-cclang1400:rv32-cclang1301:rv32-cclang1300:rv32-cclang1200:rv32-cclang1201:rv32-cclang1101:rv32-cclang1100:rv32-cclang1001:rv32-cclang1000:rv32-cclang901:rv32-cclang900
group.rv32cclang.options=-target riscv32-unknown-elf -march=rv32gc -mabi=ilp32d --gcc-toolchain=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-elf
@@ -560,6 +567,7 @@ group.rv32cclang.groupName=RISC-V 32 Clang
group.rv32cclang.licenseName=LLVM Apache 2
group.rv32cclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.rv32cclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.rv32cclang.compilerCategories=clang
compiler.rv32-cclang900.exe=/opt/compiler-explorer/clang-9.0.0/bin/clang
compiler.rv32-cclang900.semver=9.0.0
@@ -602,6 +610,7 @@ group.rv64cclang.options=-target riscv64-unknown-linux-gnu -march=rv64gc -mabi=l
group.rv64cclang.objdumper=/opt/compiler-explorer/riscv64/gcc-8.2.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-objdump
group.rv64cclang.baseName=RISC-V rv64gc clang
group.rv64cclang.groupName=RISC-V 64 Clang
group.rv64cclang.compilerCategories=clang
compiler.rv64-cclang900.semver=9.0.0
compiler.rv64-cclang900.exe=/opt/compiler-explorer/clang-9.0.0/bin/clang
@@ -648,6 +657,7 @@ group.wasmcclang.supportsBinaryObject=false
group.wasmcclang.licenseName=LLVM Apache 2
group.wasmcclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
group.wasmcclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
group.wasmcclang.compilerCategories=clang
compiler.wasm32cclang.exe=/opt/compiler-explorer/clang-trunk/bin/clang
compiler.wasm32cclang.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
@@ -677,6 +687,8 @@ group.cicc.options=-x c -gcc-name=/opt/compiler-explorer/gcc-4.7.1/bin/gcc
group.cicc.groupName=ICC x86-64
group.cicc.isSemVer=true
group.cicc.baseName=x86-64 icc
group.cicc.compilerCategories=icc
group.cicc.instructionSet=amd64
compiler.cicc1301.exe=/opt/compiler-explorer/intel/bin/icc
compiler.cicc1301.semver=13.0.1
# intel 13.01 binary disabled: it just segfaults (no idea why)
@@ -754,6 +766,8 @@ group.cicx.groupName=ICX x86-64
group.cicx.baseName=x86-64 icx
group.cicx.isSemVer=true
group.cicx.compilerType=clang-intel
group.cicx.compilerCategories=icc
group.cicx.instructionSet=amd64
compiler.cicx202112.exe=/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/bin/icx
compiler.cicx202112.ldPath=/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/compiler/lib/intel64_lin:/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/lib
@@ -812,6 +826,7 @@ group.ccross.groupName=Cross GCC
group.ccross.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
group.ccross.licenseName=GNU General Public License
group.ccross.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
group.ccross.compilerCategories=gcc
###############################
# Cross for BPF
@@ -1166,7 +1181,7 @@ compiler.carm1031_07.supportsBinary=false
compiler.carm1031_10.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc
compiler.carm1031_10.name=ARM gcc 10.3.1 (2021.10 none)
compiler.carm1031_10.semver=10.3.1
compiler.carm1031_10.supportsBinary=false
compiler.carm1031_10.supportsBinary=false
compiler.carm1121.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-11.2-2022.02/bin/arm-none-eabi-gcc
compiler.carm1121.name=ARM gcc 11.2.1 (none)
compiler.carm1121.semver=11.2.1
@@ -1867,6 +1882,8 @@ group.ccl.versionRe=^Microsoft \(R\) C/C\+\+.*$
group.ccl.isSemVer=true
group.ccl.supportsBinary=false
group.ccl.objdumper=
group.ccl.compilerCategories=msvc
group.ccl.instructionSet=amd64
group.ccl19.groupName=WINE MSVC 2017
group.ccl19.compilers=ccl19_64:ccl19_32:ccl19_arm
group.ccl19.options=/I/opt/compiler-explorer/windows/10.0.10240.0/ucrt/ /I/opt/compiler-explorer/windows/19.10.25017/lib/native/include/ /TC
@@ -1879,7 +1896,7 @@ compiler.ccl19_32.semver=19.10.25017
compiler.ccl19_arm.exe=/opt/compiler-explorer/windows/19.10.25017/lib/native/bin/amd64_arm/cl.exe
compiler.ccl19_arm.name=ARM msvc v19.10 (WINE)
compiler.ccl19_arm.semver=19.10.25017
compiler.ccl19_arm.instructionSet=arm
compiler.ccl19_arm.instructionSet=arm32
group.ccl19_2015_u3.groupName=WINE MSVC 2015
group.ccl19_2015_u3.compilers=ccl19_2015_u3_64:ccl19_2015_u3_32:ccl19_2015_u3_arm
@@ -1893,7 +1910,7 @@ compiler.ccl19_2015_u3_32.semver=19.00.24210
compiler.ccl19_2015_u3_arm.exe=/opt/compiler-explorer/windows/19.00.24210/bin/amd64_arm/cl.exe
compiler.ccl19_2015_u3_arm.name=ARM msvc v19.0 (WINE)
compiler.ccl19_2015_u3_arm.semver=19.00.24210
compiler.ccl19_2015_u3_arm.instructionSet=arm
compiler.ccl19_2015_u3_arm.instructionSet=arm32
group.ccl_new.groupName=WINE MSVC 2017
group.ccl_new.compilers=ccl_new_64:ccl_new_32:ccl_new_arm32:ccl_new_arm64

View File

@@ -37,6 +37,11 @@ export function unique<V>(arr: V[]): V[] {
return [...new Set(arr)];
}
export function intersection<V>(a: V[], b: V[]): V[] {
const B = new Set(b);
return [...a].filter(item => B.has(item));
}
// arr.filter(x => x !== null) returns a (T | null)[] even though it is a T[]
// Apparently the idiomatic solution is arr.filter((x): x is T => x !== null), but this is shorter (and the type
// predicate also isn't type checked so it doesn't seem safe to me)

View File

@@ -261,6 +261,7 @@ export class CompilerFinder {
versionRe: props<string>('versionRe'),
explicitVersion: props<string>('explicitVersion'),
compilerType: props('compilerType', ''),
compilerCategories: props<string | undefined>('compilerCategories', undefined)?.split(':'),
debugPatched: props('debugPatched', false),
demangler: demangler,
demanglerType: props('demanglerType', ''),
@@ -269,7 +270,7 @@ export class CompilerFinder {
objdumperType: props('objdumperType', ''),
intelAsm: props('intelAsm', ''),
supportsAsmDocs: props('supportsAsmDocs', true),
instructionSet: props('instructionSet', ''),
instructionSet: props<string | number>('instructionSet', '').toString(),
needsMulti: !!props('needsMulti', true),
adarts: props('adarts', ''),
supportsDemangle: !!demangler,

20
package-lock.json generated
View File

@@ -15,6 +15,7 @@
"@aws-sdk/client-ssm": "^3.282.0",
"@flatten-js/interval-tree": "^1.0.20",
"@fortawesome/fontawesome-free": "^6.2.1",
"@orchidjs/sifter": "^1.0.3",
"@sentry/browser": "^7.28.1",
"@sentry/node": "^7.28.1",
"@types/morgan": "^1.9.4",
@@ -2991,9 +2992,17 @@
}
},
"node_modules/@orchidjs/sifter": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/@orchidjs/sifter/-/sifter-0.9.3.tgz",
"integrity": "sha512-9XGiAJcWvEektxjR9X+dYeG+kg8GdojM6ZCmrnuDaWoVew+GAKxiesvYxyY+RLUgWTv8B1qpLIVYlswxKcW5XQ=="
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@orchidjs/sifter/-/sifter-1.0.3.tgz",
"integrity": "sha512-zCZbwKegHytfsPm8Amcfh7v/4vHqTAaOu6xFswBYcn8nznBOuseu6COB2ON7ez0tFV0mKL0nRNnCiZZA+lU9/g==",
"dependencies": {
"@orchidjs/unicode-variants": "^1.0.4"
}
},
"node_modules/@orchidjs/unicode-variants": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@orchidjs/unicode-variants/-/unicode-variants-1.0.4.tgz",
"integrity": "sha512-NvVBRnZNE+dugiXERFsET1JlKZfM5lJDEpSMilKW4bToYJ7pxf0Zne78xyXB2ny2c2aHfJ6WLnz1AaTNHAmQeQ=="
},
"node_modules/@pkgr/utils": {
"version": "2.3.1",
@@ -15356,6 +15365,11 @@
"url": "https://opencollective.com/tom-select"
}
},
"node_modules/tom-select/node_modules/@orchidjs/sifter": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/@orchidjs/sifter/-/sifter-0.9.3.tgz",
"integrity": "sha512-9XGiAJcWvEektxjR9X+dYeG+kg8GdojM6ZCmrnuDaWoVew+GAKxiesvYxyY+RLUgWTv8B1qpLIVYlswxKcW5XQ=="
},
"node_modules/tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",

View File

@@ -24,6 +24,7 @@
"@aws-sdk/client-ssm": "^3.282.0",
"@flatten-js/interval-tree": "^1.0.20",
"@fortawesome/fontawesome-free": "^6.2.1",
"@orchidjs/sifter": "^1.0.3",
"@sentry/browser": "^7.28.1",
"@sentry/node": "^7.28.1",
"@types/morgan": "^1.9.4",

View File

@@ -27,9 +27,9 @@ rules:
- error
- smart
indent:
- error
- 4
- SwitchCase: 1
- off
#- 4
#- SwitchCase: 1
max-len:
- error
- 120

81
static/highlight.ts Normal file
View File

@@ -0,0 +1,81 @@
// Copyright (c) 2023, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
type Interval = {start: number; length: number};
function regexExecAll(base_re: RegExp, s: string) {
const re = new RegExp(base_re.source, base_re.flags + 'gd');
let m: any;
const matches: Interval[] = [];
while ((m = re.exec(s)) != null) {
// TODO(jeremy-rifkin): Find a way to get TS to understand that m.indices is real
matches.push({
start: m.indices[0][0],
length: m.indices[0][1] - m.indices[0][0],
});
}
return matches;
}
export function highlight(str: string, regexes: RegExp[]) {
// At the moment, because compiler names are short, I think this solution is best. It's easiest to just
// track intervals with an array. The ideal solution in the general case is probably something along the
// lines of an interval tree.
const intervals: Interval[] = [];
for (const regex of regexes) {
intervals.push(...regexExecAll(regex, str));
}
// sort by interval start
intervals.sort((a, b) => a.start - b.start);
// combine intervals
let i = 0;
while (i < intervals.length - 1) {
const {start: AStart, length: ALength} = intervals[i];
const {start: BStart, length: BLength} = intervals[i + 1];
if (AStart + ALength >= BStart) {
intervals.splice(i, 2, {
start: AStart,
length: BStart + BLength - AStart,
});
} else {
i++;
}
}
// for each interval, highlight
let offset = 0;
for (const {start, length} of intervals) {
const tagStart = '<span class="highlight">';
const tagEnd = '</span>';
const intervalStart = offset + start;
const intervalEnd = offset + start + length;
str =
str.slice(0, intervalStart) +
tagStart +
str.slice(intervalStart, intervalEnd) +
tagEnd +
str.slice(intervalEnd);
offset += tagStart.length + tagEnd.length;
}
return str;
}

View File

@@ -234,7 +234,8 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
private linkedFadeTimeoutId: NodeJS.Timeout | null;
private toolsMenu: JQuery<HTMLElement> | null;
private revealJumpStack: (monaco.editor.ICodeEditorViewState | null)[];
private compilerPicker: CompilerPicker | JQuery<HTMLElement>;
private compilerPickerElement: JQuery<HTMLElement>;
private compilerPicker: CompilerPicker;
private compiler: CompilerInfo | null;
private currentLangId: string | null;
private filters: Toggles;
@@ -470,6 +471,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
this.eventHub.unsubscribe();
this.eventHub.emit('compilerClose', this.id, this.sourceTreeId ?? 0);
this.editor.dispose();
this.compilerPicker.destroy();
}
onCompiler(compilerId: number, compiler: unknown, options: string, editorId: number, treeId: number): void {}
@@ -2353,7 +2355,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
this.optionsField.val(this.options);
this.shortCompilerName = this.domRoot.find('.short-compiler-name');
this.compilerPicker = this.domRoot.find('.compiler-picker');
this.compilerPickerElement = this.domRoot.find('.compiler-picker');
this.setCompilerVersionPopover({version: '', fullVersion: ''}, '');
this.topBar = this.domRoot.find('.top-bar');

View File

@@ -339,7 +339,7 @@ export class Conformance extends Pane<ConformanceViewState> {
this.compilerPickers = _.reject(this.compilerPickers, function (entry) {
return compilerEntry.picker?.id === entry.picker?.id;
});
compilerEntry.picker?.tomSelect?.close();
compilerEntry.picker?.destroy();
compilerEntry.parent.remove();
this.updateLibraries();
@@ -596,7 +596,7 @@ export class Conformance extends Pane<ConformanceViewState> {
override close(): void {
this.eventHub.unsubscribe();
this.compilerPickers.forEach(compilerEntry => {
compilerEntry.picker?.tomSelect?.close();
compilerEntry.picker?.destroy();
compilerEntry.parent.remove();
});
if (this.compilerInfo.editorId) this.eventHub.emit('conformanceViewClose', this.compilerInfo.editorId);

View File

@@ -284,7 +284,7 @@ export class Executor extends Pane<ExecutorState> {
close(): void {
this.eventHub.unsubscribe();
if (this.compilerPicker instanceof CompilerPicker) {
this.compilerPicker.close();
this.compilerPicker.destroy();
}
this.eventHub.emit('executorClose', this.id);

View File

@@ -547,12 +547,12 @@ input.vim-check {
height: 20px;
}
/* While we find a better solution, lets up this a bit */
.compiler-picker .ts-dropdown-content {
max-height: 300px !important;
.compiler-picker-dropdown .ts-dropdown-content {
// Default max-height, the compiler picker will override this to prevent overflowing the window
max-height: 600px;
}
.compiler-picker .ts-dropdown-content .option {
.compiler-picker-dropdown .ts-dropdown-content .option {
padding: 0 10px;
}
@@ -834,6 +834,105 @@ div.populararguments div.dropdown-menu {
display: none;
}
@media (max-width: 830px) {
#compiler-picker-modal {
.compilers-row {
flex-direction: column-reverse;
}
}
}
@media (max-width: 1200px) {
#compiler-picker-modal {
.compilers-col {
.compilers {
width: 300px !important;
columns: 1 300px !important;
}
}
}
}
#compiler-picker-modal {
.modal-body {
overflow-y: scroll;
}
input.compiler-search {
margin-left: 10px;
//outline: 0 !important;
padding: 5px 10px;
}
.filters {
margin-top: 10px;
}
.architecture,
.compiler-type {
padding: 2px 5px;
border-radius: 3px;
margin: 0 0 0 3px;
cursor: pointer;
user-select: none;
}
.compilers-col {
margin-top: 5px;
h6 {
margin-top: 15px;
font-size: 16px;
}
.compilers {
width: 650px;
columns: 2 300px;
column-gap: 40px;
&.one-col {
width: 300px;
columns: 1 300px;
}
}
.favorites {
margin-left: 10px;
}
.compilers,
.favorites {
.group-wrapper {
display: inline-block;
.group {
width: 300px;
margin-bottom: 25px;
.label {
cursor: pointer;
}
.compiler {
cursor: pointer;
.highlight {
background: rgba(255, 237, 40, 0.4);
border-radius: 1px;
}
.toggle-fav {
cursor: pointer;
}
}
.folded {
display: none;
text-align: center;
}
&.collapsed {
.compiler {
display: none !important;
}
.folded {
display: block !important;
}
}
}
}
}
}
}
#timing-info .modal-content {
min-width: 500px;
min-height: 400px;
@@ -939,11 +1038,35 @@ html[data-theme='dark'] {
overflow-y: scroll;
}
.prepend-options {
.prepend-options,
.picker-popout-button {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.picker-popout-button {
font-size: 14px;
line-height: 14px;
position: relative;
i {
vertical-align: middle;
}
}
.compiler-picker-dropdown-popout-wrapper {
text-align: center;
cursor: pointer;
font-size: 15px;
position: absolute;
top: 100%;
background: inherit;
box-shadow: rgba(0, 0, 0, 0.176) 0px 6px 12px 0px; // same as the tomselect dropdown
left: 0;
.compiler-picker-dropdown-popout {
padding: 10px;
}
}
.popular-arguments-btn {
border-top-right-radius: 0;
}

View File

@@ -507,6 +507,14 @@ textarea.form-control {
background-color: #353535 !important;
}
.picker-popout-button {
border: none !important;
background: #444444 !important;
&:hover {
background: darken(#444444, 5%) !important;
}
}
.qb-logo-pri {
fill: #e2e2e2 !important;
}
@@ -622,6 +630,30 @@ textarea.form-control {
}
}
#compiler-picker-modal {
.architecture,
.compiler-type {
background: #444;
&.active {
background: #007bff;
}
}
.compilers-col .group-wrapper .group {
.label {
background: #555555;
}
.compiler {
&:hover {
background: #8d8d8e;
}
&.selected {
background: #21525f;
}
}
}
}
#alert {
&.error-alert {
.modal-content {

View File

@@ -278,6 +278,11 @@ kbd {
background-color: #e9ecef;
}
.picker-popout-button {
background-color: #fff;
border-left: none;
}
#simplecook {
background-color: #f4f4f4;
}
@@ -410,6 +415,31 @@ div.argmenuitem span.argdescription {
}
}
#compiler-picker-modal {
.architecture,
.compiler-type {
background: #eeeeee;
&.active {
background: #3c9aff;
}
}
.compilers-col .group-wrapper .group {
.label {
// taking the color tom-select uses, but I find that a little low-contrast
background: darken(#f6f6f6, 3%);
}
.compiler {
&:hover {
background: #e9ecef;
}
&.selected {
background: #e9ecef;
}
}
}
}
#alert {
&.error-alert {
.modal-content {

View File

@@ -0,0 +1,269 @@
// Copyright (c) 2023, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
import $ from 'jquery';
import _ from 'underscore';
import * as sifter from '@orchidjs/sifter';
import {CompilerInfo} from '../../types/compiler.interfaces';
import {intersection, remove, unique} from '../../lib/common-utils';
import {unwrap, unwrapString} from '../assert';
import {CompilerPicker} from './compiler-picker';
import {CompilerService} from '../compiler-service';
import {highlight} from '../highlight';
export class CompilerPickerPopup {
modal: JQuery<HTMLElement>;
searchBar: JQuery<HTMLElement>;
architectures: JQuery<HTMLElement>;
compilerTypes: JQuery<HTMLElement>;
compilersContainer: JQuery<HTMLElement>;
resultsContainer: JQuery<HTMLElement>;
favoritesContainer: JQuery<HTMLElement>;
groups: {value: string; label: string}[];
options: (CompilerInfo & {$groups: string[]})[];
langId: string;
isaFilters: string[];
categoryFilters: string[];
sifter: sifter.Sifter;
searchResults: ReturnType<sifter.Sifter['search']> | undefined;
constructor(private readonly compilerPicker: CompilerPicker) {
this.modal = $('#compiler-picker-modal').clone(true);
this.searchBar = this.modal.find('.compiler-search');
this.architectures = this.modal.find('.architectures');
this.compilerTypes = this.modal.find('.compiler-types');
this.compilersContainer = this.modal.find('.compilers-row');
this.resultsContainer = this.modal.find('.compilers');
this.favoritesContainer = this.modal.find('.favorites');
this.modal.on('shown.bs.modal', () => {
this.searchBar[0].focus();
});
}
setLang(groups: {value: string; label: string}[], options: (CompilerInfo & {$groups: string[]})[], langId: string) {
this.groups = groups;
this.options = options;
this.langId = langId;
this.setupFilters();
this.sifter = new sifter.Sifter(options, {
diacritics: false,
});
}
setupFilters() {
// get available instruction sets
const compilers = Object.values(this.compilerPicker.compilerService.getCompilersForLang(this.langId) ?? {});
// If instructionSet is '', just label it unknown
const instruction_sets = compilers.map(compiler => compiler.instructionSet || 'other');
this.architectures.empty();
this.architectures.append(
...unique(instruction_sets)
.sort()
.map(isa => `<span class="architecture" data-value=${_.escape(isa)}>${_.escape(isa)}</span>`),
);
// get available compiler types
const compilerTypes = compilers.map(compiler => compiler.compilerCategories ?? ['other']).flat();
this.compilerTypes.empty();
this.compilerTypes.append(
...unique(compilerTypes)
.sort()
.map(type => `<span class="compiler-type" data-value=${_.escape(type)}>${_.escape(type)}</span>`),
);
// search box
this.searchBar.on('input', () => {
const query = unwrapString(this.searchBar.val()).trim();
if (query === '') {
this.searchResults = undefined;
} else {
this.searchResults = this.sifter.search(query, {
fields: ['name'],
conjunction: 'and',
sort: CompilerService.getSelectizerOrder(),
});
}
this.fillCompilers();
});
// isa filters
$(this.architectures)
.find('.architecture')
.on('click', e => this.onFilterClick(e, this.isaFilters));
// category filters
$(this.compilerTypes)
.find('.compiler-type')
.on('click', e => this.onFilterClick(e, this.categoryFilters));
}
onFilterClick(e: JQuery.ClickEvent, filtersArray: string[]) {
e.preventDefault();
const elem = $(e.currentTarget);
elem.toggleClass('active');
const filterValue = unwrap(elem.attr('data-value'));
if (filtersArray.includes(filterValue)) {
// This is pretty much the best way to filter an array in-place
filtersArray.splice(0, filtersArray.length, ...filtersArray.filter(v => v !== filterValue));
} else {
filtersArray.push(filterValue);
}
this.fillCompilers();
}
fillCompilers() {
const filteredIndices = this.searchResults
? new Set(this.searchResults.items.map(item => item.id as number))
: undefined;
const filteredCompilers = this.options.filter((compiler, i) => {
if (this.isaFilters.length > 0) {
if (!this.isaFilters.includes(compiler.instructionSet || 'other')) {
return false;
}
}
if (this.categoryFilters.length > 0) {
const categories = compiler.compilerCategories ?? ['other'];
if (intersection(this.categoryFilters, categories).length === 0) {
return false;
}
}
if (filteredIndices) {
if (!filteredIndices.has(i)) {
return false;
}
}
return true;
});
// figure out if there are any empty groups, these will be ignored
const groupCounts: Partial<Record<string, number>> = {};
for (const compiler of filteredCompilers) {
for (const group of compiler.$groups) {
groupCounts[group] = (groupCounts[group] ?? 0) + 1;
}
}
// add the compiler entries / group headers themselves
this.resultsContainer.empty();
this.favoritesContainer.empty();
const groupMap: Record<string, JQuery> = {};
for (const group of this.groups) {
if ((groupCounts[group.value] ?? 0) > 0 || group.value === CompilerPicker.favoriteGroupName) {
const group_elem = $(
`
<div class="group-wrapper">
<div class="group">
<div class="label">${_.escape(group.label)}</div>
</div>
</div>
`,
);
if (group.value === CompilerPicker.favoriteGroupName) {
group_elem.appendTo(this.favoritesContainer);
} else {
group_elem.appendTo(this.resultsContainer);
}
groupMap[group.value] = group_elem.find('.group');
}
}
// if there can only ever be one column, don't bother with room for 2
this.resultsContainer.toggleClass(
'one-col',
this.groups.filter(group => group.value !== CompilerPicker.favoriteGroupName).length <= 1,
);
const searchRegexes = this.searchResults
? remove(
this.searchResults.tokens.map(token => token.regex),
null,
)
: undefined;
for (const compiler of filteredCompilers) {
const isFavorited = compiler.$groups.includes(CompilerPicker.favoriteGroupName);
const extraClasses = isFavorited ? 'fas fa-star fav' : 'far fa-star';
for (const group of compiler.$groups) {
// TODO(jeremy-rifkin): At the moment none of our compiler names should contain html special characters.
// This is just a good measure to take. If a compiler is ever added that does have special characters in
// its name it could interfere with the highlighting (e.g. if your text search is for "<" that won't
// highlight). I'm going to defer handling that to a future PR though.
const name = _.escape(compiler.name);
const compiler_elem = $(
`
<div class="compiler d-flex" data-value="${compiler.id}">
<div>${searchRegexes ? highlight(name, searchRegexes) : name}</div>
<div title="Click to mark or unmark as a favorite" class="ml-auto toggle-fav">
<i class="${extraClasses}"></i>
</div>
</div>
`,
);
if (compiler.id === this.compilerPicker.lastCompilerId) {
compiler_elem.addClass('selected');
}
compiler_elem.appendTo(groupMap[group]);
}
}
// group header click events
this.compilersContainer.find('.group').append('<div class="folded">&#8943;</div>');
this.compilersContainer.find('.group > .label').on('click', e => {
$(e.currentTarget).closest('.group').toggleClass('collapsed');
});
// compiler click events
this.compilersContainer.find('.compiler').on('click', e => {
this.compilerPicker.selectCompiler(unwrap(e.currentTarget.getAttribute('data-value')));
this.hide();
});
// favorite stars
this.compilersContainer.find('.compiler .toggle-fav').on('click', e => {
const compilerId = unwrap($(e.currentTarget).closest('.compiler').attr('data-value'));
const data = filteredCompilers.filter(c => c.id === compilerId)[0];
const isAddingNewFavorite = !data.$groups.includes(CompilerPicker.favoriteGroupName);
if (isAddingNewFavorite) {
data.$groups.push(CompilerPicker.favoriteGroupName);
this.compilerPicker.addToFavorites(data.id);
} else {
data.$groups.splice(data.$groups.indexOf(CompilerPicker.favoriteGroupName), 1);
this.compilerPicker.removeFromFavorites(data.id);
}
this.fillCompilers();
});
}
show() {
// reflow the compilers to get any new favorites from the compiler picker dropdown and reset filters and whatnot
this.isaFilters = [];
this.categoryFilters = [];
this.searchBar.val('');
this.searchBar.trigger('input');
this.modal.find('.architectures .active, .compiler-types .active').toggleClass('active');
this.fillCompilers();
this.modal.modal({});
}
hide() {
this.modal.modal('hide');
}
}

View File

@@ -30,6 +30,10 @@ import * as local from '../local.js';
import {EventHub} from '../event-hub.js';
import {Hub} from '../hub.js';
import {CompilerService} from '../compiler-service.js';
import {CompilerInfo} from '../../types/compiler.interfaces.js';
import {unique} from '../../lib/common-utils.js';
import {unwrap} from '../assert.js';
import {CompilerPickerPopup} from './compiler-picker-popup.js';
type Favourites = {
[compilerId: string]: boolean;
@@ -39,7 +43,6 @@ export class CompilerPicker {
static readonly favoriteGroupName = '__favorites__';
static readonly favoriteStoreKey = 'favCompilerIds';
static nextSelectorId = 1;
domRoot: JQuery;
domNode: HTMLSelectElement;
eventHub: EventHub;
id: number;
@@ -49,6 +52,9 @@ export class CompilerPicker {
lastLangId: string;
lastCompilerId: string;
compilerIsVisible: (any) => any; // TODO => bool probably
popup: CompilerPickerPopup;
toolbarPopoutButton: JQuery<HTMLElement>;
popupTooltip: JQuery<HTMLElement>;
constructor(
domRoot: JQuery,
hub: Hub,
@@ -63,6 +69,11 @@ export class CompilerPicker {
if (!(compilerPicker instanceof HTMLSelectElement)) {
throw new Error('.compiler-picker is not an HTMLSelectElement');
}
this.toolbarPopoutButton = domRoot.find('.picker-popout-button');
domRoot.find('.picker-popout-button').on('click', () => {
unwrap(this.tomSelect).close();
this.popup.show();
});
this.domNode = compilerPicker;
this.compilerService = hub.compilerService;
this.onCompilerChange = onCompilerChange;
@@ -74,22 +85,24 @@ export class CompilerPicker {
this.compilerIsVisible = () => true;
}
this.popup = new CompilerPickerPopup(this);
this.initialize(langId, compilerId);
}
close() {
// Quick note while I'm here: This function is never called. It probably should be. The conformance view
// bypasses this function and does compilerEntry.picker.tomSelect.close(); manually. This function is the
// only time this.tomSelect can be null, might be nice if we can get rid of that.
destroy() {
this.eventHub.unsubscribe();
if (this.tomSelect) this.tomSelect.destroy();
this.tomSelect = null;
}
initialize(langId: string, compilerId: string) {
private initialize(langId: string, compilerId: string) {
this.lastLangId = langId;
this.lastCompilerId = compilerId;
const groups = this.getGroups(langId);
const options = this.getOptions(langId, compilerId);
this.tomSelect = new TomSelect(this.domNode, {
sortField: CompilerService.getSelectizerOrder(),
valueField: 'id',
@@ -97,9 +110,9 @@ export class CompilerPicker {
searchField: ['name'],
placeholder: '🔍 Select a compiler...',
optgroupField: '$groups',
optgroups: this.getGroups(langId),
optgroups: groups,
lockOptgroupOrder: true,
options: this.getOptions(langId, compilerId),
options: options,
items: compilerId ? [compilerId] : [],
dropdownParent: 'body',
closeAfterSelect: true,
@@ -110,14 +123,14 @@ export class CompilerPicker {
// Typing here needs improvement later anyway.
/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */
if (val) {
const compilerId = val as any as string;
ga.proxy('send', {
hitType: 'event',
eventCategory: 'SelectCompiler',
eventAction: val,
eventAction: compilerId,
});
const str = val as any as string;
this.onCompilerChange(str);
this.lastCompilerId = str;
this.onCompilerChange(compilerId);
this.lastCompilerId = compilerId;
}
},
duplicates: true,
@@ -140,6 +153,32 @@ export class CompilerPicker {
},
});
this.tomSelect.on('dropdown_open', () => {
// Prevent overflowing the window
const dropdown = unwrap(this.tomSelect).dropdown_content;
dropdown.style.maxHeight = `${window.innerHeight - dropdown.getBoundingClientRect().top - 10}px`;
this.popupTooltip = $(`
<div class="compiler-picker-dropdown-popout-wrapper">
<div class="compiler-picker-dropdown-popout">
<i class="fa-solid fa-arrow-up-right-from-square"></i> Pop Out
</div>
</div>
`);
// I think tomselect is stealing the click event here. Somehow tomselect's global onclick prevents a click
// here from firing, maybe related to the dropdown closing and this getting removed from the dom. But,
// mousedown is a decent workaround.
this.popupTooltip.on('mousedown', () => {
unwrap(this.tomSelect).close();
this.popup.show();
});
this.popupTooltip.appendTo(this.toolbarPopoutButton);
});
this.tomSelect.on('dropdown_close', () => {
this.popupTooltip.remove();
});
$(this.tomSelect.dropdown_content).on('click', '.toggle-fav', evt => {
evt.preventDefault();
evt.stopPropagation();
@@ -156,13 +195,10 @@ export class CompilerPicker {
data.$groups.push(CompilerPicker.favoriteGroupName);
this.addToFavorites(data.id);
} else {
data.$groups.splice(data.group.indexOf(CompilerPicker.favoriteGroupName), 1);
data.$groups.splice(data.$groups.indexOf(CompilerPicker.favoriteGroupName), 1);
this.removeFromFavorites(data.id);
}
this.tomSelect.updateOption(value, data);
this.tomSelect.refreshOptions(false);
if (clickedGroup !== CompilerPicker.favoriteGroupName) {
// If the user clicked on an option that wasn't in the top "Favorite" group, then we just added
// or removed a bunch of controls way up in the list. Find the new element top and adjust the scroll
@@ -175,16 +211,21 @@ export class CompilerPicker {
}
}
});
this.popup.setLang(groups, options, langId);
}
getOptions(langId: string, compilerId: string) {
getOptions(langId: string, compilerId: string): (CompilerInfo & {$groups: string[]})[] {
const favorites = this.getFavorites();
return Object.values(this.compilerService.getCompilersForLang(langId) ?? {})
.filter(e => (this.compilerIsVisible(e) && !e.hidden) || e.id === compilerId)
.map(e => {
e.$groups = [e.group];
if (favorites[e.id]) e.$groups.unshift(CompilerPicker.favoriteGroupName);
return e;
const $groups = [e.group];
if (favorites[e.id]) $groups.unshift(CompilerPicker.favoriteGroupName);
return {
...e,
$groups,
};
});
}
@@ -225,6 +266,7 @@ export class CompilerPicker {
const faves = this.getFavorites();
faves[compilerId] = true;
this.setFavorites(faves);
this.updateTomselectOption(compilerId);
this.eventHub.emit('compilerFavoriteChange', this.id);
}
@@ -232,6 +274,20 @@ export class CompilerPicker {
const faves = this.getFavorites();
delete faves[compilerId];
this.setFavorites(faves);
this.updateTomselectOption(compilerId);
this.eventHub.emit('compilerFavoriteChange', this.id);
}
updateTomselectOption(compilerId: string) {
if (this.tomSelect) {
this.tomSelect.updateOption(compilerId, this.tomSelect.options[compilerId]);
this.tomSelect.refreshOptions(false);
}
}
selectCompiler(compilerId: string) {
if (this.tomSelect) {
this.tomSelect.addItem(compilerId);
}
}
}

View File

@@ -40,6 +40,9 @@ export type CompilerInfo = {
versionRe?: string;
explicitVersion?: string;
compilerType: string;
// groups are more fine-grained, e.g. gcc x86-64, gcc arm, clang x86-64, ...
// category is more broad: gcc, clang, msvc, ...
compilerCategories?: string[];
debugPatched: boolean;
demangler: string;
demanglerType: string;
@@ -79,7 +82,6 @@ export type CompilerInfo = {
lang: LanguageKey;
group: string;
groupName: string;
$groups: string[];
includeFlag: string;
includePath: string;
linkFlag: string;
@@ -123,10 +125,9 @@ export type CompilerInfo = {
};
// Compiler information collected by the compiler-finder
export type PreliminaryCompilerInfo = Omit<
CompilerInfo,
'version' | 'fullVersion' | 'baseName' | '$groups' | 'disabledFilters'
> & {version?: string};
export type PreliminaryCompilerInfo = Omit<CompilerInfo, 'version' | 'fullVersion' | 'baseName' | 'disabledFilters'> & {
version?: string;
};
export interface ICompiler {
possibleArguments: ICompilerArguments;

View File

@@ -2,6 +2,8 @@ include load-save
include alert
include compiler-picker-modal
include yes-no
include enter-something

View File

@@ -0,0 +1,32 @@
#compiler-picker-modal.modal.fade.gl_keep(tabindex="-1" role="dialog")
.modal-dialog.modal-lg
.modal-content
.modal-header
h5.modal-title Compilers
button.close(type="button" data-dismiss="modal" aria-hidden="true" aria-label="Close")
span(aria-hidden="true")
| &times;
.modal-body
.card
.card-body
.container
.row
.col-lg
div.filters Filter:
input.compiler-search(value="" placeholder="🔍 Search for a compiler...")
.row
.col-lg
div.filters Instruction Sets:
span.architectures
.row
.col-lg
div.filters Categories:
span.compiler-types
.row
.compilers-col.col-md
h6 Results
.row.compilers-row
.col-md
.compilers
.col-md
.favorites

View File

@@ -10,6 +10,10 @@ mixin newPaneButton(classId, text, title, icon)
.input-group-prepend
.input-group
select.compiler-picker
.input-group-append
button.btn.btn-sm.btn-light.input-group-text.picker-popout-button(data-trigger="click" style="cursor: pointer;" role="button" title="Compiler picker popout")
span
i.fa-solid.fa-arrow-up-right-from-square
.input-group-append
button.btn.btn-sm.btn-light.input-group-text.prepend-options(data-trigger="click" style="cursor: pointer;" role="button" title="All compilation options")
span.status-icon

View File

@@ -29,6 +29,10 @@
.input-group-prepend
.input-group
select.compiler-picker
.input-group-append
button.btn.btn-sm.btn-light.input-group-text.picker-popout-button(data-trigger="click" style="cursor: pointer;" role="button" title="Compiler picker popout")
span
i.fa-solid.fa-arrow-up-right-from-square
.input-group-append
button.btn.btn-sm.btn-light.input-group-text.prepend-options(data-trigger="click" style="cursor: pointer;" role="button" title="All compilation options")
span.btn.btn-sm.btn-light.status-icon

View File

@@ -4,6 +4,10 @@
.input-group-prepend
.input-group
select.compiler-picker
.input-group-append
button.btn.btn-sm.btn-light.input-group-text.picker-popout-button(data-trigger="click" style="cursor: pointer;" role="button" title="Compiler picker popout")
span
i.fa-solid.fa-arrow-up-right-from-square
.input-group-append
button.btn.btn-sm.btn-light.input-group-text.prepend-options(tabindex="0" data-trigger="focus" style="cursor: pointer;" role="button" title="All compilation options")
span.btn.btn-sm.btn-light.status-icon